Use op.Offset instead, or create and manipulate a f32.Affine2D.
API change. Update your code with a gofmt rule:
gofmt -r 'op.TransformOp{}.Offset -> op.Offset'
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit configures all remaining widgets to draw themselves in a disabled state
when their layout.Context is disabled. A description of the
strategy employed by each follows:
- Checkbox and RadioButton: Draws the icon component in a lighter color. Currently the label text is left
in its default color.
- ProgressBar: The "progress" color is lightened, but not as much as the background color. This makes the current progress value still readable.
- Editor: The cursor is no longer drawn and the text is lightened.
- Switch: The track is unchanged, but the circular "thumb" component is lightened.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
The funcs replace stack.Push and macro.Record, which become private.
This makes stack and macro faster to write, in particular for stacks
where you can just write the following line to save and restore the
state :
defer op.Push(ops).Pop()
This usage requires Push to return a pointer (since Pop has a pointer
receiver), or else the code doesn't compile.
For consistancy, I tried to do the same for op.Record, but this implied
to turn all the MacroOp fields into pointers, and this caused some
panics. As a result, op.Record doesn't return a pointer.
An other side effect pointed by Larry Clapp: StackOp and MacroOp are not
re-usable any more, you have to allocate a new one for each usage, using
the described funcs above.
Signed-off-by: Thomas Bruyelle <thomas.bruyelle@gmail.com>
Before this change, events were typically processed twice or more per
widget: once in the Layout method for refreshing the visual state, and
once per method that queries for state changes.
One example is widget.Clickable that processed events in both its Layout
and Clicked method.
This change establishes the convention that events are processed once, in
the Layout method. There are several advantages to that approach:
- Query methods such as Clickable.Clicked no longer need a layout.Context.
- State updates from events only occur in Layout.
- Widgets are simplified because they won't need a separate processEvents
(or similar) method and won't forget to call it from methods other than Layout.
- Useless calls to gtx.Events are avoided (gtx.Events only returns events
for the first call each frame for a given event.Tag).
The disadvantage is that state updates from input events will not appear
before Layout. For example, in the call sequence
var btn *widget.Clickable
if btn.Clicked() {...}
btn.Layout(...)
the Clicked call will not detect an incoming click until the frame after it
happened.
This is ok because
- The Gio event router automatically dispatches an extra frame after events
arrive, bounding the latency from events to queries such as Clicked to
at most one frame (~17 ms).
- The potential extra frame of latency does not apply to Layout methods as long
as they process events before drawing. In other words, the visual feedback
from input events are not delayed because of this change.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Instead of, say,
var th *material.Theme
var btn *widget.Clickable
material.Button(th, "Click me").Layout(gtx, btn)
move the widget state objects to the constructor:
material.Button(th, btn, "Click me").Layout(gtx)
The advatage is that several widgets can now be used without
wrapping them in function literals. For example,
layout.Inset{}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
material.Button(th, "Click me").Layout(gtx, btn)
})
collapses to just
layout.Inset{}.Layout(gtx, material.Button(th, btn, "Click me").Layout)
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Change the definition of Widget from the implicit
type Widget func()
to the explicit functional
type Widget func(gtx layout.Context) layout.Dimensions
The advantages are numerous:
- Clearer connection between the incoming context and the output dimensions.
- Returning the Dimensions are impossible to omit.
- Contexts passed by value, so its fields can be exported
and freely mutated by the program.
The only disadvantage is the longer function literals and the many "returns".
What tipped the scales in favour of the explicit Widget variant is that type
aliases can dramatically shorten the literals:
type (
C = layout.Context
D = layout.Dimensions
)
widget := func(gtx C) D {
...
}
Note that the aliases are not part of the Gio API and it is up to each user
whether they want to use them.
Finally the Go proposal for lightweight function literals,
https://github.com/golang/go/issues/21498, may remove the disadvantage
completely in future.
Context becomes a plain struct with only public fields, and its Reset is
replaced by a NewContext convenience constructor.
Signed-off-by: Elias Naur <mail@eliasnaur.com>