com.adito.agent.client.gui.swt.SWTSystemTrayGUI.java Source code

Java tutorial

Introduction

Here is the source code for com.adito.agent.client.gui.swt.SWTSystemTrayGUI.java

Source

/*
*  Adito
*
*  Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; either version 2 of
*  the License, or (at your option) any later version.
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public
*  License along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package com.adito.agent.client.gui.swt;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;

import com.maverick.http.HttpAuthenticator;
import com.adito.agent.client.ActionCallback;
import com.adito.agent.client.Agent;
import com.adito.agent.client.AgentAction;
import com.adito.agent.client.AgentClientGUI;
import com.adito.agent.client.Console;
import com.adito.agent.client.PortMonitor;
import com.adito.agent.client.TaskProgress;
import com.adito.agent.client.util.BrowserLauncher;

/**
 * {@link AbstractAWTGUI} implementation that uses the system tray API provided
 * with SWT.
 */
public class SWTSystemTrayGUI implements AgentClientGUI {

    // #ifdef DEBUG
    static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
            .getLog(SWTSystemTrayGUI.class);
    // #endif

    final int IDLE_ICON = 0;
    final int TX_ICON = 1;
    final int RX_ICON = 2;
    final int TXRX_ICON = 3;
    final int DISCONNECTED_ICON = 4;

    /**
     * Default timeout
     */
    public final static int DEFAULT_TIMEOUT = 10000;

    // Private instance variables

    private Image[] icons;
    private Tray tray;
    private TrayItem trayItem;
    private Display display;
    private Agent agent;
    private Menu popupMenu;
    private Shell shell;
    private Object initLock = new Object() {
    };
    private SWTBalloonWindow balloon;
    private Label messageLabel;
    private PortMonitor portMonitor;
    private PopupTimer popupTimer;
    private Console console;
    private int menuIdx = 0;

    private Hashtable menuLookup = new Hashtable();
    private Hashtable menuItemLookup = new Hashtable();

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#init(com.adito.vpn.client.VPNClientGUIListener)
     */
    public void init(Agent agent) {
        this.agent = agent;
        Thread t = new Thread() {
            public void run() {
                doInit();
                eventLoop();
            }
        };
        t.start();
        synchronized (initLock) {
            try {
                initLock.wait();
            } catch (InterruptedException e) {
            }
        }

    }

    public Menu getMenu() {
        return popupMenu;
    }

    public Agent getAgent() {
        return agent;
    }

    public Display getDisplay() {
        return display;
    }

    public Shell getShell() {
        return shell;
    }

    protected void doInit() {
        //
        display = new Display();
        shell = new Shell(display);

        // Load the icons
        icons = new Image[5];
        icons[IDLE_ICON] = loadImage(SWTSystemTrayGUI.class, "/images/tray-idle.gif"); //$NON-NLS-1$
        icons[TX_ICON] = loadImage(SWTSystemTrayGUI.class, "/images/tray-tx.gif"); //$NON-NLS-1$
        icons[RX_ICON] = loadImage(SWTSystemTrayGUI.class, "/images/tray-rx.gif"); //$NON-NLS-1$
        icons[TXRX_ICON] = loadImage(SWTSystemTrayGUI.class, "/images/tray-txrx.gif"); //$NON-NLS-1$
        icons[DISCONNECTED_ICON] = loadImage(SWTSystemTrayGUI.class, "/images/tray-disconnecting.gif"); //$NON-NLS-1$

        // Create the menu
        popupMenu = new Menu(shell, SWT.POP_UP);

        MenuItem open = new MenuItem(popupMenu, SWT.PUSH);
        open.setText(Messages.getString("GUI.menu.openBrowser")); //$NON-NLS-1$
        open.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
            }

