How to add a line separator in a Flex Tree component
// May 8th, 2009 // Flex framework
Ever wanted to use a line separator in a Tree? It’s all a matter of customizing the Flex Tree and TreeItemRenderer and you can obtain what is shown in the example below.
Here are the steps to implement it:
- define a property in your model to indicate that an item is a separator;
- implement a customized TreeItemRenderer which stores a flag to keep track about the fact the node is a separator. This flag is used in some overridden methods to handle icon display and line drawing;
- implement a customized Tree control which overrides some methods to avoid separator to be selected.
Let’s start by defining a property which indicates that an item in a tree is a separator. I keep things simple here and use a code snippet inspired by the Adobe Flex3 Component Explorer in MyTree.mxml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="my.controls.*" layout="vertical" backgroundColor="#777777" viewSourceURL="srcview/index.html"> <mx:XMLList id="treeData"> <node label="Mail Box"> <node label="Inbox"> <node label="Marketing"/> <node label="Product Management"/> <node label="Personal"/> </node> <node label="Outbox"> <node label="Professional"/> <node label="Personal"/> </node> <node separator="true" /> <node label="Spam"/> <node label="Sent"/> </node> </mx:XMLList> <my:MyTree width="100%" height="100%" dataProvider="{treeData}" labelField="@label" /> </mx:Application> |
You can notice that to indicate a node is a separator I simply use a separator XML attribute whose value is set to true.
The second step consists of implementing a MyTreeItemRenderer class which extends TreeItemRenderer and declares a isSeparator property used to store information about whether the current node is a separator.
I then override the set data method in order to store isSeparator value as shown in the code below taken from MyTreeItemRenderer.as:
102 103 104 105 106 107 108 109 | override public function set data(value:Object):void { super.data = value; // Check whether current node is a separator isSeparator = (value != null && value.@separator != null && "true" == String(value.@separator).toLowerCase()); } |
I also need to avoid icon display in separator nodes, so I have to set the visibility of the icon to false. I can’t do that in the set data method because in component creation life cycle visibility property is not yet available in that method. So I override the commitProperties method in the following way (code from MyTreeItemRenderer.as):
115 116 117 118 119 120 121 122 | override protected function commitProperties():void { super.commitProperties(); if (isSeparator) { icon.visible = false; } } |
To finish TreeItemRenderer customization I have to override the updateDisplayList method in order to draw a line in case the node is a separator. To do that I don’t reinvent the wheel and simply copy the algorithm from the HRule component. You can substitute you own drawing algorithm if you don’t like that. Here is the code of updateDisplayList method taken from MyTreeItemRenderer.as:
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number):void { // Get graphics var g:Graphics = graphics; g.clear(); // Call super method super.updateDisplayList(unscaledWidth, unscaledHeight); // Draw the line if current node is separator if (isSeparator) { // // Code taken from the HRule drawing algorithm. // ... |
The TreeItemRenderer customization is almost done. At this point the separator is displayable in the tree but I still need to prevent mouse hovering and selection. To to that I implement a MyTree class which extends Tree. The first step consists of associating the MyTree ItemRenderer to the itemRenderer property of the MyTree class. I do that in class constructor of MyTree.as:
25 26 27 28 29 30 | public function MyTree() { super(); itemRenderer = new ClassFactory(MyTreeItemRenderer); } |
Then I have to override both mouseOverHandler and mouseDownHandler methods in order to avoid node to be highlighted and selected. Here is the code from MyTree.as:
41 42 43 44 45 46 47 48 | override protected function mouseOverHandler(event:MouseEvent):void { var item:IListItemRenderer = mouseEventToItemRenderer(event); if (item != null && !MyTreeItemRenderer(item).isSeparator) { super.mouseOverHandler(event); } } |
53 54 55 56 57 58 59 60 | override protected function mouseDownHandler(event:MouseEvent):void { var item:IListItemRenderer = mouseEventToItemRenderer(event); if (item != null && !MyTreeItemRenderer(item).isSeparator) { super.mouseDownHandler(event); } } |
That’s it! You can download the full source code here or by right clicking on the example you find on the top of the page. I hope this helps you. Enjoy Flex coding!



