diff --git a/build.xml b/build.xml index e34b7458..fc4cb3a9 100644 --- a/build.xml +++ b/build.xml @@ -1,5 +1,5 @@ - + @@ -56,8 +56,9 @@ - + + diff --git a/davmail.jsmooth b/davmail.jsmooth index 27189fd4..c584eff9 100644 --- a/davmail.jsmooth +++ b/davmail.jsmooth @@ -17,6 +17,7 @@ dist\lib\mail-1.3.2.jar dist\lib\saxpath-1.0-FCS.jar dist\lib\slide-webdavlib-2.1.jar +dist\lib\swt-3.3-win32-win32-x86.jar dist\davmail.jar false dist\davmail.exe diff --git a/davmailconsole.jsmooth b/davmailconsole.jsmooth index 80544c9b..b0a8af5b 100644 --- a/davmailconsole.jsmooth +++ b/davmailconsole.jsmooth @@ -17,6 +17,7 @@ dist\lib\mail-1.3.2.jar dist\lib\saxpath-1.0-FCS.jar dist\lib\slide-webdavlib-2.1.jar +dist\lib\swt-3.3-win32-win32-x86.jar dist\davmail.jar false dist\davmailconsole.exe diff --git a/lib/swt-3.3-carbon-macosx.jar b/lib/swt-3.3-carbon-macosx.jar new file mode 100644 index 00000000..9ce25056 Binary files /dev/null and b/lib/swt-3.3-carbon-macosx.jar differ diff --git a/lib/swt-3.3-gtk-linux-x86.jar b/lib/swt-3.3-gtk-linux-x86.jar new file mode 100644 index 00000000..b29be023 Binary files /dev/null and b/lib/swt-3.3-gtk-linux-x86.jar differ diff --git a/lib/swt-3.3-win32-win32-x86.jar b/lib/swt-3.3-win32-win32-x86.jar new file mode 100644 index 00000000..9c7e113b Binary files /dev/null and b/lib/swt-3.3-win32-win32-x86.jar differ diff --git a/src/java/davmail/AwtGatewayTray.java b/src/java/davmail/AwtGatewayTray.java new file mode 100644 index 00000000..b62a330a --- /dev/null +++ b/src/java/davmail/AwtGatewayTray.java @@ -0,0 +1,149 @@ +package davmail; + +import org.apache.log4j.Logger; +import org.apache.log4j.Priority; +import org.apache.log4j.lf5.LF5Appender; +import org.apache.log4j.lf5.LogLevel; +import org.apache.log4j.lf5.viewer.LogBrokerMonitor; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; + +/** + * Tray icon handler based on java 1.6 + */ +public class AwtGatewayTray implements DavGatewayTrayInterface { + protected AwtGatewayTray() { + } + + protected static final Logger LOGGER = Logger.getLogger("davmail"); + + // LOCK for synchronized block + protected static final Object LOCK = new Object(); + + private static TrayIcon trayIcon = null; + private static Image image = null; + private static Image image2 = null; + + public void switchIcon() { + synchronized (LOCK) { + if (trayIcon.getImage() == image) { + trayIcon.setImage(image2); + } else { + trayIcon.setImage(image); + } + } + } + + public void resetIcon() { + synchronized (LOCK) { + trayIcon.setImage(image); + } + } + + public void displayMessage(String message, Priority priority) { + synchronized (LOCK) { + if (trayIcon != null) { + TrayIcon.MessageType messageType = null; + if (priority == Priority.INFO) { + messageType = TrayIcon.MessageType.INFO; + } else if (priority == Priority.WARN) { + messageType = TrayIcon.MessageType.WARNING; + } else if (priority == Priority.ERROR) { + messageType = TrayIcon.MessageType.ERROR; + } + if (messageType != null) { + trayIcon.displayMessage("DavMail gateway", message, messageType); + } + trayIcon.setToolTip("DavMail gateway \n" + message); + } + LOGGER.log(priority, message); + } + + } + + public void init() { + // set native look and feel + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + LOGGER.warn("Unable to set system look and feel"); + } + + // get the SystemTray instance + SystemTray tray = SystemTray.getSystemTray(); + // load an image + ClassLoader classloader = DavGatewayTray.class.getClassLoader(); + URL imageUrl = classloader.getResource("tray.png"); + image = Toolkit.getDefaultToolkit().getImage(imageUrl); + URL imageUrl2 = classloader.getResource("tray2.png"); + image2 = Toolkit.getDefaultToolkit().getImage(imageUrl2); + // create a popup menu + PopupMenu popup = new PopupMenu(); + final SettingsFrame settingsFrame = new SettingsFrame(); + settingsFrame.setIconImage(image); + // create an action settingsListener to listen for settings action executed on the tray icon + ActionListener settingsListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + settingsFrame.setVisible(true); + } + }; + // create menu item for the default action + MenuItem defaultItem = new MenuItem("Settings..."); + defaultItem.addActionListener(settingsListener); + popup.add(defaultItem); + + MenuItem logItem = new MenuItem("Show logs..."); + logItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Logger rootLogger = Logger.getRootLogger(); + LF5Appender lf5Appender = (LF5Appender) rootLogger.getAppender("LF5Appender"); + if (lf5Appender == null) { + lf5Appender = new LF5Appender(new LogBrokerMonitor(LogLevel.getLog4JLevels()) { + protected void closeAfterConfirm() { + hide(); + } + }); + lf5Appender.setName("LF5Appender"); + rootLogger.addAppender(lf5Appender); + } + lf5Appender.getLogBrokerMonitor().show(); + } + }); + popup.add(logItem); + + // create an action exitListener to listen for exit action executed on the tray icon + ActionListener exitListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + SystemTray.getSystemTray().remove(trayIcon); + //noinspection CallToSystemExit + System.exit(0); + } + }; + // create menu item for the exit action + MenuItem exitItem = new MenuItem("Exit"); + exitItem.addActionListener(exitListener); + popup.add(exitItem); + + /// ... add other items + // construct a TrayIcon + trayIcon = new TrayIcon(image, "DavMail Gateway", popup); + // set the TrayIcon properties + trayIcon.addActionListener(settingsListener); + // ... + // add the tray image + try { + tray.add(trayIcon); + } catch (AWTException e) { + System.err.println(e); + } + + // display settings frame on first start + if (Settings.isFirstStart()) { + settingsFrame.setVisible(true); + } + } +} diff --git a/src/java/davmail/DavGatewayTray.java b/src/java/davmail/DavGatewayTray.java index 878fe7d2..f433b7e3 100644 --- a/src/java/davmail/DavGatewayTray.java +++ b/src/java/davmail/DavGatewayTray.java @@ -1,16 +1,9 @@ package davmail; -import org.apache.log4j.Logger; import org.apache.log4j.Priority; -import org.apache.log4j.lf5.LF5Appender; -import org.apache.log4j.lf5.LogLevel; -import org.apache.log4j.lf5.viewer.LogBrokerMonitor; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.net.URL; +import java.awt.SystemTray; + /** * Tray icon handler @@ -19,59 +12,24 @@ public class DavGatewayTray { protected DavGatewayTray() { } - protected static final Logger LOGGER = Logger.getLogger("davmail"); - - // LOCK for synchronized block - protected static final Object LOCK = new Object(); - - private static TrayIcon trayIcon = null; - private static Image image = null; - private static Image image2 = null; + protected static DavGatewayTrayInterface davGatewayTray; public static void switchIcon() { - try { - synchronized (LOCK) { - if (trayIcon.getImage() == image) { - trayIcon.setImage(image2); - } else { - trayIcon.setImage(image); - } - } - } catch (NoClassDefFoundError e) { - LOGGER.debug("JDK not at least 1.6, tray not supported"); + if (davGatewayTray != null) { + davGatewayTray.switchIcon(); } - } public static void resetIcon() { - try { - synchronized (LOCK) { - trayIcon.setImage(image); - } - } catch (NoClassDefFoundError e) { - LOGGER.debug("JDK not at least 1.6, tray not supported"); + if (davGatewayTray != null) { + davGatewayTray.resetIcon(); } } protected static void displayMessage(String message, Priority priority) { - synchronized (LOCK) { - if (trayIcon != null) { - TrayIcon.MessageType messageType = null; - if (priority == Priority.INFO) { - messageType = TrayIcon.MessageType.INFO; - } else if (priority == Priority.WARN) { - messageType = TrayIcon.MessageType.WARNING; - } else if (priority == Priority.ERROR) { - messageType = TrayIcon.MessageType.ERROR; - } - if (messageType != null) { - trayIcon.displayMessage("DavMail gateway", message, messageType); - } - trayIcon.setToolTip("DavMail gateway \n" + message); - } - LOGGER.log(priority, message); + if (davGatewayTray != null) { + davGatewayTray.displayMessage(message, priority); } - } public static void debug(String message) { @@ -107,92 +65,31 @@ public class DavGatewayTray { } public static void init() { + ClassLoader classloader = DavGatewayTray.class.getClassLoader(); + // first try to load SWT try { - if (SystemTray.isSupported()) { - // set native look and feel - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { - LOGGER.warn("Unable to set system look and feel"); - } - - // get the SystemTray instance - SystemTray tray = SystemTray.getSystemTray(); - // load an image - ClassLoader classloader = DavGatewayTray.class.getClassLoader(); - URL imageUrl = classloader.getResource("tray.png"); - image = Toolkit.getDefaultToolkit().getImage(imageUrl); - URL imageUrl2 = classloader.getResource("tray2.png"); - image2 = Toolkit.getDefaultToolkit().getImage(imageUrl2); - // create a popup menu - PopupMenu popup = new PopupMenu(); - final SettingsFrame settingsFrame = new SettingsFrame(); - settingsFrame.setIconImage(image); - // create an action settingsListener to listen for settings action executed on the tray icon - ActionListener settingsListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - settingsFrame.setVisible(true); - } - }; - // create menu item for the default action - MenuItem defaultItem = new MenuItem("Settings..."); - defaultItem.addActionListener(settingsListener); - popup.add(defaultItem); - - MenuItem logItem = new MenuItem("Show logs..."); - logItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger rootLogger = Logger.getRootLogger(); - LF5Appender lf5Appender = (LF5Appender) rootLogger.getAppender("LF5Appender"); - if (lf5Appender == null) { - lf5Appender = new LF5Appender(new LogBrokerMonitor(LogLevel.getLog4JLevels()) { - protected void closeAfterConfirm() { - hide(); - } - }); - lf5Appender.setName("LF5Appender"); - rootLogger.addAppender(lf5Appender); - } - lf5Appender.getLogBrokerMonitor().show(); - } - }); - popup.add(logItem); - - // create an action exitListener to listen for exit action executed on the tray icon - ActionListener exitListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - SystemTray.getSystemTray().remove(trayIcon); - //noinspection CallToSystemExit - System.exit(0); - } - }; - // create menu item for the exit action - MenuItem exitItem = new MenuItem("Exit"); - exitItem.addActionListener(exitListener); - popup.add(exitItem); - - /// ... add other items - // construct a TrayIcon - trayIcon = new TrayIcon(image, "DavMail Gateway", popup); - // set the TrayIcon properties - trayIcon.addActionListener(settingsListener); - // ... - // add the tray image - try { - tray.add(trayIcon); - } catch (AWTException e) { - System.err.println(e); - } - - // display settings frame on first start - if (Settings.isFirstStart()) { - settingsFrame.setVisible(true); - } - } - - } catch (NoClassDefFoundError e) { - DavGatewayTray.warn("JDK 1.6 needed for system tray support"); + // trigger ClassNotFoundException + classloader.loadClass("org.eclipse.swt.SWT"); + // SWT available, create tray + davGatewayTray = new SwtGatewayTray(); + davGatewayTray.init(); + } catch (ClassNotFoundException e) { + DavGatewayTray.info("SWT not available, fallback to JDK 1.6 system tray support"); } + // try java6 tray support + if (davGatewayTray == null) { + try { + if (SystemTray.isSupported()) { + davGatewayTray = new AwtGatewayTray(); + davGatewayTray.init(); + } + } catch (NoClassDefFoundError e) { + DavGatewayTray.info("JDK 1.6 needed for system tray support"); + } + } + if (davGatewayTray == null) { + DavGatewayTray.warn("No system tray support found (tried SWT and native java)"); + } } } diff --git a/src/java/davmail/DavGatewayTrayInterface.java b/src/java/davmail/DavGatewayTrayInterface.java new file mode 100644 index 00000000..ecafa664 --- /dev/null +++ b/src/java/davmail/DavGatewayTrayInterface.java @@ -0,0 +1,13 @@ +package davmail; + +import org.apache.log4j.Priority; + +/** + * Gateway tray interface common to SWT and pure java implementations + */ +public interface DavGatewayTrayInterface { + void switchIcon(); + void resetIcon(); + void displayMessage(String message, Priority priority); + void init(); +} diff --git a/src/java/davmail/SwtGatewayTray.java b/src/java/davmail/SwtGatewayTray.java new file mode 100644 index 00000000..a2379ef8 --- /dev/null +++ b/src/java/davmail/SwtGatewayTray.java @@ -0,0 +1,229 @@ +package davmail; + +import org.apache.log4j.Logger; +import org.apache.log4j.Priority; +import org.apache.log4j.lf5.LF5Appender; +import org.apache.log4j.lf5.LogLevel; +import org.apache.log4j.lf5.viewer.LogBrokerMonitor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.*; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; + +import javax.swing.*; +import java.io.IOException; +import java.net.URL; +import java.awt.*; + +/** + * Tray icon handler based on SWT + */ +public class SwtGatewayTray implements DavGatewayTrayInterface { + protected SwtGatewayTray() { + } + + protected static final Logger LOGGER = Logger.getLogger("davmail"); + + // LOCK for synchronized block + protected static final Object LOCK = new Object(); + + private static TrayItem trayItem = null; + private static Image image = null; + private static Image image2 = null; + private static Display display; + private static Shell shell; + + public void switchIcon() { + display.syncExec( + new Runnable() { + public void run() { + if (trayItem.getImage() == image) { + trayItem.setImage(image2); + } else { + trayItem.setImage(image); + } + } + }); + + } + + public void resetIcon() { + display.syncExec( + new Runnable() { + public void run() { + trayItem.setImage(image); + } + }); + } + + public void displayMessage(final String message, final Priority priority) { + synchronized (LOCK) { + if (trayItem != null) { + display.syncExec( + new Runnable() { + public void run() { + int messageType = 0; + if (priority == Priority.INFO) { + messageType = SWT.ICON_INFORMATION; + } else if (priority == Priority.WARN) { + messageType = SWT.ICON_WARNING; + } else if (priority == Priority.ERROR) { + messageType = SWT.ICON_ERROR; + } + if (messageType == 0) { + trayItem.setToolTipText("DavMail gateway \n" + message); + } else { + final ToolTip toolTip = new ToolTip(shell, SWT.BALLOON | messageType); + toolTip.setText("DavMail gateway"); + toolTip.setMessage(message); + trayItem.setToolTip(toolTip); + toolTip.setVisible(true); + } + } + }); + } + LOGGER.log(priority, message); + } + + } + + public void init() { + // set native look and feel + try { + String lafClassName = UIManager.getSystemLookAndFeelClassName(); + // workaround for bug when SWT and AWT both try to access Gtk + if (lafClassName.indexOf("gtk") > 0) { + lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + } + UIManager.setLookAndFeel(lafClassName); + } catch (Exception e) { + LOGGER.warn("Unable to set look and feel"); + } + + new Thread() { + public void run() { + display = new Display(); + shell = new Shell(display); + + final Tray tray = display.getSystemTray(); + if (tray != null) { + + trayItem = new TrayItem(tray, SWT.NONE); + trayItem.setToolTipText("DavMail gateway"); + + // load an image + ClassLoader classloader = DavGatewayTray.class.getClassLoader(); + java.awt.Image awtImage = null; + try { + URL imageUrl = classloader.getResource("tray.png"); + image = new Image(display, imageUrl.openStream()); + awtImage = Toolkit.getDefaultToolkit().getImage(imageUrl); + } catch (IOException e) { + LOGGER.warn("Unable to load image"); + } + + try { + URL imageUrl2 = classloader.getResource("tray2.png"); + image2 = new Image(display, imageUrl2.openStream()); + } catch (IOException e) { + LOGGER.warn("Unable to load image"); + } + + trayItem.setImage(image); + + // create a popup menu + final Menu popup = new Menu(shell, SWT.POP_UP); + trayItem.addListener(SWT.MenuDetect, new Listener() { + public void handleEvent(Event event) { + popup.setVisible(true); + } + }); + + final SettingsFrame settingsFrame = new SettingsFrame(); + if (awtImage != null) { + settingsFrame.setIconImage(awtImage); + } + trayItem.addListener(SWT.DefaultSelection, new Listener() { + public void handleEvent(Event event) { + display.asyncExec( + new Runnable() { + public void run() { + settingsFrame.setVisible(true); + } + }); + } + }); + + // create menu item for the default action + MenuItem defaultItem = new MenuItem(popup, SWT.PUSH); + defaultItem.setText("Settings..."); + defaultItem.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + settingsFrame.setVisible(true); + } + }); + + MenuItem logItem = new MenuItem(popup, SWT.PUSH); + logItem.setText("Show logs..."); + logItem.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + display.asyncExec( + new Runnable() { + public void run() { + + Logger rootLogger = Logger.getRootLogger(); + LF5Appender lf5Appender = (LF5Appender) rootLogger.getAppender("LF5Appender"); + if (lf5Appender == null) { + lf5Appender = new LF5Appender(new LogBrokerMonitor(LogLevel.getLog4JLevels()) { + protected void closeAfterConfirm() { + hide(); + } + }); + lf5Appender.setName("LF5Appender"); + rootLogger.addAppender(lf5Appender); + } + lf5Appender.getLogBrokerMonitor().show(); + } + }); + } + }); + + MenuItem exitItem = new MenuItem(popup, SWT.PUSH); + exitItem.setText("Exit"); + exitItem.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + shell.dispose(); + + if (image != null) + image.dispose(); + if (image2 != null) + image2.dispose(); + display.dispose(); + + //noinspection CallToSystemExit + System.exit(0); + } + }); + + // display settings frame on first start + if (Settings.isFirstStart()) { + settingsFrame.setVisible(true); + } + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + + if (image != null) + image.dispose(); + if (image2 != null) + image2.dispose(); + display.dispose(); + } + } + }.start(); + } +}