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:
Chris Waldon
2022-12-19 10:09:00 -05:00
committed by Elias Naur
parent 5d1d1df206
commit fe5878bc63
2 changed files with 55 additions and 36 deletions
+21 -16
View File
@@ -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
View File
@@ -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)
}
})
}
}
}
}