PureMVC Tutorial – Flex, PureMVC, Jabber and XIFF 3: Part 8 – The Roster View & Mediator

Introduction
Part 1 – Frameworks
Part 2 – Directory structure
Part 3 – Application and ApplicationFacade
Part 4 – Notifications, Commands & Use Cases
Part 5 – Model & Proxy
Part 6 – The Application View & Mediator
Part 7 – The Login View & Mediator
Part 8 – The Roster View & Mediator
Part 9 – The Chat View & Mediator
Conclusion, Demo & Downloads

By now you should be becoming a bit of an old hand at this PureMVC lark, so I’m going to be explaining stuff in a bit less detail.  If you get stuck re-read the previous sections until you have everything clear in your head.

The Roster is very simple.  We want a Flex DataGrid displaying usernames and login status and we need a ‘Start chat…’ button that opens a chat window.

In order to implement this view we’ll need a new event called ChatEvent.as.  The JID class is part of the XIFF framework and is used to identify a Jabber user.  The RosterView will only use START_CHAT, but we’ll need SEND_MESSAGE in the next and final view.

   1: package org.davekeen.xiffer.events {
   2:     import flash.events.Event;
   3:     import org.jivesoftware.xiff.core.JID;
   4:     
   5:     /**
   6:     * This event is related to the ChatViews
   7:     * 
   8:     * @author Dave Keen
   9:     */
  10:     public class ChatEvent extends Event {
  11:         
  12:         public static const START_CHAT:String = "start_chat";
  13:         public static const SEND_MESSAGE:String = "send_message";
  14:         
  15:         private var jid:JID;
  16:         private var message:String;
  17:         
  18:         public function ChatEvent(type:String, jid:JID, message:String = null, bubbles:Boolean=false, cancelable:Boolean=false) { 
  19:             super(type, bubbles, cancelable);
  20:             
  21:             this.jid = jid;
  22:             this.message = message;
  23:         } 
  24:         
  25:         public function getJID():JID {
  26:             return jid;
  27:         }
  28:         
  29:         public function getMessage():String {
  30:             return message;
  31:         }
  32:         
  33:         public override function clone():Event { 
  34:             return new ChatEvent(type, jid, message, bubbles, cancelable);
  35:         } 
  36:         
  37:     }
  38:     
  39: }

We’ll also need to define one new notification in ApplicationFacade.as called OPEN_CHAT_WINDOW:

   1: public static const OPEN_CHAT_WINDOW:String = "open_chat_window";

Next we create our RosterView.mxml file in components:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" width="100%" height="100%">
   3:     <mx:Script>
   4:         <![CDATA[
   5:         import flash.events.Event;
   6:         import mx.events.ListEvent;
   7:         import org.davekeen.xiffer.events.ChatEvent;
   8:         import org.jivesoftware.xiff.core.JID;
   9:         
  10:         private function onChatClick():void {
  11:             if (rosterGrid.selectedItem) {
  12:                 // Get the selected item and convert it to a JID
  13:                 var jid:JID = new JID(rosterGrid.selectedItem.jid);
  14:                 
  15:                 // Dispatch an event for the mediator
  16:                 dispatchEvent(new ChatEvent(ChatEvent.START_CHAT, jid));
  17:             }
  18:         }
  19:         
  20:         ]]>
  21:     </mx:Script>
  22:     <mx:TitleWindow id="titleWindow" title="Buddy list" enabled="false">
  23:         <mx:DataGrid id="rosterGrid" editable="false" width="160" height="300" showHeaders="true">
  24:             <mx:columns>
  25:                 <mx:DataGridColumn dataField="displayName" headerText="Username" />
  26:                 <mx:DataGridColumn dataField="online" width="55" headerText="Online?" />
  27:             </mx:columns>
  28:         </mx:DataGrid>
  29:         <mx:Button width="160" label="Chat..." click="onChatClick()" />
  30:     </mx:TitleWindow>
  31: </mx:Canvas>

