From 419b86ff0ce2c7f78492851f4aa498715708db9e Mon Sep 17 00:00:00 2001 From: linuxerwang Date: Thu, 22 Jun 2023 21:05:03 -0700 Subject: [PATCH] Add drag-drop support to interactive objects. (#360) --- lib/src/display/interactive_object.dart | 20 ++++++ lib/src/display/stage.dart | 84 ++++++++++++++++--------- lib/src/events.dart | 1 + lib/src/events/mouse_event.dart | 6 +- 4 files changed, 78 insertions(+), 33 deletions(-) diff --git a/lib/src/display/interactive_object.dart b/lib/src/display/interactive_object.dart index c5ffc894..29504823 100644 --- a/lib/src/display/interactive_object.dart +++ b/lib/src/display/interactive_object.dart @@ -94,6 +94,12 @@ abstract class InteractiveObject extends DisplayObject { EventStreamProvider(MouseEvent.MOUSE_WHEEL); static const EventStreamProvider mouseContextMenu = EventStreamProvider(MouseEvent.CONTEXT_MENU); + static const EventStreamProvider dragEnter = + EventStreamProvider(MouseEvent.DRAG_ENTER); + static const EventStreamProvider dragLeave = + EventStreamProvider(MouseEvent.DRAG_LEAVE); + static const EventStreamProvider drop = + EventStreamProvider(MouseEvent.DROP); /// Dispatched when the user moves a pointing device away from an /// InteractiveObject instance. @@ -282,6 +288,20 @@ abstract class InteractiveObject extends DisplayObject { EventStream get onMouseContextMenu => InteractiveObject.mouseContextMenu.forTarget(this); + /// Dispatched when a HTML element was dragged entering an InteractiveObject + /// instance. + EventStream get onDragEnter => + InteractiveObject.dragEnter.forTarget(this); + + /// Dispatched when a HTML element was dragged leaving an InteractiveObject + /// instance. + EventStream get onDragLeave => + InteractiveObject.dragLeave.forTarget(this); + + /// Dispatched when a HTML element was dropped in an InteractiveObject + /// instance. + EventStream get onDrop => InteractiveObject.drop.forTarget(this); + // touch events static const EventStreamProvider touchOutEvent = diff --git a/lib/src/display/stage.dart b/lib/src/display/stage.dart index 39790070..b2a2e1f7 100644 --- a/lib/src/display/stage.dart +++ b/lib/src/display/stage.dart @@ -138,28 +138,6 @@ class Stage extends DisplayObjectContainer { EventStream get onMouseLeave => Stage.mouseLeaveEvent.forTarget(this); - /// Dispatched when an external HTML element was dragged entering the stage - /// canvas. - EventStream get onDragEnter => - const EventStreamProvider(MouseEvent.DRAG_ENTER) - .forTarget(this); - - /// Dispatched when an external HTML element was dragged leaving the stage - /// canvas. - EventStream get onDragLeave => - const EventStreamProvider(MouseEvent.DRAG_LEAVE) - .forTarget(this); - - /// Dispatched when an external HTML element was dragged over the stage - /// canvas. - EventStream get onDragOver => - const EventStreamProvider(MouseEvent.DRAG_OVER) - .forTarget(this); - - /// Dispatched when an external HTML element was dropped on stage canvas. - EventStream get onDrop => - const EventStreamProvider(MouseEvent.DROP).forTarget(this); - //---------------------------------------------------------------------------- Stage(CanvasElement canvas, @@ -661,6 +639,11 @@ class Stage extends DisplayObjectContainer { dispatchEvent(Event(Event.MOUSE_LEAVE)); } + var isDnD = event.type == 'dragenter' || + event.type == 'dragleave' || + event.type == 'dragover' || + event.type == 'drop'; + //----------------------------------------------------------------- // MOUSE_OUT, ROLL_OUT, ROLL_OVER, MOUSE_OVER @@ -702,7 +685,25 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - 0)); + 0, + null)); + if (isDnD) { + oldTarget.dispatchEvent(MouseEvent( + MouseEvent.DRAG_LEAVE, + true, + localPoint.x, + localPoint.y, + stagePoint.x, + stagePoint.y, + event.altKey, + event.ctrlKey, + event.shiftKey, + 0.0, + 0.0, + mouseButton.buttonDown, + 0, + event.dataTransfer)); + } } for (var i = 0; i < oldTargetList.length - commonCount; i++) { @@ -721,7 +722,8 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - 0)); + 0, + null)); } for (var i = newTargetList.length - commonCount - 1; i >= 0; i--) { @@ -740,7 +742,8 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - 0)); + 0, + null)); } if (newTarget != null) { @@ -758,7 +761,25 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - 0)); + 0, + null)); + if (isDnD) { + newTarget.dispatchEvent(MouseEvent( + MouseEvent.DRAG_ENTER, + true, + localPoint.x, + localPoint.y, + stagePoint.x, + stagePoint.y, + event.altKey, + event.ctrlKey, + event.shiftKey, + 0.0, + 0.0, + mouseButton.buttonDown, + 0, + event.dataTransfer)); + } } _mouseTarget = newTarget; @@ -800,8 +821,6 @@ class Stage extends DisplayObjectContainer { mouseEventType = MouseEvent.DRAG_ENTER; } else if (event.type == 'dragleave') { mouseEventType = MouseEvent.DRAG_LEAVE; - } else if (event.type == 'dragover') { - mouseEventType = MouseEvent.DRAG_OVER; } else if (event.type == 'drop') { mouseEventType = MouseEvent.DROP; } @@ -823,7 +842,8 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - mouseButton.clickCount)); + mouseButton.clickCount, + isDnD ? event.dataTransfer : null)); if (isClick) { mouseEventType = isDoubleClick && target.doubleClickEnabled @@ -843,7 +863,8 @@ class Stage extends DisplayObjectContainer { 0.0, 0.0, mouseButton.buttonDown, - 0)); + 0, + null)); } } } @@ -873,7 +894,8 @@ class Stage extends DisplayObjectContainer { event.deltaX, event.deltaY, false, - 0); + 0, + null); target.dispatchEvent(mouseEvent); diff --git a/lib/src/events.dart b/lib/src/events.dart index f7643229..f989858d 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -8,6 +8,7 @@ library stagexl.events; import 'dart:async'; +import 'dart:html'; part 'events/broadcast_event.dart'; part 'events/event.dart'; diff --git a/lib/src/events/mouse_event.dart b/lib/src/events/mouse_event.dart index b69110d7..99067ea0 100644 --- a/lib/src/events/mouse_event.dart +++ b/lib/src/events/mouse_event.dart @@ -36,7 +36,6 @@ class MouseEvent extends InputEvent { static const String DRAG_ENTER = 'dragEnter'; static const String DRAG_LEAVE = 'dragLeave'; - static const String DRAG_OVER = 'dragOver'; static const String DROP = 'drop'; //--------------------------------------------------------------------------- @@ -73,6 +72,8 @@ class MouseEvent extends InputEvent { final int clickCount; + final DataTransfer? dataTransfer; + /// Creates a new [MouseEvent]. MouseEvent( @@ -88,5 +89,6 @@ class MouseEvent extends InputEvent { this.deltaX, this.deltaY, this.buttonDown, - this.clickCount); + this.clickCount, + this.dataTransfer); }