by Joe Ward

Joe Ward

Created

9 June 2010

Dock and system tray icons provide a convenient means to let users access an application that has no visible windows as well as to notify users that an event of interest has occurred. Adobe AIR provides two classes, DockIcon and SystemTrayIcon, that let you change the appearance, add menus, and respond to events of the application icon.

The Stopwatch example application, shown in Figure 1, illustrates the following Adobe AIR features:

  • Setting, showing, and animating an icon image
  • Responding to events dispatched when a user clicks an icon
  • Adding a menu to an icon
  • Bouncing a dock icon
  • Flashing a window button on the Windows taskbar

Note: This is a sample application provided, as is, for instructional purposes.

About application icons

Applications icons are supported on both the Mac OS X and Windows operating systems, although the conventions for using these icons on each system are a bit different. On Mac OS X, the application icon is the dock icon and is represented by a DockIcon object. On Windows, the application icon is the system tray icon and is represented by the SystemTrayIcon class. The DockIcon and the SystemTrayIcon classes are both subclasses of the InteractiveIcon class. The icon object for your application is created automatically. The object type is determined by the operating system on which the instance of your application is running.

Because the object type is not determined until run-time, you must be careful not to access the members of the wrong icon class. You can check which icon type is available using the static NativeApplication properties: supportsDockIcon and supportsSystemTrayIcon. Both types of icon support menus and images. The main differences are that:

  • System tray icons are only visible when an image is set.
  • Dock icons display the image specified in the application descriptor, unless a different image is set.
  • System tray icons have a tooltip property.
  • System tray icons dispatch mouse events.
  • Dock icons do not dispatch events directly, but a click can be detected by listening for the invoke event from the NativeApplication object.

Dock icons

Dock icons provide a means for users to easily access applications. An application icon is shown in the dock whenever the application is running. The user can also choose to keep the icon in the dock even when the application is not running. The image used for the icon in both cases is specified in the application descriptor file within the <icon> element. When your application is running, you can change the icon image by setting the NativeApplication.nativeApplication.icon.bitmaps property. When the application shuts down, the icon, if left in the dock, reverts back to the original image.

In addition to setting the icon image, you can add a menu to the dock icon. When you add a menu, the items are displayed above the standard, operating-system provided menu.

Although you cannot listen for mouse events on the dock icon directly, an invoke event is dispatched by the NativeApplication object whenever the user clicks the dock icon.

System tray icons

On Windows, the official purpose of the system tray is to notify the user that important application events have occurred, such as the arrival of an e-mail—hence the official name of the system tray is the notification area. In practice, the system tray has also become a place where users can access applications or utilities that do not ordinarily display windows.

The system tray icon for an AIR application is not displayed by default. To show the icon, you must provide an image for the icon by setting the bitmaps array. Likewise, to remove the icon from the system tray, you clear the image by setting the bitmaps property to an empty array.

System tray icons support a menu, a tooltip, and dispatches events for mouse events.

The Stopwatch example application

The Stopwatch application creates a 60-second timer utility that animates the system tray or dock icon as it counts down. Stopwatch illustrates how to use and animate system tray and dock icons.

To test the application, launch the Stopwatch application (Stopwatch.air) file. Click the triangular start button to start the watch. Note that the system tray or dock icon changes as the time ticks down. Click the small yellow button to minimize the application to the system tray or dock. The stopwatch window automatically reappears when the countdown reaches zero. You can also click on the application icon to restore the window.

Understanding the code

The Stopwatch example has two key parts. The main Stopwatch class serves as the entry point into the application and defines all the functions for working with the application icons. The rest of the classes, in the application package, define the user interface for displaying, setting, and controlling the clock. These classes use ActionScript and basic Flash APIs. They are not discussed in detail in this article.

Setting up

The Stopwatch class constructor function adds child display objects for the clock and clock controls, and initializes the timer.

To set up the application icon, Stopwatch checks which type of icon is available using the static supportsDockIcon and supportsSystemTrayIcon properties of the NativeApplication class and then adds event listeners, menus, and a tooltip:

if(NativeApplication.supportsDockIcon){ var dockIcon:DockIcon = NativeApplication.nativeApplication.icon as DockIcon; NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, undock); dockIcon.menu = createIconMenu(); } else if (NativeApplication.supportsSystemTrayIcon){ var sysTrayIcon:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon; sysTrayIcon.tooltip = "Stopwatch"; sysTrayIcon.addEventListener(MouseEvent.CLICK,undock); sysTrayIcon.menu = createIconMenu(); }

Adding a menu

The createIconMenu() function creates the menus for the application. The function creates a NativeMenu object with the command items: Start and Pause to control the timer. For the system tray icon, the function also adds Show window and Exit commands. These commands are unnecessary for the dock icon menu, because the standard menu of the dock icon already includes commands for these functions. The standard menu items cannot be removed or changed by your application. Any menu commands added to the dock menu are displayed above the standard items.

