You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by yi...@apache.org on 2018/12/17 15:45:26 UTC

[royale-asjs] branch develop updated: Make drop target sensitive to position in item renderer

This is an automated email from the ASF dual-hosted git repository.

yishayw pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git


The following commit(s) were added to refs/heads/develop by this push:
     new c96c967  Make drop target sensitive to position in item renderer
c96c967 is described below

commit c96c9672751af0b7eadaf318e55ae448a6109399
Author: DESKTOP-RH4S838\Yishay <yi...@hotmail.com>
AuthorDate: Mon Dec 17 17:45:11 2018 +0200

    Make drop target sensitive to position in item renderer
---
 .../DragDrop/src/main/resources/basic-manifest.xml |   1 +
 .../SensitiveSingleSelectionDropTargetBead.as      | 395 +++++++++++++++++++++
 2 files changed, 396 insertions(+)

diff --git a/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml b/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
index 8e59e0f..1295ed4 100644
--- a/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
+++ b/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
@@ -25,6 +25,7 @@
 	<component id="SingleSelectionDragSourceBead" class="org.apache.royale.html.beads.SingleSelectionDragSourceBead" />
 	<component id="SingleSelectionDropIndicatorBead" class="org.apache.royale.html.beads.SingleSelectionDropIndicatorBead"/>
 	<component id="SingleSelectionDropTargetBead" class="org.apache.royale.html.beads.SingleSelectionDropTargetBead" />
+	<component id="SensitiveSingleSelectionDropTargetBead" class="org.apache.royale.html.beads.SensitiveSingleSelectionDropTargetBead" />
     <component id="DragMouseController" class="org.apache.royale.html.beads.controllers.DragMouseController" />
     <component id="DropMouseController" class="org.apache.royale.html.beads.controllers.DropMouseController" />
     	
diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveSingleSelectionDropTargetBead.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveSingleSelectionDropTargetBead.as
new file mode 100644
index 0000000..a5f3b0a
--- /dev/null
+++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveSingleSelectionDropTargetBead.as
@@ -0,0 +1,395 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// TODO:yishayw rename this class
+// TODO:yishayw move some of the logic to the controller
+package org.apache.royale.html.beads
+{
+	import org.apache.royale.collections.ArrayList;
+	import org.apache.royale.core.DropType;
+	import org.apache.royale.core.IBead;
+	import org.apache.royale.core.IChild;
+	import org.apache.royale.core.IDataProviderModel;
+	import org.apache.royale.core.IItemRenderer;
+	import org.apache.royale.core.IItemRendererParent;
+	import org.apache.royale.core.ILayoutHost;
+	import org.apache.royale.core.IParent;
+	import org.apache.royale.core.IRenderedObject;
+	import org.apache.royale.core.ISelectionModel;
+	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.Event;
+	import org.apache.royale.events.EventDispatcher;
+	import org.apache.royale.events.IEventDispatcher;
+	import org.apache.royale.events.MouseEvent;
+	import org.apache.royale.geom.Point;
+	import org.apache.royale.geom.Rectangle;
+	import org.apache.royale.html.beads.controllers.DropMouseController;
+	import org.apache.royale.html.supportClasses.DataItemRenderer;
+	import org.apache.royale.utils.PointUtils;
+	import org.apache.royale.utils.UIUtils;
+
+
+	/**
+	 * The enter event is dispatched when a DragEnter has been detected in the drop target
+	 * strand. This event can be used to determine if the strand can and will accept the data
+	 * being dragged onto it. If the data cannot be used by the drop target strand this event
+	 * should be cancelled.
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9
+	 */
+	[Event(name="enter", type="org.apache.royale.events.Event")]
+
+	/**
+	 * The exit event is sent when the drag goes outside of the drop target space.
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9
+	 */
+	[Event(name="exit", type="org.apache.royale.events.Event")]
+
+	/**
+	 * The over event is dispatched while the drag is happening over the drop target space. This
+	 * event may be cancelled if that particular area of the drop target cannot accept the
+	 * drag source data.
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9
+	 */
+	[Event(name="over", type="org.apache.royale.events.Event")]
+
+	/**
+	 * The drop event is dispatched just prior to incorporating the drag source data into the drop
+	 * target's dataProvider. This event may be cancelled to prevent that from happening.
+	 * Note that a "exit" event always precedes this event to allow any drag-drop graphics
+	 * to be cleared.
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9
+	 */
+	[Event(name="drop", type="org.apache.royale.events.Event")]
+
+	/**
+	 * The complete event is dispatched when the drop operation has completed from the drop
+	 * target's perspective.
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9
+	 */
+	[Event(name="complete", type="org.apache.royale.events.Event")]
+
+	/**
+	 *  The SingleSelectionDropTargetBead enables items to be dropped onto single-selection List
+	 *  components. This bead can be used with SingleSelectionDragSourceBead to enable the re-arrangement
+	 *  of rows within the same list.
+     *
+	 *  @see org.apache.royale.html.beads.SingleSelectionDropIndicatorBead
+     *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.8
+	 */
+	public class SensitiveSingleSelectionDropTargetBead extends EventDispatcher implements IBead
+	{
+		/**
+		 * Constructor
+	     *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.8
+		 */
+		public function SensitiveSingleSelectionDropTargetBead()
+		{
+			super();
+		}
+
+		private var _dropController:DropMouseController;
+		private var _itemRendererParent:IItemRendererParent;
+		private var _dropIndicatorBead:SingleSelectionDropIndicatorBead;
+		private var _dropIndicator:UIBase;
+		private var targetIndex:int = -1;
+		private var indicatorVisible:Boolean = false;
+
+		private var _strand:IStrand;
+
+		/**
+		 * @private
+		 */
+		public function set strand(value:IStrand):void
+		{
+			_strand = value;
+
+			_dropController = new DropMouseController();
+			_strand.addBead(_dropController);
+
+			IEventDispatcher(_dropController).addEventListener(DragEvent.DRAG_ENTER, handleDragEnter);
+			IEventDispatcher(_dropController).addEventListener(DragEvent.DRAG_EXIT, handleDragExit);
+			IEventDispatcher(_dropController).addEventListener(DragEvent.DRAG_OVER, handleDragOver);
+			IEventDispatcher(_dropController).addEventListener(DragEvent.DRAG_DROP, handleDragDrop);
+		}
+
+		private var _dropDirection: String = "horizontal";
+
+		/**
+		 * The direction the drop indicator should display. "horizontal" (default) or "vertical".
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9
+		 */
+		public function get dropDirection():String
+		{
+			return _dropDirection;
+		}
+		public function set dropDirection(value:String):void
+		{
+			_dropDirection = value;
+		}
+
+		protected var _indicatorParent:UIBase;
+
+		/**
+		 * @private
+		 */
+		protected function get indicatorParent():UIBase
+		{
+			if (_indicatorParent == null) {
+				var layerBead:IDrawingLayerBead = _strand.getBeadByType(IDrawingLayerBead) as IDrawingLayerBead;
+				if (layerBead != null) {
+					_indicatorParent = layerBead.layer;
+				}
+			}
+			return _indicatorParent;
+		}
+		/**
+		 * @private
+		 */
+		private function get itemRendererParent():IItemRendererParent
+		{
+			if (!_itemRendererParent)
+				_itemRendererParent = _strand.getBeadByType(IItemRendererParent) as IItemRendererParent;
+			return _itemRendererParent;
+		}
+
+		/**
+		 * @private
+		 */
+		protected function getDropIndicator(ir:Object, width:Number, height:Number):UIBase
+		{
+			if (_dropIndicatorBead == null) {
+				_dropIndicatorBead = _strand.getBeadByType(SingleSelectionDropIndicatorBead) as SingleSelectionDropIndicatorBead;
+				if (_dropIndicatorBead == null) return null;
+			}
+			_dropIndicator = _dropIndicatorBead.getDropIndicator(ir, width, height);
+			return _dropIndicator;
+		}
+
+		/**
+		 * @private
+		 */
+		private function handleDragEnter(event:DragEvent):void
+		{
+			var newEvent:Event = new Event("enter", false, true);
+			dispatchEvent(newEvent);
+			if (newEvent.defaultPrevented) return;
+
+
+			var pt0:Point;
+			var pt1:Point;
+			var pt2:Point;
+
+			_dropController.acceptDragDrop(event.relatedObject as IUIBase, DropType.COPY);
+			listenToMouseMove();
+		}
+		
+		private function listenToMouseMove():void
+		{
+			(_strand as IEventDispatcher).addEventListener(MouseEvent.MOUSE_MOVE, checkForNextItemRenderer);
+		}
+
+		private function stopListeningToMouseMove():void
+		{
+			(_strand as IEventDispatcher).addEventListener(MouseEvent.MOUSE_MOVE, checkForNextItemRenderer);
+		}
+		
+		private function checkForNextItemRenderer(e:MouseEvent):void
+		{
+			var changeMade:Boolean = true;
+			var calculatedIndex:int = -1;
+			for (var i:int = 0; i < itemRendererParent.numItemRenderers; i++)
+			{
+				var ir:IUIBase = itemRendererParent.getItemRendererAt(i) as IUIBase;
+				var localY:Number = PointUtils.globalToLocal(new Point(e.clientX, e.clientY), ir).y;
+				if (localY >= 0 && localY <= ir.height)
+				{
+					calculatedIndex = i;
+					if (localY > ir.height / 2 && i < itemRendererParent.numItemRenderers - 1)
+					{
+						calculatedIndex++;
+					}
+					break;
+				}
+			}
+			if (targetIndex != calculatedIndex && calculatedIndex != -1 && indicatorParent && (targetIndex != calculatedIndex || !indicatorVisible)) {
+				targetIndex = calculatedIndex;
+				var lastItemVisited:IUIBase = itemRendererParent.getItemRendererAt(targetIndex) as IUIBase;
+				var di:UIBase = getDropIndicator(lastItemVisited, (dropDirection == "horizontal") ? indicatorParent.width : 4,
+					(dropDirection == "horizontal") ? 4 : indicatorParent.height);
+				indicatorVisible = true;
+				displayDropIndicator(lastItemVisited);
+				
+				if (indicatorParent != null) {
+					indicatorParent.addElement(di);
+				}
+			}
+		}
+		
+		/**
+		 * @private
+		 */
+		private function handleDragExit(event:DragEvent):void
+		{
+			//trace("SingleSelectionDropTargetBead received DragExit via: "+event.relatedObject.toString());
+			dispatchEvent(new Event("exit", false, true));
+
+			if (indicatorVisible) {
+				if (indicatorParent != null) {
+					indicatorParent.removeElement(_dropIndicator);
+				}
+				indicatorVisible = false;
+			}
+			stopListeningToMouseMove();
+		}
+
+		/**
+		 * @private
+		 */
+		private function handleDragOver(event:DragEvent):void
+		{
+			//trace("SingleSelectionDropTargetBead received DragOver via: "+event.relatedObject.toString());
+			var newEvent:Event = new Event("over", false, true);
+			dispatchEvent(newEvent);
+			if (event.defaultPrevented) {
+				return;
+			}
+		}
+
+		/**
+		 * @private
+		 */
+		private function handleDragDrop(event:DragEvent):void
+		{
+			//trace("SingleSelectionDropTargetBead received DragDrop via: "+event.relatedObject.toString());
+
+			handleDragExit(event);
+
+			var newEvent:Event = new Event("drop", false, true);
+			dispatchEvent(newEvent);
+			if (newEvent.defaultPrevented) {
+				return;
+			}
+
+			if (DragEvent.dragInitiator) {
+				DragEvent.dragInitiator.acceptingDrop(_strand, "object");
+			}
+
+			var dragSource:Object = DragEvent.dragSource;
+			var sourceIndex:int = 0;
+
+			var dataProviderModel:IDataProviderModel = _strand.getBeadByType(IDataProviderModel) as IDataProviderModel;
+			if (dataProviderModel.dataProvider is Array) {
+				var dataArray:Array = dataProviderModel.dataProvider as Array;
+				dataArray.splice(targetIndex, 0, dragSource);
+
+				var newArray:Array = dataArray.slice()
+				dataProviderModel.dataProvider = newArray;
+			} else if (dataProviderModel.dataProvider is ArrayList)
+			{
+				var dataList:ArrayList = dataProviderModel.dataProvider as ArrayList;
+				dataList.addItem(dragSource);
+			}
+
+			// Let the dragInitiator know the drop has been completed.
+			if (DragEvent.dragInitiator) {
+				DragEvent.dragInitiator.acceptedDrop(_strand, "object");
+			}
+			
+			if (dataProviderModel is ISelectionModel) {
+				(dataProviderModel as ISelectionModel).selectedIndex = targetIndex;
+			}
+
+			// is this event necessary? isn't "complete" enough?
+			IEventDispatcher(_strand).dispatchEvent(new Event("dragDropAccepted"));
+
+			dispatchEvent(new Event("complete"));
+		}
+
+		COMPILE::SWF
+		private function displayDropIndicator(item:IUIBase):void
+		{
+			var pt0:Point;
+			var pt1:Point;
+			var pt2:Point;
+
+			if (dropDirection == "horizontal") {
+				pt0 = new Point(0, item.y+item.height);
+				pt1 = PointUtils.localToGlobal(pt0, item.parent);
+				pt2 = PointUtils.globalToLocal(pt1, indicatorParent);
+				_dropIndicator.x = 0;
+				_dropIndicator.y = pt2.y - 1;
+			}
+			else {
+				pt0 = new Point(item.x, 0);
+				pt1 = PointUtils.localToGlobal(pt0, item.parent);
+				pt2 = PointUtils.globalToLocal(pt1, indicatorParent);
+				_dropIndicator.x = pt2.x - 1;
+				_dropIndicator.y = 0;
+			}
+		}
+
+		COMPILE::JS
+		private function displayDropIndicator(item:IUIBase):void
+		{
+			trace("displayDropIndicator: " + (item as IRenderedObject).element.innerText);
+			if (dropDirection == "horizontal") {
+				_dropIndicator.x = 0;
+				_dropIndicator.y = item.y;
+			} else {
+				_dropIndicator.x = item.x;
+				_dropIndicator.y = 0;
+			}
+		}
+	}
+}