Wednesday, October 28, 2009

Section 6.3.  System Tray Integration










6.3. System Tray Integration


Another common feature of instant messaging applications is integration into the system tray. Using this idea, we want Hyperbola to appear in the system tray as an icon representing the user's presence. This also allows Hyperbola to minimize to the system tray rather than continuing to be displayed in the task bar even though it is minimized. The tray items are also a popular location for adding actions related to your application. Figure 6-8 shows how this looks for Hyperbola.



Figure 6-8. Context menu on the Hyperbola task tray item







Tip



If you are going to use the system tray, it is good practice to make its use optionalif every application put itself in the system tray, it would get cluttered. When it is enabled, it should be used to display important status information to the user and provide a quick access point for running frequent actions.


Also, the system tray is not available on all platforms, so do not make it the focal point of your application's workflow. It should be used as an optional integration feature.




In this section, we show you how to:


  • Add the Hyperbola icon to the task tray.

  • Allow Hyperbola to minimize to the task tray.

  • Add the About and Exit actions to the context menu of the task tray item.



6.3.1. Obtaining a Display


To get the system tray, you need a Display. A Display is an SWT object that represents the underlying graphics system. Typically, the Display is not available until the window has been created. Figure 6-9 shows the WorkbenchWindow lifecycle and highlights the earliest point, in postWindowOpen(), where the Display is available. So, the first time a window is opened, the WorkbenchWindowAdvisor can get the Display via the window's shell and set up the system tray for Hyperbola. At this point, the tray item is created and configured such that when its menu is shown, the ActionBarAdvisor populates the menu.



Figure 6-9. How the ActionBarAdvisor contributes actions to the task item









6.3.2. Creating the Tray Item


The code snippet below from ApplicationWorkbenchWindowAdvisor shows how the system tray item is created and how it operates. First, the item is created and configured and then listeners are added to support showing the menu and minimizing into the tray item. After the tray item is set up, a menu listener is added to it. That way, when the tray item is right-clicked, a context menu appears and is populated by the ActionBarAdvisor. Some platforms do not have system trays and initTaskItem() may return null. In that case, the tray item is not created.


org.eclipsercp.hyperbola/ApplicationWorkbenchWindowAdvisor
public void postWindowOpen() {
initStatusLine();
final IWorkbenchWindow window = getWindowConfigurer().getWindow();
trayItem = initTaskItem(window);
if (trayItem != null) {
hookPopupMenu(window);
hookMinimize(window);
}
}

private void hookMinimize(final IWorkbenchWindow window) {
window.getShell().addShellListener(new ShellAdapter() {
public void shellIconified(ShellEvent e) {
window.getShell().setVisible(false);
}
});
trayItem.addListener(SWT.DefaultSelection, new Listener() {
public void handleEvent(Event event) {
Shell shell = window.getShell();
if (!shell.isVisible()) {
shell.setVisible(true);
window.getShell().setMinimized(false);
}
}
});
}

private void hookPopupMenu(final IWorkbenchWindow window) {
trayItem.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
MenuManager trayMenu = new MenuManager();
Menu menu = trayMenu.createContextMenu(window.getShell());
actionBarAdvisor.fillTrayItem(trayMenu);
menu.setVisible(true);
}
});
}

private TrayItem initTaskItem(IWorkbenchWindow window) {
final Tray tray = window.getShell().getDisplay().getSystemTray();
if (tray == null)
return null;
TrayItem trayItem = new TrayItem(tray, SWT.NONE);
trayImage = AbstractUIPlugin.imageDescriptorFromPlugin(
"org.eclipsercp.hyperbola", IImageKeys.ONLINE).createImage();
trayItem.setImage(trayImage);
trayItem.setToolTipText("Hyperbola");
return trayItem;
}

public void dispose() {
if (trayImage != null) {
trayImage.dispose();
trayItem.dispose();
}
}


Note



The image and tray item area are saved as fields on the WorkbenchWindowAdvisor so that they can be deleted when the window is closed.




Since the ActionBarAdvisor already manages all of Hyperbola's actions, it is a good place to put the method that fills the system tray item's menu. This also allows the tray item menu to reuse actions created in the ActionBarAdvisor. Add the following snippet to ApplicationActionBarAdvisor:


org.eclipsercp.hyperbola/ApplicationActionBarAdvisor
protected void fillTrayItem(IMenuManager trayItem) {
trayItem.add(aboutAction);
trayItem.add(exitAction);
}


A shell listener is added in the hookMinimize() method to the window so that the window is marked as hidden when minimized. This simulates minimizing the window into the task bar. When the window is invisible, the only indication that Hyperbola is running is the system tray icon.


Another listener, also added in the hookMinimize() method, listens to the tray item to detect when it is selected. Selecting the task item is the cue that Hyperbola's window should be made visible if it had previously been minimized.


After setting this up, run Hyperbola and look for the system tray icon. Right-click it and the context menu appears. Minimize Hyperbola and notice that Hyperbola is completely gone except for the task tray icon. Click the tray icon and Hyperbola reappears.













No comments:

Post a Comment