mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget: [API] add content widget argument to Editor.Layout
To make the semantic relation between the editor and its content clear, the editor clip operation must cover the content. This change adds an explicit widget argument to editor, and lays it out inside the clip rect. This is an API change. Users of Editor.Layout must provide a content widget. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+7
-4
@@ -462,8 +462,8 @@ func (e *Editor) Focused() bool {
|
||||
return e.focused
|
||||
}
|
||||
|
||||
// Layout lays out the editor.
|
||||
func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size unit.Value) layout.Dimensions {
|
||||
// Layout lays out the editor. If content is not nil, it is laid out on top.
|
||||
func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size unit.Value, content layout.Widget) layout.Dimensions {
|
||||
textSize := fixed.I(gtx.Px(size))
|
||||
if e.font != font || e.textSize != textSize {
|
||||
e.invalidate()
|
||||
@@ -497,10 +497,10 @@ func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size
|
||||
}
|
||||
e.makeValid()
|
||||
|
||||
return e.layout(gtx)
|
||||
return e.layout(gtx, content)
|
||||
}
|
||||
|
||||
func (e *Editor) layout(gtx layout.Context) layout.Dimensions {
|
||||
func (e *Editor) layout(gtx layout.Context, content layout.Widget) layout.Dimensions {
|
||||
// Adjust scrolling for new viewport and layout.
|
||||
e.scrollRel(0, 0)
|
||||
|
||||
@@ -576,6 +576,9 @@ func (e *Editor) layout(gtx layout.Context) layout.Dimensions {
|
||||
e.caret.on = e.focused && (!blinking || dt%timePerBlink < timePerBlink/2)
|
||||
}
|
||||
|
||||
if content != nil {
|
||||
content(gtx)
|
||||
}
|
||||
return layout.Dimensions{Size: e.viewSize, Baseline: e.dims.Baseline}
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -39,7 +39,7 @@ func TestEditor(t *testing.T) {
|
||||
e.SetCaret(0, 0) // shouldn't panic
|
||||
assertCaret(t, e, 0, 0, 0)
|
||||
e.SetText("æbc\naøå•")
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
assertCaret(t, e, 0, 0, 0)
|
||||
e.moveEnd(selectionClear)
|
||||
assertCaret(t, e, 0, 3, len("æbc"))
|
||||
@@ -65,12 +65,12 @@ func TestEditor(t *testing.T) {
|
||||
e.MoveCaret(-3, -3)
|
||||
assertCaret(t, e, 1, 1, len("æbc\na"))
|
||||
e.Mask = '*'
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
assertCaret(t, e, 1, 1, len("æbc\na"))
|
||||
e.MoveCaret(-3, -3)
|
||||
assertCaret(t, e, 0, 2, len("æb"))
|
||||
e.Mask = '\U0001F92B'
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
e.moveEnd(selectionClear)
|
||||
assertCaret(t, e, 0, 3, len("æbc"))
|
||||
|
||||
@@ -99,7 +99,7 @@ func TestEditorDimensions(t *testing.T) {
|
||||
cache := text.NewCache(gofont.Collection())
|
||||
fontSize := unit.Px(10)
|
||||
font := text.Font{}
|
||||
dims := e.Layout(gtx, cache, font, fontSize)
|
||||
dims := e.Layout(gtx, cache, font, fontSize, nil)
|
||||
if dims.Size.X == 0 {
|
||||
t.Errorf("EditEvent was not reflected in Editor width")
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func TestEditorCaretConsistency(t *testing.T) {
|
||||
e := &Editor{
|
||||
Alignment: a,
|
||||
}
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
|
||||
consistent := func() error {
|
||||
t.Helper()
|
||||
@@ -167,7 +167,7 @@ func TestEditorCaretConsistency(t *testing.T) {
|
||||
switch mutation {
|
||||
case setText:
|
||||
e.SetText(str)
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
case moveRune:
|
||||
e.MoveCaret(int(distance), int(distance))
|
||||
case moveLine:
|
||||
@@ -232,7 +232,7 @@ func TestEditorMoveWord(t *testing.T) {
|
||||
fontSize := unit.Px(10)
|
||||
font := text.Font{}
|
||||
e.SetText(t)
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
return e
|
||||
}
|
||||
for ii, tt := range tests {
|
||||
@@ -314,7 +314,7 @@ func TestEditorDeleteWord(t *testing.T) {
|
||||
fontSize := unit.Px(10)
|
||||
font := text.Font{}
|
||||
e.SetText(t)
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
return e
|
||||
}
|
||||
for ii, tt := range tests {
|
||||
@@ -367,7 +367,7 @@ g123456789g
|
||||
selected := func(start, end int) string {
|
||||
// Layout once with no events; populate e.lines.
|
||||
gtx.Queue = nil
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
_ = e.Events() // throw away any events from this layout
|
||||
|
||||
// Build the selection events
|
||||
@@ -389,7 +389,7 @@ g123456789g
|
||||
}
|
||||
gtx.Queue = tq
|
||||
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
for _, evt := range e.Events() {
|
||||
switch evt.(type) {
|
||||
case SelectEvent:
|
||||
@@ -428,7 +428,7 @@ g123456789g
|
||||
gtx.Constraints = layout.Exact(image.Pt(36, 36))
|
||||
// Keep existing selection
|
||||
gtx.Queue = nil
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
|
||||
if e.caret.end.lineCol != tst.startPos || e.caret.start.lineCol != tst.endPos {
|
||||
t.Errorf("Test %d pt2: Expected %#v, %#v; got %#v, %#v",
|
||||
@@ -454,7 +454,7 @@ func TestSelectMove(t *testing.T) {
|
||||
|
||||
// Layout once to populate e.lines and get focus.
|
||||
gtx.Queue = newQueue(key.FocusEvent{Focus: true})
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
|
||||
testKey := func(keyName string) {
|
||||
// Select 345
|
||||
@@ -465,7 +465,7 @@ func TestSelectMove(t *testing.T) {
|
||||
|
||||
// Press the key
|
||||
gtx.Queue = newQueue(key.Event{State: key.Press, Name: keyName})
|
||||
e.Layout(gtx, cache, font, fontSize)
|
||||
e.Layout(gtx, cache, font, fontSize, nil)
|
||||
|
||||
if expected, got := "", e.SelectedText(); expected != got {
|
||||
t.Errorf("KeyName %s, expected %q, got %q", keyName, expected, got)
|
||||
|
||||
+16
-14
@@ -58,20 +58,22 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
if h := dims.Size.Y; gtx.Constraints.Min.Y < h {
|
||||
gtx.Constraints.Min.Y = h
|
||||
}
|
||||
dims = e.Editor.Layout(gtx, e.shaper, e.Font, e.TextSize)
|
||||
disabled := gtx.Queue == nil
|
||||
if e.Editor.Len() > 0 {
|
||||
paint.ColorOp{Color: blendDisabledColor(disabled, e.SelectionColor)}.Add(gtx.Ops)
|
||||
e.Editor.PaintSelection(gtx)
|
||||
paint.ColorOp{Color: blendDisabledColor(disabled, e.Color)}.Add(gtx.Ops)
|
||||
e.Editor.PaintText(gtx)
|
||||
} else {
|
||||
call.Add(gtx.Ops)
|
||||
}
|
||||
if !disabled {
|
||||
paint.ColorOp{Color: e.Color}.Add(gtx.Ops)
|
||||
e.Editor.PaintCaret(gtx)
|
||||
}
|
||||
dims = e.Editor.Layout(gtx, e.shaper, e.Font, e.TextSize, func(gtx layout.Context) layout.Dimensions {
|
||||
disabled := gtx.Queue == nil
|
||||
if e.Editor.Len() > 0 {
|
||||
paint.ColorOp{Color: blendDisabledColor(disabled, e.SelectionColor)}.Add(gtx.Ops)
|
||||
e.Editor.PaintSelection(gtx)
|
||||
paint.ColorOp{Color: blendDisabledColor(disabled, e.Color)}.Add(gtx.Ops)
|
||||
e.Editor.PaintText(gtx)
|
||||
} else {
|
||||
call.Add(gtx.Ops)
|
||||
}
|
||||
if !disabled {
|
||||
paint.ColorOp{Color: e.Color}.Add(gtx.Ops)
|
||||
e.Editor.PaintCaret(gtx)
|
||||
}
|
||||
return dims
|
||||
})
|
||||
return dims
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user