This blog post is related to My LFPUG Presentation about Mate blog post.

This is the fifth of a series of gradually more complex examples on how to use Mate. If you haven’t done it yet you should have a look first at our previous examples: #1, #2, #3 and #4.

In the previous example, we added the capability to add/remove counters to the Tile component dynamically. Now let’s imagine that each counter is now embedding two subcounters, each one being capable of interacting with the other, but without affecting the subcounters in other counters.

The demo should probably be clearer (source is available by right-clicking on the demo after launching it):

Mate example

#5 LocalEventMap (click to Launch)

When you click on the [+]/[-] buttons of one a the subcounters, it increases/decreases its own amount, the globalAmount (at every level of the application) and its subtotal along with the subtotal of its counterpart (the other subcounter of its parent counter), without affecting the subtotal values of the other subcounters.


Demo #5: src/views/Counter.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
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
          width="264"
          height="380"
          title="{counterTitle}"
          layout="absolute"
          xmlns:views="views.*"
          xmlns:maps="maps.*">

    <mx:Script>
        <![CDATA[
            import Events.CounterEvent;

            [Bindable]
            public var globalAmount : int = 0;

            [Bindable]
            private var subTotal : int = 0;

            [Bindable]
            private var amount : int = 0;

            private var _counterTitle : String = "Counter Title";

            [Bindable]
            public function get counterTitle() : String
            {
                return _counterTitle;
            }

            public function set counterTitle( v : String ) : void
            {
                _counterTitle = v;
            }

            public function increaseSubTotal( event : CounterEvent ) : void
            {
                ++subTotal;
            }

            public function decreaseSubTotal( event : CounterEvent ) : void
            {
                --subTotal;
            }
        ]]>
    </mx:Script>

    <maps:SubEventMap dispatcher="{this}"/>

    <mx:Label x="27"
              y="10"
              text="Global Amount:"/>
    <mx:Label x="121"
              y="10"
              text="{globalAmount}"/>
    <views:SubCounter y="64"
                      horizontalCenter="0"
                      borderStyle="inset">
    </views:SubCounter>
    <views:SubCounter y="208"
                      horizontalCenter="0"
                      borderStyle="inset">
    </views:SubCounter>
    <mx:Label x="63"
              y="35"
              text="Subtotal:"/>
    <mx:Label x="124"
              y="35"
              text="{subTotal}"/>

</mx:Panel>

Plenty of novelties in Counter.mxml: 2 new SubCounter components, a new subTotal private variable incremented/decremented by 2 new public methods: increaseSubTotal and decreaseSubTotal.

A very important new thing as well: the appearing of a new SubEventMap. We’ll come back to that one a bit later. Let’s have a look at SubCounter.mxml first:


Demo #5: src/views/SubCounter.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
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
57
58
59
60
61
62
63
64
65
66
67
68
69
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
           width="220"
           height="120">

    <mx:Script>
        <![CDATA[
            import Events.CounterEvent;

            [Bindable]
            private var subTotal : int = 0;

            [Bindable]
            private var amount : int = 0;
           
            public function increaseSubTotal ( event : CounterEvent ) : void
            {
                ++subTotal;
            }
           
            public function decreaseSubTotal ( event : CounterEvent ) : void
            {
                --subTotal;
            }

            protected function buttonIncrease_clickHandler( event : MouseEvent ) : void
            {
                ++amount;
                dispatchEvent( new CounterEvent( CounterEvent.INCREASE_GLOBAL ));
                dispatchEvent( new CounterEvent( CounterEvent.INCREASE_SUB_TOTAL ));
            }

            protected function buttonDecrease_clickHandler( event : MouseEvent ) : void
            {
                --amount;
                dispatchEvent( new CounterEvent( CounterEvent.DECREASE_GLOBAL ));
                dispatchEvent( new CounterEvent( CounterEvent.DECREASE_SUB_TOTAL ));
            }

        ]]>
    </mx:Script>

    <mx:Label x="50"
              y="15"
              text="Subtotal:"/>
    <mx:Label x="111"
              y="15"
              text="{subTotal}"/>

    <mx:Label x="57"
              y="50"
              text="Amount:"/>
    <mx:Label x="111"
              y="50"
              text="{amount}"/>

    <mx:Button id="buttonIncrease"
               x="58"
               y="77"
               label="+"
               click="buttonIncrease_clickHandler(event)"/>

    <mx:Button id="buttonDecrease"
               x="130"
               y="77"
               label="-"
               click="buttonDecrease_clickHandler(event)"/>

