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

This is the seventh 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, #4, #5, and #6.

In the previous example, we added a reset countdown which sets all the counters to 0 when the countdown is off. But it’s a bit of a pain this unstoppable countdown. It would be cool to add a start/stop button, wouldn’t it?

OK, let’s do it (source is available by right-clicking on the demo after launching it):

Mate example

#7 Reset Countdown (pt 2) (click to Launch)

So we’ve first added this start/stop button (yeah, let’s have a toggle button this time):


Demo #7: src/views/MainView.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
          width="860"
          height="600"
          title="{mainTitle}"
          layout="absolute"
          xmlns:views="views.*">

    <mx:Script>
        <![CDATA[
            import Events.CountdownEvent;
            import Events.CounterEvent;
            [Bindable]
            public var globalAmount : int = 0;

            [Bindable]
            public var isCountdownRunning : Boolean;

            [Bindable]
            private var numCounters : int = 0;

            [Bindable]
            private var mainTitle : String = "MainView";

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

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

            protected function addCounterButton_clickHandler( event : MouseEvent ) : void
            {
                var counter : Counter = new Counter();
                counter.counterTitle = "Counter " + ++numCounters;
                mainTile.addChild( counter );
            }

            protected function deleteCounterButton_clickHandler( event : MouseEvent ) : void
            {
                mainTile.removeChildAt( mainTile.numChildren - 1 );
                --numCounters;
            }

            public function updateTitle( event : CountdownEvent ) : void
            {
                mainTitle = "MainView (" + event.countdown + ")";
            }


            protected function countdownButton_clickHandler( event : MouseEvent ) : void
            {
                if ( isCountdownRunning )
                {
                    countdownButton.label = "START COUNTDOWN";
                    dispatchEvent( new CountdownEvent( CountdownEvent.STOP_COUNTDOWN ));
                }
                else
                {
                    countdownButton.label = "STOP COUNTDOWN";
                    dispatchEvent( new CountdownEvent( CountdownEvent.START_COUNTDOWN ));
                }
            }
        ]]>
    </mx:Script>

    <mx:Label text="Global Amount:"
              x="28"
              y="16"/>
    <mx:Label text="{globalAmount}"
              x="124"
              y="16"/>


    <mx:Tile id="mainTile"
             left="10"
             right="10"
             top="82"
             bottom="10">
    </mx:Tile>

    <mx:Button id="buttonIncrease"
               x="68"
               y="34"
               label="+"
               click="buttonIncrease_clickHandler(event)"/>
    <mx:Button id="buttonDecrease"
               x="140"
               y="34"
               label="-"
               click="buttonDecrease_clickHandler(event)"/>

    <mx:Button id="addCounterButton"
               x="614"
               y="31"
               label="Add Counter"
               click="addCounterButton_clickHandler(event)"/>
    <mx:Button id="countdownButton"
               x="366"
               y="31"
               label="STOP COUNTDOWN"
               click="countdownButton_clickHandler(event)"/>

    <mx:Button id="deleteCounterButton"
               x="716"
               y="31"
               label="Delete Counter"
               enabled="{numCounters > 0}"
               click="deleteCounterButton_clickHandler(event)"/>

</mx:Panel>

Depending on isCountdownRunning (note that it is bindable…), the button’s label will change, and a click on the button will dispatch the new CountdownEvent.START_COUNTDOWN or CountdownEvent.STOP_COUNTDOWN.


Demo #7: src/Events/CountdownEvent.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Events
{
    import flash.events.Event;
   
    public class CountdownEvent extends Event
    {
        public static const COUNTDOWN : String = "countDown";
        public static const START_COUNTDOWN : String = "startCountDown";
        public static const STOP_COUNTDOWN : String = "stopCountDown";
       
        public var countdown : int;
       
        public function CountdownEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
        }
    }
}

We can see those two new types here. What about CountdownManager?


