Categories
Archives
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- April 2007
- March 2007
- February 2007
- January 2007
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
Patrick & Avi's Java Tips #2: Graceful JVM Shutdown in Eclipse | Home | Updated : SVN Notifier 1.0.1
Filed under Quick Tips on April 21, 2008 by Javier JulioAdding A ContextMenu To A Flex Tree
I've been working on an AIR application for managing SQLite databases where I've been using the Flex Tree component to list out all databases. I've been having a hard time finding good resources on working with a ContextMenu (right click menu) on a Tree component.
I tried my luck on adding a ContextMenu to the Tree component itself and managing it there. But that idea went sour because I couldn't find a way to get the current Tree item selected since right-clicking doesn't actually select it. After checking out what others have done, this wasn't getting any easier because I wasn't convinced by the solutions provided. They seemed more like hacks when I knew this should be pretty simple.
It never occurred to me to try adding the ContextMenu on a Tree ItemRenderer, so when I originally thought of it, I figured eureka, that's it! Ultimately, though, I didn't think it through that well since adding a renderer would also remove the folding arrows and folder/leaf icons. Ouch! Although now I know what was needed, I realized that adding a TreeItemRenderer is not the same as another List-based renderer such as one for a DataGrid or List component.
After following the solution on the Flex Cookbook, I dropped in that demo item renderer and was able to attach a ContextMenu object to it in the renderer constructor. So something like this:
public function DatabaseListRenderer()
{
super();
var contextMenu:ContextMenu = new ContextMenu();
var menuItems:Array = [];
var edit:ContextMenuItem = new ContextMenuItem("Edit Name");
edit.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, databases_menuItemSelectHandler);
menuItems.push(edit);
contextMenu.customItems = menuItems;
this.contextMenu = contextMenu;
}
private function databases_menuItemSelectHandler(event:ContextMenuEvent):void {
trace("menu item selected: " + data);
}
Now when I right-click on a particular item and select a menu option, the event handler fires and I see my trace message. Notice I dump out the data to see what's there (debugger is a better place for this) and I see the data for that specific Tree item as if it were selected. Problem solved!
Trackback Pings (TrackBack URL for this entry)
http://www.arc90.com/cgi-bin/mt4/mt-tb.cgi/136.
Comments
JT,
I apologize but I don't have a sample with just this functionality. All I did was take the sample from the Flex Cookbook article and customized it with a simple a test (which you can see in the code view in this blog post) and that was it.
There really is nothing else to it. Just remember the trick to adding a context menu to the Tree component is to add it on the item renderer.
Posted on May 5, 2008 2:12 PM by Javier Julio
JT,
Sorry about that! It would have helped if the blog post had links! I'll have to chat with the person here who posts the Quick Tip blog articles. :)
If you follow the links now mentioned in the article above things will be much clearer. The subclass in the example above is TreeItemRenderer. I just followed the same sample on the Flex Cookbook article and everything worked great. Let me know if you have any trouble.
Posted on May 5, 2008 7:17 PM by Javier Julio
Ok I got it figured out. The superclass of the above code is TreeItemRenderer and then you set the itemRenderer property of your Tree instance to your new TreeItemRenderer extended class.
Posted on May 5, 2008 7:19 PM by JT
Have you tried using an Event Listener to listen for right clicks in the TreeItemRenderer extended class?
For example putting "this.addEventListener(MouseEvent.RIGHT_CLICK, rightClickHandler);" in the DatabaseListRenderer constructor.
It seems like the when you attach the ContextMenu, the ContextMenu consumes the right click event and the rightClickHandler method is never called.
I'm trying to have it setup so when you right click on the a tree item there will be a ContextMenu and that tree item will be selected. So far I can not get both to happen at the same time.
Posted on May 6, 2008 10:18 AM by JT
JT,
I've had a very similar issue with a component where I was trying to create a line numbered TextArea. I needed a set of utility methods that would get me the line the user was on based on an x and y coordinate. Luckily the flash component TextField has those methods. You'll need to use the getObjectsUnderPoint method of the TreeItemRenderer.
Scratch that.. I did some more digging through events and I think I got it. At the end of the constructor for the TreeItemRenderer I added an event listener for MouseEvent.CONTEXT_MENU. That will fire once the context menu is displayed.
Since you are in the item renderer you have access to the data property so you already know the item that is to be selected. If you set the selectedItem property of the Tree it will appear selected. Although if a previous selection was made it too is selected. Not sure how to get around that but this should give you plenty to fool around with!
Again add this to the ItemRenderer constructor (I'm following my example above so change accordingly for you):
addEventListener(MouseEvent.CONTEXT_MENU, database_contextMenuHandler);
And then define the event handler function:
private function database_contextMenuHandler(event:MouseEvent):void {
var xmlData:XML = data as XML;
trace( xmlData.toXMLString() );
var tree:Tree = this.owner as Tree;
tree.selectedItem = xmlData;
trace("new selected item!\n" + tree.selectedItem);
}
Note that I used XML as my dataProvider for the Tree but you would do something very similar if it were an ArrayCollection. Hope this helps in you getting further! Let me know how you make out.
Posted on May 6, 2008 1:31 PM by Javier Julio
What I ended up doing was using "addEventListener(MouseRight.RIGHT_CLICK, rightClickHandler);" in the constructor and not attaching the ContextMenu to the item renderer in the constructor.
Then in the "rightClickHandler" method I set the selected tree node and show the ContextMenu.
private function rightClickHandler(event:MouseEvent):void {
var x:int = event.stageX;
var y:int = event.stageY;
Tree (parent.parent).selectedItem = data;
treeContextMenu.display(stage, x, y); // I declared this ContextMenu in the constructor
}
I found out that if you click on the actual icon of the tree item after setting the selected node the x and y values of the "event.stageX, event.stageY" get screwed up. It is weird if you click on the tree item text they are fine. So I save the x and y values then set the new selected tree node. Then I display the ContextMenu.
So far it is working as I want.
I can right click on a tree node and it will select it and the ContextMenu will display.
Thanks for your help!
Posted on May 7, 2008 8:36 AM by JT
Patrick & Avi's Java Tips #2: Graceful JVM Shutdown in Eclipse | Main | Updated : SVN Notifier 1.0.1

I'm trying to do the same with with a ContextMenu when right clicking on a Tree control in Flex. Can you post a sample showing your complete tree code? Thank you.
Posted on May 2, 2008 4:30 PM by JT