mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget: track minWidth of editor for alignment
This commit extends the editor to keep track of its own minimum constraint and to provide that value to the text shaper for the purpose of aligning text. Without this, the shaper does not know how much of the width of the editor to use for alignment purposes. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
+21
-16
@@ -52,21 +52,21 @@ type Editor struct {
|
||||
// all characters are allowed.
|
||||
Filter string
|
||||
|
||||
eventKey int
|
||||
font text.Font
|
||||
shaper *text.Shaper
|
||||
textSize fixed.Int26_6
|
||||
blinkStart time.Time
|
||||
focused bool
|
||||
rr editBuffer
|
||||
maskReader maskReader
|
||||
lastMask rune
|
||||
maxWidth int
|
||||
viewSize image.Point
|
||||
valid bool
|
||||
regions []region
|
||||
dims layout.Dimensions
|
||||
requestFocus bool
|
||||
eventKey int
|
||||
font text.Font
|
||||
shaper *text.Shaper
|
||||
textSize fixed.Int26_6
|
||||
blinkStart time.Time
|
||||
focused bool
|
||||
rr editBuffer
|
||||
maskReader maskReader
|
||||
lastMask rune
|
||||
maxWidth, minWidth int
|
||||
viewSize image.Point
|
||||
valid bool
|
||||
regions []region
|
||||
dims layout.Dimensions
|
||||
requestFocus bool
|
||||
|
||||
// offIndex is an index of rune index to byte offsets.
|
||||
offIndex []offEntry
|
||||
@@ -547,10 +547,15 @@ func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font text.Font, siz
|
||||
if e.SingleLine {
|
||||
maxWidth = math.MaxInt
|
||||
}
|
||||
minWidth := gtx.Constraints.Min.X
|
||||
if maxWidth != e.maxWidth {
|
||||
e.maxWidth = maxWidth
|
||||
e.invalidate()
|
||||
}
|
||||
if minWidth != e.minWidth {
|
||||
e.minWidth = minWidth
|
||||
e.invalidate()
|
||||
}
|
||||
if lt != e.shaper {
|
||||
e.shaper = lt
|
||||
e.invalidate()
|
||||
@@ -891,7 +896,7 @@ func (e *Editor) layoutText(lt *text.Shaper) {
|
||||
Font: e.font,
|
||||
PxPerEm: e.textSize,
|
||||
Alignment: e.Alignment,
|
||||
}, 0, e.maxWidth, e.locale, r)
|
||||
}, e.minWidth, e.maxWidth, e.locale, r)
|
||||
for glyph, ok := it.processGlyph(lt.NextGlyph()); ok; glyph, ok = it.processGlyph(lt.NextGlyph()) {
|
||||
e.index.Glyph(glyph)
|
||||
}
|
||||
|
||||
+34
-20
@@ -115,7 +115,7 @@ func TestEditorZeroDimensions(t *testing.T) {
|
||||
func TestEditorConfigurations(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Constraints: layout.Exact(image.Pt(300, 300)),
|
||||
Locale: english,
|
||||
}
|
||||
cache := text.NewShaper(gofont.Collection())
|
||||
@@ -126,27 +126,41 @@ func TestEditorConfigurations(t *testing.T) {
|
||||
|
||||
// Ensure that both ends of the text are reachable in all permutations
|
||||
// of settings that influence layout.
|
||||
for _, lineMode := range []bool{true, false} {
|
||||
for _, singleLine := range []bool{true, false} {
|
||||
for _, alignment := range []text.Alignment{text.Start, text.Middle, text.End} {
|
||||
t.Run(fmt.Sprintf("SingleLine: %v Alignment: %v", lineMode, alignment), func(t *testing.T) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
t.Error(err)
|
||||
for _, zeroMin := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("SingleLine: %v Alignment: %v ZeroMinConstraint: %v", singleLine, alignment, zeroMin), func(t *testing.T) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
if zeroMin {
|
||||
gtx.Constraints.Min = image.Point{}
|
||||
} else {
|
||||
gtx.Constraints.Min = gtx.Constraints.Max
|
||||
}
|
||||
}()
|
||||
e := new(Editor)
|
||||
e.SingleLine = lineMode
|
||||
e.Alignment = alignment
|
||||
e.SetText(sentence)
|
||||
e.SetCaret(0, 0)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
e.SetCaret(runes, runes)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
coords := e.CaretCoords()
|
||||
if int(coords.X) > gtx.Constraints.Max.X || int(coords.Y) > gtx.Constraints.Max.Y {
|
||||
t.Errorf("caret coordinates %v exceed constraints %v", coords, gtx.Constraints.Max)
|
||||
}
|
||||
})
|
||||
e := new(Editor)
|
||||
e.SingleLine = singleLine
|
||||
e.Alignment = alignment
|
||||
e.SetText(sentence)
|
||||
e.SetCaret(0, 0)
|
||||
dims := e.Layout(gtx, cache, font, fontSize, nil)
|
||||
if dims.Size.X < gtx.Constraints.Min.X || dims.Size.Y < gtx.Constraints.Min.Y {
|
||||
t.Errorf("expected min size %#+v, got %#+v", gtx.Constraints.Min, dims.Size)
|
||||
}
|
||||
coords := e.CaretCoords()
|
||||
if halfway := float32(gtx.Constraints.Min.X) * .5; !singleLine && alignment == text.Middle && !zeroMin && coords.X != halfway {
|
||||
t.Errorf("expected caret X to be %f, got %f", halfway, coords.X)
|
||||
}
|
||||
e.SetCaret(runes, runes)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
coords = e.CaretCoords()
|
||||
if int(coords.X) > gtx.Constraints.Max.X || int(coords.Y) > gtx.Constraints.Max.Y {
|
||||
t.Errorf("caret coordinates %v exceed constraints %v", coords, gtx.Constraints.Max)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user