From 23e44292bbeaea0fb633b1d1efe38ea00591096c Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 5 Oct 2023 16:40:21 -0500 Subject: [PATCH] widget: [API] separate state changes from Draggable.Layout to Update Signed-off-by: Elias Naur --- widget/dnd.go | 81 ++++++++++++++++++------------------------ widget/example_test.go | 2 +- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/widget/dnd.go b/widget/dnd.go index e336f659..55b6c0a0 100644 --- a/widget/dnd.go +++ b/widget/dnd.go @@ -17,18 +17,44 @@ type Draggable struct { // Type contains the MIME type and matches transfer.SourceOp. Type string - handle struct{} - drag gesture.Drag - click f32.Point - pos f32.Point - requested bool - request string + handle struct{} + drag gesture.Drag + click f32.Point + pos f32.Point } func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions { if gtx.Queue == nil { 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 for _, ev := range d.drag.Events(gtx.Metric, gtx.Queue, gesture.Both) { switch ev.Kind { @@ -42,48 +68,11 @@ func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dim d.pos = pos for _, ev := range gtx.Queue.Events(&d.handle) { - switch e := ev.(type) { - case transfer.RequestEvent: - d.requested = true - d.request = e.Type - case transfer.CancelEvent: - d.requested = false - d.request = "" + if e, ok := ev.(transfer.RequestEvent); ok { + return e.Type, true } } - - 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 + return "", false } // Offer the data ready for a drop. Must be called after being Requested. diff --git a/widget/example_test.go b/widget/example_test.go index 2bfdbf8e..b04cf25f 100644 --- a/widget/example_test.go +++ b/widget/example_test.go @@ -93,7 +93,7 @@ func ExampleDraggable_Layout() { drag.Layout(gtx, w, w) // drag must respond with an Offer event when requested. // 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"}) }