From 2713f73d0f8cded094b2e77199ff45e7b2a6f6f7 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Sep 2019 10:21:47 +0900 Subject: [PATCH] Implement the Draggable interface for mobile driver This is not 'mobile dragging' as widgets will need to adapt to the form factor. Progresses #65 --- internal/driver/gomobile/canvas.go | 50 +++++++++++++++++++++++-- internal/driver/gomobile/canvas_test.go | 28 ++++++++++++++ internal/driver/gomobile/driver.go | 14 +++++++ 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/internal/driver/gomobile/canvas.go b/internal/driver/gomobile/canvas.go index 4023643c37..64e4816df4 100644 --- a/internal/driver/gomobile/canvas.go +++ b/internal/driver/gomobile/canvas.go @@ -23,9 +23,11 @@ type canvas struct { typedKey func(event *fyne.KeyEvent) shortcut fyne.ShortcutHandler - inited, dirty bool - lastTapDown int64 - refreshQueue chan fyne.CanvasObject + inited, dirty bool + lastTapDown int64 + lastTapDownPos fyne.Position + dragging fyne.Draggable + refreshQueue chan fyne.CanvasObject } func (c *canvas) Content() fyne.CanvasObject { @@ -170,11 +172,51 @@ func (c *canvas) walkTree( func (c *canvas) tapDown(pos fyne.Position) { c.lastTapDown = time.Now().UnixNano() + c.lastTapDownPos = pos + c.dragging = nil +} + +func (c *canvas) tapMove(pos fyne.Position, + dragCallback func(fyne.Draggable, *fyne.DragEvent)) { + + if c.dragging == nil { + co, _ := driver.FindObjectAtPositionMatching(c.lastTapDownPos, func(object fyne.CanvasObject) bool { + if _, ok := object.(fyne.Draggable); ok { + return true + } + + return false + }, c.overlay, c.content) + + if drag, ok := co.(fyne.Draggable); ok { + c.dragging = drag + } else { + return + } + } + deltaX := pos.X - c.lastTapDownPos.X + deltaY := pos.Y - c.lastTapDownPos.Y + objPos := pos.Subtract(c.dragging.(fyne.CanvasObject).Position()) + + ev := new(fyne.DragEvent) + ev.Position = objPos + ev.DraggedX = deltaX + ev.DraggedY = deltaY + + dragCallback(c.dragging, ev) + c.lastTapDownPos = pos } func (c *canvas) tapUp(pos fyne.Position, tapCallback func(fyne.Tappable, *fyne.PointEvent), - tapAltCallback func(fyne.Tappable, *fyne.PointEvent)) { + tapAltCallback func(fyne.Tappable, *fyne.PointEvent), + dragCallback func(fyne.Draggable, *fyne.DragEvent)) { + if c.dragging != nil { + c.dragging.DragEnd() + + c.dragging = nil + } + duration := time.Now().UnixNano() - c.lastTapDown co, objPos := driver.FindObjectAtPositionMatching(pos, func(object fyne.CanvasObject) bool { diff --git a/internal/driver/gomobile/canvas_test.go b/internal/driver/gomobile/canvas_test.go index 03325de7ff..977caa5809 100644 --- a/internal/driver/gomobile/canvas_test.go +++ b/internal/driver/gomobile/canvas_test.go @@ -43,6 +43,7 @@ func TestCanvas_Tapped(t *testing.T) { wid.Tapped(ev) }, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.TappedSecondary(ev) + }, func(wid fyne.Draggable, ev *fyne.DragEvent) { }) assert.True(t, tapped) @@ -70,9 +71,36 @@ func TestCanvas_TappedSecondary(t *testing.T) { tapped = true tappedObj = wid wid.TappedSecondary(ev) + }, func(wid fyne.Draggable, ev *fyne.DragEvent) { }) assert.True(t, tapped) assert.False(t, buttonTap) assert.Equal(t, button, tappedObj) } + +func TestCanvas_Dragged(t *testing.T) { + dragged := false + var draggedObj fyne.Draggable + scroll := widget.NewScrollContainer(widget.NewLabel("Hi\nHi\nHi")) + c := &canvas{content: scroll} + c.Resize(fyne.NewSize(36, 24)) + assert.Equal(t, 0, scroll.Offset.Y) + + c.tapDown(fyne.NewPos(35, 3)) + c.tapMove(fyne.NewPos(35, 10), func(wid fyne.Draggable, ev *fyne.DragEvent) { + wid.Dragged(ev) + dragged = true + draggedObj = wid + }) + + offset := scroll.Offset.Y + assert.True(t, dragged) + assert.NotNil(t, draggedObj) + assert.Greater(t, offset, 0) + + c.tapMove(fyne.NewPos(35, 5), func(wid fyne.Draggable, ev *fyne.DragEvent) { + wid.Dragged(ev) + }) + assert.Less(t, scroll.Offset.Y, offset) +} diff --git a/internal/driver/gomobile/driver.go b/internal/driver/gomobile/driver.go index 24a0a82c2b..b35e8d0a2b 100644 --- a/internal/driver/gomobile/driver.go +++ b/internal/driver/gomobile/driver.go @@ -152,6 +152,8 @@ func (d *mobileDriver) Run() { switch e.Type { case touch.TypeBegin: d.tapDownCanvas(canvas, e.X, e.Y) + case touch.TypeMove: + d.tapMoveCanvas(canvas, e.X, e.Y) case touch.TypeEnd: d.tapUpCanvas(canvas, e.X, e.Y) } @@ -212,6 +214,16 @@ func (d *mobileDriver) tapDownCanvas(canvas *canvas, x, y float32) { canvas.tapDown(pos) } +func (d *mobileDriver) tapMoveCanvas(canvas *canvas, x, y float32) { + tapX := internal.UnscaleInt(canvas, int(x)) + tapY := internal.UnscaleInt(canvas, int(y)) + pos := fyne.NewPos(tapX, tapY) + + canvas.tapMove(pos, func(wid fyne.Draggable, ev *fyne.DragEvent) { + go wid.Dragged(ev) + }) +} + func (d *mobileDriver) tapUpCanvas(canvas *canvas, x, y float32) { tapX := internal.UnscaleInt(canvas, int(x)) tapY := internal.UnscaleInt(canvas, int(y)) @@ -221,6 +233,8 @@ func (d *mobileDriver) tapUpCanvas(canvas *canvas, x, y float32) { go wid.Tapped(ev) }, func(wid fyne.Tappable, ev *fyne.PointEvent) { go wid.TappedSecondary(ev) + }, func(wid fyne.Draggable, ev *fyne.DragEvent) { + go wid.DragEnd() }) }