Mate

109
Mate Flex Framework Using Flex Frameworks to Build Data- Driven Applications Flex@Beach'10

Transcript of Mate

Page 1: Mate

Mate Flex Framework

Using Flex Frameworks to Build Data-Driven Applications

Flex@Beach'10

Page 2: Mate

What is Mate?

<MXML>

Event Handling

Dependency Injection

Flex@Beach'10

Page 3: Mate

Sample Projects

InsyncMate1

Exact copy of original app with a model and central event handling

InsyncMate2

Logic moved to ContactManager

InsyncMate3

Better architecture with Presentation Model pattern

Modularized application

InsyncMate4

Modularized application

Flex@Beach'10

Page 4: Mate

Before & After

Contact List

Flex@Beach'10

Page 5: Mate

ContactList.mxml

Toolbar.mxml

ContactList.mxml Flex@Beach'10

Page 6: Mate

6

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

Flex@Beach'10

Page 7: Mate

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

Flex@Beach'10

Page 8: Mate

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

called by parentexecutes service call

Flex@Beach'10

Page 9: Mate

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

Flex@Beach'10

Page 10: Mate

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

Flex@Beach'10

Page 11: Mate

<mx:DataGrid id="dg" dataProvider="{ contacts }" doubleClick="dispatchEvent(

new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )" ... />

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var contacts:ArrayCollection; private var lastSearchStr:String;

<mx:RemoteObject id="service" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf"> <mx:method name="getContactsByName" result="getContacts_result(event)"/></mx:RemoteObject>

private function getContacts_result(event:ResultEvent):void {contacts = event.result as ArrayCollection;

}

</mx:Canvas>

</mx:Script>

public function search(searchStr:String):void {service.getContactsByName(searchStr);

lastSearchStr = searchStr;}

ContactList.mxml - Plain version

Flex@Beach'10

Page 12: Mate

Plain version

services

business logic

view

ContactList

MainViewcalls search

Toolbar

Flex@Beach'10

Page 13: Mate

Open file (InsyncMate1):

8

src

mate

ui

insync

views

ContactList.mxml

Flex@Beach'10

Page 14: Mate

ContactList.mxml - Mate version 1

9

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">

<mx:Metadata> [Event(name="editContact", type="insync.mate.events.ContactEvent")] </mx:Metadata> <mx:Script>

import mx.collections.ArrayCollection; import insync.mate.model.Contact; import insync.mate.events.ContactEvent;

[Bindable] public var contacts:ArrayCollection; </mx:Script> <mx:DataGrid id="dg" dataProvider="{ contacts }" top=" 0" left="0" right=" 0" bottom="0" doubleClickEnabled=" true" doubleClick="dispatchEvent( new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )"> <mx:columns> <mx:DataGridColumn dataField="firstName" headerText="First Name"/> <mx:DataGridColumn dataField="lastName" headerText="Last Name"/> <mx:DataGridColumn dataField="phone" headerText="Phone"/> </mx:columns> </mx:DataGrid></mx:Canvas>

Flex@Beach'10

Page 15: Mate

ContactList.mxml - Mate version 1

9

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">

<mx:Metadata> [Event(name="editContact", type="insync.mate.events.ContactEvent")] </mx:Metadata> <mx:Script>

import mx.collections.ArrayCollection; import insync.mate.model.Contact; import insync.mate.events.ContactEvent;

[Bindable] public var contacts:ArrayCollection; </mx:Script> <mx:DataGrid id="dg" dataProvider="{ contacts }" top=" 0" left="0" right=" 0" bottom="0" doubleClickEnabled=" true" doubleClick="dispatchEvent( new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )"> <mx:columns> <mx:DataGridColumn dataField="firstName" headerText="First Name"/> <mx:DataGridColumn dataField="lastName" headerText="Last Name"/> <mx:DataGridColumn dataField="phone" headerText="Phone"/> </mx:columns> </mx:DataGrid></mx:Canvas>

provided by injection

Flex@Beach'10

Page 16: Mate

ContactList.mxml - Mate version 1

9

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">

<mx:Metadata> [Event(name="editContact", type="insync.mate.events.ContactEvent")] </mx:Metadata> <mx:Script>

import mx.collections.ArrayCollection; import insync.mate.model.Contact; import insync.mate.events.ContactEvent;

[Bindable] public var contacts:ArrayCollection; </mx:Script> <mx:DataGrid id="dg" dataProvider="{ contacts }" top=" 0" left="0" right=" 0" bottom="0" doubleClickEnabled=" true" doubleClick="dispatchEvent( new ContactEvent( ContactEvent.EDIT, dg.selectedItem as Contact) )"> <mx:columns> <mx:DataGridColumn dataField="firstName" headerText="First Name"/> <mx:DataGridColumn dataField="lastName" headerText="Last Name"/> <mx:DataGridColumn dataField="phone" headerText="Phone"/> </mx:columns> </mx:DataGrid></mx:Canvas>

