views:

766

answers:

2

I'm doing a drag and drop operation on a tree using some help from Adobe's quick Starts: http://www.adobe.com/devnet/flex/quickstart/working_with_tree/

The code suggested is roughly this:

var dropTarget:Tree = Tree(evt.currentTarget);
var i:int = dropTarget.calculateDropIndex(evt);
myTree.selectedIndex = i;
var node:XML = myTree.selectedItem as XML;
var drugXML:XML = XML(Tree(evt.dragInitiator).selectedItem);
if(node.localName() != drugXML.localName()){
    DragManager.showFeedback(DragManager.NONE);
    return;
}else{
    DragManager.showFeedback(DragManager.COPY);
}

This is all well and good, but I don't like the way it is selecting(highlighting) each item in the tree I'm dropping on, it's less clear where the item is going to drop. I want to implement this without the selection but there doesn't seem to be a way to get the XML of the node using just the index. I would like something like this:

var dropTarget:Tree = Tree(evt.currentTarget);
var i:int = dropTarget.calculateDropIndex(evt);

var node:XML = myTree.itemAt(i) as XML; 
//AFAIK itemAt(i) or anything like it does not exist

var drugXML:XML = XML(Tree(evt.dragInitiator).selectedItem);
if(node.localName() != drugXML.localName()){
    DragManager.showFeedback(DragManager.NONE);
    return;
}else{
    DragManager.showFeedback(DragManager.COPY);
}

So does anyone know what function is, or what I can do to extend the tree to have a function, like "itemAt(i)"

Thanks ~Mike

EDIT: I forgot to post that my current workaround is setting the selectedIndex = -1 after I get my node:XML. I'm afraid that if something bogs on the processor the user may see it select then deselect.

A: 

If your dataProvider is explicitly or implicitly a collection (see the linked docs for conversion rules), you should be able to use getItemAt to resolve the index.

It appears that an XML provider will be converted implicitly:

var tree:Tree = ...;
var data:XML = ...;
tree.dataProvider = data; // could just as well be from MXML

var provider:ICollectionView = tree.collection; // tree converted it for us
trace(provider.getItemAt(index));

If you have something other than the convertible types (XML, Array, etc.), you might consider wrapping your dataProvider in an XMLListCollection or what have you to gain access to that method.


The above is aiming in the right direction but missing.

Turns out you don't want the dataProvider since Tree overrides that; you want the collection property (protected). So you could override Tree and provide an indexToItem method to go with the thisToThat methods already present in Tree.

Michael Brewer-Davis
My dataProvider is an XML type. I had problems (probably my own lack of skill) making it work with the rest of my app when I made it an XMLListCollection.
invertedSpear
Added some notes about how Flex will convert your XML to a collection.
Michael Brewer-Davis
I tried what you suggested, it tells me getItemAt() is not a method of ICollectionView. So I just did "trace(tree.dataProvider.getItemAt(i))" since the doc says it was automatically converted to a list collection this should be no problem. When I run the code it crashes saying the index is out of bounds. Why would that be? And BTW I got some good answers back about the threads, so at least I know I'm good with what you said in the comment to the question.
invertedSpear
I worked on it some more, threw in a break point to analyze the tree.dataprovider, it's an XMLListCollection but with only the 0 index which contains the XML of my tree. So it makes sense the getItemAt is failing.
invertedSpear
Yeah, I think this avenue was a false lead. I'm going to try again. =)
Michael Brewer-Davis
+1  A: 

Much simpler, though there may be gotchas:

var index:int = ...
var renderer:IListItemRenderer = tree.indexToItemRenderer(index);
var item:Object = renderer.data;

This won't work if the index is offscreen (since there might not be an active itemRenderer); shouldn't be an issue for drag and drop.

Michael Brewer-Davis
Thanks for trying so hard, there's no itemRendererToItem method for a tree, I can do itemRendererToIndex, but then we're right back where we started :-)
invertedSpear
Sorry--the itemRenderer already owns the data, doesn't need an aToB function.
Michael Brewer-Davis
YAY! latest edit works! Thanks Michael, We should be able to trade rep in to buy people like you a beer.
invertedSpear
Oh In case anyone needs to try this themselves, you will want to wrap Michael's Solution with "if(tree.indexToItemRenderer(index))", for some reason if you drag past the bottom of a list that index value goes way up so you get a null ref error when you try to assign a value to it.
invertedSpear