프로그램/flex

Flex 자유롭게

mulderu 2009. 10. 24. 00:45

Posts Tagged ‘TreeItemRenderer’

How to add a line separator in a Flex Tree component

// May 8th, 2009 // No Comments » // 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!