Add this component to the display list of our top-level Application.mxml component so that the <mx:Canvas> component now reads:

   1: <mx:Canvas left="0" top="0" right="0" bottom="0">
   2:     <view:LoginView id="loginView" />
   3:     <view:RosterView y="30" id="rosterView" />
   4: </mx:Canvas>

Now we need to create RosterMediator.as in the view folder, and register it with PureMVC.  Using the rule we applied in the previous section we can see that we need to do this registration in ApplicationMediator.as:

   1: public function ApplicationMediator(viewComponent:Object) {
   2:     // pass the viewComponent to the superclass where 
   3:     // it will be stored in the inherited viewComponent property
   4:     super(NAME, viewComponent);
   5:     
   6:     facade.registerMediator(new LoginMediator(application.loginView));
   7:     facade.registerMediator(new RosterMediator(application.rosterView));
   8: }

All that is left now is to configure our mediator using the same steps as in the previous section.

1. Add listeners

RosterView.mxml dispatches only ChatEvent.START_CHAT so let’s add a listener in the constructor:

   1: public function RosterMediator(viewComponent:Object) {
   2:     // pass the viewComponent to the superclass where 
   3:     // it will be stored in the inherited viewComponent property
   4:     super(NAME, viewComponent);
   5:     
   6:     rosterView.addEventListener(ChatEvent.START_CHAT, onStartChat);
   7: }
   8:  
   9: private function onStartChat(chatEvent:ChatEvent):void { }

2. Add notifications

The Roster window need to enable and disable depending on whether or not the user is connected to a jabber server, and also needs to fill in the DataGrid with the list of buddies.  To achieve these goals the mediator will need to register an interest in ApplicationFacade.VALID_LOGIN and ApplicationFacade.DISCONNECT.

   1: override public function listNotificationInterests():Array {
   2:     return [
   3:             ApplicationFacade.VALID_LOGIN,
   4:             ApplicationFacade.DISCONNECT
   5:             ];
   6: }

And here are the clauses for the switch statement:

   1: override public function handleNotification(note:INotification):void {
   2:     switch (note.getName()) {
   3:         case ApplicationFacade.VALID_LOGIN:
   4:              break;
   5:         case ApplicationFacade.DISCONNECT:
   6:             break;
   7:         default:
   8:             break;        
   9:     }
  10: }

3. Fill in the event listeners and switch clauses

Firstly we’ll fill in the onStartChat event listener.  This will very simply send an ApplicationFacade.OPEN_CHAT_WINDOW with the JID as the argument.  Although we could have passed the ChatEvent itself as a parameter in this case there is no need to use a value object as to open a chat window we only require a single item of information – the JID.

   1: private function onStartChat(chatEvent:ChatEvent):void {
   2:     sendNotification(ApplicationFacade.OPEN_CHAT_WINDOW, chatEvent.getJID());
   3: }

You’ll notice that the ApplicationFacade.OPEN_CHAT_WINDOW notification is not mapped to a command – this is because the only responder to the notification will be the ChatMediator that we are about to create in the next section so there is no need to have a command.  However, one of the beautiful things about PureMVC is that if it turned out later in the development that this notification needed to affect the model in some way we could implement this merely by adding a new command and registering it, and there will be no need to make any changes to the rest of the application.

Compile and run the application and enjoy the working buddy list!  Only one view left to go…

8 comments

  1. In step “1. Add listeners” you say LoginView.mxml when I think it should be RosterView.mxml that dispatches such event.

  2. Hi! Very nice tutorial, many things became much more clear to me. But I didn’t get how we populate the buddy list? Probably we should take some actions on ApplicationFacade.VALID_LOGIN notification, but this part missed.

  3. Hey Konstantin,

    Buddy lists are outside the scope of this tutorial, but you want to have a look at the RosterEvent class – specifically ROSTER_LOADED to let you know the buddy list is ready and USER_PRESENCE_UPDATED to let you know that the status of a buddy has changed.

    Good luck!

    Dave

Leave a Reply

Your email address will not be published. Required fields are marked *