no business logic

not dependent on service

independent from Mate

Flex@Beach'10

Page 17: Mate

Open file (InsyncMate1):

10

src

mate

services

insync

Services.mxml

Flex@Beach'10

Page 18: Mate

Services.mxml - Mate version 1

11

<Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">

</Object>centralized services

<mx:RemoteObject id="contacts" destination="contacts" endpoint="http://localhost:8400/messagebroker/amf" />

Flex@Beach'10

Page 19: Mate

Services.mxml - Mate version 1

11

<Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">

</Object>

<MockRemoteObject id="contacts" mockGenerator="{ MockContactService }" delay="3"> <methods> <MockMethod name="search" dataUrl="assets/xml/contacts.xml"/> </methods></MockRemoteObject>

Flex@Beach'10

Page 20: Mate

Open file (InsyncMate1):

12

src

mate

managers

insync

ContactsManager.as

Flex@Beach'10

Page 21: Mate

ContactsManager.as - Mate version 1

13

public class ContactsManager extends EventDispatcher {

// property to store the last search keyword public var lastSearch:String = "";

// Read-only public variable used to access the current contacts to show in list private var _contacts:ArrayCollection; [Bindable(event="contactsChanged")] public function get contacts():ArrayCollection { return _contacts; }

// Stores given contacts and the current search keyword public function saveContacts( list:ArrayCollection, searchKey:String ):void { _contacts = list;

//trigger binding by dispatching change event dispatchEvent( new Event( "contactsChanged" ) ); lastSearch = searchKey; }}

Flex@Beach'10

Page 22: Mate

ContactsManager.as - Mate version 1

13

public class ContactsManager extends EventDispatcher {

// property to store the last search keyword public var lastSearch:String = "";

// Read-only public variable used to access the current contacts to show in list private var _contacts:ArrayCollection; [Bindable(event="contactsChanged")] public function get contacts():ArrayCollection { return _contacts; }

// Stores given contacts and the current search keyword public function saveContacts( list:ArrayCollection, searchKey:String ):void { _contacts = list;

//trigger binding by dispatching change event dispatchEvent( new Event( "contactsChanged" ) ); lastSearch = searchKey; }}

Flex@Beach'10

Page 23: Mate

ContactsManager.as - Mate version 1

13

public class ContactsManager extends EventDispatcher {

// property to store the last search keyword public var lastSearch:String = "";

// Read-only public variable used to access the current contacts to show in list private var _contacts:ArrayCollection; [Bindable(event="contactsChanged")] public function get contacts():ArrayCollection { return _contacts; }

// Stores given contacts and the current search keyword public function saveContacts( list:ArrayCollection, searchKey:String ):void { _contacts = list;

//trigger binding by dispatching change event dispatchEvent( new Event( "contactsChanged" ) ); lastSearch = searchKey; }}

independent from services

easy to mock and test

Flex@Beach'10

Page 24: Mate

Open file (InsyncMate1):

14

src

mate

ui

insync

views

Toolbar.mxml

Flex@Beach'10

Page 25: Mate

Toolbar.mxml - Mate version 1

15

<?xml version="1.0" encoding="utf-8"?><mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%">

<mx:Metadata> [Event(name="search", type="insync.plain.events.SearchEvent")] [Event(name="addContact", type="insync.plain.events.ContactEvent")] </mx:Metadata>

<mx:Script> <![CDATA[ import insync.plain.events.SearchEvent; import insync.plain.events.ContactEvent; ]]> </mx:Script> <mx:Button toolTip="Add Contact" click="dispatchEvent( new ContactEvent(ContactEvent.ADD))"/>

<mx:Label text="Search:" /> <mx:TextInput id="searchBox" change="dispatchEvent( new SearchEvent(SearchEvent.SEARCH, searchBox.text))"/></mx:Canvas>

Flex@Beach'10

Page 26: Mate

Open file (InsyncMate1):

16

src

mate

maps

insync

MainMap.mxml

Flex@Beach'10

Page 27: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 28: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 29: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 30: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 31: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 32: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

</EventMap>

Flex@Beach'10

Page 33: Mate

MainMap.mxml - Mate version 1

17

<EventHandlers type="{ SearchEvent.SEARCH }">

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" saveContacts" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:services="insync.mate.services.*">

<services:Services id="services" />

service methods separated from view and business logic

</EventMap>

Flex@Beach'10

Page 34: Mate

Open file (InsyncMate1):

18

src

InsyncMate1.mxml

Flex@Beach'10

Page 35: Mate

InsyncMate1.mxml (version 1)

19

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"xmlns:views=" insync.mate.ui.views.*" xmlns:maps=" insync.mate.maps.*" xmlns:mate="http://mate.asfusion.com/"> <!-- Styles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mx:Style source="assets/styles/styles.css" /> <!-- EventMaps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <maps:MainMap /> <!-- UI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <views:MainView/> <!-- Debugger ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mate:Debugger level="{Debugger.ALL}" /></mx:Application>

Flex@Beach'10

Page 36: Mate

InsyncMate1.mxml (version 1)

19

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"xmlns:views=" insync.mate.ui.views.*" xmlns:maps=" insync.mate.maps.*" xmlns:mate="http://mate.asfusion.com/"> <!-- Styles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mx:Style source="assets/styles/styles.css" /> <!-- EventMaps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <maps:MainMap /> <!-- UI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <views:MainView/> <!-- Debugger ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mate:Debugger level="{Debugger.ALL}" /></mx:Application>

Flex@Beach'10

Page 37: Mate

InsyncMate1.mxml (version 1)

19

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"xmlns:views=" insync.mate.ui.views.*" xmlns:maps=" insync.mate.maps.*" xmlns:mate="http://mate.asfusion.com/"> <!-- Styles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mx:Style source="assets/styles/styles.css" /> <!-- EventMaps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <maps:MainMap /> <!-- UI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <views:MainView/> <!-- Debugger ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <mate:Debugger level="{Debugger.ALL}" /></mx:Application>

Flex@Beach'10

Page 38: Mate

Debugging Output

<EventHandlers (started) type="SearchEvent.SEARCH" (search) priority="0" useCapture="false" useWeakReference="true" dispatcherType="inherit" scope="[object Scope]">

<RemoteObjectInvoker instance="[RemoteObject destination="contacts" channelSet="[ChannelSet null ]"]" arguments="Pam" showBusyCursor="false" makeObjectsBindable="true" method="getContactsByName" requestTimeout="0" debug="false"/>

</EventHandlers (end) type="SearchEvent.SEARCH" (search)>

Flex@Beach'10

Page 39: Mate

Debugging Output

<EventHandlers (started) type="SearchEvent.SEARCH" (search) priority="0" useCapture="false" useWeakReference="true" dispatcherType="inherit" scope="[object Scope]">

<RemoteObjectInvoker instance="[RemoteObject destination="contacts" channelSet="[ChannelSet null ]"]" arguments="Pam" showBusyCursor="false" makeObjectsBindable="true" method="getContactsByName" requestTimeout="0" debug="false"/>

</EventHandlers (end) type="SearchEvent.SEARCH" (search)>

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" debug="true" arguments=" { event.searchStr }">

Flex@Beach'10

Page 40: Mate

Debugging Output

<EventHandlers (started) type="SearchEvent.SEARCH" (search) priority="0" useCapture="false" useWeakReference="true" dispatcherType="inherit" scope="[object Scope]">

<RemoteObjectInvoker instance="[RemoteObject destination="contacts" channelSet="[ChannelSet null ]"]" arguments="Pam" showBusyCursor="false" makeObjectsBindable="true" method="getContactsByName" requestTimeout="0" debug="false"/>

</EventHandlers (end) type="SearchEvent.SEARCH" (search)>

<ServiceHandlers (started) type="SearchEvent.SEARCH" (search) token="[object AsyncToken]" priority="0" useCapture="false" useWeakReference="true" scope="[object ServiceScope]" dispatcherType="local">

<MethodInvoker method="saveContacts" arguments="[ [object Contact], Pam ]" generator="[class ContactsManager]" cache="inherit" registerTarget="true"/>

</ServiceHandlers (end) type="SearchEvent.SEARCH" (search)>

<RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" debug="true" arguments=" { event.searchStr }">

Flex@Beach'10

Page 41: Mate

Event Bus

View(ContactList.mxml)

EventMap

Remote Object(Services.mxml)

Model(ContactManager.as)

binding via Injection

Event Handling

Toolbar

Flex@Beach'10

Page 42: Mate

Open file (InsyncMate1):

22

src

mate

maps

insync

MainMap.mxml

Flex@Beach'10

Page 43: Mate

MainMap.mxml - Mate version 1

23

<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/">

<Injectors target="{ ContactList }"> <PropertyInjector targetKey="contacts" source=" { ContactsManager }" sourceKey="contacts"/> </Injectors>

</EventMap>

Takes advantage of bindings

Flex@Beach'10

Page 44: Mate

Event Bus

ContactList

Injection

Flex@Beach'10

Page 45: Mate

Event Bus

ContactList

creationCompletedispatched

1

Injection

Flex@Beach'10

Page 46: Mate

Event Bus

ContactList

EventMap

creationCompletedispatched

1

Injection

Flex@Beach'10

Page 47: Mate

Event Bus

ContactList

EventMapContactManager

creationCompletedispatched

1

Injection

Flex@Beach'10

Page 48: Mate

Event Bus

ContactList

EventMapContactManager

creationCompletedispatched

1

creates binding between model and view

2

Injection

Flex@Beach'10

Page 49: Mate

Event Bus

ContactList

EventMapContactManager

creationCompletedispatched

1

creates binding between model and view

2

bindingupdates

3

Injection

Flex@Beach'10

Page 50: Mate

Event Bus

ContactList

ContactManager

bindingupdates

3

Injection

Flex@Beach'10

Page 51: Mate

Version 1

Contact Form

Flex@Beach'10

Page 52: Mate

ContactEvent.DELETE ContactEvent.SAVE

Flex@Beach'10

Page 53: Mate

Open file (InsyncMate2):

27

src

mate

ui

insync

views

ContactForm.mxml

Flex@Beach'10

Page 54: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 55: Mate

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 56: Mate

Event Bus

View(ContactList.mxml)

EventMap

Remote Object(Services.mxml)

Model(ContactManager.as)

binding via Injection

Event Handling

Toolbar

Flex@Beach'10

Page 57: Mate

<mx:Form> <mx:FormItem label="Id"> <mx:TextInput text="{contact.id}" enabled="false"/> </mx:FormItem> <mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{contact.firstName}"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lastName" text="{contact.lastName}"/> </mx:FormItem> <mx:FormItem label="Email"> <mx:TextInput id="email" text="{contact.email}"/> </mx:FormItem> <-- all of the other fields here -->

</mx:Form>

<controls:PictureInput id="picture" source="{contact.pic}"/> <mx:Button label="Save" click="save()"/> <mx:Button label="Delete" click="remove()"/>

<mx:Label id="status" /></mx:Canvas>

Flex@Beach'10

Page 58: Mate

<mx:Form> <mx:FormItem label="Id"> <mx:TextInput text="{contact.id}" enabled="false"/> </mx:FormItem> <mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{contact.firstName}"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lastName" text="{contact.lastName}"/> </mx:FormItem> <mx:FormItem label="Email"> <mx:TextInput id="email" text="{contact.email}"/> </mx:FormItem> <-- all of the other fields here -->

</mx:Form>

<controls:PictureInput id="picture" source="{contact.pic}"/> <mx:Button label="Save" click="save()"/> <mx:Button label="Delete" click="remove()"/>

<mx:Label id="status" /></mx:Canvas>

Flex@Beach'10

Page 59: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 60: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 61: Mate

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 62: Mate

Open file (InsyncMate1):

src

mate

maps

insync

MainMap.mxml

Flex@Beach'10

Page 63: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 64: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 65: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 66: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 67: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 68: Mate

<EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method=" save" arguments=" { event.contact }"> <resultHandlers>

<CallBack method="save_result"/>

<EventAnnouncer generator="{ SearchEvent }" type=" { SearchEvent.SEARCH }"> <Property targetKey="searchStr" source="{ ContactsManager }"

sourceKey="lastSearch"/> </EventAnnouncer>

</resultHandlers> </RemoteObjectInvoker>

</EventHandlers>

®

<EventMap>

</EventMap>

Flex@Beach'10

Page 69: Mate

Open file (InsyncMate1):

src

mate

ui

insync

views

ContactForm.mxml

Flex@Beach'10

Page 70: Mate

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 71: Mate

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" label="{contact.id>0?contact.fullName:'New Contact'}">

<mx:Script> <![CDATA[ [Bindable] public var contact:Contact; private function save():void { contact.firstName = firstName.text; contact.lastName = lastName.text; contact.email = email.text; contact.phone = phone.text; contact.address = address.text; contact.city = city.text; contact.state = state.text; contact.zip = zip.text; contact.pic = picture.source;

dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } private function remove():void { dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); } public function save_result( ):void { status.text = "Contact saved successfully"; } ]]> </mx:Script>

Flex@Beach'10

Page 72: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Saving a contact

Flex@Beach'10

Page 73: Mate

Version 3

Contact Form

Flex@Beach'10

Page 74: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Presentation Model

• User input & visualization• Maintains its state• Dispatches events• Receives data• Validates user input

Flex@Beach'10

Page 75: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Presentation Model

• User input & visualization• Maintains its state• Dispatches events• Receives data• Validates user input

Flex@Beach'10

Page 76: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Presentation Model

Flex@Beach'10

Page 77: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Presentation Model

Presentation Model

Flex@Beach'10

Page 78: Mate

Event Bus

View(ContacForm.mxml) EventMap

Remote Object(Services.mxml)

Presentation Model

Presentation Model

Flex@Beach'10

Page 79: Mate

Open file (InsyncMate3):

src

mate

ui

insync

views

ContactForm.mxml

contacts

Flex@Beach'10

Page 80: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var model:ContactFormPresentationModel;

</mx:Script> <mx:Form>

<mx:FormItem label="Id"> <mx:TextInput text="{ model.contact.id }" enabled="false" /> </mx:FormItem>

<mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{ model.contact.firstName }" change="model.updateFirstName( firstName.text )" /> </mx:FormItem>

<-- all of the other fields here --> </mx:Form>

<controls:PictureInput id="picture" source=" { model.contact.pic }"/> <mx:Button bottom="26" left="12" label="Save" click="model.save()"/> <mx:Button bottom="26" left="72" label="Delete" click="model.remove()"/>

<mx:Label id="status" text="{ model.status }" /></mx:Canvas>

Flex@Beach'10

Page 81: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var model:ContactFormPresentationModel;

</mx:Script> <mx:Form>

<mx:FormItem label="Id"> <mx:TextInput text="{ model.contact.id }" enabled="false" /> </mx:FormItem>

<mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{ model.contact.firstName }" change="model.updateFirstName( firstName.text )" /> </mx:FormItem>

<-- all of the other fields here --> </mx:Form>

<controls:PictureInput id="picture" source=" { model.contact.pic }"/> <mx:Button bottom="26" left="12" label="Save" click="model.save()"/> <mx:Button bottom="26" left="72" label="Delete" click="model.remove()"/>

<mx:Label id="status" text="{ model.status }" /></mx:Canvas>

Flex@Beach'10

Page 82: Mate

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var model:ContactFormPresentationModel;

</mx:Script> <mx:Form>

<mx:FormItem label="Id"> <mx:TextInput text="{ model.contact.id }" enabled="false" /> </mx:FormItem>

<mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{ model.contact.firstName }" change="model.updateFirstName( firstName.text )" /> </mx:FormItem>

<-- all of the other fields here --> </mx:Form>

<controls:PictureInput id="picture" source=" { model.contact.pic }"/> <mx:Button bottom="26" left="12" label="Save" click="model.save()"/> <mx:Button bottom="26" left="72" label="Delete" click="model.remove()"/>

<mx:Label id="status" text="{ model.status }" /></mx:Canvas>

Flex@Beach'10

Page 83: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var model:ContactFormPresentationModel;

</mx:Script> <mx:Form>

<mx:FormItem label="Id"> <mx:TextInput text="{ model.contact.id }" enabled="false" /> </mx:FormItem>

<mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{ model.contact.firstName }" change="model.updateFirstName( firstName.text )" /> </mx:FormItem>

<-- all of the other fields here --> </mx:Form>

<controls:PictureInput id="picture" source=" { model.contact.pic }"/> <mx:Button bottom="26" left="12" label="Save" click="model.save()"/> <mx:Button bottom="26" left="72" label="Delete" click="model.remove()"/>

<mx:Label id="status" text="{ model.status }" /></mx:Canvas>

Flex@Beach'10

Page 84: Mate

®

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script> [Bindable] public var model:ContactFormPresentationModel;

</mx:Script> <mx:Form>

<mx:FormItem label="Id"> <mx:TextInput text="{ model.contact.id }" enabled="false" /> </mx:FormItem>

<mx:FormItem label="First Name"> <mx:TextInput id="firstName" text="{ model.contact.firstName }" change="model.updateFirstName( firstName.text )" /> </mx:FormItem>

<-- all of the other fields here --> </mx:Form>

<controls:PictureInput id="picture" source=" { model.contact.pic }"/> <mx:Button bottom="26" left="12" label="Save" click="model.save()"/> <mx:Button bottom="26" left="72" label="Delete" click="model.remove()"/>

<mx:Label id="status" text="{ model.status }" /></mx:Canvas>

Flex@Beach'10

Page 85: Mate

Open file (InsyncMate3):

src

mate

ui

insync

presenters

ContactPresentationModel.as

contacts

Flex@Beach'10

Page 86: Mate

®

public class ContactFormPresentationModel extends EventDispatcher {

// ---------------------------------- private var _title:String; [Bindable(Event="titleChange")] public function get title():String { return _title; } // ----------------------------------- private var _status:String; [Bindable(Event="statusChange")] public function get status():String { return _status; } // ----------------------------------- private var _contact:Contact; [Bindable(Event="contactChange")] public function get contact():Contact { return _contact; }

Flex@Beach'10

Page 87: Mate

public class ContactFormPresentationModel extends EventDispatcher {

// ---------------------------------- private var _title:String; [Bindable(Event="titleChange")] public function get title():String { return _title; } // ----------------------------------- private var _status:String; [Bindable(Event="statusChange")] public function get status():String { return _status; } // ----------------------------------- private var _contact:Contact; [Bindable(Event="contactChange")] public function get contact():Contact { return _contact; }

Flex@Beach'10

Page 88: Mate

// ----------------------------------- private var dispatcher:IEventDispatcher; public function ContactFormPresentationModel(dispatcher:IEventDispatcher, contact:Contact) { this.dispatcher = dispatcher; _contact = contact; _title = contact.id > 0 ? contact.fullName: 'New Contact'; } // ----------------------------------- public function save():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } // ----------------------------------- public function remove():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); }

// ----------------------------------- public function contactSaved( event:ContactEvent ):void { if( event.contact == contact ) { _status = "Contact saved successfully"; dispatchEvent( new Event( "statusChange" ) ); } }

Flex@Beach'10

Page 89: Mate

// ----------------------------------- private var dispatcher:IEventDispatcher; public function ContactFormPresentationModel(dispatcher:IEventDispatcher, contact:Contact) { this.dispatcher = dispatcher; _contact = contact; _title = contact.id > 0 ? contact.fullName: 'New Contact'; } // ----------------------------------- public function save():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } // ----------------------------------- public function remove():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); }

// ----------------------------------- public function contactSaved( event:ContactEvent ):void { if( event.contact == contact ) { _status = "Contact saved successfully"; dispatchEvent( new Event( "statusChange" ) ); } }

Flex@Beach'10

Page 90: Mate

// ----------------------------------- private var dispatcher:IEventDispatcher; public function ContactFormPresentationModel(dispatcher:IEventDispatcher, contact:Contact) { this.dispatcher = dispatcher; _contact = contact; _title = contact.id > 0 ? contact.fullName: 'New Contact'; } // ----------------------------------- public function save():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.SAVE, contact ) ); } // ----------------------------------- public function remove():void { dispatcher.dispatchEvent( new ContactEvent( ContactEvent.DELETE, contact ) ); }

// ----------------------------------- public function contactSaved( event:ContactEvent ):void { if( event.contact == contact ) { _status = "Contact saved successfully"; dispatchEvent( new Event( "statusChange" ) ); } }

Flex@Beach'10

Page 91: Mate

// Update functions ---------------------------------------------- public function updateFirstName( firstName:String ):void { contact.firstName = firstName; } // ----------------------------------- public function updateLastName( lastName:String ):void { contact.lastName = lastName; } // ----------------------------------- public function updateEmail( email:String ):void { contact.email = email; }

// ----------------------------------- public function updatePhone( phone:String ):void { contact.phone = phone; }

Flex@Beach'10

Page 92: Mate

Open file (InsyncMate3):

src

mate

insync

managers

ContactsManager.as

contacts

Flex@Beach'10

Page 93: Mate

ContactsManager.as (InsyncMate3)

public class ContactsManager extends EventDispatcher { private var editOpenContacts:Dictionary = new Dictionary( true ); private var newOpenContacts:Dictionary = new Dictionary( true ); // ------------------------------------------------------------------------ // property to store the last search keyword public var lastSearch:String = " "; // ------------------------------------------------------------------------ // Read-only public variable used to access the current contacts to show in list private var _contacts:ArrayCollection; [Bindable(event="contactsChanged")] public function get contacts():ArrayCollection { return _contacts; } // ------------------------------------------------------------------------ // Read-only public variable used to access the current contact (last selected contact) private var currentContact:Contact; public function getCurrentContact():Contact { return currentContact; } // ------------------------------------------------------------------------- // Stores given contacts and the current search keyword public function storeSearch( list:ArrayCollection, searchKey:String ):void { _contacts = list; dispatchEvent( new Event( "contactsChanged" ) ); lastSearch = searchKey; } // ------------------------------------------------------------------------- // Applies updates to a contact public function save( contact:Contact, originalContact:Contact ):void { if( originalContact.id == 0) { var form:Object; form = newOpenContacts[ originalContact ]; editOpenContacts[ contact.id ] = form; } originalContact.copyFrom( contact ); } // ------------------------------------------------------------------------- public function openNewContact( template:Class ):Object { currentContact = new Contact(); var form:Object = new template(); newOpenContacts[ currentContact ] = form; return form; } // ------------------------------------------------------------------------- public function openEditContact( contact:Contact, template:Class ):Object { var form:Object = editOpenContacts[ contact.id ]; if( !form ) { form = new template(); editOpenContacts[ contact.id ] = form; } currentContact = contact; return form; } // ------------------------------------------------------------------------- public function closeContact( contact:Contact ):Object { var form:Object; if( editOpenContacts[ contact.id ] != undefined && contact.id != 0 ) { form = editOpenContacts[ currentContact.id ]; delete editOpenContacts[ currentContact ] } else if( newOpenContacts[ currentContact ] != undefined ) { form = newOpenContacts[ currentContact ]; delete newOpenContacts[ currentContact ]; } return form; } }}

Flex@Beach'10

Page 94: Mate

ContactsManager.as (InsyncMate3)

public class ContactsManager extends EventDispatcher { private var editOpenContacts:Dictionary = new Dictionary( true ); private var newOpenContacts:Dictionary = new Dictionary( true ); // ------------------------------------------------------------------------ // property to store the last search keyword public var lastSearch:String = " "; // ------------------------------------------------------------------------ // Read-only public variable used to access the current contacts to show in list private var _contacts:ArrayCollection; [Bindable(event="contactsChanged")] public function get contacts():ArrayCollection { return _contacts; } // ------------------------------------------------------------------------ // Read-only public variable used to access the current contact (last selected contact) private var currentContact:Contact; public function getCurrentContact():Contact { return currentContact; } // ------------------------------------------------------------------------- // Stores given contacts and the current search keyword public function storeSearch( list:ArrayCollection, searchKey:String ):void { _contacts = list; dispatchEvent( new Event( "contactsChanged" ) ); lastSearch = searchKey; } // ------------------------------------------------------------------------- // Applies updates to a contact public function save( contact:Contact, originalContact:Contact ):void { if( originalContact.id == 0) { var form:Object; form = newOpenContacts[ originalContact ]; editOpenContacts[ contact.id ] = form; } originalContact.copyFrom( contact ); } // ------------------------------------------------------------------------- public function openNewContact( template:Class ):Object { currentContact = new Contact(); var form:Object = new template(); newOpenContacts[ currentContact ] = form; return form; } // ------------------------------------------------------------------------- public function openEditContact( contact:Contact, template:Class ):Object { var form:Object = editOpenContacts[ contact.id ]; if( !form ) { form = new template(); editOpenContacts[ contact.id ] = form; } currentContact = contact; return form; } // ------------------------------------------------------------------------- public function closeContact( contact:Contact ):Object { var form:Object; if( editOpenContacts[ contact.id ] != undefined && contact.id != 0 ) { form = editOpenContacts[ currentContact.id ]; delete editOpenContacts[ currentContact ] } else if( newOpenContacts[ currentContact ] != undefined ) { form = newOpenContacts[ currentContact ]; delete newOpenContacts[ currentContact ]; } return form; } }}

Flex@Beach'10

Page 95: Mate

Open file (InsyncMate3):

src

mate

insync

maps

ContactMap.mxml

contacts

Flex@Beach'10

Page 96: Mate

ContactMap.mxml

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <Injectors target="{ ContactForm }"> <MethodInvoker generator="{ ContactsManager }" method="getCurrentContact" /> <ObjectBuilder generator="{ ContactFormPresentationModel }" cache="none" constructorArguments=" { [ scope.dispatcher, lastReturn ] }" /> <PropertyInjector targetKey="model" source="{ lastReturn }"/> </Injectors> <Injectors target="{ ContactFormPresentationModel }"> <ListenerInjector eventType="{ ContactEvent.SAVED }" method="contactSaved" /> </Injectors></LocalEventMap>

Flex@Beach'10

Page 97: Mate

ContactMap.mxml

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <Injectors target="{ ContactForm }"> <MethodInvoker generator="{ ContactsManager }" method="getCurrentContact" /> <ObjectBuilder generator="{ ContactFormPresentationModel }" cache="none" constructorArguments=" { [ scope.dispatcher, lastReturn ] }" /> <PropertyInjector targetKey="model" source="{ lastReturn }"/> </Injectors> <Injectors target="{ ContactFormPresentationModel }"> <ListenerInjector eventType="{ ContactEvent.SAVED }" method="contactSaved" /> </Injectors></LocalEventMap>

Flex@Beach'10

Page 98: Mate

ContactMap.mxml (InsyncMate3)

<!-- ContactEvent.SAVE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.SAVE }"> <RemoteObjectInvoker instance="{ services.contacts }" method="save" arguments=" { event.contact }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method="save" arguments="{ [resultObject, event.contact] }"/> <EventAnnouncer generator="{ SearchEvent }" dispatcherType="global" type=" { ContactEvent.REFRESH }"/>

<EventAnnouncer generator="{ ContactEvent }" constructorArguments="{ [ContactEvent.SAVED, event.contact] }"/>

</resultHandlers> </RemoteObjectInvoker> </EventHandlers>

Flex@Beach'10

Page 99: Mate

Version 3

Modules

Flex@Beach'10

Page 100: Mate

Open folder (InsyncMate3):

src

mate

contacts

insync

ContactModule.mxml

shared

Flex@Beach'10

Page 101: Mate

ContactModule.mxml

<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> public function addTab( event:NavigatorEvent ):void { try { var childIndex:int = tabNavigator.getChildIndex( event.content ); tabNavigator.selectedIndex = childIndex; } catch( e:Error) { tabNavigator.addChild( event.content ); tabNavigator.selectedChild = event.content; } } public function removeTab( event:NavigatorEvent ):void { tabNavigator.removeChild( event.content ); } </mx:Script> <!-- EventMaps --> <maps:ContactMap dispatcher="{ this }"/> <!-- UI --> <mx:HDividedBox width="100%" height="100%"> <flexLib:SuperTabNavigator id="tabNavigator" width="100%" height="100%"/> <views:ContactList id="list" width="300"/> </mx:HDividedBox></mx:Module>

Flex@Beach'10

Page 102: Mate

ContactModule.mxml

<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> public function addTab( event:NavigatorEvent ):void { try { var childIndex:int = tabNavigator.getChildIndex( event.content ); tabNavigator.selectedIndex = childIndex; } catch( e:Error) { tabNavigator.addChild( event.content ); tabNavigator.selectedChild = event.content; } } public function removeTab( event:NavigatorEvent ):void { tabNavigator.removeChild( event.content ); } </mx:Script> <!-- EventMaps --> <maps:ContactMap dispatcher="{ this }"/> <!-- UI --> <mx:HDividedBox width="100%" height="100%"> <flexLib:SuperTabNavigator id="tabNavigator" width="100%" height="100%"/> <views:ContactList id="list" width="300"/> </mx:HDividedBox></mx:Module>

Flex@Beach'10

Page 103: Mate

ContactModule.mxml

<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> public function addTab( event:NavigatorEvent ):void { try { var childIndex:int = tabNavigator.getChildIndex( event.content ); tabNavigator.selectedIndex = childIndex; } catch( e:Error) { tabNavigator.addChild( event.content ); tabNavigator.selectedChild = event.content; } } public function removeTab( event:NavigatorEvent ):void { tabNavigator.removeChild( event.content ); } </mx:Script> <!-- EventMaps --> <maps:ContactMap dispatcher="{ this }"/> <!-- UI --> <mx:HDividedBox width="100%" height="100%"> <flexLib:SuperTabNavigator id="tabNavigator" width="100%" height="100%"/> <views:ContactList id="list" width="300"/> </mx:HDividedBox></mx:Module>

Flex@Beach'10

Page 104: Mate

Open file (InsyncMate3):

src

mate

insync

maps

ContactMap.mxml

contacts

Flex@Beach'10

Page 105: Mate

ContactMap.mxml

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- SearchEvent.SEARCH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ SearchEvent.SEARCH }" dispatcherType="global"> <RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" storeSearch" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker> </EventHandlers> <!-- ContactEvent.EDIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.EDIT }"> <MethodInvoker generator="{ ContactsManager }" method="openEditContact" arguments="{[ event.contact, ContactForm ]}" /> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers> <!-- ContactEvent.ADD ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.ADD }" dispatcherType="global"> <MethodInvoker generator="{ ContactsManager }" method="openNewContact" arguments="{ ContactForm }"/> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers>

</LocalEventMap>

Flex@Beach'10

Page 106: Mate

ContactMap.mxml

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- SearchEvent.SEARCH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ SearchEvent.SEARCH }" dispatcherType="global"> <RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" storeSearch" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker> </EventHandlers> <!-- ContactEvent.EDIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.EDIT }"> <MethodInvoker generator="{ ContactsManager }" method="openEditContact" arguments="{[ event.contact, ContactForm ]}" /> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers> <!-- ContactEvent.ADD ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.ADD }" dispatcherType="global"> <MethodInvoker generator="{ ContactsManager }" method="openNewContact" arguments="{ ContactForm }"/> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers>

</LocalEventMap>

Flex@Beach'10

Page 107: Mate

ContactMap.mxml

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- SearchEvent.SEARCH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ SearchEvent.SEARCH }" dispatcherType="global"> <RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" storeSearch" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker> </EventHandlers> <!-- ContactEvent.EDIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.EDIT }"> <MethodInvoker generator="{ ContactsManager }" method="openEditContact" arguments="{[ event.contact, ContactForm ]}" /> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers> <!-- ContactEvent.ADD ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.ADD }" dispatcherType="global"> <MethodInvoker generator="{ ContactsManager }" method="openNewContact" arguments="{ ContactForm }"/> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers>

