From c692059150d65ec77f4e41fa3535bd215435b4ed Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 28 Jun 2015 01:47:02 +0200 Subject: [PATCH] Fixed issues with loading libappindicator (for incorrect versions), now falls back to GTK. Compiled as java6. --- src/dorkbox/util/tray/FailureCallback.java | 5 +- src/dorkbox/util/tray/SystemTray.java | 85 +++++++++------- .../util/tray/SystemTrayMenuAction.java | 3 +- .../util/tray/SystemTrayMenuPopup.java | 44 +++++---- .../util/tray/linux/AppIndicatorTray.java | 73 ++++++++------ .../util/tray/linux/GtkSystemTray.java | 98 +++++++++++-------- src/dorkbox/util/tray/linux/MenuEntry.java | 10 +- .../util/tray/swing/SwingSystemTray.java | 90 ++++++++++------- 8 files changed, 242 insertions(+), 166 deletions(-) diff --git a/src/dorkbox/util/tray/FailureCallback.java b/src/dorkbox/util/tray/FailureCallback.java index b677abdf..1bee1c9c 100644 --- a/src/dorkbox/util/tray/FailureCallback.java +++ b/src/dorkbox/util/tray/FailureCallback.java @@ -15,6 +15,7 @@ */ package dorkbox.util.tray; -public interface FailureCallback { - public void createTrayFailed(); +public +interface FailureCallback { + void createTrayFailed(); } diff --git a/src/dorkbox/util/tray/SystemTray.java b/src/dorkbox/util/tray/SystemTray.java index 033c2c1f..7d296319 100644 --- a/src/dorkbox/util/tray/SystemTray.java +++ b/src/dorkbox/util/tray/SystemTray.java @@ -15,13 +15,17 @@ */ package dorkbox.util.tray; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import dorkbox.util.NamedThreadFactory; +import dorkbox.util.OS; +import dorkbox.util.jna.linux.AppIndicator; +import dorkbox.util.jna.linux.GtkSupport; +import dorkbox.util.tray.linux.AppIndicatorTray; +import dorkbox.util.tray.linux.GtkSystemTray; +import dorkbox.util.tray.swing.SwingSystemTray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; import java.math.BigInteger; import java.net.URL; import java.nio.ByteBuffer; @@ -32,21 +36,12 @@ import java.security.SecureRandom; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import dorkbox.util.NamedThreadFactory; -import dorkbox.util.OS; -import dorkbox.util.jna.linux.GtkSupport; -import dorkbox.util.tray.linux.AppIndicatorTray; -import dorkbox.util.tray.linux.GtkSystemTray; -import dorkbox.util.tray.swing.SwingSystemTray; - /** * Interface for system tray implementations. */ -public abstract class SystemTray { +public abstract +class SystemTray { private static final Charset UTF_8 = Charset.forName("UTF-8"); private static MessageDigest digest; @@ -80,7 +75,7 @@ public abstract class SystemTray { if (getenv != null && getenv.equals("Unity")) { try { trayType = AppIndicatorTray.class; - } catch (Exception ignored) { + } catch (Throwable ignored) { } } @@ -107,7 +102,13 @@ public abstract class SystemTray { bin = new BufferedReader(new FileReader(status)); String readLine = bin.readLine(); if (readLine != null && readLine.contains("indicator-app")) { - trayType = AppIndicatorTray.class; + // make sure we can also load the library (it might be the wrong version) + try { + final AppIndicator instance = AppIndicator.INSTANCE; + trayType = AppIndicatorTray.class; + } catch (Throwable ignored) { + logger.error("AppIndicator support detected, but unable to load the library. Falling back to GTK"); + } break; } } finally { @@ -118,7 +119,7 @@ public abstract class SystemTray { } } } - } catch (Exception ignored) { + } catch (Throwable ignored) { } finally { if (bin != null) { try { @@ -129,6 +130,7 @@ public abstract class SystemTray { } } + if (trayType == null) { trayType = GtkSystemTray.class; } @@ -143,7 +145,8 @@ public abstract class SystemTray { if (trayType == null) { // unsupported tray logger.error("Unsupported tray type!"); - } else { + } + else { try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { @@ -159,7 +162,8 @@ public abstract class SystemTray { protected volatile boolean active = false; protected String appName; - public static SystemTray create(String appName) { + public static + SystemTray create(String appName) { if (trayType != null) { try { SystemTray newInstance = trayType.newInstance(); @@ -167,7 +171,7 @@ public abstract class SystemTray { newInstance.setAppName(appName); } return newInstance; - } catch (Exception e) { + } catch (Throwable e) { e.printStackTrace(); } } @@ -176,34 +180,43 @@ public abstract class SystemTray { return null; } - private void setAppName(String appName) { + private + void setAppName(String appName) { this.appName = appName; } - public abstract void createTray(String iconName); + public abstract + void createTray(String iconName); - public void removeTray() { + public + void removeTray() { SystemTray.this.callbackExecutor.shutdown(); } - public abstract void setStatus(String infoString, String iconName); + public abstract + void setStatus(String infoString, String iconName); - public abstract void addMenuEntry(String menuText, SystemTrayMenuAction callback); + public abstract + void addMenuEntry(String menuText, SystemTrayMenuAction callback); - public abstract void updateMenuEntry(String origMenuText, String newMenuText, SystemTrayMenuAction newCallback); + public abstract + void updateMenuEntry(String origMenuText, String newMenuText, SystemTrayMenuAction newCallback); - protected String iconPath(String fileName) { + protected + String iconPath(String fileName) { // is file sitting on drive File iconTest; if (ICON_PATH.isEmpty()) { iconTest = new File(fileName); - } else { + } + else { iconTest = new File(ICON_PATH, fileName); } if (iconTest.isFile() && iconTest.canRead()) { return iconTest.getAbsolutePath(); - } else { + } + else { if (!ICON_PATH.isEmpty()) { fileName = ICON_PATH + "/" + fileName; } @@ -291,11 +304,13 @@ public abstract class SystemTray { throw new RuntimeException(message); } - public final void setFailureCallback(FailureCallback failureCallback) { + public final + void setFailureCallback(FailureCallback failureCallback) { this.failureCallback = failureCallback; } - public final boolean isActive() { + public final + boolean isActive() { return this.active; } } diff --git a/src/dorkbox/util/tray/SystemTrayMenuAction.java b/src/dorkbox/util/tray/SystemTrayMenuAction.java index bd813113..d8282a2b 100644 --- a/src/dorkbox/util/tray/SystemTrayMenuAction.java +++ b/src/dorkbox/util/tray/SystemTrayMenuAction.java @@ -15,6 +15,7 @@ */ package dorkbox.util.tray; -public interface SystemTrayMenuAction { +public +interface SystemTrayMenuAction { void onClick(SystemTray systemTray); } diff --git a/src/dorkbox/util/tray/SystemTrayMenuPopup.java b/src/dorkbox/util/tray/SystemTrayMenuPopup.java index 0f95f202..5c2e11c0 100644 --- a/src/dorkbox/util/tray/SystemTrayMenuPopup.java +++ b/src/dorkbox/util/tray/SystemTrayMenuPopup.java @@ -1,46 +1,50 @@ package dorkbox.util.tray; -import java.awt.Dimension; -import java.awt.MouseInfo; -import java.awt.Point; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -import javax.swing.JPopupMenu; - import dorkbox.util.DelayTimer; import dorkbox.util.SwingUtil; -public class SystemTrayMenuPopup extends JPopupMenu { +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public +class SystemTrayMenuPopup extends JPopupMenu { private static final long serialVersionUID = 1L; - /** Allows you to customize the delay (for hiding the popup) when the cursor is "moused out" of the popup menu */ + /** + * Allows you to customize the delay (for hiding the popup) when the cursor is "moused out" of the popup menu + */ public static long hidePopupDelay = 1000L; private DelayTimer timer; - protected boolean mouseStillOnMenu; +// protected boolean mouseStillOnMenu; // private JDialog hiddenDialog; - public SystemTrayMenuPopup() { + public + SystemTrayMenuPopup() { super(); setFocusable(true); this.timer = new DelayTimer("PopupMenuHider", true, new DelayTimer.Callback() { @Override - public void execute() { + public + void execute() { SwingUtil.invokeLater(new Runnable() { @Override - public void run() { + public + void run() { Point location = MouseInfo.getPointerInfo().getLocation(); Point locationOnScreen = getLocationOnScreen(); Dimension size = getSize(); - if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width - && location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) { + if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width && + location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) { SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay()); - } else { + } + else { setVisible(false); } } @@ -50,7 +54,8 @@ public class SystemTrayMenuPopup extends JPopupMenu { addMouseListener(new MouseAdapter() { @Override - public void mouseExited(MouseEvent event) { + public + void mouseExited(MouseEvent event) { // wait before checking if mouse is still on the menu SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay()); } @@ -75,7 +80,8 @@ public class SystemTrayMenuPopup extends JPopupMenu { } @Override - public void setVisible(boolean makeVisible) { + public + void setVisible(boolean makeVisible) { this.timer.cancel(); if (makeVisible) { diff --git a/src/dorkbox/util/tray/linux/AppIndicatorTray.java b/src/dorkbox/util/tray/linux/AppIndicatorTray.java index 4c8c37ad..9a7a1c4a 100644 --- a/src/dorkbox/util/tray/linux/AppIndicatorTray.java +++ b/src/dorkbox/util/tray/linux/AppIndicatorTray.java @@ -15,13 +15,7 @@ */ package dorkbox.util.tray.linux; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.sun.jna.Pointer; - import dorkbox.util.jna.linux.AppIndicator; import dorkbox.util.jna.linux.Gobject; import dorkbox.util.jna.linux.Gtk; @@ -29,16 +23,22 @@ import dorkbox.util.jna.linux.GtkSupport; import dorkbox.util.tray.SystemTray; import dorkbox.util.tray.SystemTrayMenuAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Class for handling all system tray interactions. - * + *

* specialization for using app indicators in ubuntu unity - * + *

* Heavily modified from - * + *

* Lantern: https://github.com/getlantern/lantern/ Apache 2.0 License Copyright 2010 Brave New Software Project, Inc. */ -public class AppIndicatorTray extends SystemTray { +public +class AppIndicatorTray extends SystemTray { private static final AppIndicator libappindicator = AppIndicator.INSTANCE; private static final Gobject libgobject = Gobject.INSTANCE; private static final Gtk libgtk = Gtk.INSTANCE; @@ -54,29 +54,33 @@ public class AppIndicatorTray extends SystemTray { private final List widgets = new ArrayList(4); - public AppIndicatorTray() { + public + AppIndicatorTray() { } @Override - public void createTray(String iconName) { + public + void createTray(String iconName) { libgtk.gdk_threads_enter(); - this.appIndicator = - libappindicator.app_indicator_new(this.appName, "indicator-messages-new", AppIndicator.CATEGORY_APPLICATION_STATUS); + this.appIndicator = libappindicator.app_indicator_new(this.appName, "indicator-messages-new", + AppIndicator.CATEGORY_APPLICATION_STATUS); /* * basically a hack -- we should subclass the AppIndicator type and override the fallback entry in the 'vtable', instead we just * hack the app indicator class itself. Not an issue unless we need other appindicators. */ - AppIndicator.AppIndicatorClassStruct aiclass = - new AppIndicator.AppIndicatorClassStruct(this.appIndicator.parent.g_type_instance.g_class); + AppIndicator.AppIndicatorClassStruct aiclass = new AppIndicator.AppIndicatorClassStruct( + this.appIndicator.parent.g_type_instance.g_class); aiclass.fallback = new AppIndicator.Fallback() { @Override - public Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) { + public + Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) { AppIndicatorTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { logger.warn("Failed to create appindicator system tray."); if (AppIndicatorTray.this.failureCallback != null) { @@ -101,7 +105,8 @@ public class AppIndicatorTray extends SystemTray { } @Override - public void removeTray() { + public + void removeTray() { libgtk.gdk_threads_enter(); for (Pointer widget : this.widgets) { libgtk.gtk_widget_destroy(widget); @@ -135,14 +140,16 @@ public class AppIndicatorTray extends SystemTray { } @Override - public void setStatus(String infoString, String iconName) { + public + void setStatus(String infoString, String iconName) { libgtk.gdk_threads_enter(); if (this.connectionStatusItem == null) { this.connectionStatusItem = libgtk.gtk_menu_item_new_with_label(infoString); this.widgets.add(this.connectionStatusItem); libgtk.gtk_widget_set_sensitive(this.connectionStatusItem, Gtk.FALSE); libgtk.gtk_menu_shell_append(this.menu, this.connectionStatusItem); - } else { + } + else { libgtk.gtk_menu_item_set_label(this.connectionStatusItem, infoString); } @@ -156,7 +163,8 @@ public class AppIndicatorTray extends SystemTray { * Will add a new menu entry, or update one if it already exists */ @Override - public void addMenuEntry(String menuText, final SystemTrayMenuAction callback) { + public + void addMenuEntry(String menuText, final SystemTrayMenuAction callback) { synchronized (this.menuEntries) { MenuEntry menuEntry = this.menuEntries.get(menuText); @@ -168,10 +176,12 @@ public class AppIndicatorTray extends SystemTray { // have to watch out! These can get garbage collected! Gobject.GCallback gtkCallback = new Gobject.GCallback() { @Override - public void callback(Pointer instance, Pointer data) { + public + void callback(Pointer instance, Pointer data) { AppIndicatorTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { callback.onClick(AppIndicatorTray.this); } }); @@ -189,7 +199,8 @@ public class AppIndicatorTray extends SystemTray { menuEntry.gtkCallback = gtkCallback; this.menuEntries.put(menuText, menuEntry); - } else { + } + else { updateMenuEntry(menuText, menuText, callback); } } @@ -199,7 +210,8 @@ public class AppIndicatorTray extends SystemTray { * Will update an already existing menu entry (or add a new one, if it doesn't exist) */ @Override - public void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) { + public + void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) { synchronized (this.menuEntries) { MenuEntry menuEntry = this.menuEntries.get(origMenuText); @@ -210,10 +222,12 @@ public class AppIndicatorTray extends SystemTray { // have to watch out! These can get garbage collected! menuEntry.gtkCallback = new Gobject.GCallback() { @Override - public void callback(Pointer instance, Pointer data) { + public + void callback(Pointer instance, Pointer data) { AppIndicatorTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { newCallback.onClick(AppIndicatorTray.this); } }); @@ -224,7 +238,8 @@ public class AppIndicatorTray extends SystemTray { libgtk.gtk_widget_show_all(menuEntry.dashboardItem); libgtk.gdk_threads_leave(); - } else { + } + else { addMenuEntry(origMenuText, newCallback); } } diff --git a/src/dorkbox/util/tray/linux/GtkSystemTray.java b/src/dorkbox/util/tray/linux/GtkSystemTray.java index 7a9c2722..0ad107d3 100644 --- a/src/dorkbox/util/tray/linux/GtkSystemTray.java +++ b/src/dorkbox/util/tray/linux/GtkSystemTray.java @@ -15,20 +15,7 @@ */ package dorkbox.util.tray.linux; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.JMenuItem; - import com.sun.jna.Pointer; - import dorkbox.util.SwingUtil; import dorkbox.util.jna.linux.Gobject; import dorkbox.util.jna.linux.Gtk; @@ -38,12 +25,22 @@ import dorkbox.util.tray.SystemTray; import dorkbox.util.tray.SystemTrayMenuAction; import dorkbox.util.tray.SystemTrayMenuPopup; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Class for handling all system tray interactions via GTK. - * + *

* This is the "old" way to do it, and does not work with some desktop environments. */ -public class GtkSystemTray extends SystemTray { +public +class GtkSystemTray extends SystemTray { private static final Gobject libgobject = Gobject.INSTANCE; private static final Gtk libgtk = Gtk.INSTANCE; @@ -58,14 +55,17 @@ public class GtkSystemTray extends SystemTray { private final List widgets = new ArrayList(4); private Gobject.GEventCallback gtkCallback; - public GtkSystemTray() { + public + GtkSystemTray() { } @Override - public void createTray(String iconName) { + public + void createTray(String iconName) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { GtkSystemTray.this.jmenu = new SystemTrayMenuPopup(); } }); @@ -80,28 +80,32 @@ public class GtkSystemTray extends SystemTray { // have to make this a field, to prevent GC on this object this.gtkCallback = new Gobject.GEventCallback() { @Override - public void callback(Pointer system_tray, final GdkEventButton event) { + public + void callback(Pointer system_tray, final GdkEventButton event) { // BUTTON_PRESS only (any mouse click) if (event.type == 4) { SwingUtil.invokeLater(new Runnable() { @Override - public void run() { + public + void run() { // test this using cinnamon (which still uses status icon) if (GtkSystemTray.this.jmenu.isVisible()) { GtkSystemTray.this.jmenu.setVisible(false); - } else { + } + else { Dimension size = GtkSystemTray.this.jmenu.getPreferredSize(); int x = (int) event.x_root; - int y = (int) event.y_root; + int y = (int) event.y_root; Point point = new Point(x, y); Rectangle bounds = SwingUtil.getScreenBoundsAt(point); if (y < bounds.y) { y = bounds.y; - } else if (y + size.height > bounds.y + bounds.height) { + } + else if (y + size.height > bounds.y + bounds.height) { // our menu cannot have the top-edge snap to the mouse // so we make the bottom-edge snap to the mouse y -= size.height; // snap to edge of mouse @@ -109,7 +113,8 @@ public class GtkSystemTray extends SystemTray { if (x < bounds.x) { x = bounds.x; - } else if (x + size.width > bounds.x + bounds.width) { + } + else if (x + size.width > bounds.x + bounds.width) { // our menu cannot have the left-edge snap to the mouse // so we make the right-edge snap to the mouse x -= size.width; // snap to edge of mouse @@ -122,7 +127,8 @@ public class GtkSystemTray extends SystemTray { // we are at the top of the screen if (y < 100) { y += distanceToEdgeOfTray + 4; - } else { + } + else { y -= distanceToEdgeOfTray + 4; } @@ -144,7 +150,8 @@ public class GtkSystemTray extends SystemTray { } @Override - public void removeTray() { + public + void removeTray() { libgtk.gdk_threads_enter(); for (Pointer widget : this.widgets) { libgtk.gtk_widget_destroy(widget); @@ -177,15 +184,18 @@ public class GtkSystemTray extends SystemTray { } @Override - public void setStatus(final String infoString, String iconName) { + public + void setStatus(final String infoString, String iconName) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { if (GtkSystemTray.this.connectionStatusItem == null) { GtkSystemTray.this.connectionStatusItem = new JMenuItem(infoString); GtkSystemTray.this.connectionStatusItem.setEnabled(false); GtkSystemTray.this.jmenu.add(GtkSystemTray.this.connectionStatusItem); - } else { + } + else { GtkSystemTray.this.connectionStatusItem.setText(infoString); } } @@ -200,10 +210,12 @@ public class GtkSystemTray extends SystemTray { * Will add a new menu entry, or update one if it already exists */ @Override - public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) { + public + void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { Map menuEntries2 = GtkSystemTray.this.menuEntries; synchronized (menuEntries2) { @@ -215,12 +227,14 @@ public class GtkSystemTray extends SystemTray { menuEntry = new JMenuItem(menuText); menuEntry.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public + void actionPerformed(ActionEvent e) { // SystemTrayMenuPopup source = (SystemTrayMenuPopup) ((JMenuItem)e.getSource()).getParent(); GtkSystemTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { callback.onClick(GtkSystemTray.this); } }); @@ -229,7 +243,8 @@ public class GtkSystemTray extends SystemTray { menu.add(menuEntry); menuEntries2.put(menuText, menuEntry); - } else { + } + else { updateMenuEntry(menuText, menuText, callback); } } @@ -241,10 +256,12 @@ public class GtkSystemTray extends SystemTray { * Will update an already existing menu entry (or add a new one, if it doesn't exist) */ @Override - public void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) { + public + void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { Map menuEntries2 = GtkSystemTray.this.menuEntries; synchronized (menuEntries2) { @@ -258,10 +275,12 @@ public class GtkSystemTray extends SystemTray { menuEntry.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public + void actionPerformed(ActionEvent e) { GtkSystemTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { newCallback.onClick(GtkSystemTray.this); } }); @@ -269,7 +288,8 @@ public class GtkSystemTray extends SystemTray { }); menuEntry.setText(newMenuText); menuEntry.revalidate(); - } else { + } + else { addMenuEntry(origMenuText, newCallback); } } diff --git a/src/dorkbox/util/tray/linux/MenuEntry.java b/src/dorkbox/util/tray/linux/MenuEntry.java index 31a53d42..405ab222 100644 --- a/src/dorkbox/util/tray/linux/MenuEntry.java +++ b/src/dorkbox/util/tray/linux/MenuEntry.java @@ -16,7 +16,6 @@ package dorkbox.util.tray.linux; import com.sun.jna.Pointer; - import dorkbox.util.jna.linux.Gobject.GCallback; /** @@ -28,18 +27,21 @@ class MenuEntry { public Pointer dashboardItem; public GCallback gtkCallback; - public MenuEntry() { + public + MenuEntry() { long time = System.nanoTime(); this.hashCode = (int) (time ^ time >>> 32); } @Override - public int hashCode() { + public + int hashCode() { return this.hashCode; } @Override - public boolean equals(Object obj) { + public + boolean equals(Object obj) { if (this == obj) { return true; } diff --git a/src/dorkbox/util/tray/swing/SwingSystemTray.java b/src/dorkbox/util/tray/swing/SwingSystemTray.java index 477c13fa..f4bec9b8 100644 --- a/src/dorkbox/util/tray/swing/SwingSystemTray.java +++ b/src/dorkbox/util/tray/swing/SwingSystemTray.java @@ -15,13 +15,12 @@ */ package dorkbox.util.tray.swing; -import java.awt.AWTException; -import java.awt.Dimension; -import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.SystemTray; -import java.awt.TrayIcon; +import dorkbox.util.SwingUtil; +import dorkbox.util.tray.SystemTrayMenuAction; +import dorkbox.util.tray.SystemTrayMenuPopup; + +import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -29,17 +28,11 @@ import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.Map; -import javax.swing.ImageIcon; -import javax.swing.JMenuItem; - -import dorkbox.util.SwingUtil; -import dorkbox.util.tray.SystemTrayMenuAction; -import dorkbox.util.tray.SystemTrayMenuPopup; - /** * Class for handling all system tray interaction, via SWING */ -public class SwingSystemTray extends dorkbox.util.tray.SystemTray { +public +class SwingSystemTray extends dorkbox.util.tray.SystemTray { private final Map menuEntries = new HashMap(2); @@ -52,14 +45,18 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { /** * Creates a new system tray handler class. */ - public SwingSystemTray() {} + public + SwingSystemTray() { + } @Override - public void removeTray() { + public + void removeTray() { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { SwingSystemTray.this.tray.remove(SwingSystemTray.this.trayIcon); SwingSystemTray.this.menuEntries.clear(); } @@ -69,14 +66,17 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { } @Override - public void createTray(final String iconName) { + public + void createTray(final String iconName) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { SwingSystemTray.this.tray = SystemTray.getSystemTray(); if (SwingSystemTray.this.tray == null) { logger.error("The system tray is not available"); - } else { + } + else { SwingSystemTray.this.jmenu = new SystemTrayMenuPopup(); Image trayImage = newImage(iconName); @@ -85,7 +85,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { SwingSystemTray.this.trayIcon.addMouseListener(new MouseAdapter() { @Override - public void mousePressed(MouseEvent e) { + public + void mousePressed(MouseEvent e) { Dimension size = SwingSystemTray.this.jmenu.getPreferredSize(); Point point = e.getPoint(); @@ -96,7 +97,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { if (y < bounds.y) { y = bounds.y; - } else if (y + size.height > bounds.y + bounds.height) { + } + else if (y + size.height > bounds.y + bounds.height) { // our menu cannot have the top-edge snap to the mouse // so we make the bottom-edge snap to the mouse y -= size.height; // snap to edge of mouse @@ -104,7 +106,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { if (x < bounds.x) { x = bounds.x; - } else if (x + size.width > bounds.x + bounds.width) { + } + else if (x + size.width > bounds.x + bounds.width) { // our menu cannot have the left-edge snap to the mouse // so we make the right-edge snap to the mouse x -= size.width; // snap to edge of mouse @@ -135,15 +138,18 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { } @Override - public void setStatus(final String infoString, final String iconName) { + public + void setStatus(final String infoString, final String iconName) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { if (SwingSystemTray.this.connectionStatusItem == null) { SwingSystemTray.this.connectionStatusItem = new JMenuItem(infoString); SwingSystemTray.this.connectionStatusItem.setEnabled(false); SwingSystemTray.this.jmenu.add(SwingSystemTray.this.connectionStatusItem); - } else { + } + else { SwingSystemTray.this.connectionStatusItem.setText(infoString); } } @@ -157,10 +163,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { * Will add a new menu entry, or update one if it already exists */ @Override - public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) { + public + void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { Map menuEntries2 = SwingSystemTray.this.menuEntries; synchronized (menuEntries2) { @@ -172,10 +180,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { menuEntry = new JMenuItem(menuText); menuEntry.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public + void actionPerformed(ActionEvent e) { SwingSystemTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { callback.onClick(SwingSystemTray.this); } }); @@ -184,7 +194,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { menu.add(menuEntry); menuEntries2.put(menuText, menuEntry); - } else { + } + else { updateMenuEntry(menuText, menuText, callback); } } @@ -196,10 +207,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { * Will update an already existing menu entry (or add a new one, if it doesn't exist) */ @Override - public void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) { + public + void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) { SwingUtil.invokeAndWait(new Runnable() { @Override - public void run() { + public + void run() { Map menuEntries2 = SwingSystemTray.this.menuEntries; synchronized (menuEntries2) { @@ -213,10 +226,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { menuEntry.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public + void actionPerformed(ActionEvent e) { SwingSystemTray.this.callbackExecutor.execute(new Runnable() { @Override - public void run() { + public + void run() { newCallback.onClick(SwingSystemTray.this); } }); @@ -224,7 +239,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray { }); menuEntry.setText(newMenuText); menuEntry.revalidate(); - } else { + } + else { addMenuEntry(origMenuText, newCallback); } }