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 2019/12/02 11:10:17 UTC
[royale-asjs] branch develop updated: Multi Selection beads added,
still need to change drop order and handle case where nothing is
selected
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 9d5f1c2 Multi Selection beads added, still need to change drop order and handle case where nothing is selected
new fc64ff9 Merge branch 'develop' of https://github.com/apache/royale-asjs into develop
9d5f1c2 is described below
commit 9d5f1c27694e55c654f05861144f764b5a8f838d
Author: DESKTOP-RH4S838\Yishay <yi...@hotmail.com>
AuthorDate: Mon Dec 2 13:09:47 2019 +0200
Multi Selection beads added, still need to change drop order and handle case where nothing is selected
---
.../DragDrop/src/main/resources/basic-manifest.xml | 3 +
.../DragDrop/src/main/royale/DragDropClasses.as | 2 +
.../html/beads/MultiSelectionDragImageBead.as | 153 ++++++++
.../html/beads/MultiSelectionDragSourceBead.as | 270 ++++++++++++++
.../beads/SensitiveMultiSelectionDropTargetBead.as | 407 +++++++++++++++++++++
5 files changed, 835 insertions(+)
diff --git a/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml b/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
index 1295ed4..c21964c 100644
--- a/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
+++ b/frameworks/projects/DragDrop/src/main/resources/basic-manifest.xml
@@ -21,11 +21,14 @@
<componentPackage>
+ <component id="MultiSelectionDragImageBead" class="org.apache.royale.html.beads.MultiSelectionDragImageBead" />
+ <component id="MultiSelectionDragSourceBead" class="org.apache.royale.html.beads.MultiSelectionDragSourceBead" />
<component id="SingleSelectionDragImageBead" class="org.apache.royale.html.beads.SingleSelectionDragImageBead" />
<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="SensitiveMultiSelectionDropTargetBead" class="org.apache.royale.html.beads.SensitiveMultiSelectionDropTargetBead" />
<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/DragDropClasses.as b/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as
index cc64931..107c31c 100644
--- a/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as
+++ b/frameworks/projects/DragDrop/src/main/royale/DragDropClasses.as
@@ -30,6 +30,8 @@ internal class DragDropClasses
import org.apache.royale.core.DropType; DropType;
import org.apache.royale.events.DragEvent; DragEvent;
+ import org.apache.royale.html.beads.MultiSelectionDragImageBead; MultiSelectionDragImageBead;
+ import org.apache.royale.html.beads.MultiSelectionDragSourceBead; MultiSelectionDragSourceBead;
import org.apache.royale.html.beads.SingleSelectionDragImageBead; SingleSelectionDragImageBead;
import org.apache.royale.html.beads.SingleSelectionDragSourceBead; SingleSelectionDragSourceBead;
import org.apache.royale.html.beads.SingleSelectionDropIndicatorBead; SingleSelectionDropIndicatorBead;
diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragImageBead.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragImageBead.as
new file mode 100644
index 0000000..94a2730
--- /dev/null
+++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragImageBead.as
@@ -0,0 +1,153 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.html.beads
+{
+
+ import org.apache.royale.collections.ArrayList;
+ import org.apache.royale.core.IBead;
+ import org.apache.royale.core.IBeadLayout;
+ import org.apache.royale.core.IChild;
+ import org.apache.royale.core.IMultiSelectionModel;
+ import org.apache.royale.core.IDocument;
+ import org.apache.royale.core.IDragInitiator;
+ import org.apache.royale.core.IItemRenderer;
+ import org.apache.royale.core.IItemRendererParent;
+ import org.apache.royale.core.IParent;
+ import org.apache.royale.core.ISelectableItemRenderer;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IUIBase;
+ import org.apache.royale.core.Lookalike;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.core.IBeadView;
+ import org.apache.royale.html.IListView;
+ 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.geom.Point;
+ import org.apache.royale.geom.Rectangle;
+ import org.apache.royale.html.Button;
+ import org.apache.royale.html.Container;
+ import org.apache.royale.html.Label;
+ import org.apache.royale.html.beads.controllers.DragMouseController;
+ import org.apache.royale.utils.PointUtils;
+ import org.apache.royale.utils.getParentOrSelfByType;
+ import org.apache.royale.html.beads.layouts.VerticalLayout;
+ import org.apache.royale.html.beads.layouts.HorizontalLayout;
+
+ COMPILE::JS
+ {
+ import org.apache.royale.core.WrappedHTMLElement;
+ }
+
+
+ /**
+ * The MultiSelectionDragImageBead produces a UIBase component that represents
+ * the item being dragged. It does this by creating lookalikes to all selected items
+ * and adding them to a container.
+ *
+ * The createDragImage() function can be overridden and a different component returned.
+ *
+ * @see org.apache.royale.html.beads.SingleSelectionDragSourceBead.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public class MultiSelectionDragImageBead extends EventDispatcher implements IBead
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function MultiSelectionDragImageBead()
+ {
+ super();
+ }
+
+ private var _strand:IStrand;
+
+ /**
+ * @private
+ */
+ public function set strand(value:IStrand):void
+ {
+ _strand = value;
+
+ IEventDispatcher(_strand).addEventListener(DragEvent.DRAG_START, handleDragStart);
+ }
+
+ /**
+ * Creates an example/temporary component to be dragged and returns it.
+ *
+ * @param ir IItemRenderer The itemRenderer to be used as a template.
+ * @return UIBase The "dragImage" to use.
+ *
+ * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ protected function createDragImage():UIBase
+ {
+ var dragImage:Container = new Container();
+ var layoutBead:IBead = _strand.getBeadByType(IBeadLayout);
+ if (layoutBead is VerticalLayout)
+ {
+ dragImage.addBead(new VerticalLayout())
+ } else
+ {
+ dragImage.addBead(new HorizontalLayout())
+ }
+ var itemRendererParent:IItemRendererParent = (_strand.getBeadByType(IBeadView) as IListView).dataGroup as IItemRendererParent;
+ var selectedIndices:Array = (_strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel).selectedIndices;
+ for (var i:int = 0; i < selectedIndices.length; i++)
+ {
+ var ir:IItemRenderer = itemRendererParent.getItemRendererForIndex(selectedIndices[i]);
+ var lookalike:UIBase = new Lookalike(ir);
+ lookalike.width = IUIBase(ir).width;
+ lookalike.height = IUIBase(ir).height;
+ dragImage.addElement(lookalike);
+ }
+
+ dragImage.className = "DragImage";
+ COMPILE::JS
+ {
+ dragImage.element.style.position = 'absolute';
+ dragImage.element.style.cursor = 'pointer';
+ }
+ return dragImage;
+ }
+
+ /**
+ * @private
+ *
+ */
+ private function handleDragStart(event:DragEvent):void
+ {
+ DragMouseController.dragImage = createDragImage();
+ }
+ }
+}
diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragSourceBead.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragSourceBead.as
new file mode 100644
index 0000000..ab40159
--- /dev/null
+++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/MultiSelectionDragSourceBead.as
@@ -0,0 +1,270 @@
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.html.beads
+{
+ import org.apache.royale.collections.ArrayList;
+ import org.apache.royale.core.IBead;
+ import org.apache.royale.core.IChild;
+ import org.apache.royale.core.IMultiSelectionModel;
+ import org.apache.royale.core.IDocument;
+ import org.apache.royale.core.IDragInitiator;
+ import org.apache.royale.core.IItemRenderer;
+ import org.apache.royale.core.ILayoutHost;
+ import org.apache.royale.core.IItemRendererParent;
+ import org.apache.royale.core.IParent;
+ import org.apache.royale.core.ISelectionModel;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IUIBase;
+ 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.geom.Point;
+ import org.apache.royale.geom.Rectangle;
+ import org.apache.royale.html.Group;
+ import org.apache.royale.html.Label;
+ import org.apache.royale.html.beads.controllers.DragMouseController;
+ import org.apache.royale.html.supportClasses.DataItemRenderer;
+ import org.apache.royale.utils.PointUtils;
+ import org.apache.royale.utils.UIUtils;
+ import org.apache.royale.utils.getParentOrSelfByType;
+
+ /**
+ * The start event is dispatched when a DragStart event happens. The DragEvent.dragSource
+ * is set before this event is dispatched. A listener for this event can then decide if
+ * if the drag-drop action should continue or not. If not, the event should be cancelled.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9
+ */
+ [Event(name="start", type="org.apache.royale.events.Event")]
+
+ /**
+ * The accept event is dispatched when the drop happens but just before the data being
+ * dragged as been incorporated into the drop target's data source. Cancelling this event
+ * prevents that from happening.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9
+ */
+ [Event(name="accept", type="org.apache.royale.events.Event")]
+
+ /**
+ * The complete event is dispatched when the entire drag-and-drop operation has completed
+ * from the drag source'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 MultiSelectionDragSourceBead brings drag capability to single-selection List components.
+ * By adding this bead, a user can drag a row of the List to a new location within the list. This bead
+ * should be used in conjunction with SingleSelectionDropTargetBead.
+ *
+ * This bead adds a new event to the strand, "dragImageNeeded", which is dispatched on the strand
+ * just prior to the dragImage's appearance. An event listener can create its own dragImage if the
+ * default, taken from the data item, is not suitable.
+ *
+ * @see org.apache.royale.html.beads.SingleSelectionDropTargetBead.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public class MultiSelectionDragSourceBead extends EventDispatcher implements IBead, IDragInitiator
+ {
+ /**
+ * Constructor
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function MultiSelectionDragSourceBead()
+ {
+ super();
+ }
+
+ private var _strand:IStrand;
+ private var _dragController:DragMouseController;
+ private var continueDragOperation:Boolean = true;
+
+ private var _dragType:String = "move";
+
+ /**
+ * The type of drag and drop operation: move or copy.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function get dragType():String
+ {
+ return _dragType;
+ }
+ public function set dragType(value:String):void
+ {
+ _dragType = value;
+ }
+
+ /**
+ * @private
+ */
+ public function set strand(value:IStrand):void
+ {
+ _strand = value;
+
+ _dragController = new DragMouseController();
+ _strand.addBead(_dragController);
+
+ IEventDispatcher(_strand).addEventListener(DragEvent.DRAG_START, handleDragStart);
+ IEventDispatcher(_strand).addEventListener(DragEvent.DRAG_MOVE, handleDragMove);
+ IEventDispatcher(_strand).addEventListener(DragEvent.DRAG_END, handleDragEnd);
+ }
+
+ /**
+ * The index into the dataProvider of the strand's model where the dragSource
+ * can be found. If -1, the dragSource is not in the dataProvider.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9
+ */
+ public function get dragSourceIndices():Array
+ {
+ var dataProviderModel:IMultiSelectionModel = _strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel;
+ return dataProviderModel.selectedIndices;
+ }
+
+ /**
+ * @private
+ */
+ private function handleDragStart(event:DragEvent):void
+ {
+ //trace("MultiSelectionDragSourceBead received the DragStart");
+
+ DragEvent.dragInitiator = this;
+ DragMouseController.dragImageOffsetX = 0;
+ DragMouseController.dragImageOffsetY = -30;
+
+ var dataProviderModel:IMultiSelectionModel = _strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel;
+ DragEvent.dragSource = dataProviderModel.selectedItems;
+
+ var newEvent:Event = new Event("start", false, true);
+ dispatchEvent(newEvent);
+ if (newEvent.defaultPrevented) {
+ continueDragOperation = false;
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected function handleDragMove(event:DragEvent):void
+ {
+ // ignored for now
+ }
+
+ /**
+ * @private
+ */
+ protected function handleDragEnd(event:DragEvent):void
+ {
+ // ignored for now
+ }
+
+ /* IDragInitiator */
+
+ /**
+ * Handles pre-drop actions.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function acceptingDrop(dropTarget:Object, type:String):void
+ {
+ if (!continueDragOperation) return;
+
+ //trace("MultiSelectionDragSourceBead accepting drop of type "+type);
+ var newEvent:Event = new Event("accept", false, true);
+ dispatchEvent(newEvent);
+ if (newEvent.defaultPrevented) return;
+
+ var dataProviderModel:IMultiSelectionModel = _strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel;
+ if (dataProviderModel is ISelectionModel) {
+ (dataProviderModel as IMultiSelectionModel).selectedIndices = null;
+ }
+
+ if (dragType == "copy") return;
+ var dragSource:Array = DragEvent.dragSource as Array;
+ if (dataProviderModel.dataProvider is Array) {
+ var dataArray:Array = dataProviderModel.dataProvider as Array;
+
+ for (var i:int = 0; i < dragSource.length; i++)
+ {
+ dataArray.removeAt(dataArray.indexOf(dragSource[i]));
+ }
+
+ // refresh the dataProvider model
+ var newArray:Array = dataArray.slice()
+ dataProviderModel.dataProvider = newArray;
+ }
+ else if (dataProviderModel.dataProvider is ArrayList) {
+ var dataList:ArrayList = dataProviderModel.dataProvider as ArrayList;
+
+ for (i = 0; i < dragSource.length; i++)
+ {
+ dataList.removeItem(dragSource[i]);
+ }
+ }
+ }
+
+ /**
+ * Handles post-drop actions.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function acceptedDrop(dropTarget:Object, type:String):void
+ {
+ var dataProviderModel:IMultiSelectionModel = _strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel;
+ dataProviderModel.selectedIndices = null;
+ dispatchEvent(new Event("complete"));
+ }
+
+ }
+}
diff --git a/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveMultiSelectionDropTargetBead.as b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveMultiSelectionDropTargetBead.as
new file mode 100644
index 0000000..58a8380
--- /dev/null
+++ b/frameworks/projects/DragDrop/src/main/royale/org/apache/royale/html/beads/SensitiveMultiSelectionDropTargetBead.as
@@ -0,0 +1,407 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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
+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.IMultiSelectionModel;
+ import org.apache.royale.core.IItemRenderer;
+ import org.apache.royale.core.IItemRendererParent;
+ 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.geom.Point;
+ import org.apache.royale.html.beads.controllers.DropMouseController;
+ import org.apache.royale.utils.PointUtils;
+
+
+ /**
+ * 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.7
+ */
+ [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.7
+ */
+ [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.7
+ */
+ [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.7
+ */
+ [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.7
+ */
+ [Event(name="complete", type="org.apache.royale.events.Event")]
+
+ /**
+ * The SensitiveMultiSelectionDropTargetBead enables items to be dropped onto multi-selection List
+ * components. When the pointing device is in the first half of an item renderer it assumes the item is to be dropped on that item renderer.
+ * If it is on the second half it assumes the drop target is the next item renderer.
+ *
+ * @see org.apache.royale.html.beads.SingleSelectionDropTargetBead
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public class SensitiveMultiSelectionDropTargetBead extends EventDispatcher implements IBead
+ {
+ /**
+ * Constructor
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.7
+ */
+ public function SensitiveMultiSelectionDropTargetBead()
+ {
+ 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 isEndOfList:Boolean = false;
+
+ private var _strand:IStrand;
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ public function set strand(value:IStrand):void
+ {
+ _strand = value;
+
+ _dropController = new DropMouseController();
+ _strand.addBead(_dropController);
+
+ _dropController.addEventListener(DragEvent.DRAG_ENTER, handleDragEnter);
+ _dropController.addEventListener(DragEvent.DRAG_EXIT, handleDragExit);
+ _dropController.addEventListener(DragEvent.DRAG_OVER, handleDragOver);
+ _dropController.addEventListener(DragEvent.DRAG_DROP, handleDragDrop);
+ IEventDispatcher(_strand).addEventListener(DragEvent.DRAG_MOVE, handleDragMove);
+ }
+
+ 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.7
+ */
+ 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);
+ }
+
+ private function checkForNextItemRenderer(e:DragEvent):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)
+ {
+ calculatedIndex++;
+ }
+ break;
+ }
+ }
+ if (targetIndex != calculatedIndex && calculatedIndex != -1 && indicatorParent && (targetIndex != calculatedIndex || !indicatorVisible)) {
+ targetIndex = calculatedIndex;
+ // in case we're at the end of the list, we want to choose the last renderer
+ // but we also want to drop the source after the least renderer, not before it
+ isEndOfList = calculatedIndex == itemRendererParent.numItemRenderers;
+ // calculated index may have been increased beyond bounds
+ var lastItemVisitedIndex:int = !isEndOfList ? calculatedIndex : calculatedIndex - 1;
+ var lastItemVisited:IUIBase = itemRendererParent.getItemRendererAt(lastItemVisitedIndex) as IUIBase;
+
+ var di:UIBase = getDropIndicator(lastItemVisited, (dropDirection == "horizontal") ? indicatorParent.width : 4,
+ (dropDirection == "horizontal") ? 4 : indicatorParent.height);
+ if (indicatorParent != null) {
+ indicatorParent.addElement(di);
+ }
+ displayDropIndicator(lastItemVisited, isEndOfList);
+ indicatorVisible = true;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleDragExit(event:DragEvent):void
+ {
+ //trace("MultiSelectionDropTargetBead received DragExit via: "+event.relatedObject.toString());
+ dispatchEvent(new Event("exit", false, true));
+
+ if (indicatorVisible) {
+ if (indicatorParent != null) {
+ indicatorParent.removeElement(_dropIndicator);
+ }
+ indicatorVisible = false;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleDragOver(event:DragEvent):void
+ {
+ //trace("MultiSelectionDropTargetBead received DragOver via: "+event.relatedObject.toString());
+ var newEvent:Event = new Event("over", false, true);
+ dispatchEvent(newEvent);
+ if (event.defaultPrevented) {
+ return;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleDragMove(event:DragEvent):void
+ {
+ checkForNextItemRenderer(event);
+ }
+
+ /**
+ * @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;
+ }
+
+
+ var dragSource:Array = DragEvent.dragSource as Array;
+ var calculatedTargetIndex:int = targetIndex;
+
+ // dragging somewhere higher on the list, fix items jumping down before it's dropped
+ for (var i:int = 0; i < calculatedTargetIndex; i++)
+ {
+ if (itemRendererParent.getItemRendererAt(i).data == dragSource[0])
+ {
+ calculatedTargetIndex--;
+ break;
+ }
+ }
+
+ if (DragEvent.dragInitiator) {
+ DragEvent.dragInitiator.acceptingDrop(_strand, "object");
+ }
+
+ var dataProviderModel:IMultiSelectionModel = _strand.getBeadByType(IMultiSelectionModel) as IMultiSelectionModel;
+ if (dataProviderModel.dataProvider is Array) {
+ var dataArray:Array = dataProviderModel.dataProvider as Array;
+ for (i = 0; i < dragSource.length; i++)
+ {
+ dataArray.insertAt(calculatedTargetIndex++, dragSource[i]);
+ }
+ var newArray:Array = dataArray.slice()
+ dataProviderModel.dataProvider = newArray;
+ } else if (dataProviderModel.dataProvider is ArrayList)
+ {
+ var dataList:ArrayList = dataProviderModel.dataProvider as ArrayList;
+ for (i = 0; i < dragSource.length; i++)
+ {
+ dataList.addItemAt(dragSource[i], calculatedTargetIndex++);
+ }
+ }
+
+ // 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 = calculatedTargetIndex;
+ }
+
+ // 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, isEndOfList:Boolean=false):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, isEndOfList:Boolean=false):void
+ {
+ var pt:Point = PointUtils.localToGlobal(new Point(0,0), item);
+ pt = PointUtils.globalToLocal(pt,indicatorParent);
+ if (dropDirection == "horizontal") {
+ _dropIndicator.x = 0;
+ _dropIndicator.y = pt.y + (isEndOfList ? item.height : 0);
+ } else {
+ _dropIndicator.x = pt.x + (isEndOfList ? item.width : 0);
+ _dropIndicator.y = 0;
+ }
+ }
+ }
+}