forked from joejulian/gio
io/input: [API] introduce Source, the interface between a Router and widgets
This change gets rid of the event.Queue interface by replacing it with input.Source values. Source provides the interface to Router necessary to implement interface widgets. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+3
-3
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gioui.org/io/event"
|
||||
"gioui.org/io/input"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op"
|
||||
"gioui.org/unit"
|
||||
@@ -53,8 +53,8 @@ type FrameEvent struct {
|
||||
// Frame completes the FrameEvent by drawing the graphical operations
|
||||
// from ops into the window.
|
||||
Frame func(frame *op.Ops)
|
||||
// Source supplies the events for event handlers.
|
||||
Source event.Queue
|
||||
// Source is the interface between the interface state and widgets.
|
||||
Source input.Source
|
||||
}
|
||||
|
||||
// Insets is the space taken up by
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ func FuzzIME(f *testing.F) {
|
||||
e.Focus()
|
||||
|
||||
var r input.Router
|
||||
gtx := layout.Context{Ops: new(op.Ops), Source: &r}
|
||||
gtx := layout.Context{Ops: new(op.Ops), Source: r.Source()}
|
||||
// Layout once to register focus.
|
||||
e.Layout(gtx, cache, font.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{})
|
||||
r.Frame(gtx.Ops)
|
||||
|
||||
+1
-1
@@ -832,7 +832,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool {
|
||||
w.metric = e2.Metric
|
||||
w.hasNextFrame = false
|
||||
e2.Frame = w.update
|
||||
e2.Source = &w.queue
|
||||
e2.Source = w.queue.Source()
|
||||
|
||||
// Prepare the decorations and update the frame insets.
|
||||
wrapper := &w.decorations.Ops
|
||||
|
||||
+5
-5
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/fling"
|
||||
"gioui.org/io/event"
|
||||
"gioui.org/io/input"
|
||||
"gioui.org/io/key"
|
||||
"gioui.org/io/pointer"
|
||||
"gioui.org/op"
|
||||
@@ -44,7 +44,7 @@ func (h *Hover) Add(ops *op.Ops) {
|
||||
}
|
||||
|
||||
// Update state and report whether a pointer is inside the area.
|
||||
func (h *Hover) Update(q event.Queue) bool {
|
||||
func (h *Hover) Update(q input.Source) bool {
|
||||
for _, ev := range q.Events(h) {
|
||||
e, ok := ev.(pointer.Event)
|
||||
if !ok {
|
||||
@@ -178,7 +178,7 @@ func (c *Click) Pressed() bool {
|
||||
}
|
||||
|
||||
// Update state and return the click events.
|
||||
func (c *Click) Update(q event.Queue) []ClickEvent {
|
||||
func (c *Click) Update(q input.Source) []ClickEvent {
|
||||
var events []ClickEvent
|
||||
for _, evt := range q.Events(c) {
|
||||
e, ok := evt.(pointer.Event)
|
||||
@@ -269,7 +269,7 @@ func (s *Scroll) Stop() {
|
||||
}
|
||||
|
||||
// Update state and report the scroll distance along axis.
|
||||
func (s *Scroll) Update(cfg unit.Metric, q event.Queue, t time.Time, axis Axis) int {
|
||||
func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis) int {
|
||||
if s.axis != axis {
|
||||
s.axis = axis
|
||||
return 0
|
||||
@@ -372,7 +372,7 @@ func (d *Drag) Add(ops *op.Ops) {
|
||||
}
|
||||
|
||||
// Update state and return the drag events.
|
||||
func (d *Drag) Update(cfg unit.Metric, q event.Queue, axis Axis) []pointer.Event {
|
||||
func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Event {
|
||||
var events []pointer.Event
|
||||
for _, e := range q.Events(d) {
|
||||
e, ok := e.(pointer.Event)
|
||||
|
||||
@@ -28,14 +28,14 @@ func TestHover(t *testing.T) {
|
||||
r.Queue(
|
||||
pointer.Event{Kind: pointer.Move, Position: f32.Pt(30, 30)},
|
||||
)
|
||||
if !h.Update(r) {
|
||||
if !h.Update(r.Source()) {
|
||||
t.Fatal("expected hovered")
|
||||
}
|
||||
|
||||
r.Queue(
|
||||
pointer.Event{Kind: pointer.Move, Position: f32.Pt(50, 50)},
|
||||
)
|
||||
if h.Update(r) {
|
||||
if h.Update(r.Source()) {
|
||||
t.Fatal("expected not hovered")
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func TestMouseClicks(t *testing.T) {
|
||||
r.Frame(&ops)
|
||||
r.Queue(tc.events...)
|
||||
|
||||
events := click.Update(&r)
|
||||
events := click.Update(r.Source())
|
||||
clicks := filterMouseClicks(events)
|
||||
if got, want := len(clicks), len(tc.clicks); got != want {
|
||||
t.Fatalf("got %d mouse clicks, expected %d", got, want)
|
||||
|
||||
+1
-35
@@ -1,42 +1,8 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
/*
|
||||
Package event contains the types for event handling.
|
||||
|
||||
The Queue interface is the protocol for receiving external events.
|
||||
|
||||
For example:
|
||||
|
||||
var queue event.Queue = ...
|
||||
|
||||
for _, e := range queue.Events(h) {
|
||||
switch e.(type) {
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
In general, handlers must be declared before events become
|
||||
available. Other packages such as pointer and key provide
|
||||
the means for declaring handlers for specific event types.
|
||||
|
||||
The following example declares a handler ready for key input:
|
||||
|
||||
import gioui.org/io/key
|
||||
|
||||
ops := new(op.Ops)
|
||||
var h *Handler = ...
|
||||
key.InputOp{Tag: h, Filter: ...}.Add(ops)
|
||||
*/
|
||||
// Package event contains types for event handling.
|
||||
package event
|
||||
|
||||
// Queue maps an event handler key to the events
|
||||
// available to the handler.
|
||||
type Queue interface {
|
||||
// Events returns the available events for an
|
||||
// event handler tag.
|
||||
Events(t Tag) []Event
|
||||
}
|
||||
|
||||
// Tag is the stable identifier for an event handler.
|
||||
// For a handler h, the tag is typically &h.
|
||||
type Tag interface{}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
/*
|
||||
Package input implements input routing and tracking of interface
|
||||
state for a window.
|
||||
|
||||
The [Source] is the interface between the window and the widgets
|
||||
of a user interface and is exposed by [gioui.org/app.FrameEvent]
|
||||
received from windows.
|
||||
|
||||
The [Router] is used by [gioui.org/app.Window] to track window state and route
|
||||
events from the platform to event handlers. It is otherwise only
|
||||
useful for using Gio with external window implementations.
|
||||
*/
|
||||
package input
|
||||
+27
-11
@@ -1,13 +1,5 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
/*
|
||||
Package input implements Router, an event.Queue implementation
|
||||
that disambiguates and routes events to handlers declared
|
||||
in operation lists.
|
||||
|
||||
Router is used by app.Window and is otherwise only useful for
|
||||
using Gio with external window implementations.
|
||||
*/
|
||||
package input
|
||||
|
||||
import (
|
||||
@@ -31,8 +23,8 @@ import (
|
||||
"gioui.org/op"
|
||||
)
|
||||
|
||||
// Router is a Queue implementation that routes events
|
||||
// to handlers declared in operation lists.
|
||||
// Router tracks the [io/event.Tag] identifiers of user interface widgets
|
||||
// and routes events to them. [Source] is its interface exposed to widgets.
|
||||
type Router struct {
|
||||
savedTrans []f32.Affine2D
|
||||
transStack []f32.Affine2D
|
||||
@@ -55,6 +47,12 @@ type Router struct {
|
||||
wakeupTime time.Time
|
||||
}
|
||||
|
||||
// Source implements the interface between a Router and user interface widgets.
|
||||
// The value Source is disabled.
|
||||
type Source struct {
|
||||
r *Router
|
||||
}
|
||||
|
||||
// SemanticNode represents a node in the tree describing the components
|
||||
// contained in a frame.
|
||||
type SemanticNode struct {
|
||||
@@ -95,7 +93,25 @@ type handlerEvents struct {
|
||||
hadEvents bool
|
||||
}
|
||||
|
||||
// Events returns the available events for the handler key.
|
||||
// Source returns a Source backed by this Router.
|
||||
func (q *Router) Source() Source {
|
||||
return Source{r: q}
|
||||
}
|
||||
|
||||
// Enabled reports whether the source is enabled. Only enabled
|
||||
// Sources deliver events and respond to commands.
|
||||
func (s Source) Enabled() bool {
|
||||
return s.r != nil
|
||||
}
|
||||
|
||||
// Events returns the available events for the handler tag.
|
||||
func (s Source) Events(k event.Tag) []event.Event {
|
||||
if !s.Enabled() {
|
||||
return nil
|
||||
}
|
||||
return s.r.Events(k)
|
||||
}
|
||||
|
||||
func (q *Router) Events(k event.Tag) []event.Event {
|
||||
events := q.handlers.Events(k)
|
||||
return events
|
||||
|
||||
+5
-19
@@ -5,7 +5,7 @@ package layout
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gioui.org/io/event"
|
||||
"gioui.org/io/input"
|
||||
"gioui.org/io/system"
|
||||
"gioui.org/op"
|
||||
"gioui.org/unit"
|
||||
@@ -20,9 +20,6 @@ type Context struct {
|
||||
Constraints Constraints
|
||||
|
||||
Metric unit.Metric
|
||||
// By convention, a nil Source is a signal to widgets to draw themselves
|
||||
// in a disabled state.
|
||||
Source event.Queue
|
||||
// Now is the animation time.
|
||||
Now time.Time
|
||||
|
||||
@@ -31,6 +28,7 @@ type Context struct {
|
||||
// Interested users must look up and populate these values manually.
|
||||
Locale system.Locale
|
||||
|
||||
input.Source
|
||||
*op.Ops
|
||||
}
|
||||
|
||||
@@ -44,21 +42,9 @@ func (c Context) Sp(v unit.Sp) int {
|
||||
return c.Metric.Sp(v)
|
||||
}
|
||||
|
||||
// Events returns the events available for the key. If no
|
||||
// queue is configured, Events returns nil.
|
||||
func (c Context) Events(k event.Tag) []event.Event {
|
||||
if c.Source == nil {
|
||||
return nil
|
||||
}
|
||||
return c.Source.Events(k)
|
||||
}
|
||||
|
||||
// Disabled returns a copy of this context with a nil Queue,
|
||||
// blocking events to widgets using it.
|
||||
//
|
||||
// By convention, a nil Queue is a signal to widgets to draw themselves
|
||||
// in a disabled state.
|
||||
// Disabled returns a copy of this context with a disabled Source,
|
||||
// blocking widgets from changing its state and receiving events.
|
||||
func (c Context) Disabled() Context {
|
||||
c.Source = nil
|
||||
c.Source = input.Source{}
|
||||
return c
|
||||
}
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ func (l *List) Dragging() bool {
|
||||
}
|
||||
|
||||
func (l *List) update(gtx Context) {
|
||||
d := l.scroll.Update(gtx.Metric, gtx, gtx.Now, gesture.Axis(l.Axis))
|
||||
d := l.scroll.Update(gtx.Metric, gtx.Source, gtx.Now, gesture.Axis(l.Axis))
|
||||
l.scrollDelta = d
|
||||
l.Position.Offset += d
|
||||
}
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ func TestListPosition(t *testing.T) {
|
||||
Constraints: Constraints{
|
||||
Max: image.Pt(20, 10),
|
||||
},
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
el := func(gtx Context, idx int) Dimensions {
|
||||
return Dimensions{Size: image.Pt(10, 10)}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ func (b *Bool) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
||||
b.Update(gtx)
|
||||
dims := b.clk.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
semantic.SelectedOp(b.Value).Add(gtx.Ops)
|
||||
semantic.EnabledOp(gtx.Source != nil).Add(gtx.Ops)
|
||||
semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops)
|
||||
return w(gtx)
|
||||
})
|
||||
return dims
|
||||
|
||||
+4
-5
@@ -101,10 +101,9 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension
|
||||
dims := w(gtx)
|
||||
c := m.Stop()
|
||||
defer clip.Rect(image.Rectangle{Max: dims.Size}).Push(gtx.Ops).Pop()
|
||||
enabled := gtx.Source != nil
|
||||
semantic.EnabledOp(enabled).Add(gtx.Ops)
|
||||
semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops)
|
||||
b.click.Add(gtx.Ops)
|
||||
if enabled {
|
||||
if gtx.Enabled() {
|
||||
keys := key.Set("⏎|Space")
|
||||
if !b.focused {
|
||||
keys = ""
|
||||
@@ -119,7 +118,7 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension
|
||||
// clicks, if any.
|
||||
func (b *Clickable) Update(gtx layout.Context) []Click {
|
||||
b.clicks = nil
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
b.focused = false
|
||||
}
|
||||
if b.requestFocus {
|
||||
@@ -141,7 +140,7 @@ func (b *Clickable) Update(gtx layout.Context) []Click {
|
||||
NumClicks: c,
|
||||
})
|
||||
}
|
||||
for _, e := range b.click.Update(gtx) {
|
||||
for _, e := range b.click.Update(gtx.Source) {
|
||||
switch e.Kind {
|
||||
case gesture.KindClick:
|
||||
if l := len(b.history); l > 0 {
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestClickable(t *testing.T) {
|
||||
b1 widget.Clickable
|
||||
b2 widget.Clickable
|
||||
)
|
||||
gtx := app.NewContext(&ops, app.FrameEvent{Source: &r})
|
||||
gtx := app.NewContext(&ops, app.FrameEvent{Source: r.Source()})
|
||||
layout := func() {
|
||||
b1.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Dimensions{Size: image.Pt(100, 100)}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ type Draggable struct {
|
||||
}
|
||||
|
||||
func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions {
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
return w(gtx)
|
||||
}
|
||||
dims := w(gtx)
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ func TestDraggable(t *testing.T) {
|
||||
var r input.Router
|
||||
gtx := layout.Context{
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: &r,
|
||||
Source: r.Source(),
|
||||
Ops: new(op.Ops),
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -225,7 +225,7 @@ func (e *Editor) processPointer(gtx layout.Context) {
|
||||
axis = gesture.Vertical
|
||||
smin, smax = sbounds.Min.Y, sbounds.Max.Y
|
||||
}
|
||||
sdist := e.scroller.Update(gtx.Metric, gtx, gtx.Now, axis)
|
||||
sdist := e.scroller.Update(gtx.Metric, gtx.Source, gtx.Now, axis)
|
||||
var soff int
|
||||
if e.SingleLine {
|
||||
e.text.ScrollRel(sdist, 0)
|
||||
@@ -305,10 +305,10 @@ func (e *Editor) processPointer(gtx layout.Context) {
|
||||
|
||||
func (e *Editor) clickDragEvents(gtx layout.Context) []event.Event {
|
||||
var combinedEvents []event.Event
|
||||
for _, evt := range e.clicker.Update(gtx) {
|
||||
for _, evt := range e.clicker.Update(gtx.Source) {
|
||||
combinedEvents = append(combinedEvents, evt)
|
||||
}
|
||||
for _, evt := range e.dragger.Update(gtx.Metric, gtx, gesture.Both) {
|
||||
for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) {
|
||||
combinedEvents = append(combinedEvents, evt)
|
||||
}
|
||||
return combinedEvents
|
||||
@@ -677,14 +677,12 @@ func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.Call
|
||||
}
|
||||
e.showCaret = e.focused && (!blinking || dt%timePerBlink < timePerBlink/2)
|
||||
}
|
||||
disabled := gtx.Source == nil
|
||||
|
||||
semantic.Editor.Add(gtx.Ops)
|
||||
if e.Len() > 0 {
|
||||
e.paintSelection(gtx, selectMaterial)
|
||||
e.paintText(gtx, textMaterial)
|
||||
}
|
||||
if !disabled {
|
||||
if gtx.Enabled() {
|
||||
e.paintCaret(gtx, textMaterial)
|
||||
}
|
||||
return visibleDims
|
||||
|
||||
+10
-10
@@ -103,7 +103,7 @@ func TestEditorReadOnly(t *testing.T) {
|
||||
Max: image.Pt(100, 100),
|
||||
},
|
||||
Locale: english,
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
fontSize := unit.Sp(10)
|
||||
@@ -505,7 +505,7 @@ func TestEditorDimensions(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Constraints{Max: image.Pt(100, 100)},
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
Locale: english,
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
@@ -891,7 +891,7 @@ g 2 4 6 8 g
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Locale: english,
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
font := font.Font{}
|
||||
@@ -900,13 +900,13 @@ g 2 4 6 8 g
|
||||
var tim time.Duration
|
||||
selected := func(start, end int) string {
|
||||
// Layout once with no events; populate e.lines.
|
||||
gtx.Source = nil
|
||||
gtx = gtx.Disabled()
|
||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||
e.Events() // throw away any events from this layout
|
||||
|
||||
e.Focus()
|
||||
r.Frame(gtx.Ops)
|
||||
gtx.Source = r
|
||||
gtx.Source = r.Source()
|
||||
// Build the selection events
|
||||
startPos := e.text.closestToRune(start)
|
||||
endPos := e.text.closestToRune(end)
|
||||
@@ -972,7 +972,7 @@ g 2 4 6 8 g
|
||||
// Constrain the editor to roughly 6 columns wide and redraw
|
||||
gtx.Constraints = layout.Exact(image.Pt(36, 36))
|
||||
// Keep existing selection
|
||||
gtx.Source = nil
|
||||
gtx = gtx.Disabled()
|
||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||
|
||||
caretStart := e.text.closestToRune(e.text.caret.start)
|
||||
@@ -991,7 +991,7 @@ func TestSelectMove(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Locale: english,
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
font := font.Font{}
|
||||
@@ -1080,7 +1080,7 @@ func TestEditor_MaxLen(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
fontSize := unit.Sp(10)
|
||||
@@ -1116,7 +1116,7 @@ func TestEditor_Filter(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
fontSize := unit.Sp(10)
|
||||
@@ -1146,7 +1146,7 @@ func TestEditor_Submit(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
fontSize := unit.Sp(10)
|
||||
|
||||
+4
-5
@@ -40,13 +40,13 @@ func (e *Enum) index(k string) *enumKey {
|
||||
|
||||
// Update the state and report whether Value has changed by user interaction.
|
||||
func (e *Enum) Update(gtx layout.Context) bool {
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
e.focused = false
|
||||
}
|
||||
e.hovering = false
|
||||
changed := false
|
||||
for _, state := range e.keys {
|
||||
for _, ev := range state.click.Update(gtx) {
|
||||
for _, ev := range state.click.Update(gtx.Source) {
|
||||
switch ev.Kind {
|
||||
case gesture.KindPress:
|
||||
if ev.Source == pointer.Mouse {
|
||||
@@ -117,12 +117,11 @@ func (e *Enum) Layout(gtx layout.Context, k string, content layout.Widget) layou
|
||||
}
|
||||
clk := &state.click
|
||||
clk.Add(gtx.Ops)
|
||||
enabled := gtx.Source != nil
|
||||
if enabled {
|
||||
if gtx.Enabled() {
|
||||
key.InputOp{Tag: &state.tag, Keys: "⏎|Space"}.Add(gtx.Ops)
|
||||
}
|
||||
semantic.SelectedOp(k == e.Value).Add(gtx.Ops)
|
||||
semantic.EnabledOp(enabled).Add(gtx.Ops)
|
||||
semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops)
|
||||
c.Add(gtx.Ops)
|
||||
|
||||
return dims
|
||||
|
||||
@@ -25,7 +25,7 @@ func ExampleClickable_passthrough() {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: &r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
|
||||
// widget lays out two buttons on top of each other.
|
||||
@@ -75,7 +75,7 @@ func ExampleDraggable_Layout() {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||
Source: &r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
// mime is the type used to match drag and drop operations.
|
||||
// It could be left empty in this example.
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ func (f *Float) Layout(gtx layout.Context, axis layout.Axis, pointerMargin unit.
|
||||
// The range of f is set by the minimum constraints main axis value.
|
||||
func (f *Float) Update(gtx layout.Context) bool {
|
||||
changed := false
|
||||
for _, e := range f.drag.Update(gtx.Metric, gtx, gesture.Axis(f.axis)) {
|
||||
for _, e := range f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis)) {
|
||||
if f.length > 0 && (e.Kind == pointer.Press || e.Kind == pointer.Drag) {
|
||||
pos := e.Position.X
|
||||
if f.axis == layout.Vertical {
|
||||
|
||||
+3
-3
@@ -61,7 +61,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart,
|
||||
}
|
||||
|
||||
// Jump to a click in the track.
|
||||
for _, event := range s.track.Update(gtx) {
|
||||
for _, event := range s.track.Update(gtx.Source) {
|
||||
if event.Kind != gesture.KindClick ||
|
||||
event.Modifiers != key.Modifiers(0) ||
|
||||
event.NumClicks > 1 {
|
||||
@@ -80,7 +80,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart,
|
||||
}
|
||||
|
||||
// Offset to account for any drags.
|
||||
for _, event := range s.drag.Update(gtx.Metric, gtx, gesture.Axis(axis)) {
|
||||
for _, event := range s.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(axis)) {
|
||||
switch event.Kind {
|
||||
case pointer.Drag:
|
||||
case pointer.Release, pointer.Cancel:
|
||||
@@ -136,7 +136,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart,
|
||||
|
||||
// Process events from the indicator so that hover is
|
||||
// detected properly.
|
||||
_ = s.indicator.Update(gtx)
|
||||
_ = s.indicator.Update(gtx.Source)
|
||||
}
|
||||
|
||||
// AddTrack configures the track click listener for the scrollbar to use
|
||||
|
||||
@@ -133,7 +133,7 @@ func (b ButtonLayoutStyle) Layout(gtx layout.Context, w layout.Widget) layout.Di
|
||||
defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop()
|
||||
background := b.Background
|
||||
switch {
|
||||
case gtx.Source == nil:
|
||||
case !gtx.Enabled():
|
||||
background = f32color.Disabled(b.Background)
|
||||
case b.Button.Hovered() || b.Button.Focused():
|
||||
background = f32color.Hovered(b.Background)
|
||||
@@ -165,7 +165,7 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop()
|
||||
background := b.Background
|
||||
switch {
|
||||
case gtx.Source == nil:
|
||||
case !gtx.Enabled():
|
||||
background = f32color.Disabled(b.Background)
|
||||
case b.Button.Hovered() || b.Button.Focused():
|
||||
background = f32color.Hovered(b.Background)
|
||||
|
||||
@@ -60,7 +60,7 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim
|
||||
return layout.UniformInset(2).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
size := gtx.Dp(c.Size)
|
||||
col := c.IconColor
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
col = f32color.Disabled(col)
|
||||
}
|
||||
gtx.Constraints.Min = image.Point{X: size}
|
||||
|
||||
@@ -61,7 +61,7 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops)
|
||||
hintColor := hintColorMacro.Stop()
|
||||
selectionColorMacro := op.Record(gtx.Ops)
|
||||
paint.ColorOp{Color: blendDisabledColor(gtx.Source == nil, e.SelectionColor)}.Add(gtx.Ops)
|
||||
paint.ColorOp{Color: blendDisabledColor(!gtx.Enabled(), e.SelectionColor)}.Add(gtx.Ops)
|
||||
selectionColor := selectionColorMacro.Stop()
|
||||
|
||||
var maxlines int
|
||||
|
||||
@@ -51,7 +51,7 @@ func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
fillWidth := int(float32(progressBarWidth) * clamp1(p.Progress))
|
||||
fillColor := p.Color
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
fillColor = f32color.Disabled(fillColor)
|
||||
}
|
||||
return shader(fillWidth, fillColor)
|
||||
|
||||
@@ -56,7 +56,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
trans.Pop()
|
||||
|
||||
color := s.Color
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
color = f32color.Disabled(color)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
if s.Switch.Value {
|
||||
col = s.Color.Enabled
|
||||
}
|
||||
if gtx.Source == nil {
|
||||
if !gtx.Enabled() {
|
||||
col = f32color.Disabled(col)
|
||||
}
|
||||
trackColor := s.Color.Track
|
||||
|
||||
@@ -298,10 +298,10 @@ func (e *Selectable) processPointer(gtx layout.Context) {
|
||||
|
||||
func (e *Selectable) clickDragEvents(gtx layout.Context) []event.Event {
|
||||
var combinedEvents []event.Event
|
||||
for _, evt := range e.clicker.Update(gtx) {
|
||||
for _, evt := range e.clicker.Update(gtx.Source) {
|
||||
combinedEvents = append(combinedEvents, evt)
|
||||
}
|
||||
for _, evt := range e.dragger.Update(gtx.Metric, gtx, gesture.Both) {
|
||||
for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) {
|
||||
combinedEvents = append(combinedEvents, evt)
|
||||
}
|
||||
return combinedEvents
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestSelectableMove(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Locale: english,
|
||||
Source: r,
|
||||
Source: r.Source(),
|
||||
}
|
||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||
fnt := font.Font{}
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestBool(t *testing.T) {
|
||||
r input.Router
|
||||
b widget.Bool
|
||||
)
|
||||
gtx := app.NewContext(&ops, app.FrameEvent{Source: &r})
|
||||
gtx := app.NewContext(&ops, app.FrameEvent{Source: r.Source()})
|
||||
layout := func() {
|
||||
b.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
semantic.CheckBox.Add(gtx.Ops)
|
||||
|
||||
Reference in New Issue
Block a user