Demo #7: src/managers/CountdownManager.as

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
package managers
{
    import Events.CountdownEvent;
    import Events.CounterEvent;
   
    import com.asfusion.mate.events.Dispatcher;
   
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    public class CountdownManager extends EventDispatcher
    {
        private var timer : Timer;

        private var duration : int = 10;
        private var countdown : int;

        private var dispatcher : Dispatcher = new Dispatcher();

        [Bindable]
        public var isCountdownRunning : Boolean = true;

        public function CountdownManager( target : IEventDispatcher = null )
        {
            super( target );
            init();
        }

        private function init() : void
        {
            countdown = duration;
            timer = new Timer( 1000, 1 );
            timer.addEventListener( TimerEvent.TIMER_COMPLETE, onTimerComplete );
            timer.start();
        }

        private function onTimerComplete( event : TimerEvent ) : void
        {
            timer.reset();
            timer.start();

            --countdown;
            var counterEvent : CountdownEvent = new CountdownEvent( CountdownEvent.COUNTDOWN );
            counterEvent.countdown = this.countdown;
            dispatcher.dispatchEvent( counterEvent );

            if ( countdown < 1 )
            {
                dispatcher.dispatchEvent( new CounterEvent( CounterEvent.RESET ));
                countdown = duration;
            }

        }

        public function startCountdown() : void
        {
            timer.start();
            isCountdownRunning = true;
        }

        public function stopCountdown() : void
        {
            timer.stop();
            isCountdownRunning = false;
        }
    }
}

The same bindable isCountdownRunning here. And two dead simple methods: startCountdown() and stopCountdown().

Last, but not least: the now famous MainEventMap:


Demo #7: 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
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
<?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 Events.CountdownEvent;
            import views.SubCounter;
            import managers.CountdownManager;
            import mx.events.FlexEvent;
            import views.Counter;
            import views.MainView;
            import managers.CounterManager;
            import Events.CounterEvent;
        ]]>
    </mx:Script>

    <mate:Debugger level="{Debugger.ALL}"/>

    <mate:EventHandlers type="{FlexEvent.APPLICATION_COMPLETE}">
        <mate:ObjectBuilder generator="{CountdownManager}"/>
    </mate:EventHandlers>

    <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:EventHandlers type="{CounterEvent.RESET}">
        <mate:MethodInvoker generator="{CounterManager}"
                            method="reset"/>
    </mate:EventHandlers>

    <mate:EventHandlers type="{CountdownEvent.START_COUNTDOWN}">
        <mate:MethodInvoker generator="{CountdownManager}"
                            method="startCountdown"/>
    </mate:EventHandlers>

    <mate:EventHandlers type="{CountdownEvent.STOP_COUNTDOWN}">
        <mate:MethodInvoker generator="{CountdownManager}"
                            method="stopCountdown"/>
    </mate:EventHandlers>

    <mate:Injectors targets="{[Counter, MainView]}">
        <mate:PropertyInjector source="{CounterManager}"
                               sourceKey="globalAmount"
                               targetKey="globalAmount"/>
    </mate:Injectors>

    <mate:Injectors targets="{[Counter, SubCounter]}">
        <mate:ListenerInjector eventType="{CounterEvent.RESET}"
                               method="reset"/>
    </mate:Injectors>

    <mate:Injectors target="{MainView}"
                    debug="true">
        <mate:PropertyInjector source="{CountdownManager}"
                               sourceKey="isCountdownRunning"
                               targetKey="isCountdownRunning"/>
        <mate:ListenerInjector eventType="{CountdownEvent.COUNTDOWN}"
                               method="updateTitle"/>
    </mate:Injectors>

</mate:EventMap>

EventHandlers and ListenerInjectors catch events, then invoke methods, or inject properties, blah, blah, blah.

I bet you start to get it by now ;)

Next: #8 Modules Example (pt 1)

Related posts:

  1. Mate examples: #6 Reset Countdown (pt 1) This blog post is related to My LFPUG Presentation...
  2. Mate examples: #8 Modules Example (pt 1) This is the eigth of a series of gradually more...
  3. Mate examples: #9 Modules Example (pt 2) This is the ninth of a series of gradually more...
  4. Mate examples: #5 LocalEventMap This is the fifth of a series of gradually more...
  5. Mate examples: #4 Counters created dynamically This is the fourth of a series of gradually more...

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

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