tags:

views:

2315

answers:

2

So I have a flex tree component with a xmllistcollection as it's data provider. I would like to be able to rearrange the leaves and branches in the tree by drag and drop. I want to limit the drop area to the current level of the item being dragged. Like

      branch
       branch 0
         leaf 1
         leaf 2
       branch x
         leaf a
         leaf b
       
So, branch x can't be moved under branch 0 and leaf a could not be moved under branch 0.

+3  A: 

Okay, here's a pretty simple way to do this, based on the last example in this Flex Quick Starts article. This should probably be improved by using the "proper" drop indicators (the lines between items) instead of just selecting the item under the mouse when dragging.

The most relevant part is the onDragOver() method, where we restrict where items can be dropped.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"&gt;
    <mx:Script>
        <![CDATA[

            import mx.events.DragEvent;
            import mx.managers.DragManager;
            import mx.core.DragSource;
            import mx.core.UIComponent;
            import mx.controls.Tree;

            private var _draggedItem:XML = null;


            private function onDragEnter( event:DragEvent ) : void
            {
                event.preventDefault();
                event.currentTarget.hideDropFeedback(event);

                var ds:DragSource = event.dragSource;
                var items:Array = ds.dataForFormat("treeItems") as Array;
                if (items != null && items.length > 0 && (items[0] is XML))
                    _draggedItem = items[0];

                DragManager.acceptDragDrop(UIComponent(event.currentTarget));
            }

            private function onDragOver( event:DragEvent ) : void
            {
                event.preventDefault();
                event.currentTarget.hideDropFeedback(event);

                tree.selectedIndex = tree.calculateDropIndex(event);
                var node:XML = tree.selectedItem as XML;

                // restrict drag & drop to nodes within same parent
                if (_draggedItem.parent() != node.parent())
                {
                    DragManager.showFeedback(DragManager.NONE);
                    return;
                }

                DragManager.showFeedback(DragManager.MOVE);
            }

            private function onDragDrop( event:DragEvent ) : void
            {
                event.preventDefault();
                event.currentTarget.hideDropFeedback(event);

                tree.selectedIndex = tree.calculateDropIndex(event);
                var node:XML = tree.selectedItem as XML;

                var addToIndex:int = node.childIndex();
                if ((_draggedItem.parent() == node.parent()) && (addToIndex != _draggedItem.childIndex()))
                {
                    tree.dataDescriptor.removeChildAt(node.parent(), _draggedItem, _draggedItem.childIndex());
                    tree.dataDescriptor.addChildAt(node.parent(), _draggedItem, addToIndex);
                }
            }

            private function onDragComplete( event:DragEvent ) : void
            {
                tree.selectedIndex = -1;
            }    
        ]]>
    </mx:Script>    
    <mx:XML id="treeData" xmlns="">
        <root>
            <node label="Massachusetts" type="state" data="MA">
                <node label="Boston" type="city" >
                    <node label="Smoke House Grill" type="restaurant" />
                    <node label="Equator" type="restaurant" />
                    <node label="Aquataine" type="restaurant" />
                    <node label="Grill 23" type="restaurant" />
                </node>
                <node label="Provincetown" type="city" >
                    <node label="Lobster Pot" type="restaurant" />
                    <node label="The Mews" type="restaurant" />
                </node>
            </node>
            <node label="California" type="state" data="CA">
                <node label="San Francisco" type="city" >
                    <node label="Frog Lane" type="restaurant" />
                </node>
            </node>
        </root>
    </mx:XML>
    <mx:Tree width="100%" height="100%" id="tree"
        labelField="@label"
        dataProvider="{treeData.node}"
        allowMultipleSelection="false"
        dragEnabled="true"
        dropEnabled="true"
        dragMoveEnabled="false"
        dragEnter="onDragEnter(event)"
        dragOver="onDragOver(event)"
        dragDrop="onDragDrop(event)"
        dragComplete="onDragComplete(event)">
    </mx:Tree>        
</mx:Application>
hasseg
Thanks so much. It works great.
smartdirt
A: 

Thanks a lot "hasseg". It just answered a lot of my queries about drag and dropping on the same tree. :)