</mx:Canvas>

As you can see, it looks a lot like Counter used to in our previous examples. But there are differences: almost any references to globalAmount were replaced by references to SubTotal. It also refers to 2 new event types:


Demo #5: src/Events/CounterEvent.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Events
{
    import flash.events.Event;
   
    public class CounterEvent extends Event
    {
        public static const INCREASE_GLOBAL : String = "increaseGlobal";
        public static const DECREASE_GLOBAL : String = "decreaseGlobal";
        public static const INCREASE_SUB_TOTAL : String = "increaseSubTotal";
        public static const DECREASE_SUB_TOTAL : String = "decreaseSubTotal";
       
        public function CounterEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
        }
    }
}

CounterEvent.INCREASE_SUB_TOTAL and CounterEvent.DECREASE_SUB_TOTAL were added to the previous ones. Now let’s see the EventMaps. First the MainEventMap.mxml:


Demo #5: src/maps/MainEventMap.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
28
29
30
31
<?xml version="1.0" encoding="utf-8"?>
<mate:EventMap xmlns:mx="http://www.adobe.com/2006/mxml"
               xmlns:mate="http://mate.asfusion.com/">
    <mx:Script>
        <![CDATA[
            import views.Counter;
            import views.MainView;
            import managers.CounterManager;
            import Events.CounterEvent;
        ]]>
    </mx:Script>
   
    <mate:Debugger level="{Debugger.ALL}" />

    <mate:EventHandlers type="{CounterEvent.INCREASE_GLOBAL}">
        <mate:MethodInvoker generator="{CounterManager}"
                            method="increaseGlobal"/>
    </mate:EventHandlers>

    <mate:EventHandlers type="{CounterEvent.DECREASE_GLOBAL}">
        <mate:MethodInvoker generator="{CounterManager}"
                            method="decreaseGlobal"/>
    </mate:EventHandlers>

    <mate:Injectors targets="{[Counter, MainView]}" start="trace('MAIN INJECTORS')">
        <mate:PropertyInjector source="{CounterManager}"
                               sourceKey="globalAmount"
                               targetKey="globalAmount"/>
    </mate:Injectors>

</mate:EventMap>

Well, except for the Debugger tag and the trace inside the start property (an eventListener actually) it hasn’t changed at all! So, what’s in the new SubEventMap.mxml?


Demo #5: src/maps/SubEventMap.mxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<mate:LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"
                    xmlns:mate="http://mate.asfusion.com/">
    <mx:Script>
        <![CDATA[
            import views.Counter;
            import Events.CounterEvent;
            import views.SubCounter;
        ]]>
    </mx:Script>
   
    <mate:Debugger level="{Debugger.ALL}" />

    <mate:Injectors targets="{[Counter, SubCounter]}">
        <mate:ListenerInjector eventType="{CounterEvent.INCREASE_SUB_TOTAL}"
                               method="increaseSubTotal"/>
        <mate:ListenerInjector eventType="{CounterEvent.DECREASE_SUB_TOTAL}"
                               method="decreaseSubTotal"/>
    </mate:Injectors>

</mate:LocalEventMap>

Here again, it’s pretty simple and still all the power lies here. The only true novelty here is the fact that the component now extends LocalEventMap (instead of EventMap). The main difference between LocalEventMap and the regular EventMap is that the LocalEventMap listens only for events coming from the view it was declared in and its children. Nothing from the outside (unless explicitly told so). Exactly what we were looking for!

One last important bit here: when you instantiate your SubEventMap in Counter.mxml, you must declare a dispatcher:


Demo #5: src/views/Counter.mxml (detail)

48
    <maps:SubEventMap dispatcher="{this}"/>

If you don’t declare {this} as a dispatcher it will simple won’t work at all and won’t catch any event.

That’s it for now. Next to come: #6 Reset Countdown (part 1)

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...