1 Reply Latest reply on Nov 4, 2010 6:31 PM by jjjones50

    Manual Drag and Drop from Tree to Tree with XML dataProvider

    jjjones50

      Been struggling with Drag-n-Drop between Tree controls. As far as I can tell, it doesn't work very well.

       

      I have boiled it down to a minimal project below and would be ever so grateful if someone can tell me what I am doing wrong.

       

      The complete MXML application file is below. Flex 3.5.

       

      Two trees side-by-side. One has XML that I want to drag over to the drop tree.

      On the DragOver() event, I select the node which is given to me by the calculateDropIndex() function.

       

      After startup; first open the L1 branch on the left and drag L11 over and drop it on the right Tree.

      Looks good, root node is selected/highlighted and dropFeedback is correct and dropping the node drops it as a child of "Start Here".

      Open the Start Here root node to see it.

      Now proceded to #1 below.

       

      Here are the problems:

      1) Drag "L12" from the left tree over to the middle of the right tree (below "L11" just dropped). "L11" will not be selected. The Selected node (with dropIndex=4) will be the entire new nested XML "<L><L11/></L>"; and therefore only "Start Here" node will be highlighted. Drop "L12" anyway. So, it is acting like selectedIndex = <anynumber> will only select the root node. How do I get the new L11 to show as a drop target?

      2) Now drag "L21" from the left tree onto the right tree; again starting below all nodes on the right tree. Selected node will not change until you drag it above #2 out of 3. Then, you can drag it anywhere, and correctly highlight/select any node as the target, and get that node in code. This is a problem. Go ahead and drop it anywhere. Now if you drag, for example, L22 from the left it will correctly highlight/select any node without having to first drag above #2 in the list.

      3) Now, grab and drag L11 a second time and drop it at the bottom on the right. Drag L23 over. No matter which L11 you hover over, it highlights the one at the bottom. How can this be right?

       

      Those are the bugs I would like to figure out. If I am doing it wrong, I sure would like to know what I am doing wrong. The code below is distilled down to one simple mxml application module.

       

      Thanks,

      Jeff

       

       

       

      <?xml version="1.0" encoding="utf-8"?>

      <mx:Application

       

       

      xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" minWidth="955" minHeight="600">

       

       

       

      <mx:Script>

      <![CDATA[

       

       

      import mx.collections.XMLListCollection;

       

      import mx.core.IUIComponent;

       

      import mx.events.DragEvent;

       

      import mx.managers.DragManager;

       

      [

      Bindable]

       

      private var dragXML:XML =

       

      <Tree label="root">

      <L1 label="L1">

      <L11 label="L11"/>

      <L12 label="L12"/>

      </L1>

      <L2 label="L2">

      <L21 label="L21"/>

      <L22 label="L22"/>

      <L23 label="L23"/>

      </L2>

      </Tree>

       

      ;

       

      [

       

      Bindable]

       

      private var dragXMLListCollection:XMLListCollection = new XMLListCollection(dragXML.*);

       

      [

      Bindable]

       

      private var dropXML:XML =

       

      <Tree label="root">

      <L label="Start Here"/>

      </Tree>

       

      ;

       

      [

       

      Bindable]

       

      private var dropXMLListCollection:XMLListCollection = new XMLListCollection(dropXML.*);

       

       

      // ************* Drag Drop Events ********************

       

       

       

      private function dragEnter(evt:DragEvent):void

      {

       

       

      if (evt.dragSource.hasFormat("treeItems")) DragManager.acceptDragDrop(IUIComponent(evt.target));

      }

       

       

      private function dragOver(evt:DragEvent):void

      {

       

       

      // Calculate dropindex and set selected item

       

       

      var dropIndex:int = dropTree.calculateDropIndex(evt);

      dropTree.selectedIndex = dropIndex;

      // setting the selected item based on calculateDropIndex()

       

       

      var selNode:XML = dropTree.selectedItem as XML; // Getting XML for selected node in Tree

       

       

      var selNodeName:String = (selNode != null ? selNode.localName() : "");

       

      // Get dragged XML

       

       

      var dragNode:XML = XML(evt.dragSource.dataForFormat("treeItems")[0]);

       

      var dragNodeName:String = dragNode.localName();

       

       

      trace(evt, "\n", dropIndex, "\n", (selNode ? selNode.toXMLString() : "null"), "\n", dragNode.toXMLString());

       

       

      // you cannot drop a shorter name on a longer name

       

       

      if ((dragNodeName.length >= selNodeName.length) && (selNode != null)) DragManager.showFeedback(DragManager.COPY);

       

      else DragManager.showFeedback(DragManager.NONE);

      }

       

       

      private function dragDrop(evt:DragEvent):void

      {

       

       

      // get selected node in drop tree

       

       

      var selNode:XML = dropTree.selectedItem as XML; //selected in dragOver() event

       

       

      // Get dragged XML

       

       

      var dragNode:XML = XML(evt.dragSource.dataForFormat("treeItems")[0]);

       

       

      // Drop logic

       

       

      // Compare dragNode.localName().length to dropNode.localName().length

       

       

      // if drag longer; drop as child

       

       

      // if drag is equal; drop as sibling

       

       

      // Drag can never be shorter in this example.

       

       

      var isChild:Boolean = String(dragNode.localName()).length > String(selNode.localName()).length;

       

       

      if (isChild)

      {

      selNode.insertChildAfter(

      null, dragNode);

      }

       

      else

      {

      selNode.parent().insertChildAfter(selNode, dragNode);

      }

      }

       

       

      ]]>

       

       

      </mx:Script>

       

       

       

      <mx:Tree id="dragTree" width="30%" showRoot="true" height="100%" labelField="@label"

      dataProvider="

      {dragXMLListCollection}"

      dragEnabled="

      true" dragMoveEnabled="false" dropEnabled="false" />

       

       

       

      <mx:Tree id="dropTree" width="30%" showRoot="true" height="100%" labelField="@label"

      dataProvider="

      {dropXMLListCollection}"

      dragEnter="dragEnter(event);" dragDrop="dragDrop(event);" dragOver="dragOver(event);"

      />

       

       

      </mx:Application>

       

       

       

       

        • 1. Re: Manual Drag and Drop from Tree to Tree with XML dataProvider
          jjjones50 Level 1

          I just found out that by setting the dataProvider for each tree to the XML variable instead of the XMLListCollection variable, problems #1 and #2 went away!

           

          But the documentation says to use an XMLListCollection if you will be dynamically changing the tree contents.

           

          And, I just found out that #1 returns if I specify showRoot="false". But with it set to "true" that problem goes away. Is there some sort of minimum XML required to make drag-n-drop work on these Tree controls?

           

          Hmmmm. It appears that (for #3) the calculateDropIndex() will always return the last matching XML node - by name - in the tree.