This is an automated email from the ASF dual-hosted git repository. gregdove pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit e637fdcbef6def1daaefaa7f937ea4220d0601a0 Author: greg-dove <[email protected]> AuthorDate: Sun Oct 25 13:33:46 2020 +1300 Added a new (WIP) SimpleDraggableController, supported more variants with the regular DragDrop beads (light code addition). --- .../DragDrop/src/main/royale/DragDropClasses.as | 2 + .../html/beads/SingleSelectionDragSourceBead.as | 46 ++++- .../html/beads/controllers/DragMouseController.as | 50 ++++- ...eController.as => SimpleDraggableController.as} | 206 ++++++++++++--------- 4 files changed, 212 insertions(+), 92 deletions(-) diff --git a/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as b/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as index 54194db..4b894a3 100644 --- a/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as +++ b/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as @@ -52,6 +52,8 @@ internal class DragDropClasses import org.apache.royale.html.beads.DragDropListItemRendererInitializer; DragDropListItemRendererInitializer; + import org.apache.royale.html.beads.controllers.SimpleDraggableController; SimpleDraggableController; + } } diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SingleSelectionDragSourceBead.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SingleSelectionDragSourceBead.as index ec2dc2a..32cc175 100644 --- a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SingleSelectionDragSourceBead.as +++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SingleSelectionDragSourceBead.as @@ -30,6 +30,7 @@ package org.apache.royale.html.beads import org.apache.royale.events.DragEvent; import org.apache.royale.events.Event; import org.apache.royale.events.EventDispatcher; + import org.apache.royale.events.IEventDispatcher; import org.apache.royale.html.beads.controllers.DragMouseController; import org.apache.royale.utils.getParentOrSelfByType; @@ -142,14 +143,57 @@ package org.apache.royale.html.beads _dragType = value; } + private var _approveDragStart:Function; + /** + * Provides the ability to approve (or prevent) a mouseDown event being considered + * as the start of a drag sequence. This can be useful for renderers with some controls + * that must remain interactive, so that dragging is only supported by other parts of the renderer. + * The function should return true for the mouseDown event to be approved as the possible start + * of a drag sequence + * + * @param value a function that takes a MouseEvent as a parameter and returns a Boolean value that + * pre-approves a mouseDown event (or not) + */ + public function set approveDragStart(value:Function):void{ + if (_dragController) { + _dragController.approveDragStart=value + } else { + _approveDragStart = value; + } + } + public function get approveDragStart():Function{ + return _dragController? _dragController.approveDragStart :_approveDragStart; + } + + private var _explicitTopmostDispatcher:IEventDispatcher; + /** + * Provides the ability to specify a non-default topMostEventDispatcher. + * A Basic Royale application looks on the document.body tag for an associated Royale EventDispatcher instance, + * and the default behaviour is to consider that to be valid. + * Other Application types may not be associated with the body tag, so this provides a way to explicitly specify + * the top level instance. + * + */ + public function set explicitTopmostDispatcher(value:IEventDispatcher):void{ + if (_dragController) { + _dragController.topMostDispatcher = value; + _explicitTopmostDispatcher = null; + } + else _explicitTopmostDispatcher = value; + } + public function get explicitTopmostDispatcher():IEventDispatcher{ + return _dragController? _dragController.topMostDispatcher :_explicitTopmostDispatcher; + } + /** * @private */ public function set strand(value:IStrand):void { _strand = value; - _dragController = new DragMouseController(); + _dragController.topMostDispatcher = _explicitTopmostDispatcher; + _dragController.approveDragStart = _approveDragStart; _strand.addBead(_dragController); _dragController.addEventListener(DragEvent.DRAG_START, handleDragStart); diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as index 5fd7222..e3da127 100644 --- a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as +++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as @@ -220,19 +220,52 @@ package org.apache.royale.html.beads.controllers private var host:IPopUpHost; + private var _approveDragStart:Function; + /** + * Provides the ability to approve (or prevent) a mouseDown event being considered + * as the start of a drag sequence. This can be useful for renderers with some controls + * that must remain interactive, so that dragging is only supported by other parts of the renderer. + * The function should return true for the mouseDown event to be approved as the possible start + * of a drag sequence + * + * @param value a function that takes a MouseEvent as a parameter, its boolean return value pre-approves a mouseDown event (or not) + */ + public function set approveDragStart(value:Function):void{ + _approveDragStart = value; + } + public function get approveDragStart():Function{ + return _approveDragStart; + } + + private var _topMostDispatcher:IEventDispatcher; /** - * @private * @royaleignorecoercion org.apache.royale.core.IUIBase */ + public function get topMostDispatcher():IEventDispatcher{ + if (_topMostDispatcher) return _topMostDispatcher; + if (_strand) _topMostDispatcher = (_strand as IUIBase).topMostEventDispatcher; + return _topMostDispatcher; + } + public function set topMostDispatcher(value:IEventDispatcher):void{ + _topMostDispatcher = value; + } + + private var _listeningDispatcher:IEventDispatcher; + /** + * @private + */ private function dragMouseDownHandler(event:MouseEvent):void { + if (_approveDragStart && !_approveDragStart(event)) return; // trace("DRAG-MOUSE: dragMouseDown"); - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.CLICK, dragMouseUpHandler); + var dispatcher:IEventDispatcher = topMostDispatcher; + dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); + dispatcher.addEventListener(MouseEvent.CLICK, dragMouseUpHandler); COMPILE::SWF { - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); + dispatcher.addEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); } + _listeningDispatcher = dispatcher; /** * In browser, we need to listen to window to get mouseup events outside the window */ @@ -374,13 +407,14 @@ package org.apache.royale.html.beads.controllers DragEvent.dragSource = null; DragEvent.dragInitiator = null; dragImage = null; - - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.CLICK, dragMouseUpHandler); + var dispatcher:IEventDispatcher = _listeningDispatcher; + _listeningDispatcher = null; + dispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); + dispatcher.removeEventListener(MouseEvent.CLICK, dragMouseUpHandler); COMPILE::SWF { - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); + dispatcher.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); } COMPILE::JS diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/SimpleDraggableController.as similarity index 65% copy from frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as copy to frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/SimpleDraggableController.as index 5fd7222..a6316e4 100644 --- a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/DragMouseController.as +++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/controllers/SimpleDraggableController.as @@ -18,22 +18,22 @@ //////////////////////////////////////////////////////////////////////////////// package org.apache.royale.html.beads.controllers { - COMPILE::SWF { - import flash.display.InteractiveObject; - import flash.display.DisplayObjectContainer; +//@todo refactor topMostDispatcher stuff similar to elsewhere + + COMPILE::SWF { + import flash.display.InteractiveObject; + import flash.display.DisplayObjectContainer; } COMPILE::JS { import org.apache.royale.events.utils.MouseEventConverter; + import org.apache.royale.core.WrappedHTMLElement; } import org.apache.royale.core.IBead; - import org.apache.royale.core.IDragInitiator; - import org.apache.royale.core.IPopUpHost; import org.apache.royale.core.IStrand; import org.apache.royale.core.IUIBase; - import org.apache.royale.core.UIBase; import org.apache.royale.events.DragEvent; import org.apache.royale.events.EventDispatcher; import org.apache.royale.events.IEventDispatcher; @@ -41,7 +41,9 @@ package org.apache.royale.html.beads.controllers import org.apache.royale.geom.Point; import org.apache.royale.utils.PointUtils; import org.apache.royale.utils.UIUtils; - import org.apache.royale.css2.Cursors; + import org.apache.royale.utils.DisplayUtils; + import org.apache.royale.geom.Rectangle; + /** * Indicates that a drag/drop operation is starting. @@ -86,7 +88,7 @@ package org.apache.royale.html.beads.controllers * @playerversion AIR 2.6 * @productversion Royale 0.8 */ - public class DragMouseController extends EventDispatcher implements IBead + public class SimpleDraggableController extends EventDispatcher implements IBead { /** * Whether there is a drag operation @@ -101,41 +103,7 @@ package org.apache.royale.html.beads.controllers */ public static var dragging:Boolean = false; - /** - * The drag image. - * - * @langversion 3.0 - * @playerversion Flash 10.2 - * @playerversion AIR 2.6 - * @productversion Royale 0.8 - * - * @royalesuppresspublicvarwarning - */ - public static var dragImage:IUIBase; - /** - * The offset of the drag image. - * - * @langversion 3.0 - * @playerversion Flash 10.2 - * @playerversion AIR 2.6 - * @productversion Royale 0.8 - * - * @royalesuppresspublicvarwarning - */ - public static var dragImageOffsetX:Number = 0; - - /** - * The offset of the drag image. - * - * @langversion 3.0 - * @playerversion Flash 10.2 - * @playerversion AIR 2.6 - * @productversion Royale 0.8 - * - * @royalesuppresspublicvarwarning - */ - public static var dragImageOffsetY:Number = 0; /** * The default movement in x and or y that @@ -158,7 +126,7 @@ package org.apache.royale.html.beads.controllers * @playerversion AIR 2.6 * @productversion Royale 0.8 */ - public function DragMouseController() + public function SimpleDraggableController() { threshold = defaultThreshold; } @@ -182,6 +150,7 @@ package org.apache.royale.html.beads.controllers { _threshold = value; } + private var _strand:IStrand; @@ -207,7 +176,7 @@ package org.apache.royale.html.beads.controllers IEventDispatcher(_strand).addEventListener(MouseEvent.MOUSE_DOWN, dragMouseDownHandler); - DragMouseController.instanceNumber += 100; + instanceNumber += 100; } public function get strand():IStrand @@ -215,10 +184,42 @@ package org.apache.royale.html.beads.controllers return _strand; } + private var _parentDraggable:IUIBase; + private var mouseDownX:Number; private var mouseDownY:Number; + private var lastPositionX:Number; + private var lastPositionY:Number; + + private var _approveDragStart:Function; + /** + * Provides the ability to approve (or prevent) a mouseDown event being considered + * as the start of a drag sequence. + * + * @param value a function that takes a MouseEvent as a parameter, its boolean return value pre-approves a mouseDown event (or not) + */ + public function set approveDragStart(value:Function):void{ + _approveDragStart = value; + } + public function get approveDragStart():Function{ + return _approveDragStart; + } + + + private var _topMostDispatcher:IEventDispatcher; + /** + * @royaleignorecoercion org.apache.royale.core.IUIBase + */ + public function get topMostDispatcher():IEventDispatcher{ + if (_topMostDispatcher) return _topMostDispatcher; + if (_strand) _topMostDispatcher = (_strand as IUIBase).topMostEventDispatcher; + return _topMostDispatcher; + } + public function set topMostDispatcher(value:IEventDispatcher):void{ + _topMostDispatcher = value; + } - private var host:IPopUpHost; + private var _listeningDispatcher:IEventDispatcher; /** * @private @@ -227,12 +228,21 @@ package org.apache.royale.html.beads.controllers private function dragMouseDownHandler(event:MouseEvent):void { // trace("DRAG-MOUSE: dragMouseDown"); - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.CLICK, dragMouseUpHandler); + if (_approveDragStart && !_approveDragStart(event)) return; + topMostDispatcher = (_strand as IUIBase).topMostEventDispatcher; + if (!topMostDispatcher) { + trace('there was a problem finding the topmost EventDispatcher'); + return; + } + + topMostDispatcher.addEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); + topMostDispatcher.addEventListener(MouseEvent.CLICK, dragMouseUpHandler); + COMPILE::SWF { - (_strand as IUIBase).topMostEventDispatcher.addEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); + topMostDispatcher.addEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); } + /** * In browser, we need to listen to window to get mouseup events outside the window */ @@ -240,8 +250,12 @@ package org.apache.royale.html.beads.controllers { window.addEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); } + + mouseDownX = event.screenX; mouseDownY = event.screenY; + lastPositionX = event.clientX; + lastPositionY = event.clientY; event.preventDefault(); } @@ -251,61 +265,78 @@ package org.apache.royale.html.beads.controllers */ private function dragMouseMoveHandler(event:MouseEvent):void { - var pt:Point; var dragEvent:DragEvent; -// trace("DRAG-MOUSE: dragMouseMove"); - event.preventDefault(); - + var draggable:IUIBase; if (!dragging) { -// trace("DRAG-MOUSE: not dragging anything else"); + if (Math.abs(event.screenX - mouseDownX) > threshold || Math.abs(event.screenY - mouseDownY) > threshold) { dragEvent = DragEvent.createDragEvent("dragStart", event); - dragEvent.clientX = mouseDownX; - dragEvent.clientY = mouseDownY; + dragEvent.clientX = lastPositionX; + dragEvent.clientY = lastPositionY; + // trace("DRAG-MOUSE: sending dragStart via "+event.target.toString()+" == "+dragImageOffsetX); COMPILE::SWF { - dragEvent.relatedObject = event.target as InteractiveObject; + dragEvent.relatedObject = _strand as InteractiveObject; } COMPILE::JS { - dragEvent.relatedObject = event.target; + dragEvent.relatedObject = _strand; } DragEvent.dispatchDragEvent(dragEvent, event.target); dispatchEvent(dragEvent); - if (DragEvent.dragSource != null) + var avoid:Boolean; + COMPILE::SWF { + avoid = dragEvent.isDefaultPrevented(); + } + COMPILE::JS { + avoid = dragEvent.defaultPrevented; + } + + if (!avoid) { dragging = true; - host = UIUtils.findPopUpHost(_strand as IUIBase); - if (host == null) return; - host.popUpParent.addElement(dragImage); - pt = PointUtils.globalToLocal(new Point(event.clientX, event.clientY), host); - dragImage.x = pt.x + dragImageOffsetX; - dragImage.y = pt.y + dragImageOffsetY; - (dragImage as UIBase).id = "drag_image"; + + var deltaX:Number = event.clientX -lastPositionX; + var deltaY:Number = event.clientY - lastPositionY; + lastPositionX = event.clientX; + lastPositionY = event.clientY; + draggable = parentDraggable; + + draggable.x = draggable.x + deltaX ; + draggable.y = draggable.y + deltaY ; + COMPILE::SWF { - (dragImage as InteractiveObject).mouseEnabled = false; - (dragImage as DisplayObjectContainer).mouseChildren = false; + (draggable as InteractiveObject).mouseEnabled = false; + (draggable as DisplayObjectContainer).mouseChildren = false; } COMPILE::JS { - dragImage.element.style['pointer-events'] = 'none'; - dragImage.element.style['position'] = 'absolute'; + draggable.element.style['cursor'] = 'move'; + draggable.element.style['position'] = 'absolute'; } } } } else { - host = UIUtils.findPopUpHost(_strand as IUIBase); - if (host == null) return; // trace("DRAG-MOUSE: sending dragMove via " + event.target.toString()+" == "+dragImageOffsetX); dragEvent = DragEvent.createDragEvent("dragMove", event); - pt = PointUtils.globalToLocal(new Point(event.clientX, event.clientY), host); - dragImage.x = pt.x + dragImageOffsetX; - dragImage.y = pt.y + dragImageOffsetY; + draggable = parentDraggable; + + deltaX = event.clientX - lastPositionX; + deltaY = event.clientY - lastPositionY; + lastPositionX = event.clientX; + lastPositionY = event.clientY; + + //@todo support some constraint approach + + draggable.x = draggable.x + deltaX; + draggable.y = draggable.y + deltaY; + + COMPILE::SWF { dragEvent.relatedObject = event.target as InteractiveObject; } @@ -325,11 +356,9 @@ package org.apache.royale.html.beads.controllers //trace("DRAG-MOUSE: dragMouseUp"); var dragEvent:DragEvent; - host = UIUtils.findPopUpHost(_strand as IUIBase); - if (dragImage && host) { - host.popUpParent.removeElement(dragImage); - } + // host = UIUtils.findPopUpHost(_strand as IUIBase); + var draggable:IUIBase; if (dragging && event.target) { //trace("DRAG-MOUSE: sending dragEnd via: "+event.target.toString()); @@ -373,22 +402,33 @@ package org.apache.royale.html.beads.controllers dragging = false; DragEvent.dragSource = null; DragEvent.dragInitiator = null; - dragImage = null; - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.CLICK, dragMouseUpHandler); + topMostDispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, dragMouseMoveHandler); + topMostDispatcher.removeEventListener(MouseEvent.CLICK, dragMouseUpHandler); COMPILE::SWF { - (_strand as IUIBase).topMostEventDispatcher.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); + topMostDispatcher.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); } COMPILE::JS { window.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUpHandler); + parentDraggable.element.style['cursor'] = 'auto'; } } - } + /** + * allows explicitly setting a parent that can be dragged by this bead being + * active on one of its children (e.g. use case: panel draggable from its header) + */ + public function get parentDraggable():IUIBase { + return _parentDraggable || _strand as IUIBase; + } + + public function set parentDraggable(value:IUIBase):void { + _parentDraggable = value; + } + } }