</LocalEventMap>

Flex@Beach'10

Page 108: Mate

ContactMap.mxml

54

<LocalEventMap xmlns:mx="http://www.adobe.com/2006/mxml"xmlns="http://mate.asfusion.com/"> <!-- SearchEvent.SEARCH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ SearchEvent.SEARCH }" dispatcherType="global"> <RemoteObjectInvoker instance="{ services.contacts }" method=" getContactsByName" arguments=" { event.searchStr }"> <resultHandlers> <MethodInvoker generator="{ ContactsManager }" method=" storeSearch" arguments=" { [resultObject, event.searchStr] }"/> </resultHandlers> </RemoteObjectInvoker> </EventHandlers> <!-- ContactEvent.EDIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.EDIT }"> <MethodInvoker generator="{ ContactsManager }" method="openEditContact" arguments="{[ event.contact, ContactForm ]}" /> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers> <!-- ContactEvent.ADD ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <EventHandlers type="{ ContactEvent.ADD }" dispatcherType="global"> <MethodInvoker generator="{ ContactsManager }" method="openNewContact" arguments="{ ContactForm }"/> <EventAnnouncer generator="{ NavigatorEvent }" type="{ NavigatorEvent.ADD_CONTENT }" > <Property targetKey="content" source="{ lastReturn }"/> </EventAnnouncer> </EventHandlers>

</LocalEventMap>

Flex@Beach'10

Page 109: Mate

Learn more

57

http://mate.asfusion.com

Flex@Beach'10