Fix cursor Y positioning logic in editor
This commit is contained in:
parent
6939550527
commit
979656c2d0
|
|
@ -457,47 +457,72 @@ func SetCursorFromPoint(x, y float64) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Find the best line based on y
|
lineHeight := float64(EditorLineHeight())
|
||||||
bestLineY := layout.Y[0]
|
|
||||||
minYDist := 1e9
|
// 1. Identify the intended line index based on y
|
||||||
for _, yVal := range layout.Y {
|
// layout.Y values are relative to the text region origin.
|
||||||
yDist := float64(yVal) - y
|
// We need to account for scroll offset.
|
||||||
if yDist < 0 {
|
visualLine := int((y + float64(TheState.ScrollOffset)) / lineHeight)
|
||||||
yDist = -yDist
|
|
||||||
|
// Group glyphs by their Y-baseline
|
||||||
|
type lineGroup struct {
|
||||||
|
y float64
|
||||||
|
indices []int
|
||||||
}
|
}
|
||||||
if yDist < minYDist {
|
groups := []lineGroup{}
|
||||||
minYDist = yDist
|
seenY := make(map[float64]int) // maps Y to group index
|
||||||
bestLineY = yVal
|
|
||||||
|
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
|
rightmostX := 0.0
|
||||||
rightmostIdx := -1
|
rightmostIdx := -1
|
||||||
for i, yVal := range layout.Y {
|
for _, i := range targetGroup.indices {
|
||||||
if yVal == bestLineY {
|
|
||||||
xEnd := float64(layout.X[i] + layout.Advance[i])
|
xEnd := float64(layout.X[i] + layout.Advance[i])
|
||||||
if xEnd > rightmostX {
|
if xEnd > rightmostX {
|
||||||
rightmostX = xEnd
|
rightmostX = xEnd
|
||||||
rightmostIdx = i
|
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 {
|
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]
|
start := layout.ByteOffsets[rightmostIdx]
|
||||||
_, size := utf8.DecodeRuneInString(TheState.Editor.Buffer[start:])
|
r, size := utf8.DecodeRuneInString(TheState.Editor.Buffer[start:])
|
||||||
|
if r == '\n' {
|
||||||
|
TheState.Editor.CursorPosition = start
|
||||||
|
} else {
|
||||||
TheState.Editor.CursorPosition = start + size
|
TheState.Editor.CursorPosition = start + size
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Otherwise, find the closest glyph on this line.
|
// 5. Otherwise, find the closest glyph on this line.
|
||||||
bestIdx := -1
|
bestIdx := -1
|
||||||
minDist := float64(1e9)
|
minDist := float64(1e9)
|
||||||
for i, yVal := range layout.Y {
|
for _, i := range targetGroup.indices {
|
||||||
if yVal == bestLineY {
|
|
||||||
if bestIdx == -1 {
|
if bestIdx == -1 {
|
||||||
bestIdx = i
|
bestIdx = i
|
||||||
}
|
}
|
||||||
|
|
@ -512,7 +537,6 @@ func SetCursorFromPoint(x, y float64) {
|
||||||
bestIdx = i
|
bestIdx = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if bestIdx != -1 {
|
if bestIdx != -1 {
|
||||||
TheState.Editor.CursorPosition = layout.ByteOffsets[bestIdx]
|
TheState.Editor.CursorPosition = layout.ByteOffsets[bestIdx]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user