改造AdvancedDataGrid — 节点copy

接着上一篇:改造AdvancedDataGrid — 支持外部drag-drop。本篇就来解决dragDropHandler的重写,让它既支持外部drag-drop,也支持内部节点drag-drop,不但是MOVE也可以COPY。

在正题之前,先看看我的案例:一个AdvancedDataGrid 内部有个tree结构,外面有一个List,现在需要将List里面的item拖到tree里,同时tree内部也能MOVE或者COPY。前面那篇已经解决了外部drag的问题,但是如何drop,或者说如何处理drop呢?OK,杀入正题了。还是从flex sdk源码入手吧,找到AdvancedDataGrid的dragdropHandler函数:

    /**
     *  Handler for the <code>DragEvent.DRAG_DROP</code> event.
     *  This method  hides
     *  the drop feedback by calling the <code>hideDropFeedback()</code> method.
     *
     *  By default, only the <code>DragManager.MOVE</code> drag action is supported.
     *  To support the <code>DragManager.COPY</code>
     *  drag action, you must write an event handler for the
     *  <code>DragEvent.DRAG_DROP</code> event that
     *  implements the copy of the AdvancedDataGrid data based on its structure.
     *
     *  @param event The DragEvent object.
     */
    override protected function dragDropHandler(event:DragEvent):void
    {
        // Drag-and-drop not supported for cells
        if (isCellSelectionMode())
            return;
 
        if (!(_rootModel is IHierarchicalData) &amp;&amp; event.dragSource.hasFormat("items"))
        {
            super.dragDropHandler(event);
            return;
        }
 
        if (event.isDefaultPrevented())
            return;
 
        hideDropFeedback(event);
 
        if ((!_rootModel || _rootModel is IHierarchicalData) &amp;&amp; event.dragSource.hasFormat("treeDataGridItems"))
        {
            //we only support MOVE by default
            if (event.action == DragManager.MOVE &amp;&amp; dragMoveEnabled)
            {
                var items:Array = event.dragSource.dataForFormat("treeDataGridItems") as Array;
                //Are we dropping on ourselves?
                if (event.dragInitiator == this)
                {
                    // If we're dropping onto ourselves or a child of a descendant then dont actually drop
 
                    calculateDropIndex(event);
 
                    // If we did start this drag op then we need to remove first
                    var index:int;
                    var parent:*;
                    var parentItem:*;
                    //get ancestors of the drop target item
                    var dropParentStack:Array = getParentStack(_dropData.parent);
                    dropParentStack.unshift(_dropData.parent); //optimize stack method
                    for (var i:int = 0; i &lt; items.length; i++)
                    {
                        parent = getParentItem(items[i]);
                        index = getChildIndexInParent(parent, items[i]);
                        //check ancestors of the dropTarget if the item matches, we're invalid
                        for each (parentItem in dropParentStack)
                            {
                                //we dont want to drop into one of our own sets of children
                                if (items[i] == parentItem)
                                    return;
                            }
                        //we remove before we add due to the behavior
                        //of structures with parent pointers like e4x
                        removeChildItem(parent, items[i], index);
                        //is the removed item before the drop location?
                        if (parent == _dropData.parent &amp;&amp; index &lt; _dropData.index)
                        {
                            addChildItem(_dropData.parent, items[i], (_dropData.index - i - 1));
                        }
                        else
                        {
                            addChildItem(_dropData.parent, items[i], _dropData.index);
                        }
                    }
                }
            }
        }
    }

当我看到“//we only support MOVE by default”这句该死的注释就郁闷了,AdvancedDataGrid本身不支持COPY节点的。看来如果要处理COPY就只能自己写代码。不过不用急,源码里处理MOVE的逻辑还是可以借鉴借鉴的。慢慢的读下来看看sdk是如何处理MOVE的:先计算当前位置(calculateDropIndex),然后检测是否会MOVE到它的子节点去(这是逻辑错误),然后remove再add。照这个思路,完全可以将remove步骤去掉,这样就是COPY了对不。如果你仔细考虑一下,还能发现这么几个注意点:

  • 不需要检测“是否会MOVE到它的子节点去”
  • 深拷贝节点然后COPY,否则会有冲突(一个节点有两个parent啦),现象也非常奇妙,不信试试看。

我的代码是:

		protected override function dragDropHandler(event:DragEvent):void
		{
			if (event.isDefaultPrevented())
			{
	            return;
	  		}
 
			trace(event.action)
			trace(event.type)
			trace(event.draggedItem)
 
			if(event.dragSource.hasFormat("items"))
			{
				event.dragSource.addData(event.dragSource.dataForFormat("items"),"treeDataGridItems");
			}
			event.dragInitiator = this;
			// copy and move
			if(event.action == DragManager.MOVE)
			{
				super.dragDropHandler(event);
			}
			else if(event.action == DragManager.COPY)
			{
				//super.dragDropHandler(event);
				var items:Array = event.dragSource.dataForFormat("treeDataGridItems") as Array;
				for (var i:int = 0; i < items.length; i++)
				{
					var newItem:Object = new Object();
					var dupItem:Object = items[i];
					if(dupItem["categories"])
					{
						newItem["Region"] = dupItem["Region"];
						newItem["categories"] = new Array();
						for(i=0 ; i<dupItem["categories"].length ; i++)
						{
							var oi:Object = new Object();
							oi["Territory_Rep"] = dupItem["categories"][i]["Territory_Rep"];
							oi["Actual"] = dupItem["categories"][i]["Actual"];
							oi["Estimate"] = dupItem["categories"][i]["Estimate"];
							newItem["categories"].push(oi)
						}
					}
					else
					{
						newItem["Territory_Rep"] = items[i]["Territory_Rep"];
						newItem["Actual"] = items[i]["Actual"];
						newItem["Estimate"] = items[i]["Estimate"];
					}
					addChildItem(_dropData.parent, newItem, _dropData.index);
				}
				super.hideDropFeedback(event);
				clearSelected(false);
			}
		}

 

原文:http://gain-loss.org/?p=356

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值