private var startCommand:NativeMenuItem = new NativeMenuItem("Start"); private var pauseCommand:NativeMenuItem = new NativeMenuItem("Pause"); private var showCommand: NativeMenuItem = new NativeMenuItem("Show clock"); private function createIconMenu():NativeMenu{ var iconMenu:NativeMenu = new NativeMenu(); iconMenu.addItem(startCommand); startCommand.addEventListener(Event.SELECT, toggleTimer); iconMenu.addItem(pauseCommand); pauseCommand.addEventListener(Event.SELECT, toggleTimer); iconMenu.addItem(new NativeMenuItem("", true));//Separator if(NativeApplication.supportsSystemTrayIcon){ iconMenu.addItem(showCommand); showCommand.addEventListener(Event.SELECT, undock); iconMenu.addItem(new NativeMenuItem("", true));//Separator var exitCommand: NativeMenuItem = iconMenu.addItem(new NativeMenuItem("Exit")); exitCommand.addEventListener(Event.SELECT, exit); } iconMenu.addItem(new NativeMenuItem("", true));//Separator iconMenu.addSubmenu(createSourceCodeMenu(), "Source code"); iconMenu.addEventListener(Event.DISPLAYING, setMenuCommandStates); return iconMenu; }

Because the state of the Start, Pause, and Show clock menu items depends on the current application state, a handler for the menu displaying event is used. The menu dispatches the displaying event before showing the menu items. The following event handler updates the enabled property of the startCommand and pauseCommand objects and the checked property of the showCommand object:

private function setMenuCommandStates(event:Event):void{ startCommand.enabled = goButton.startState; pauseCommand.enabled = !goButton.startState; showCommand.checked = stage.nativeWindow.visible; }

Docking the application

Stopwatch docks the application by hiding the clock window and setting the icon image to a snapshot of the clock face:

public function dock(event:Event = null):void{ stage.nativeWindow.visible = false; NativeApplication.nativeApplication.icon.bitmaps = [clock.bitmapData]; }

On Mac OS X, setting the icon image is not strictly necessary, because an image is always shown. On Windows, setting the image is critical, because otherwise there would be no icon and no way for the user to restore the application.

To undock the application, Stopwatch makes the window visible again and clears the icon image to remove the icon from the system tray on Windows. (On Mac OS X, this restores the default icon image.)

public function undock(event:Event = null):void{ stage.nativeWindow.visible = true; NativeApplication.nativeApplication.icon.bitmaps = []; }

Animating the icon

Stopwatch animates the icon by updating the icon bitmaps array on every one second tick of the stopwatch timer. The Clock class, which defines the stopwatch visuals, provides a property bitmapData that provides a snapshot of the clock display. The following function creates a bitmap image of the current visual state of the Clock object using the BitmapData object draw() method:

public function get bitmapData():BitmapData{ var clockImage:BitmapData = new BitmapData(this.width, this.height,true,0x00ffffff); clockImage.draw(this); return clockImage; }

To create an icon with transparency, the BitmapData object used to define the image for the icon must be created with the transparent parameter of its constructor set to true. In addition, the fill color should be set using a 32-bit ARGB color value, setting the alpha component to 0. In hexadecimal format, for example, you could use: 0x00ffffff.

The Stopwatch example assigns the BitmapData object provided by the Clock bitmapData property to the bitmaps array of the icon. Because bitmaps is an Array object, you must place the image into an array, in this case, using bracket notation: [clock.bitmapData]. If you supply an array containing more than one image, the system chooses the image closest to the displayed size of the icon. For example, the dock icon uses the icon closest to 128x128 pixels, while the system tray icon uses the icon closest to 16x16 pixels. Your icons typically look better when the display size matches the image size, since no scaling has to be performed.

public function changeIcon():void{ NativeApplication.nativeApplication.icon.bitmaps = [clock.bitmapData]; }

Note: You cannot modify the Array object referenced by the bitmaps property. You can only assign a new array. For example, the following statement:

NativeApplication.nativeApplication.icon.bitmaps.push(clock.bitmapData);

would not work.

Notifying the user that an event has occurred

On Mac OS X, the dock icon can be used to notify the user that an event of interest has occurred. In Stopwatch, the dock icon is bounced when the timer reaches zero by calling icon.bounce(). If the critical notification type is used, the dock icon bounces until the user activates the application. If the informational type is used, the dock icon bounces once. (If the application already has focus, the dock icon does not bounce at all.)

Windows does not use the same notification scheme. You can change the system tray icon image or pop-up a lightweight window containing a message, but the system tray icon cannot be bounced. A window-level notification function is provided on Windows that can be used when your application has a window button in the taskbar. This function, notifyUser(), called on the NativeWindow object, highlights or flashes the window taskbar button.

Stopwatch checks which type of icon the current operating system supports and calls either the DockIcon.bounce() or the NativeWindow.notifyUser() function.

public function notify():void{ if(NativeApplication.supportsDockIcon){ var dock:DockIcon = NativeApplication.nativeApplication.icon as DockIcon; dock.bounce(NotificationType.CRITICAL); } else if (NativeApplication.supportsSystemTrayIcon){ stage.nativeWindow.notifyUser(NotificationType.CRITICAL); } }

Requirements

Prerequisite knowledge

General experience of building applications with Flash Professional is suggested. For more details on getting started with this Quick Start, refer to Building the Quick Start sample applications with Flash.

User level

Intermediate