Adding a Tray Icon functionality to SWT application is quite easy. But to do something similar in Eclipse RCP is a little involved. This Blog entry explains how I do it in JBlogEditor.

    We want our RCP application to behave thusly:

  1. Minimize to taskbar when minimize button is clicked.
  2. Minimize to tray when close button is clicked.
  3. Restore workbench window when tray icon is double clicked.
  4. Show Exit and Open menu when the tray icon is right clicked.

For the 1st behaviour, we do not need to alter the normal window behaviour.

For the 2nd behaviour, we need to prevent the Workbench from perform its default behaviour of closing. To do that we override public boolean preWindowShellClose() method of WorkbenchWindowAdvisor. Quite possibly you already have your own XXXWorkbenchWindowAdvisor. Just override public boolean preWindowShellClose() method in there. To prevent the workbench from closing, we return false from this method.
Before we return false from the public boolean preWindowShellClose() method to prevent the workbench from closing, we need to take care of creating the tray icon. to do so, we use the following code:
[java]
//get the display and image using standard eclipse mechanisms
TrayItem trayItem = new TrayItem(display.getSystemTray(), SWT.NONE);
trayItem.setImage(image, true));
trayItem.setToolTipText(“My RCP App”);
[/java]
The code above creates and puts a tray icon in the System tray. Next we hide the workbench window.
getWindowConfigurer().getWindow().getShell().setVisible(false);
Now we can return false;

For the 3rd behaviour, we need to attach a listener to the tray icon double click and show the workbench in the event handler. To attach the listener, we use this code before returning false in the public boolean preWindowShellClose() method:
[java]
trayItem.addSelectionListener(new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
Shell workbenchWindowShell = getWindowConfigurer().getWindow().getShell();
workbenchWindowShell.setVisible(true);
workbenchWindowShell.setActive();
workbenchWindowShell.setFocus();
workbenchWindowShell.setMinimized(false);
image.dispose();
trayItem.dispose();
}
});
[/java]
In the event handler, make the workbench shell visible, active, in focus and set minimized to false. We also dispose the tray item and the image.

For the 4th and final behaviour, we attach a menu to the tray item using standard SWT mechanism. Here’s the code:
[java]
Shell workbenchWindowShell = getWindowConfigurer().getWindow().getShell();
//Create a Menu
final Menu menu = new Menu(workbenchWindowShell, SWT.POP_UP);
//Create the exit menu item.
final MenuItem exit = new MenuItem(menu, SWT.PUSH);
exit.setText(“Exit”);
//Do a workbench close in the event handler for exit menu item.
exit.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
image.dispose();
trayItem.dispose();
open.dispose();
exit.dispose();
menu.dispose();
getWindowConfigurer().getWorkbenchConfigurer().getWorkbench().close();
}
});

//Create the open menu item.
final MenuItem open = new MenuItem(menu, SWT.PUSH);
open.setText(“Open”);
//make the workbench visible in the event handler for exit menu item.
open.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
Shell workbenchWindowShell = getWindowConfigurer().getWindow().getShell();
workbenchWindowShell.setVisible(true);
workbenchWindowShell.setActive();
workbenchWindowShell.setFocus();
workbenchWindowShell.setMinimized(false);
image.dispose();
trayItem.dispose();
open.dispose();
exit.dispose();
menu.dispose();
}
});
trayItem.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
menu.setVisible(true);
}
});
[/java]

NOTE: It will be more efficient to close the workbench on minimize to tray and then recreate a new one when the tray icon is double clicked. But that’s another entry 🙂

Suggestions to improve this code are welcome.

Advertisements