mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 18:35:34 +00:00
widget: simplify Editor.offsetToScreenPos
It used to return an iterator function, now it just takes the result of a previous call. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+33
-43
@@ -773,62 +773,52 @@ func (e *Editor) CaretCoords() f32.Point {
|
|||||||
// offsetToScreenPos2 is a utility function to shortcut the common case of
|
// offsetToScreenPos2 is a utility function to shortcut the common case of
|
||||||
// wanting the positions of exactly two offsets.
|
// wanting the positions of exactly two offsets.
|
||||||
func (e *Editor) offsetToScreenPos2(o1, o2 int) (combinedPos, combinedPos) {
|
func (e *Editor) offsetToScreenPos2(o1, o2 int) (combinedPos, combinedPos) {
|
||||||
cp1, iter := e.offsetToScreenPos(o1)
|
cp1 := e.offsetToScreenPos(combinedPos{}, o1)
|
||||||
return cp1, iter(o2)
|
cp2 := e.offsetToScreenPos(cp1, o2)
|
||||||
|
return cp1, cp2
|
||||||
}
|
}
|
||||||
|
|
||||||
// offsetToScreenPos takes an offset into the editor text (e.g.
|
// offsetToScreenPos takes an offset into the editor text (e.g.
|
||||||
// e.caret.end.ofs) and returns a combinedPos that corresponds to its current
|
// e.caret.end.ofs) and returns a combinedPos that corresponds to its current
|
||||||
// screen position, as well as an iterator that lets you get the combinedPos
|
// screen position. Hint is either the zero-value position or the result of
|
||||||
// of a later offset. The offsets given to offsetToScreenPos and to the
|
// a previous call with a lower offset.
|
||||||
// returned iterator must be sorted, lowest first, and they must be valid (0
|
|
||||||
// <= offset <= e.Len()).
|
|
||||||
//
|
//
|
||||||
// This function is written this way to take advantage of previous work done
|
// This function is written this way to take advantage of previous work done
|
||||||
// for offsets after the first. Otherwise you have to start from the top each
|
// for offsets after the first. Otherwise you have to start from the top each
|
||||||
// time.
|
// time.
|
||||||
func (e *Editor) offsetToScreenPos(offset int) (combinedPos, func(int) combinedPos) {
|
func (e *Editor) offsetToScreenPos(hint combinedPos, offset int) combinedPos {
|
||||||
var col, line, idx int
|
if hint == (combinedPos{}) {
|
||||||
var x fixed.Int26_6
|
l := e.lines[0]
|
||||||
runes := 0
|
hint = combinedPos{
|
||||||
|
x: align(e.Alignment, l.Width, e.viewSize.X),
|
||||||
l := e.lines[line]
|
y: l.Ascent.Ceil(),
|
||||||
y := l.Ascent.Ceil()
|
}
|
||||||
prevDesc := l.Descent
|
}
|
||||||
|
LOOP:
|
||||||
iter := func(offset int) combinedPos {
|
|
||||||
LOOP:
|
|
||||||
for {
|
for {
|
||||||
for ; col < len(l.Layout.Advances); col++ {
|
l := e.lines[hint.lineCol.Y]
|
||||||
if idx >= offset {
|
for ; hint.lineCol.X < len(l.Layout.Advances); hint.lineCol.X++ {
|
||||||
|
if hint.ofs >= offset {
|
||||||
break LOOP
|
break LOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
x += l.Layout.Advances[col]
|
hint.x += l.Layout.Advances[hint.lineCol.X]
|
||||||
_, s := e.rr.runeAt(idx)
|
_, s := e.rr.runeAt(hint.ofs)
|
||||||
idx += s
|
hint.ofs += s
|
||||||
runes++
|
hint.runes++
|
||||||
}
|
}
|
||||||
if lastLine := line == len(e.lines)-1; lastLine || idx > offset {
|
if lastLine := hint.lineCol.Y == len(e.lines)-1; lastLine || hint.ofs > offset {
|
||||||
break LOOP
|
break LOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
line++
|
prevDesc := l.Descent
|
||||||
x = 0
|
hint.lineCol.Y++
|
||||||
col = 0
|
hint.lineCol.X = 0
|
||||||
l = e.lines[line]
|
l = e.lines[hint.lineCol.Y]
|
||||||
y += (prevDesc + l.Ascent).Ceil()
|
hint.x = align(e.Alignment, l.Width, e.viewSize.X)
|
||||||
prevDesc = l.Descent
|
hint.y += (prevDesc + l.Ascent).Ceil()
|
||||||
}
|
}
|
||||||
return combinedPos{
|
return hint
|
||||||
lineCol: screenPos{Y: line, X: col},
|
|
||||||
x: x + align(e.Alignment, e.lines[line].Width, e.viewSize.X),
|
|
||||||
y: y,
|
|
||||||
ofs: offset,
|
|
||||||
runes: runes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iter(offset), iter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Editor) invalidate() {
|
func (e *Editor) invalidate() {
|
||||||
@@ -1271,10 +1261,10 @@ func (e *Editor) makeValidCaret(positions ...*combinedPos) {
|
|||||||
sort.Slice(positions, func(i, j int) bool {
|
sort.Slice(positions, func(i, j int) bool {
|
||||||
return positions[i].ofs < positions[j].ofs
|
return positions[i].ofs < positions[j].ofs
|
||||||
})
|
})
|
||||||
var iter func(offset int) combinedPos
|
var hint combinedPos
|
||||||
*positions[0], iter = e.offsetToScreenPos(positions[0].ofs)
|
for _, cp := range positions {
|
||||||
for _, cp := range positions[1:] {
|
hint = e.offsetToScreenPos(hint, cp.ofs)
|
||||||
*cp = iter(cp.ofs)
|
*cp = hint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ func TestEditorCaretConsistency(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
gotLine, gotCol := e.CaretPos()
|
gotLine, gotCol := e.CaretPos()
|
||||||
gotCoords := e.CaretCoords()
|
gotCoords := e.CaretCoords()
|
||||||
want, _ := e.offsetToScreenPos(e.caret.start.ofs)
|
want := e.offsetToScreenPos(combinedPos{}, e.caret.start.ofs)
|
||||||
wantCoords := f32.Pt(float32(want.x)/64, float32(want.y))
|
wantCoords := f32.Pt(float32(want.x)/64, float32(want.y))
|
||||||
if want.lineCol.Y != gotLine || want.lineCol.X != gotCol || gotCoords != wantCoords {
|
if want.lineCol.Y != gotLine || want.lineCol.X != gotCol || gotCoords != wantCoords {
|
||||||
return fmt.Errorf("caret (%d,%d) pos %s, want (%d,%d) pos %s",
|
return fmt.Errorf("caret (%d,%d) pos %s, want (%d,%d) pos %s",
|
||||||
|
|||||||
Reference in New Issue
Block a user