widget: [API] split text widget Update from Layout

This commit introduces Update(gtx) functions for both Selectable and Editor, allowing their
state to be updated explicitly prior to layout. This completes the transition that allows all
Gio widgets to have their state updated ahead-of-time, ensuring that there is zero frame lag
between an input event and the widget response to that event.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2023-11-10 14:59:06 -05:00
parent 9d89f7c8b1
commit 3fde0c0061
3 changed files with 22 additions and 19 deletions
+12 -9
View File
@@ -517,15 +517,10 @@ func (e *Editor) initBuffer() {
e.text.WrapPolicy = e.WrapPolicy
}
// Layout lays out the editor using the provided textMaterial as the paint material
// for the text glyphs+caret and the selectMaterial as the paint material for the
// selection rectangle.
func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectMaterial op.CallOp) layout.Dimensions {
// Update the state of the editor in response to input events.
func (e *Editor) Update(gtx layout.Context) {
e.initBuffer()
e.text.Update(gtx, lt, font, size, e.processEvents)
dims := e.layout(gtx, textMaterial, selectMaterial)
e.processEvents(gtx)
if e.focused {
// Notify IME of selection if it changed.
newSel := e.ime.selection
@@ -551,8 +546,16 @@ func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, siz
e.updateSnippet(gtx, e.ime.start, e.ime.end)
}
}
return dims
// Layout lays out the editor using the provided textMaterial as the paint material
// for the text glyphs+caret and the selectMaterial as the paint material for the
// selection rectangle.
func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectMaterial op.CallOp) layout.Dimensions {
e.Update(gtx)
e.text.Layout(gtx, lt, font, size)
return e.layout(gtx, textMaterial, selectMaterial)
}
// updateSnippet adds a key.SnippetOp if the snippet content or position
+8 -2
View File
@@ -182,18 +182,24 @@ func (l *Selectable) Truncated() bool {
return l.text.Truncated()
}
// Update the state of the selectable in response to input events.
func (l *Selectable) Update(gtx layout.Context) {
l.initialize()
l.handleEvents(gtx)
}
// Layout clips to the dimensions of the selectable, updates the shaped text, configures input handling, and paints
// the text and selection rectangles. The provided textMaterial and selectionMaterial ops are used to set the
// paint material for the text and selection rectangles, respectively.
func (l *Selectable) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectionMaterial op.CallOp) layout.Dimensions {
l.initialize()
l.Update(gtx)
l.text.LineHeight = l.LineHeight
l.text.LineHeightScale = l.LineHeightScale
l.text.Alignment = l.Alignment
l.text.MaxLines = l.MaxLines
l.text.Truncator = l.Truncator
l.text.WrapPolicy = l.WrapPolicy
l.text.Update(gtx, lt, font, size, l.handleEvents)
l.text.Layout(gtx, lt, font, size)
dims := l.text.Dimensions()
defer clip.Rect(image.Rectangle{Max: dims.Size}).Push(gtx.Ops).Pop()
pointer.CursorText.Add(gtx.Ops)
+2 -8
View File
@@ -228,10 +228,8 @@ func (e *textView) calculateViewSize(gtx layout.Context) image.Point {
return gtx.Constraints.Constrain(base)
}
// Update the text, reshaping it as necessary. If not nil, eventHandling will be invoked after reshaping the text to
// allow parent widgets to adapt to any changes in text content or positioning. If eventHandling modifies the contents
// of the textView, it is guaranteed to be reshaped (and ready for painting) before Update returns.
func (e *textView) Update(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, eventHandling func(gtx layout.Context)) {
// Layout the text, reshaping it as necessary.
func (e *textView) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp) {
if e.params.Locale != gtx.Locale {
e.params.Locale = gtx.Locale
e.invalidate()
@@ -289,10 +287,6 @@ func (e *textView) Update(gtx layout.Context, lt *text.Shaper, font font.Font, s
}
e.makeValid()
if eventHandling != nil {
eventHandling(gtx)
e.makeValid()
}
if viewSize := e.calculateViewSize(gtx); viewSize != e.viewSize {
e.viewSize = viewSize