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

If you haven’t done it yet you should have a look first at our previous examples: #1, #2, #3, #4, #5, #6, #7, #8, and #9.

Today we’re going to put aside our (I know: boooring) counters. We will come back to them in a couple of posts for the great finale: Mate and versioned applications.
But for now I wanted to illustrate a really good practice with Mate (and in general): the Presentation Model pattern. For those who want to know more about the Presentation Model, have a look at Paul Williams great article. Basically, the idea is to keep the view as simple as possible, separating all the logic in a dedicated class. That way, Mate communicates with the presentation model class and not directly with the view, the latter being updated via data binding. In this configuration, the view’s only concern is its own elements and its only dependency is its model.

Let’s have a look at our very simple demo (source is available by right-clicking on the demo after launching it):

Mate example

#10 Presentation Model (click to Launch)

So what do we have here (apart from the opportunity to learn a bit of French)? Two visually different panels, each with two buttons, each button triggering an alert with a different message. The structure is dead simple: the two different panels are instantiated in the now usual MainView:


Demo #10: src/views/MainView.mxml

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
           width="656"
           height="314"
           xmlns:views="views.*">

    <views:FirstPanel verticalCenter="0"
                      left="25"
                      width="298"/>
    <views:SecondPanel verticalCenter="0"
                       right="25"/>
                       
</mx:Canvas>

FirstPanel and SecondPanel are pretty similar, the main differences being various “cosmetic” properties:


Demo #10: src/views/FirstPanel.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
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
          width="298"
          height="164"
          layout="absolute"
          title="First Panel">

    <mx:Script>
        <![CDATA[
            import views.presentationmodel.IPresentationModel;

            [Bindable]
            public var pm : IPresentationModel;
        ]]>
    </mx:Script>

    <mx:Button id="button1"
               label="Button One"
               left="30"
               verticalCenter="0"
               click="pm.button1_clickHandler(event)"/>
    <mx:Button id="button2"
               label="Button Two"
               right="30"
               verticalCenter="0"
               click="pm.button2_clickHandler(event)"/>

</mx:Panel>


Demo #10: src/views/SecondPanel.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
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
          width="246"
          height="232"
          layout="absolute"
          title="Deuxieme Panel"
          borderStyle="inset"
          backgroundColor="#A5C5ED">

    <mx:Script>
        <![CDATA[
            import views.presentationmodel.IPresentationModel;

            [Bindable]
            public var pm : IPresentationModel;
        ]]>
    </mx:Script>

    <mx:Button id="button1"
               label="Bouton Un"
               horizontalCenter="0"
               top="20"
               emphasized="true"
               cornerRadius="0"
               click="pm.button1_clickHandler(event)"/>
    <mx:Button id="button2"
               label="Bouton Deux"
               horizontalCenter="0"
               bottom="20"
               cornerRadius="0"
               fillAlphas="[1.0, 1.0]"
               fillColors="[#FF0000, #FF0000]"
               color="#FFFFFF"
               click="pm.button2_clickHandler(event)"/>

</mx:Panel>

One important thing to notice though: they both share a same pm variable referring to an Interface, IPresentationModel. Also, the 2 buttons call 2 methods within this interface: button1_clickHandler and button2_clickHandler.


Demo #10: src/views/presentationmodel/IPresentationModel.as

1
2
3
4
5
6
7
8
9
10
package views.presentationmodel
{
    import flash.events.MouseEvent;

    public interface IPresentationModel
    {
        function button1_clickHandler( event : MouseEvent ) : void;
        function button2_clickHandler( event : MouseEvent ) : void;
    }
}

Now, there are two classes in the views/presentationmodel package: PresentationModel1 and PresentationModel2. Once again, those two are pretty similar, the only differences being the different messages thrown by the Alerts:


Demo #10: src/views/presentationmodel/PresentationModel1.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package views.presentationmodel
{
    import flash.events.EventDispatcher;
    import flash.events.MouseEvent;
   
    import mx.controls.Alert;

    public class PresentationModel1 extends EventDispatcher implements IPresentationModel
    {

        public function button1_clickHandler( event : MouseEvent ) : void
        {
            Alert.show("Button1 Clicked");
        }

        public function button2_clickHandler( event : MouseEvent ) : void
        {
            Alert.show("Button2 Clicked");
        }

    }
}


Demo #10: src/views/presentationmodel/PresentationModel2.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package views.presentationmodel
{
    import flash.events.EventDispatcher;
    import flash.events.MouseEvent;
   
    import mx.controls.Alert;

    public class PresentationModel2 extends EventDispatcher implements IPresentationModel
    {

        public function button1_clickHandler( event : MouseEvent ) : void
        {
            Alert.show("Oh! I do not like this.");
        }

        public function button2_clickHandler( event : MouseEvent ) : void
        {
            Alert.show("Please don't do that.");
        }

    }
}

And now, the glue, as usual:


Demo #10: 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
<?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.SecondPanel;
            import views.presentationmodel.PresentationModel2;
            import views.presentationmodel.PresentationModel1;
            import views.FirstPanel;
        ]]>
    </mx:Script>

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

    <mate:Injectors target="{FirstPanel}">
        <mate:ObjectBuilder generator="{PresentationModel1}"/>
        <mate:PropertyInjector source="{lastReturn}"
                               targetKey="pm"/>

    </mate:Injectors>

    <mate:Injectors target="{SecondPanel}">
        <mate:ObjectBuilder generator="{PresentationModel2}"/>
        <mate:PropertyInjector source="{lastReturn}"
                               targetKey="pm"/>

    </mate:Injectors>

</mate:EventMap>

The MainEventMap maps each PresentationModel to its related view and the job is done! The beauty of it is that you can swap presentation models and views as easily as this:


Demo #10: 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
<?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.SecondPanel;
            import views.presentationmodel.PresentationModel2;
            import views.presentationmodel.PresentationModel1;
            import views.FirstPanel;
        ]]>
    </mx:Script>

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

    <mate:Injectors target="{FirstPanel}">
        <mate:ObjectBuilder generator="{PresentationModel2}"/>
        <mate:PropertyInjector source="{lastReturn}"
                               targetKey="pm"/>

    </mate:Injectors>

    <mate:Injectors target="{SecondPanel}">
        <mate:ObjectBuilder generator="{PresentationModel1}"/>
        <mate:PropertyInjector source="{lastReturn}"
                               targetKey="pm"/>

    </mate:Injectors>

</mate:EventMap>

Neat, isn’t it? You can as easily imagine using data binding to dynamically change view’s properties (visible, enabled, label, whatnot) with some bindable variables in the presentation model.

Here we go. Next, my new favourite one: a port of PureMVC’s mediator pattern which is one of the best ways to use Mate with the new Flex 4 component architecture.

Related posts:

  1. Mate examples: #11 Mediator (or Passive View) This is the eleventh of a series of gradually more...
  2. Mate examples: #9 Modules Example (pt 2) This is the ninth of a series of gradually more...
  3. Mate examples: #2 Databinding and EventHandlers This is the second of a series of gradually more...
  4. Mate examples: #3 Multiple Counters This is the third of a series of gradually more...
  5. Mate examples: #5 LocalEventMap This is the fifth of a series of gradually more...

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

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.25 out of 5)
Loading ... Loading ...