mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
a63e0cb44a
op.Offset is a convenience function most often used by layouts. Layouts usually operate in integer coordinates, and the float32 version of op.Offset needlessly force conversions from int to float32. This change makes op.Offset take integer coordinates, to better match its intended use. Signed-off-by: Elias Naur <mail@eliasnaur.com>
103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
package widget
|
|
|
|
import (
|
|
"io"
|
|
|
|
"gioui.org/f32"
|
|
"gioui.org/gesture"
|
|
"gioui.org/io/pointer"
|
|
"gioui.org/io/transfer"
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
)
|
|
|
|
// Draggable makes a widget draggable.
|
|
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
|
|
}
|
|
|
|
func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions {
|
|
if gtx.Queue == nil {
|
|
return w(gtx)
|
|
}
|
|
pos := d.pos
|
|
for _, ev := range d.drag.Events(gtx.Metric, gtx.Queue, gesture.Both) {
|
|
switch ev.Type {
|
|
case pointer.Press:
|
|
d.click = ev.Position
|
|
pos = f32.Point{}
|
|
case pointer.Drag, pointer.Release:
|
|
pos = ev.Position.Sub(d.click)
|
|
}
|
|
}
|
|
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 = ""
|
|
}
|
|
}
|
|
|
|
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.
|
|
// The mime must be one in the requested list.
|
|
func (d *Draggable) Offer(ops *op.Ops, mime string, data io.ReadCloser) {
|
|
transfer.OfferOp{
|
|
Tag: &d.handle,
|
|
Type: mime,
|
|
Data: data,
|
|
}.Add(ops)
|
|
}
|
|
|
|
// Pos returns the drag position relative to its initial click position.
|
|
func (d *Draggable) Pos() f32.Point {
|
|
return d.pos
|
|
}
|