PureMVC Architects Lounge

Announcements and General Discussion => General Discussion => Topic started by: mritchie on October 15, 2008, 11:28:33



Title: Handling AIR system tray icon
Post by: mritchie on October 15, 2008, 11:28:33
I'm have  question about PureMVC best practices with a full Adobe AIR application.   For example, I want to set the system tray icon for either PC or Mac at the start of the application and set up the AIR application to handle user action on the system tray icon (to maximize/minimize application or do a bounce/notification to the user).  Normally I would do this in the main MXML file for the application on creation complete, here is what my application code might look like:

       [Embed(source="assets/tray_icon.png")]      
         private var icon16:Class;
         
         // maximize
         private var isMaximized:Boolean = false;
         private var curWidth:Number;
         private var curHeight:Number;
         private var curX:Number;
         private var curY:Number;
         
         // system tray
         private var dock:Function;
         private var undock:Function;
         private var changeIcon:Function;
         
         public function initApp():void
         {
            var baseWindow:NativeWindow = app.stage.nativeWindow;
                 baseWindow.x = (Capabilities.screenResolutionX - baseWindow.width) /2;
                 baseWindow.y = (Capabilities.screenResolutionY - baseWindow.height) /2;
                 baseWindow.activate();

                               if (NativeApplication.supportsSystemTrayIcon){
               setSystemTrayProperties();
            } else if(NativeApplication.supportsDockIcon){
               setDockProperties();
            }
         }
         
         public function notifyHandler():void
         {
            if(NativeApplication.supportsDockIcon){
               var dock:DockIcon = NativeApplication.nativeApplication.icon as DockIcon;
                    dock.bounce();
               DockIcon(NativeApplication.nativeApplication.icon).bounce(NotificationType.CRITICAL);
            } else if (NativeApplication.supportsSystemTrayIcon){
               stage.nativeWindow.notifyUser(NotificationType.CRITICAL);
            }
         }
         
         private function setDockProperties():void
         {
            dock = OSXdock;
            undock = OSXundock;
            changeIcon = OSXchangeIcon;
            NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onIconClick);
         }
         
         private function setSystemTrayProperties():void
         {
            SystemTrayIcon(NativeApplication.nativeApplication.icon).tooltip = "PADL";
            SystemTrayIcon(NativeApplication.nativeApplication.icon).addEventListener(MouseEvent.CLICK, onIconClick);
      
            dock = DOSdock;
            undock = DOSundock;
            changeIcon = DOSchangeIcon;
         }
         
         public function OSXdock():void
         {
            stage.nativeWindow.visible = false;
            NativeApplication.nativeApplication.icon.bitmaps = [(new icon16()).bitmapData];
         }   
         
         public function OSXundock():void
         {
            stage.nativeWindow.visible = true;
         }
         
         public function OSXchangeIcon():void
         {
            NativeApplication.nativeApplication.icon.bitmaps = [(new icon16()).bitmapData];
         }
         
         public function DOSdock():void
         {
            stage.nativeWindow.visible = false;
            NativeApplication.nativeApplication.icon.bitmaps = [(new icon16()).bitmapData];
         }   
         
         public function DOSundock():void
         {
            //isDocked = false;
            stage.nativeWindow.visible = true;
            NativeApplication.nativeApplication.icon.bitmaps = [];
         }
         
         public function DOSchangeIcon():void
         {
            NativeApplication.nativeApplication.icon.bitmaps = [(new icon16()).bitmapData];
         }
         
         private function onIconClick(event:Event):void
         {
            undock();
            stage.nativeWindow.orderToFront();
         }


What I am a little confused with is whether is is best practice to leave this code in the MXML file itself or possibly and call the initApp() function from the application Mediator or move this to a Command (like the viewPrepCommand) or Proxy (create an application proxy).   I couldn't find in the examples a way for setting system tray information.  The mediator works good because it has a reference to the app, but these are setup functions for the stage basically and need to receive notifications when clicked by the user.  If any one has suggestions or experience to share, I would love to hear them, thanks!

Michael



Title: Re: Handling AIR system tray icon
Post by: Joel Hooks on October 15, 2008, 06:28:51
I do it in my ApplicationMediator or via commands. For my system tray menus, I will usually tie them into commands for interaction, and change things like bouncing or icon changes in the ApplicationMediator. I would say you definitely don't want to put this in the MXML. Not that you couldn't, it just fits nicely in a mediator. In addition, I will often mediate the menus for system items (tray and window) because their mediators can get a bit large and clutter up the ApplicationMediator.

http://code.google.com/p/as3notificationlib/

I don't know if you are using this, but it is pretty freakin sweet. He has a number of other libraries posted (http://code.google.com/u/christian.cantrell/) too.


Title: Re: Handling AIR system tray icon
Post by: mritchie on October 17, 2008, 12:57:43
Thanks Joel for the good advice and also pointing out the system notification library.   I will try to apply your advice in my application and report back if I have any further questions.  :)