Keeping state of a drag operation separately.

This commit is contained in:
Sander Schobers 2020-05-15 12:15:44 +02:00
parent c0c5235d5a
commit 5d297c98b8
2 changed files with 60 additions and 17 deletions

View File

@ -16,12 +16,12 @@ type MouseLeaveFn func()
var _ Control = &ControlBase{} var _ Control = &ControlBase{}
type ControlBase struct { type ControlBase struct {
bounds geom.RectangleF32 bounds geom.RectangleF32
offset geom.PointF32 offset geom.PointF32
parent Control parent Control
dragStart *geom.PointF32 drag Dragable
over bool over bool
pressed bool pressed bool
onClick ClickFn onClick ClickFn
onDragEnd DragEndFn onDragEnd DragEndFn
@ -62,18 +62,18 @@ func (c *ControlBase) Handle(ctx Context, e Event) {
case *MouseMoveEvent: case *MouseMoveEvent:
c.over = over(e.MouseEvent) c.over = over(e.MouseEvent)
if c.pressed { if c.pressed {
if c.dragStart == nil { if start, ok := c.drag.IsDragging(); ok {
var start = c.ToControlPosition(e.Pos())
c.dragStart = &start
if c.onDragStart != nil {
c.onDragStart(start)
}
} else {
var start = *c.dragStart
var move = c.ToControlPosition(e.Pos()) var move = c.ToControlPosition(e.Pos())
c.drag.Move(move)
if c.onDragMove != nil { if c.onDragMove != nil {
c.onDragMove(start, move) c.onDragMove(start, move)
} }
} else {
var start = c.ToControlPosition(e.Pos())
c.drag.Start(start)
if c.onDragStart != nil {
c.onDragStart(start)
}
} }
} }
case *MouseLeaveEvent: case *MouseLeaveEvent:
@ -85,10 +85,9 @@ func (c *ControlBase) Handle(ctx Context, e Event) {
} }
case *MouseButtonUpEvent: case *MouseButtonUpEvent:
if e.Button == MouseButtonLeft { if e.Button == MouseButtonLeft {
if c.dragStart != nil { if start, ok := c.drag.IsDragging(); ok {
var start = *c.dragStart
var end = c.ToControlPosition(e.Pos()) var end = c.ToControlPosition(e.Pos())
c.dragStart = nil c.drag.Cancel()
if c.onDragEnd != nil { if c.onDragEnd != nil {
c.onDragEnd(start, end) c.onDragEnd(start, end)
} }

44
ui/dragable.go Normal file
View File

@ -0,0 +1,44 @@
package ui
import "opslag.de/schobers/geom"
// Dragable keeps track of the mouse position during a drag operation.
type Dragable struct {
start *geom.PointF32
current *geom.PointF32
}
// Cancel cancels the drag operation and returns the start and end position.
func (d *Dragable) Cancel() (geom.PointF32, geom.PointF32) {
if d.start == nil {
return geom.ZeroPtF32, geom.ZeroPtF32
}
start, end := *d.start, *d.current
d.start = nil
d.current = nil
return start, end
}
// IsDragging returns if the drag operation is in progress and the start location if so.
func (d *Dragable) IsDragging() (geom.PointF32, bool) {
if d.start != nil {
return *d.start, true
}
return geom.ZeroPtF32, false
}
// Move calculates the delta between the start point and the current position.
func (d *Dragable) Move(p geom.PointF32) (geom.PointF32, bool) {
if d.start == nil {
return geom.ZeroPtF32, false
}
delta := p.Sub(*d.current)
d.current = &p
return delta, true
}
// Start set the start point of the drag operation.
func (d *Dragable) Start(p geom.PointF32) {
d.start = &p
d.current = &p
}