You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/10/25 00:34:13 UTC

[royale-asjs] 05/05: Added a new (WIP) SimpleDraggableController, supported more variants with the regular DragDrop beads (light code addition).

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 <gr...@gmail.com>
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;
+        }
+    }
 }