            public void widgetSelected(SelectionEvent e) {
                openBrowser(null);
            }
        });

        // #ifdef DEBUG
        MenuItem console = new MenuItem(popupMenu, SWT.PUSH);
        console.setText(Messages.getString("GUI.menu.debugConsole")); //$NON-NLS-1$
        console.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
            }

            public void widgetSelected(SelectionEvent e) {
                getConsole().show();
            }
        });
        // #endif
        MenuItem ports = new MenuItem(popupMenu, SWT.PUSH);
        ports.setText(Messages.getString("GUI.menu.tunnelMonitor")); //$NON-NLS-1$
        ports.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
            }

            public void widgetSelected(SelectionEvent e) {
                getPortMonitor().setVisible(!getPortMonitor().isVisible());
            }
        });
        MenuItem about = new MenuItem(popupMenu, SWT.PUSH);
        about.setText(Messages.getString("GUI.menu.about")); //$NON-NLS-1$
        about.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
            }

            public void widgetSelected(SelectionEvent e) {
                about();
            }
        });

        // Create the menu items
        new MenuItem(popupMenu, SWT.SEPARATOR);
        MenuItem exit = new MenuItem(popupMenu, SWT.PUSH);
        exit.setText(Messages.getString("GUI.menu.exit")); //$NON-NLS-1$
        exit.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
            }

            public void widgetSelected(SelectionEvent e) {
                exit();
            }
        });

        // Create the tray item
        tray = display.getSystemTray();
        if (tray == null) {
            // #ifdef DEBUG
            log.error("The system tray is not available");
            // #endif
        } else {
            // Create the icon
            trayItem = new TrayItem(tray, SWT.NONE);
            trayItem.setToolTipText(Messages.getString("GUI.appName"));
            trayItem.addListener(SWT.Show, new Listener() {
                public void handleEvent(Event event) {
                }
            });
            trayItem.addListener(SWT.Hide, new Listener() {
                public void handleEvent(Event event) {
                }
            });
            trayItem.addListener(SWT.Selection, new Listener() {
                public void handleEvent(Event event) {
                }
            });
            trayItem.addListener(SWT.DefaultSelection, new Listener() {
                public void handleEvent(Event event) {
                }
            });
            trayItem.addListener(SWT.MenuDetect, new Listener() {
                public void handleEvent(Event event) {
                    popupMenu.setVisible(true);
                }
            });
            trayItem.setImage(icons[IDLE_ICON]);
        }
    }

    void about() {
        final Image image = loadImage(SWTSystemTrayGUI.class, "/images/frame-agent.png");
        SWTAboutDialog about = new SWTAboutDialog(shell, Messages.getString("About.close"),
                Messages.getString("About.title"), image,
                MessageFormat.format(Messages.getString("About.message"),
                        new Object[] { agent.getServerVersion() }),
                Messages.getString("About.description"), Messages.getString("About.copyright"),
                Messages.getString("About.link"));

        if (agent.getState() != Agent.STATE_DISCONNECTED) {

            Composite shell = about.getAccessory();

            Composite c = new Composite(shell, 0);
            GridLayout gridLayout = new GridLayout();
            c.setLayout(gridLayout);

            Label host = new Label(c, SWT.WRAP);
            host.setText(
                    MessageFormat.format(Messages.getString("About.host"), new Object[] { agent.getAditoHost() }));
            GridData data = new GridData();
            data.horizontalAlignment = GridData.BEGINNING;
            data.grabExcessHorizontalSpace = true;
            host.setLayoutData(data);

            Label port = new Label(c, SWT.WRAP);
            port.setText(MessageFormat.format(Messages.getString("About.port"),
                    new Object[] { String.valueOf(agent.getAditoPort()) }));
            data = new GridData();
            data.horizontalAlignment = GridData.BEGINNING;
            data.grabExcessHorizontalSpace = true;
            port.setLayoutData(data);

            Label username = new Label(c, SWT.WRAP);
            username.setText(MessageFormat.format(Messages.getString("About.username"),
                    new Object[] { agent.getUsername() }));
            data = new GridData();
            data.horizontalAlignment = GridData.BEGINNING;
            data.grabExcessHorizontalSpace = true;
            username.setLayoutData(data);

            Label serverVersion = new Label(c, SWT.WRAP);
            serverVersion.setText(MessageFormat.format(Messages.getString("About.serverVersion"),
                    new Object[] { agent.getServerVersion() }));
            data = new GridData();
            data.horizontalAlignment = GridData.BEGINNING;
            data.grabExcessHorizontalSpace = true;
            serverVersion.setLayoutData(data);

            Label agentVersion = new Label(c, SWT.WRAP);
            agentVersion.setText(MessageFormat.format(Messages.getString("About.agentVersion"),
                    new Object[] { agent.getClientVersion() }));
            data = new GridData();
            data.horizontalAlignment = GridData.BEGINNING;
            data.grabExcessHorizontalSpace = true;
            agentVersion.setLayoutData(data);
        }

        about.open();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.agent.client.AgentClientGUI#openBrowser(java.lang.String)
     */
    public void openBrowser(String path) {
        try {
            String browserPath = "https://" + agent.getAditoHost() + ":" + agent.getAditoPort() + //$NON-NLS-1$ //$NON-NLS-2$ 
                    (path == null ? "" : ("/" + path));
            // #ifdef DEBUG
            log.info("Opening browser to " + browserPath);
            // #endif
            BrowserLauncher.openURL(browserPath);
        } catch (IOException ioe) {
            // #ifdef DEBUG
            log.error(ioe);
            // #endif
        }
    }

    void eventLoop() {
        synchronized (initLock) {
            initLock.notify();
        }
        while (true) {
            if (!display.readAndDispatch())
                display.sleep();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#showIdle()
     */
    public void showIdle() {
        setImage(icons[IDLE_ICON]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#showDisconnected()
     */
    public void showDisconnected() {
        setImage(icons[DISCONNECTED_ICON]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#showTx()
     */
    public void showTx() {
        setImage(icons[TX_ICON]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#showRx()
     */
    public void showRx() {
        setImage(icons[RX_ICON]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#showTxRx()
     */
    public void showTxRx() {
        setImage(icons[TXRX_ICON]);
    }

    void setImage(final Image image) {
        display.asyncExec(new Runnable() {
            public void run() {
                trayItem.setImage(image);
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.vpn.client.VPNClientGUI#setInfo(java.lang.String)
     */
    public void setInfo(final String info) {
        display.asyncExec(new Runnable() {
            public void run() {
                trayItem.setToolTipText(info);
            }
        });
    }

    protected Image loadImage(Class clazz, String path) {
        InputStream stream = clazz.getResourceAsStream(path);
        return stream == null ? null : new Image(display, stream);
    }

    public boolean confirm(final int dialogType, final String okText, final String cancelText, final String title,
            final String message) {
        final List l = new ArrayList();
        display.syncExec(new Runnable() {
            public void run() {
                int type = SWT.ICON_QUESTION;
                if (dialogType == INFORMATION) {
                    type = SWT.ICON_INFORMATION;
                } else if (dialogType == ERROR) {
                    type = SWT.ICON_ERROR;
                } else if (dialogType == WARNING) {
                    type = SWT.ICON_WARNING;
                }
                MessageBox messageBox = new MessageBox(shell,
                        type | SWT.OK | (cancelText != null ? SWT.CANCEL : 0));
                messageBox.setText(title);
                messageBox.setMessage(message);
                int buttonID = messageBox.open();
                switch (buttonID) {
                case SWT.OK:
                    l.add(Boolean.TRUE);
                default:
                    l.add(Boolean.FALSE);
                }
            }
        });
        return ((Boolean) l.get(0)).booleanValue();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.agent.client.AgentClientGUI#error(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String,
     *      java.lang.Throwable)
     */
    public boolean error(String okText, String cancelText, String title, String message, Throwable ex) {
        return confirm(ERROR, okText, cancelText, title, message);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.agent.client.AgentClientGUI#getConsole()
     */
    public synchronized Console getConsole() {
        if (console == null) {
            console = new SWTConsoleOutputStream(
                    "true".equals(System.getProperty("console.toSysOut", "false")) ? System.out : null, this); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        }
        return console;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.agent.client.AgentClientGUI#createTaskProgress(java.lang.String,
     *      java.lang.String, long, boolean)
     */
    public TaskProgress createTaskProgress(String message, String note, long maxValue, boolean allowCancel) {
        return new SWTProgressDialog(this, (int) maxValue, allowCancel, message, note);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.agent.client.AgentClientGUI#popup(com.adito.agent.client.AgentClientGUI.ActionCallback,
     *      java.lang.String, java.lang.String, java.lang.String, int)
     */
    public void popup(final ActionCallback callback, final String message, final String title,
            final String imageName, final int timeout) {
        display.syncExec(new Runnable() {
            public void run() {

                if (popupTimer != null) {
                    popupTimer.setBalloon(null);
                }
                popupTimer = new PopupTimer();

                if (balloon != null && !balloon.getShell().isDisposed()) {
                    balloon.setVisible(false);
                }
                balloon = new SWTBalloonWindow(display, SWT.ON_TOP | SWT.TITLE | SWT.CLOSE);
                balloon.setAutoLocation(SWT.BOTTOM | SWT.RIGHT);
                balloon.setLocation(56, 56);
                balloon.setAnchor(SWT.BOTTOM | SWT.RIGHT);
                balloon.setAutoAnchor(false);
                balloon.getContents().setLayout(new FillLayout());
                balloon.addListener(SWT.Selection, new Listener() {
                    public void handleEvent(Event event) {
                        // #ifdef DEBUG
                        log.debug("Balloon selected");
                        // #endif
                        if (callback != null) {
                            callback.actionPerformed();
                        }
                        balloon.close();
                    }
                });
                messageLabel = new Label(balloon.getContents(), SWT.WRAP);
                messageLabel.setForeground(balloon.getShell().getForeground());
                messageLabel.setBackground(balloon.getShell().getBackground());
                balloon.addSelectionControl(messageLabel);
                balloon.setText(title);

                // balloon.setText(title);
                messageLabel.setText(message == null ? "<No message supplied>" : message);
                messageLabel.setSize(messageLabel.computeSize(300, SWT.DEFAULT));
                Composite c = balloon.getContents();
                Point messageSize = messageLabel.getSize();
                Image image = imageName != null ? loadImage(SWTSystemTrayGUI.class, "/images/" + imageName + ".png")
                        : null;
                if (image != null) {
                    balloon.setImage(image);
                    c.setSize(messageSize.x, messageSize.y);
                } else {
                    c.setSize(messageSize);
                }
                if (!balloon.getShell().getVisible()) {
                    balloon.setVisible(true);
                }
                if (timeout != 0) {
                    popupTimer.setBalloon(balloon);
                    display.timerExec(timeout == -1 ? DEFAULT_TIMEOUT : timeout, popupTimer);
                }
            }
        });
    }

    public PortMonitor getPortMonitor() {
        if (portMonitor == null) {
            createPortMonitor();
        }
        return portMonitor;
    }

    public boolean promptForCredentials(final boolean proxy, final HttpAuthenticator authenticator) {
        return ((Boolean) SWTRunner.syncExec(display, new SWTRunner() {
            public Object doRun() {
                return new Boolean(SWTAuthenticationDialog.promptForCredentials(proxy, shell, authenticator, null));
            }

        })).booleanValue();
    }

    public void dispose() {
        shell.getDisplay().syncExec(new Runnable() {
            public void run() {
                if (tray != null) {
                    trayItem.dispose();
                    tray.dispose();
                }
                getPortMonitor().dispose();
                getConsole().dispose();
            }
        });
    }

    public void addMenu(final String name) {

        display.syncExec(new Runnable() {
            public void run() {
                if (menuIdx == 0) {
                    new MenuItem(popupMenu, SWT.SEPARATOR, 0);
                }
                MenuItem item = new MenuItem(popupMenu, SWT.CASCADE, menuIdx);
                menuIdx++;
                item.setText(name);
                Menu menu = new Menu(popupMenu);
                item.setMenu(menu);
                menuLookup.put(name, menu);
                menuItemLookup.put(name, item);
            }
        });
    }

    public void removeMenu(final String name) {

        display.syncExec(new Runnable() {
            public void run() {
                Menu menu = (Menu) menuLookup.get(name);
                MenuItem menuItem = (MenuItem) menuItemLookup.get(name);
                if (menu != null) {
                    menu.dispose();
                    menuItem.dispose();
                    menuLookup.remove(name);
                    menuItemLookup.remove(name);
                }
            }
        });
    }

    public void clearMenu(final String name) {

        display.syncExec(new Runnable() {
            public void run() {
                Menu menu = (Menu) menuLookup.get(name);
                if (menu != null) {
                    while (menu.getItemCount() > 0) {
                        menu.getItem(0).dispose();
                    }
                }
            }
        });
    }

    public boolean isMenuExists(String name) {
        return menuLookup.containsKey(name);
    }

    public void addMenuItem(String name, final AgentAction action) {

        // #ifdef DEBUG
        log.debug("Adding menu item " + action.getAction() + " to " + name);
        // #endif
        final Menu parentMenu = name == null ? popupMenu : (Menu) menuLookup.get(name);
        if (parentMenu == null) {
            // #ifdef DEBUG
            log.error("No parent menu item " + name + " for " + action.getAction());
            // #endif
            return;
        }

        display.syncExec(new Runnable() {
            public void run() {
                MenuItem item = new MenuItem(parentMenu, SWT.PUSH);
                item.setText(action.getAction());
                item.addSelectionListener(new SelectionListener() {
                    public void widgetDefaultSelected(SelectionEvent e) {
                    }

                    public void widgetSelected(SelectionEvent e) {
                        action.actionPerformed();
                    }
                });
            }
        });
    }

    public void addMenuSeperator(String name) {

        final Menu parentMenu = name == null ? popupMenu : (Menu) menuLookup.get(name);
        if (parentMenu == null)
            return;
        display.syncExec(new Runnable() {
            public void run() {
                new MenuItem(parentMenu, SWT.SEPARATOR);
            }
        });

    }

    protected void createPortMonitor() {
        display.syncExec(new Runnable() {
            public void run() {
                portMonitor = new SWTPortMonitor(SWTSystemTrayGUI.this);
            }
        });
    }

    protected void exit() {
        agent.disconnect();
    }

    class PopupTimer implements Runnable {

        private SWTBalloonWindow balloon;

        public void setBalloon(SWTBalloonWindow balloon) {
            this.balloon = balloon;
        }

        public void run() {
            display.syncExec(new Runnable() {
                public void run() {
                    if (balloon != null && !balloon.getShell().isDisposed()) {
                        balloon.setVisible(false);
                    }
                }
            });
        }
    }

}