forked from dorkbox/SystemTray
Added Menu Entry tooltip support. Emits warning on first load of
tooltips (as they are not supported by all OS configurations). This warning can be suppressed. Misc fix for loading swing with GTK.
This commit is contained in:
parent
365645ecd3
commit
65e7c669b5
@ -33,6 +33,8 @@ import dorkbox.util.SwingUtil;
|
||||
@SuppressWarnings({"unused", "SameParameterValue", "WeakerAccess"})
|
||||
public
|
||||
class MenuItem extends Entry {
|
||||
private static boolean alreadyEmittedTooltipWarning = false;
|
||||
|
||||
private volatile String text;
|
||||
private volatile File imageFile;
|
||||
private volatile ActionListener callback;
|
||||
@ -40,6 +42,7 @@ class MenuItem extends Entry {
|
||||
// default enabled is always true
|
||||
private volatile boolean enabled = true;
|
||||
private volatile char mnemonicKey;
|
||||
private volatile String tooltip;
|
||||
|
||||
public
|
||||
MenuItem() {
|
||||
@ -133,6 +136,7 @@ class MenuItem extends Entry {
|
||||
peer.setText(this);
|
||||
peer.setCallback(this);
|
||||
peer.setShortcut(this);
|
||||
peer.setTooltip(this);
|
||||
}
|
||||
|
||||
protected
|
||||
@ -343,6 +347,47 @@ class MenuItem extends Entry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the tooltip text, usually this is used to brand the SystemTray icon with your product's name, or to provide extra
|
||||
* information during mouse-over for menu entries.
|
||||
* <p>
|
||||
* NOTE: Maximum length is 64 characters long, and it is not supported on all Operating Systems and Desktop Environments.
|
||||
* <p>
|
||||
* For more details on Linux see https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12.
|
||||
*
|
||||
* @param tooltipText the text to use as a mouse-over tooltip for the tray icon or menu entry, null to remove.
|
||||
*/
|
||||
public
|
||||
void setTooltip(final String tooltipText) {
|
||||
if (tooltipText != null) {
|
||||
// this is a safety precaution, since the behavior of really long text is undefined.
|
||||
if (tooltipText.length() > 64) {
|
||||
throw new RuntimeException("Tooltip text cannot be longer than 64 characters.");
|
||||
}
|
||||
|
||||
if (!alreadyEmittedTooltipWarning) {
|
||||
alreadyEmittedTooltipWarning = true;
|
||||
SystemTray.logger.warn("Tooltips are not consistent across all platforms and tray types.");
|
||||
}
|
||||
}
|
||||
|
||||
this.tooltip = tooltipText;
|
||||
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setTooltip(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mouse-over tooltip for the meme entry.
|
||||
*
|
||||
* NOTE: This is not consistent across all platforms and tray types.
|
||||
*/
|
||||
public
|
||||
String getTooltip() {
|
||||
return this.tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
|
@ -675,7 +675,7 @@ class SystemTray {
|
||||
logger.debug("Forced tray type: {}", FORCE_TRAY_TYPE.name());
|
||||
}
|
||||
logger.debug("Force GTK2: {}", FORCE_GTK2);
|
||||
logger.debug("Prefer GTK3: {}", FORCE_GTK2);
|
||||
logger.debug("Prefer GTK3: {}", PREFER_GTK3);
|
||||
}
|
||||
|
||||
// Note: AppIndicators DO NOT support tooltips. We could try to create one, by creating a GTK widget and attaching it on
|
||||
@ -777,8 +777,9 @@ class SystemTray {
|
||||
// at this point, the tray type is what it should be. If there are failures or special cases, all types will fall back to
|
||||
// Swing.
|
||||
|
||||
if (isNix && !isTrayType(trayType, TrayType.Swing)) {
|
||||
if (isNix) {
|
||||
// linux/unix need access to GTK, so load it up before the tray is loaded!
|
||||
// Swing gets the image size info VIA gtk, so this is important as well.
|
||||
GtkEventDispatch.startGui(FORCE_GTK2, PREFER_GTK3, DEBUG);
|
||||
GtkEventDispatch.waitForEventsToComplete();
|
||||
|
||||
@ -788,65 +789,65 @@ class SystemTray {
|
||||
logger.debug("Is the system already running GTK? {}", Gtk.alreadyRunningGTK);
|
||||
}
|
||||
|
||||
// NOTE: appindicator1 -> GTk2, appindicator3 -> GTK3.
|
||||
// appindicator3 doesn't support menu icons via GTK2!!
|
||||
if (!Gtk.isLoaded) {
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
logger.error("Unable to initialize GTK! Something is severely wrong! Using the Swing Tray type instead.");
|
||||
}
|
||||
else if (OSUtil.Linux.isArch()) {
|
||||
// arch linux is fun!
|
||||
|
||||
if (isTrayType(trayType, TrayType.AppIndicator) && !AppIndicator.isLoaded) {
|
||||
// appindicators
|
||||
|
||||
// requires the install of libappindicator which is GTK2 (as of 25DEC2016)
|
||||
// requires the install of libappindicator3 which is GTK3 (as of 25DEC2016)
|
||||
if (!isTrayType(trayType, TrayType.Swing)) {
|
||||
// NOTE: appindicator1 -> GTk2, appindicator3 -> GTK3.
|
||||
// appindicator3 doesn't support menu icons via GTK2!!
|
||||
if (!Gtk.isLoaded) {
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
if (Gtk.isGtk2) {
|
||||
logger.warn("Unable to initialize AppIndicator for Arch linux, it requires GTK2! " +
|
||||
"Please install libappindicator, for example: 'sudo pacman -S libappindicator'. " +
|
||||
logger.error("Unable to initialize GTK! Something is severely wrong! Using the Swing Tray type instead.");
|
||||
}
|
||||
else if (OSUtil.Linux.isArch()) {
|
||||
// arch linux is fun!
|
||||
|
||||
if (isTrayType(trayType, TrayType.AppIndicator) && !AppIndicator.isLoaded) {
|
||||
// appindicators
|
||||
|
||||
// requires the install of libappindicator which is GTK2 (as of 25DEC2016)
|
||||
// requires the install of libappindicator3 which is GTK3 (as of 25DEC2016)
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
if (Gtk.isGtk2) {
|
||||
logger.warn("Unable to initialize AppIndicator for Arch linux, it requires GTK2! " +
|
||||
"Please install libappindicator, for example: 'sudo pacman -S libappindicator'. " +
|
||||
"Using the Swing Tray type instead.");
|
||||
} else {
|
||||
logger.error("Unable to initialize AppIndicator for Arch linux, it requires GTK3! " +
|
||||
"Please install libappindicator3, for example: 'sudo pacman -S libappindicator3'. " +
|
||||
"Using the Swing Tray type instead."); // GTK3
|
||||
}
|
||||
} else if (isTrayType(trayType, TrayType.GtkStatusIcon)) {
|
||||
if (!Extension.isInstalled()) {
|
||||
// Automatically install the extension for everyone except Arch. They are bonkers.
|
||||
Extension.ENABLE_EXTENSION_INSTALL = false;
|
||||
SystemTray.logger.info("You may need a work-around for showing the SystemTray icon - we suggest installing the " +
|
||||
"the [Top Icons] plugin (https://extensions.gnome.org/extension/1031/topicons/) which moves " +
|
||||
"icons from the *notification drawer* (it is normally collapsed) at the bottom left corner " +
|
||||
"of the screen to the menu panel next to the clock.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isTrayType(trayType, TrayType.AppIndicator)) {
|
||||
if (Gtk.isGtk2 && AppIndicator.isVersion3) {
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
logger.warn("AppIndicator3 detected with GTK2, falling back to GTK2 system tray type. " +
|
||||
"Please install libappindicator1 OR GTK3, for example: 'sudo apt-get install libappindicator1'. " +
|
||||
"Using the Swing Tray type instead.");
|
||||
} else {
|
||||
logger.error("Unable to initialize AppIndicator for Arch linux, it requires GTK3! " +
|
||||
"Please install libappindicator3, for example: 'sudo pacman -S libappindicator3'. " +
|
||||
"Using the Swing Tray type instead."); // GTK3
|
||||
|
||||
}
|
||||
} else if (isTrayType(trayType, TrayType.GtkStatusIcon)) {
|
||||
if (!Extension.isInstalled()) {
|
||||
// Automatically install the extension for everyone except Arch. They are bonkers.
|
||||
Extension.ENABLE_EXTENSION_INSTALL = false;
|
||||
SystemTray.logger.info("You may need a work-around for showing the SystemTray icon - we suggest installing the " +
|
||||
"the [Top Icons] plugin (https://extensions.gnome.org/extension/1031/topicons/) which moves " +
|
||||
"icons from the *notification drawer* (it is normally collapsed) at the bottom left corner " +
|
||||
"of the screen to the menu panel next to the clock.");
|
||||
else if (!AppIndicator.isLoaded) {
|
||||
// YIKES. Try to fallback to GtkStatusIndicator, since AppIndicator couldn't load.
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
logger.warn("Unable to initialize the AppIndicator correctly. Using the Swing Tray type instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isTrayType(trayType, TrayType.AppIndicator)) {
|
||||
if (Gtk.isGtk2 && AppIndicator.isVersion3) {
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
logger.warn("AppIndicator3 detected with GTK2, falling back to GTK2 system tray type. " +
|
||||
"Please install libappindicator1 OR GTK3, for example: 'sudo apt-get install libappindicator1'. " +
|
||||
"Using the Swing Tray type instead.");
|
||||
|
||||
}
|
||||
else if (!AppIndicator.isLoaded) {
|
||||
// YIKES. Try to fallback to GtkStatusIndicator, since AppIndicator couldn't load.
|
||||
trayType = selectTypeQuietly(TrayType.Swing);
|
||||
|
||||
logger.warn("Unable to initialize the AppIndicator correctly. Using the Swing Tray type instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// have to make adjustments BEFORE the tray/menu image size calculations
|
||||
if (AUTO_FIX_INCONSISTENCIES && isTrayType(trayType, TrayType.Swing) && SystemTray.SWING_UI == null) {
|
||||
if (isNix) {
|
||||
|
@ -90,32 +90,6 @@ class Tray extends Menu {
|
||||
}
|
||||
}
|
||||
|
||||
// method that is meant to be overridden by the tray implementations
|
||||
protected
|
||||
void setTooltip_(final String tooltipText) {
|
||||
// default is NO OP
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the tooltip text, usually this is used to brand the SystemTray icon with your product's name.
|
||||
* <p>
|
||||
* The maximum length is 64 characters long, and it is not supported on all Operating Systems and Desktop
|
||||
* Environments.
|
||||
* <p>
|
||||
* For more details on Linux see https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12.
|
||||
*
|
||||
* @param tooltipText the text to use as tooltip for the tray icon, null to remove
|
||||
*/
|
||||
final
|
||||
void setTooltip(final String tooltipText) {
|
||||
// this is a safety precaution, since the behavior of really long text is undefined.
|
||||
if (tooltipText.length() > 64) {
|
||||
throw new RuntimeException("Tooltip text cannot be longer than 64 characters.");
|
||||
}
|
||||
|
||||
setTooltip_(tooltipText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the new image to set for the tray icon.
|
||||
* <p>
|
||||
|
@ -31,4 +31,6 @@ interface MenuItemPeer extends EntryPeer {
|
||||
void setCallback(MenuItem menuItem);
|
||||
|
||||
void setShortcut(MenuItem menuItem);
|
||||
|
||||
void setTooltip(MenuItem menuItem);
|
||||
}
|
||||
|
@ -136,6 +136,18 @@ class AwtMenu implements MenuPeer {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
_native.setLabel(menuItem.getTooltip());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
|
@ -19,6 +19,7 @@ import java.awt.MenuShortcut;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.peer.MenuItemPeer;
|
||||
import dorkbox.util.SwingUtil;
|
||||
@ -114,6 +115,12 @@ class AwtMenuItem implements MenuItemPeer {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
// no op. (awt menus cannot show tooltips)
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public
|
||||
|
@ -182,6 +182,31 @@ class _AwtTray extends Tray {
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
final String text = menuItem.getTooltip();
|
||||
|
||||
if (tooltipText != null && tooltipText.equals(text) ||
|
||||
tooltipText == null && text != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipText = text;
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
// don't want to matter which (setImage/setTooltip/setEnabled) is done first, and if the image/enabled is changed, we
|
||||
// want to make sure keep the tooltip text the same as before.
|
||||
if (trayIcon != null) {
|
||||
trayIcon.setToolTip(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
@ -209,31 +234,6 @@ class _AwtTray extends Tray {
|
||||
bind(awtMenu, null, systemTray);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void setTooltip_(final String tooltipText) {
|
||||
if (this.tooltipText.equals(tooltipText)){
|
||||
return;
|
||||
}
|
||||
this.tooltipText = tooltipText;
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
if (tray == null) {
|
||||
tray = SystemTray.getSystemTray();
|
||||
}
|
||||
|
||||
// don't want to matter which (setImage/setTooltip/setEnabled) is done first, and if the image/enabled is changed, we
|
||||
// want to make sure keep the tooltip text the same as before.
|
||||
if (trayIcon != null) {
|
||||
trayIcon.setToolTip(tooltipText);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
|
@ -346,6 +346,12 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||
setText(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* called when a child removes itself from the parent menu. Does not work for sub-menus
|
||||
*
|
||||
|
@ -167,6 +167,20 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||
setText(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
GtkEventDispatch.dispatch(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
// NOTE: this will not work for AppIndicator tray types!
|
||||
// null will remove the tooltip
|
||||
Gtk2.gtk_widget_set_tooltip_text(_native, menuItem.getTooltip());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public
|
||||
|
@ -186,6 +186,12 @@ class _AppIndicatorNativeTray extends Tray {
|
||||
// no op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
// no op. see https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
@ -231,12 +237,6 @@ class _AppIndicatorNativeTray extends Tray {
|
||||
bind(gtkMenu, null, systemTray);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void setTooltip_(final String tooltipText) {
|
||||
// https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
|
@ -123,6 +123,27 @@ class _GtkStatusIconNativeTray extends Tray {
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
final String text = menuItem.getTooltip();
|
||||
|
||||
if (tooltipText != null && tooltipText.equals(text) ||
|
||||
tooltipText == null && text != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipText = text;
|
||||
|
||||
GtkEventDispatch.dispatch(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
Gtk2.gtk_status_icon_set_tooltip_text(trayIcon, text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
@ -208,23 +229,6 @@ class _GtkStatusIconNativeTray extends Tray {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void setTooltip_(final String tooltipText) {
|
||||
if (this.tooltipText.equals(tooltipText)){
|
||||
return;
|
||||
}
|
||||
this.tooltipText = tooltipText;
|
||||
|
||||
GtkEventDispatch.dispatch(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
Gtk2.gtk_status_icon_set_tooltip_text(trayIcon, tooltipText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
|
@ -173,6 +173,12 @@ class SwingMenu implements MenuPeer {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes all menu entries from this menu AND this menu from it's parent
|
||||
*/
|
||||
|
@ -166,6 +166,18 @@ class SwingMenuItem implements MenuItemPeer {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
_native.setToolTipText(menuItem.getTooltip());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
|
@ -167,6 +167,31 @@ class _SwingTray extends Tray {
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setTooltip(final MenuItem menuItem) {
|
||||
final String text = menuItem.getTooltip();
|
||||
|
||||
if (tooltipText != null && tooltipText.equals(text) ||
|
||||
tooltipText == null && text != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipText = text;
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
// don't want to matter which (setImage/setTooltip/setEnabled) is done first, and if the image/enabled is changed, we
|
||||
// want to make sure keep the tooltip text the same as before.
|
||||
if (trayIcon != null) {
|
||||
trayIcon.setToolTip(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
@ -199,27 +224,6 @@ class _SwingTray extends Tray {
|
||||
bind(swingMenu, null, systemTray);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void setTooltip_(final String tooltipText) {
|
||||
if (this.tooltipText.equals(tooltipText)){
|
||||
return;
|
||||
}
|
||||
this.tooltipText = tooltipText;
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
// don't want to matter which (setImage/setTooltip/setEnabled) is done first, and if the image/enabled is changed, we
|
||||
// want to make sure keep the tooltip text the same as before.
|
||||
if (trayIcon != null) {
|
||||
trayIcon.setToolTip(tooltipText);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
|
@ -102,12 +102,14 @@ class TestTray {
|
||||
entry.setCallback(callbackGray);
|
||||
entry.setImage(BLACK_MAIL);
|
||||
entry.setText("Delete Mail");
|
||||
entry.setTooltip(null); // remove the tooltip
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
greenEntry.setTooltip("This means you have green mail!");
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
|
||||
|
@ -164,12 +164,14 @@ class TestTrayJavaFX {
|
||||
entry.setCallback(callbackGray);
|
||||
entry.setImage(BLACK_MAIL);
|
||||
entry.setText("Delete Mail");
|
||||
entry.setTooltip(null); // remove the tooltip
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
greenEntry.setTooltip("This means you have green mail!");
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
|
||||
|
@ -118,12 +118,14 @@ class TestTraySwt {
|
||||
entry.setCallback(callbackGray);
|
||||
entry.setImage(BLACK_MAIL);
|
||||
entry.setText("Delete Mail");
|
||||
entry.setTooltip(null); // remove the tooltip
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
greenEntry.setTooltip("This means you have green mail!");
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user