widget: [API] separate state changes from Draggable.Layout to Update

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-10-05 16:40:21 -05:00
parent fe85136f99
commit 23e44292bb
2 changed files with 36 additions and 47 deletions
+35 -46
View File
@@ -17,18 +17,44 @@ type Draggable struct {
// Type contains the MIME type and matches transfer.SourceOp. // Type contains the MIME type and matches transfer.SourceOp.
Type string Type string
handle struct{} handle struct{}
drag gesture.Drag drag gesture.Drag
click f32.Point click f32.Point
pos f32.Point pos f32.Point
requested bool
request string
} }
func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions { func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions {
if gtx.Queue == nil { if gtx.Queue == nil {
return w(gtx) return w(gtx)
} }
dims := w(gtx)
stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
d.drag.Add(gtx.Ops)
transfer.SourceOp{
Tag: &d.handle,
Type: d.Type,
}.Add(gtx.Ops)
stack.Pop()
if drag != nil && d.drag.Pressed() {
rec := op.Record(gtx.Ops)
op.Offset(d.pos.Round()).Add(gtx.Ops)
drag(gtx)
op.Defer(gtx.Ops, rec.Stop())
}
return dims
}
// Dragging returns whether d is being dragged.
func (d *Draggable) Dragging() bool {
return d.drag.Dragging()
}
// Update the draggable and returns the MIME type for which the Draggable was
// requested to offer data, if any
func (d *Draggable) Update(gtx layout.Context) (mime string, requested bool) {
pos := d.pos pos := d.pos
for _, ev := range d.drag.Events(gtx.Metric, gtx.Queue, gesture.Both) { for _, ev := range d.drag.Events(gtx.Metric, gtx.Queue, gesture.Both) {
switch ev.Kind { switch ev.Kind {
@@ -42,48 +68,11 @@ func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dim
d.pos = pos d.pos = pos
for _, ev := range gtx.Queue.Events(&d.handle) { for _, ev := range gtx.Queue.Events(&d.handle) {
switch e := ev.(type) { if e, ok := ev.(transfer.RequestEvent); ok {
case transfer.RequestEvent: return e.Type, true
d.requested = true
d.request = e.Type
case transfer.CancelEvent:
d.requested = false
d.request = ""
} }
} }
return "", false
dims := w(gtx)
stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
d.drag.Add(gtx.Ops)
transfer.SourceOp{
Tag: &d.handle,
Type: d.Type,
}.Add(gtx.Ops)
stack.Pop()
if drag != nil && d.drag.Pressed() {
rec := op.Record(gtx.Ops)
op.Offset(pos.Round()).Add(gtx.Ops)
drag(gtx)
op.Defer(gtx.Ops, rec.Stop())
}
return dims
}
// Dragging returns whether d is being dragged.
func (d *Draggable) Dragging() bool {
return d.drag.Dragging()
}
// Requested returns the MIME type, if any, for which the Draggable was requested to offer data.
func (d *Draggable) Requested() (mime string, requested bool) {
mime = d.request
requested = d.requested
d.requested = false
d.request = ""
return
} }
// Offer the data ready for a drop. Must be called after being Requested. // Offer the data ready for a drop. Must be called after being Requested.
+1 -1
View File
@@ -93,7 +93,7 @@ func ExampleDraggable_Layout() {
drag.Layout(gtx, w, w) drag.Layout(gtx, w, w)
// drag must respond with an Offer event when requested. // drag must respond with an Offer event when requested.
// Use the drag method for this. // Use the drag method for this.
if m, ok := drag.Requested(); ok { if m, ok := drag.Update(gtx); ok {
drag.Offer(gtx.Ops, m, offer{Data: "hello world"}) drag.Offer(gtx.Ops, m, offer{Data: "hello world"})
} }