mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55: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:
+7
-2
@@ -61,7 +61,7 @@ type Editor struct {
|
|||||||
rr editBuffer
|
rr editBuffer
|
||||||
maskReader maskReader
|
maskReader maskReader
|
||||||
lastMask rune
|
lastMask rune
|
||||||
maxWidth int
|
maxWidth, minWidth int
|
||||||
viewSize image.Point
|
viewSize image.Point
|
||||||
valid bool
|
valid bool
|
||||||
regions []region
|
regions []region
|
||||||
@@ -547,10 +547,15 @@ func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font text.Font, siz
|
|||||||
if e.SingleLine {
|
if e.SingleLine {
|
||||||
maxWidth = math.MaxInt
|
maxWidth = math.MaxInt
|
||||||
}
|
}
|
||||||
|
minWidth := gtx.Constraints.Min.X
|
||||||
if maxWidth != e.maxWidth {
|
if maxWidth != e.maxWidth {
|
||||||
e.maxWidth = maxWidth
|
e.maxWidth = maxWidth
|
||||||
e.invalidate()
|
e.invalidate()
|
||||||
}
|
}
|
||||||
|
if minWidth != e.minWidth {
|
||||||
|
e.minWidth = minWidth
|
||||||
|
e.invalidate()
|
||||||
|
}
|
||||||
if lt != e.shaper {
|
if lt != e.shaper {
|
||||||
e.shaper = lt
|
e.shaper = lt
|
||||||
e.invalidate()
|
e.invalidate()
|
||||||
@@ -891,7 +896,7 @@ func (e *Editor) layoutText(lt *text.Shaper) {
|
|||||||
Font: e.font,
|
Font: e.font,
|
||||||
PxPerEm: e.textSize,
|
PxPerEm: e.textSize,
|
||||||
Alignment: e.Alignment,
|
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()) {
|
for glyph, ok := it.processGlyph(lt.NextGlyph()); ok; glyph, ok = it.processGlyph(lt.NextGlyph()) {
|
||||||
e.index.Glyph(glyph)
|
e.index.Glyph(glyph)
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-6
@@ -115,7 +115,7 @@ func TestEditorZeroDimensions(t *testing.T) {
|
|||||||
func TestEditorConfigurations(t *testing.T) {
|
func TestEditorConfigurations(t *testing.T) {
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
Constraints: layout.Exact(image.Pt(300, 300)),
|
||||||
Locale: english,
|
Locale: english,
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(gofont.Collection())
|
cache := text.NewShaper(gofont.Collection())
|
||||||
@@ -126,29 +126,43 @@ func TestEditorConfigurations(t *testing.T) {
|
|||||||
|
|
||||||
// Ensure that both ends of the text are reachable in all permutations
|
// Ensure that both ends of the text are reachable in all permutations
|
||||||
// of settings that influence layout.
|
// 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} {
|
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) {
|
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() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
if zeroMin {
|
||||||
|
gtx.Constraints.Min = image.Point{}
|
||||||
|
} else {
|
||||||
|
gtx.Constraints.Min = gtx.Constraints.Max
|
||||||
|
}
|
||||||
e := new(Editor)
|
e := new(Editor)
|
||||||
e.SingleLine = lineMode
|
e.SingleLine = singleLine
|
||||||
e.Alignment = alignment
|
e.Alignment = alignment
|
||||||
e.SetText(sentence)
|
e.SetText(sentence)
|
||||||
e.SetCaret(0, 0)
|
e.SetCaret(0, 0)
|
||||||
e.Layout(gtx, cache, font, fontSize, nil)
|
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.SetCaret(runes, runes)
|
||||||
e.Layout(gtx, cache, font, fontSize, nil)
|
e.Layout(gtx, cache, font, fontSize, nil)
|
||||||
coords := e.CaretCoords()
|
coords = e.CaretCoords()
|
||||||
if int(coords.X) > gtx.Constraints.Max.X || int(coords.Y) > gtx.Constraints.Max.Y {
|
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)
|
t.Errorf("caret coordinates %v exceed constraints %v", coords, gtx.Constraints.Max)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEditor(t *testing.T) {
|
func TestEditor(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user