
One of the basic aspects of an application is its tray or dock icon. A basic tray or dock icon will allow you to exit or restore the application. This is extremely important, especially for Adobe AIR applications. Since most of us Adobe AIR application creators are web programmers, or something similar, by trade it’s extremely easy to forget or overlook basic things like this only because it’s not the norm.
The reason a system tray or dock icon is so important to an application, is that it’s another way to control said application. All of us know by now, to please the end user, you must give them complete control over what they’re interacting with. Let’s say you’re making a sweet new application with all sorts of window transitions, changing visibility of windows and so on. Well, what happens if the application becomes unresponsive? What happens if the transition doesn’t complete? Especially if you’re using custom chrome, the user will not be able to close the app! Yes, they can force quit the application using operating system specific techniques, however, as the developer you need to be thinking that the end user can hardly manage to open their web browser, let alone know how to force quit an app.
Now, in terms of operating systems, windows won’t display a tray icon by default. You have to implement a solution to first even get the system tray icon to display. Along the same lines, windows doesn’t have a default tray icon menu when you click it. Macintosh, and I assume Linux, by default shows a menu when you click to the dock icon which includes an exit command. So, let start creating our system tray and dock icons, then add a few menu items, and some actions for when those items are selected.
Note this example is ActionScript 3.0 syntax.
First, lets set up our variables for the example
private var icon:Loader = new Loader(); private var systray:SystemTrayIcon; private var dock:DockIcon; private var copyrightCommand:NativeMenuItem = new NativeMenuItem("© 2009 Damon Edwards"); private var restoreCommand:NativeMenuItem = new NativeMenuItem("Restore"); private var exitCommand:NativeMenuItem = new NativeMenuItem("Exit");
So, as you can see, we need to set up a reference to instantiate an instance of the Loader class, the SystemTrayIcon class, the DockIcon class, and an instance for each menu item using the NativeMenuItem class. Now we can use these references in our application when setting up our system tray and dock icon. Next, I’ll typically add a call to a trayIcon(_sysTray:Boolean, _dock:Boolean); function like so:
public function ApplicationConstructor():void{ trayIcon(NativeApplication.supportsSystemTrayIcon, NativeApplication.supportsDockIcon); }
The trayIcon function accepts two boolean arguments, the first is the static method call to find out if the current system supports system tray icons, and the second is to find out if the current system supports dock icons. That way, we can apply the correct icons based on the operating system the application is running on. Let’s look at the trayIcon function.
private function trayIcon(_sysTray:Boolean, _dock:Boolean):void { if (_sysTray) { icon.contentLoaderInfo.addEventListener(Event.COMPLETE, iconLoadComplete); icon.load(new URLRequest("icons/icon_016.png")); systray=NativeApplication.nativeApplication.icon as SystemTrayIcon; systray.tooltip="DeskTube"; systray.menu=createIconMenu(_sysTray); } if (_dock) { icon.contentLoaderInfo.addEventListener(Event.COMPLETE,iconLoadComplete); icon.load(new URLRequest("icons/icon_128.png")); NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, undock); dock=NativeApplication.nativeApplication.icon as DockIcon; dock.menu=createIconMenu(_sysTray); } }
The first line in the function is a test case, basically saying, if _sysTray equals true, then do this. Same applies for the second case statement. Let’s run through assuming we’re running on a machine that allows system tray icons. We start by loading the correct icon, relative to your application install directory, and we add a listener to the icon loader that will fire when loading the icon completes. We then set the systray instance to the icon property of the native application, apply a tool tip, and set the menu. If you didn’t notice, I set the SystemTrayIcon’s menu to a function reference, that will return a NativeWindow, which we’ll explore shortly. If we we’re running on an operating system that supports dock icons, we’d follow almost the same steps. We have to load the correct icon, listen for it to complete loading, but here’s where the differences start. We need to add a listener to the application to call our undock function whenever the icon is clicked, and second, there is no tooltip property on dock icons. Then, of course, we create our menu which we’ll go over shortly.
Once the icon loads, we need to actually set the native application’s icon’s bitmap property to the newly loaded icon’s bitmap data, which is handled when the iconLoadComplete function is fired. This next function is pretty straight forward.
private function iconLoadComplete(e:Event):void { NativeApplication.nativeApplication.icon.bitmaps=[e.target.content.bitmapData]; }
Now on to the creation of the actual menu.
private function createIconMenu(_sysTray:Boolean):NativeMenu { var iconMenu:NativeMenu = new NativeMenu(); iconMenu.addItem(copyrightCommand); if (_sysTray) { iconMenu.addItem(new NativeMenuItem("", true)); iconMenu.addItem(restoreCommand); restoreCommand.addEventListener(Event.SELECT, undock); iconMenu.addItem(exitCommand); exitCommand.addEventListener(Event.SELECT, closeApp); } return iconMenu; }
The createIconMenu function accepts one argument, the same boolean value we user earlier for the system tray. We do this because, as explained earlier, the dock icon comes default with the exit option, and clicking the dock icon will restore the application. On windows, we need to add that manually. So, first we create a new instance of the NativeMenu class. I then add the copyright notice to the top of the menu, the item will have no actions when you click it. Now, if the system tray is present, we need to add restore and exit items, so we first add a separator by setting the second argument of the NativeMenuItem class to true, therefore signifying it as a separator. We then add our restore item, and add a listener to it that will fire when the user clicks this item. We do the same for the exit item, add it to the menu, then assign a listener for when it’s selected. After that, we return the window to be set as the menu for the icon.
We can finish up by creating our “undock” and “closeApp” functions.
private function undock(e:Event):void { stage.nativeWindow.restore(); } private function closeApp(e:Event):void { NativeApplication.exit(); }
These two functions are almost totally self explanatory, where the undock function restores the application from a minimized, or even maximized state to its default state. The close function does just that, it exits the application.
It’s really great to see all these new Adobe AIR applications popping up all over the place. Some are totally useless, but for the most part there are some extremely intuitive applications out there. We, as the new kids on the block in terms of application development, need to make sure we conform to the basic needs of an application. Thanks for having me, and check out my personal Adobe AIR application DeskTube, the desktop YouTube application.
Posted by Infantake on April 4, 2009 at 12:09 pm
Great site this baondp.wordpress.com and I am really pleased to see you have what I am actually looking for here and this this post is exactly what I am interested in. I shall be pleased to become a regular visitor
Posted by MiCdueri on April 10, 2009 at 11:34 pm
formidable site this baondp.wordpress.com terrific to see you have what I am actually looking for here and this this post is exactly what I am interested in. I shall be pleased to become a regular visitor