Fx{r} is trying to start the Fx{r} Community! Please join our group on Adobe Groups following this link: http://groups.adobe.com/groups/ab29539ab9.
Fx{r} is now on Twitter too. Follow us @ twitter.com/fx_r!
«
»

ActionScript, Components, Events, How to, MXML

How To Change The Default Behavior of DisclosureIcon of a Tree Component

Andrei Ionescu | 21.04.09 | Comment?

Google Buzz

This weekend I’ve been programming a new tree component that is intended to be used as a hierarchical menu. One thing that I have to do was to change the default behavior of the disclosureIcon. If you wonder what is the disclosureIcon, it is the grey arrow that shows if there is a node or a leaf and if that node is opened or not. That is the disclosureIcon and it has its own behavior different than the item itself.

I needed to implement the same behavior of a regular item but to do this I had to stop the default behavior. So I created a new item renderer based the default TreeItemRenderer in which we will try to modify this behavior.

First I started to study the TreeItemRenderer, to see what it implements what can be changed or overridden, etc. disclosureItem is a protected object so it can be used in our new tree item renderer that extends TreeItemRenderer.

So a logical approach was to remove the event listener of the disclosureIcon. Well that is not possible because the function bind to the event is private so we cannot do:

disclosureIcon.removeEventListener(MouseEvent.MOUSE_DOWN, disclosureMouseDownHandler);

The method disclosureMouseDownHandler is private so cannot be accessed.

Digging further into the code I discovered that the disclosureMouseDownHandler method just sets some variables and then dispatches a TreeEvent.ITEM_OPENING type of event.

With this in my mind and because I didn’t need the TreeEvent.ITEM_OPENING event I just removed the event in the init method of my tree component like this:

15
removeEventListener(TreeEvent.ITEM_OPENING, mx_internal::expandItemHandler);

Please notice that the expandItemHandler is using mx_internal name space so we had to use that name space to be able to access the method.

Now having this removed I started to implement my needed event behavior. For this article I’ll implement another behavior to be more easily understood – just an alert pop-up containing the label of the clicked node.

You need to understand that by doing this there is no other default alternative to open the nodes. You may wonder you did I replaced the default behavior of the disclosureIcon? Well I needed to have the following behavior of my custom tree:

  1. click on a closed item will select it and open it if it has children
  2. click on a opened item will select it and close it if it has children
  3. click on a closed item having already an opened node will close the previous node, then select the one clicked on and will open it

This should happen either if we click on the text or on the disclosureIcon. But this is not what we will do here only a short explanation regarding why I removed the default disclosureIcon’s behavior.

Bellow is our example. Click on an arrow to see the result – a simple alert with the name (label) of the clicked node.

In the following example we used four files (source files are bellow and also downloadable at the end of the article):

  1. main application – DisclosureIconBehaviorChangeApp.mxml
  2. our tree component – CustomTree.mxml
  3. our custom tree item renderer – CustomTreeItemRenderer.as
  4. our custom tree event – CustomTreeEvent.as

1) DisclosureIconBehaviorChangeApp

 

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" xmlns:flexer="com.flexer.*"
    creationComplete="start()"
    >
    <flexer:CustomTree id="myTree"
        x="10" y="10"
        width="200" height="200"
        labelField="@label"
        />
    <mx:Script>
        <![CDATA[
 
            // item tree structure
            private var _menuTreeContent:XML = <mlb>
    <league label="American League">
        <division label="East">
            <team label="Boston" />
            <team label="New York" />
            <team label="Toronto" />
            <team label="Baltimore" />
            <team label="Tampa Bay" />
        </division>
        <division label="Central">
            <team label="Cleveland" />
            <team label="Detroit" />
            <team label="Minnesota" />
            <team label="Chicago" />
            <team label="Kansas City" />
        </division>
        <division label="West">
            <team label="Los Angeles" />
            <team label="Seattle" />
            <team label="Oakland" />
            <team label="Texas" />
        </division>
    </league>
</mlb>;
 
            // initialization
            private function start():void
            {
                // setting the data provider
                myTree.dataProvider = _menuTreeContent.league;
                // expanding the some nodes
                callLater(
                    function (node:XML):void {
                        myTree.expandItem(node.league[0], true);
                        myTree.expandItem(node.league[0].division[1], true);
                    },
                    [_menuTreeContent]
                );
            }
        ]]>
    </mx:Script>
</mx:Application>

2) CustomTree

 

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
28
29
30
31
<?xml version="1.0" encoding="utf-8"?>
<mx:Tree xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="init()"
    itemRenderer="com.flexer.CustomTreeItemRenderer"
    >
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.TreeEvent;
 
            // initialization
            private function init():void
            {
                // removing the default event on opeining nodes
                removeEventListener(TreeEvent.ITEM_OPENING, 
                    mx_internal::expandItemHandler);
                // listening for our custom event
                addEventListener(CustomTreeEvent.ITEM_SELECTED, 
                    handleItemSelected);
            }
 
            // handler for our new custom tree event 
            private function handleItemSelected(e:CustomTreeEvent):void
            {
                Alert.show(e.data.@label.toString());
            }
 
 
        ]]>
    </mx:Script>
</mx:Tree>

3) CustomTreeItemRenderer

 

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
28
29
30
31
32
33
package com.flexer 
{
 
    import flash.events.MouseEvent;
 
    import mx.collections.*;
    import mx.controls.Tree;
    import mx.controls.treeClasses.*;
 
    public class CustomTreeItemRenderer extends TreeItemRenderer
    {
 
        public function CustomTreeItemRenderer() 
        {
            super();
        }
 
        override protected function commitProperties():void
        {
            super.commitProperties();
            disclosureIcon.addEventListener(MouseEvent.MOUSE_DOWN, 
                arrowMouseDownHandler);
        }
 
        private function arrowMouseDownHandler(e:MouseEvent):void
        {
            var stEvent:CustomTreeEvent = new CustomTreeEvent(
                CustomTreeEvent.ITEM_SELECTED, this.data);
            (listData.owner as Tree).dispatchEvent(stEvent);
        }
 
    }
}

4) CustomTreeEvent

 

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
28
29
30
31
package com.flexer
{
    import flash.events.Event;
 
    public class CustomTreeEvent extends Event
    {
 
        public static const ITEM_SELECTED:String = "itemSelected";
 
        private var _obj:*;
 
        public function CustomTreeEvent(type:String, item:*, 
            bubbles:Boolean = false, cancelable:Boolean = false)
        {
            super(type, bubbles, cancelable);
 
            _obj = item;
        }
 
        override public function clone():Event
        {
            return new CustomTreeEvent(type, _obj, bubbles, cancelable);
        }
 
        public function get data():*
        {
            return _obj;
        }
 
    }
}
Share and Enjoy:
  • Twitter
  • Google Buzz
  • LinkedIn
  • Google Bookmarks
  • del.icio.us
  • Digg
  • Sphinn
  • blogmarks
  • Reddit
  • StumbleUpon
  • Facebook
  • DZone
  • FriendFeed
  • Yahoo! Buzz
  • Yahoo! Bookmarks
  • Slashdot
  • MySpace
  • Add to favorites
DisclosureIconBehaviorChangeApp
disclosureiconbehaviorchange_sources




Tags: , ,

This post was written by Andrei Ionescu

Views: 2355

related

have your say

Add your comment below, or trackback from your own site. Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

:

:


«
»