~pierrec/giox

cb72b77c86161938916e2c893625ced9ee7498e3 — pierre 9 months ago ae28ab3
widgetx: added Draggable type

Signed-off-by: pierre <pierre.curto@gmail.com>
1 files changed, 63 insertions(+), 0 deletions(-)

A widgetx/drag.go
A widgetx/drag.go => widgetx/drag.go +63 -0
@@ 0,0 1,63 @@
package widgetx

import (
	"image"

	"gioui.org/f32"
	"gioui.org/gesture"
	"gioui.org/io/pointer"
	"gioui.org/layout"
)

// Draggable makes an area draggable and reports its position in Pos.
type Draggable struct {
	Axis    gesture.Axis
	Pos     image.Point
	drag    gesture.Drag
	changed bool
}

func (d *Draggable) Layout(gtx layout.Context) layout.Dimensions {
	size := gtx.Constraints.Min
	pointer.Rect(image.Rectangle{Max: size}).Add(gtx.Ops)
	pointer.CursorNameOp{Name: pointer.CursorGrab}.Add(gtx.Ops)
	d.drag.Add(gtx.Ops)

	var start, pos f32.Point
	for _, ev := range d.drag.Events(gtx.Metric, gtx.Queue, d.Axis) {
		if ev.Source != pointer.Mouse {
			continue
		}
		switch ev.Type {
		case pointer.Cancel:
			start = f32.Point{}
			pos = f32.Point{}
		case pointer.Press:
			start = ev.Position
			pos = ev.Position
		case pointer.Drag, pointer.Release:
			if start == (f32.Point{}) {
				start = ev.Position
			}
			pos = ev.Position
		}
	}
	if start != (f32.Point{}) {
		d.changed = true
		delta := pos.Sub(start).Mul(gtx.Metric.PxPerDp)
		d.Pos.X += int(delta.X)
		d.Pos.Y += int(delta.Y)
	}

	return layout.Dimensions{Size: size}
}

func (d *Draggable) Dragging() bool {
	return d.drag.Dragging()
}

func (d *Draggable) Changed() bool {
	changed := d.changed
	d.changed = false
	return changed
}