Fix cursor Y positioning logic in editor
This commit is contained in:
parent
6939550527
commit
979656c2d0
|
|
@ -457,60 +457,84 @@ func SetCursorFromPoint(x, y float64) {
|
|||
return
|
||||
}
|
||||
|
||||
// 1. Find the best line based on y
|
||||
bestLineY := layout.Y[0]
|
||||
minYDist := 1e9
|
||||
for _, yVal := range layout.Y {
|
||||
yDist := float64(yVal) - y
|
||||
if yDist < 0 {
|
||||
yDist = -yDist
|
||||
}
|
||||
if yDist < minYDist {
|
||||
minYDist = yDist
|
||||
bestLineY = yVal
|
||||
lineHeight := float64(EditorLineHeight())
|
||||
|
||||
// 1. Identify the intended line index based on y
|
||||
// layout.Y values are relative to the text region origin.
|
||||
// We need to account for scroll offset.
|
||||
visualLine := int((y + float64(TheState.ScrollOffset)) / lineHeight)
|
||||
|
||||
// Group glyphs by their Y-baseline
|
||||
type lineGroup struct {
|
||||
y float64
|
||||
indices []int
|
||||
}
|
||||
groups := []lineGroup{}
|
||||
seenY := make(map[float64]int) // maps Y to group index
|
||||
|
||||
for i, yVal := range layout.Y {
|
||||
yFloat := float64(yVal)
|
||||
idx, ok := seenY[yFloat]
|
||||
if !ok {
|
||||
idx = len(groups)
|
||||
groups = append(groups, lineGroup{y: yFloat, indices: []int{}})
|
||||
seenY[yFloat] = idx
|
||||
}
|
||||
groups[idx].indices = append(groups[idx].indices, i)
|
||||
}
|
||||
// Sort groups by Y
|
||||
sort.Slice(groups, func(i, j int) bool { return groups[i].y < groups[j].y })
|
||||
|
||||
// If visualLine is out of bounds, clamp
|
||||
if visualLine < 0 {
|
||||
visualLine = 0
|
||||
}
|
||||
if visualLine >= len(groups) {
|
||||
visualLine = len(groups) - 1
|
||||
}
|
||||
|
||||
// 2. Identify glyphs on this line and find the rightmost extent
|
||||
targetGroup := groups[visualLine]
|
||||
|
||||
// 3. Identify rightmost extent on this line
|
||||
rightmostX := 0.0
|
||||
rightmostIdx := -1
|
||||
for i, yVal := range layout.Y {
|
||||
if yVal == bestLineY {
|
||||
xEnd := float64(layout.X[i] + layout.Advance[i])
|
||||
if xEnd > rightmostX {
|
||||
rightmostX = xEnd
|
||||
rightmostIdx = i
|
||||
}
|
||||
for _, i := range targetGroup.indices {
|
||||
xEnd := float64(layout.X[i] + layout.Advance[i])
|
||||
if xEnd > rightmostX {
|
||||
rightmostX = xEnd
|
||||
rightmostIdx = i
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Check if tap is to the right of the last character on this line
|
||||
// 4. Check if tap is to the right of the last character
|
||||
if rightmostIdx != -1 && x > rightmostX {
|
||||
// Position after the last character on this line
|
||||
// Position at the end of the line content, before any trailing newline.
|
||||
start := layout.ByteOffsets[rightmostIdx]
|
||||
_, size := utf8.DecodeRuneInString(TheState.Editor.Buffer[start:])
|
||||
TheState.Editor.CursorPosition = start + size
|
||||
r, size := utf8.DecodeRuneInString(TheState.Editor.Buffer[start:])
|
||||
if r == '\n' {
|
||||
TheState.Editor.CursorPosition = start
|
||||
} else {
|
||||
TheState.Editor.CursorPosition = start + size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 4. Otherwise, find the closest glyph on this line.
|
||||
// 5. Otherwise, find the closest glyph on this line.
|
||||
bestIdx := -1
|
||||
minDist := float64(1e9)
|
||||
for i, yVal := range layout.Y {
|
||||
if yVal == bestLineY {
|
||||
if bestIdx == -1 {
|
||||
bestIdx = i
|
||||
}
|
||||
// Calculate distance to the glyph center
|
||||
glyphCenterX := float64(layout.X[i] + layout.Advance[i]/2)
|
||||
dist := glyphCenterX - x
|
||||
if dist < 0 {
|
||||
dist = -dist
|
||||
}
|
||||
if dist < minDist {
|
||||
minDist = dist
|
||||
bestIdx = i
|
||||
}
|
||||
for _, i := range targetGroup.indices {
|
||||
if bestIdx == -1 {
|
||||
bestIdx = i
|
||||
}
|
||||
// Calculate distance to the glyph center
|
||||
glyphCenterX := float64(layout.X[i] + layout.Advance[i]/2)
|
||||
dist := glyphCenterX - x
|
||||
if dist < 0 {
|
||||
dist = -dist
|
||||
}
|
||||
if dist < minDist {
|
||||
minDist = dist
|
||||
bestIdx = i
|
||||
}
|
||||
}
|
||||
if bestIdx != -1 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user