Added setEnabled() for menu+entries, misc bug fixes for windows
This commit is contained in:
parent
ad8cd3709c
commit
7e2834c0cb
@ -20,7 +20,6 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
@ -33,7 +32,7 @@ public abstract
|
||||
class Menu {
|
||||
public static final AtomicInteger MENU_ID_COUNTER = new AtomicInteger();
|
||||
private final int id = Menu.MENU_ID_COUNTER.getAndIncrement();
|
||||
// TODO: enable/disable entries and menus?
|
||||
|
||||
protected final java.util.List<MenuEntry> menuEntries = new ArrayList<MenuEntry>();
|
||||
|
||||
private final SystemTray systemTray;
|
||||
@ -92,6 +91,12 @@ class Menu {
|
||||
protected abstract
|
||||
Menu addMenu_(final String menuText, final File imagePath);
|
||||
|
||||
/*
|
||||
* Called when this menu is removed from it's parent menu
|
||||
*/
|
||||
protected abstract
|
||||
void removePrivate();
|
||||
|
||||
/*
|
||||
* Necessary to guarantee all updates occur on the dispatch thread
|
||||
*/
|
||||
@ -104,6 +109,13 @@ class Menu {
|
||||
protected abstract
|
||||
void dispatchAndWait(Runnable runnable);
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
public abstract
|
||||
void setEnabled(final boolean enabled);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the menu entry for a specified text
|
||||
*
|
||||
@ -353,9 +365,6 @@ class Menu {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This removes a menu entry from the dropdown menu.
|
||||
*
|
||||
@ -367,9 +376,6 @@ class Menu {
|
||||
throw new NullPointerException("No menu entry exists for menuEntry");
|
||||
}
|
||||
|
||||
// have to wait for the value
|
||||
final AtomicBoolean hasValue = new AtomicBoolean(false);
|
||||
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
@ -383,7 +389,6 @@ class Menu {
|
||||
|
||||
// this will also reset the menu
|
||||
menuEntry.remove();
|
||||
hasValue.set(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -406,10 +411,6 @@ class Menu {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasValue.get()) {
|
||||
throw new NullPointerException("Menu entry '" + menuEntry.getText() + "'not found in list while trying to remove it.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -417,17 +418,51 @@ class Menu {
|
||||
*
|
||||
* @param menu This is the menu entry to remove
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public
|
||||
void remove(final Menu menu) {
|
||||
if (menu == null) {
|
||||
throw new NullPointerException("No menu entry exists for menuEntry");
|
||||
}
|
||||
|
||||
dispatchAndWait(new Runnable() {
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
try {
|
||||
synchronized (menuEntries) {
|
||||
for (Iterator<MenuEntry> iterator = menuEntries.iterator(); iterator.hasNext(); ) {
|
||||
final MenuEntry entry = iterator.next();
|
||||
if (entry == menu) {
|
||||
iterator.remove();
|
||||
|
||||
// this will also reset the menu
|
||||
menu.removePrivate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now check to see if a spacer is at the top/bottom of the list (and remove it if so. This is a recursive function.
|
||||
if (!menuEntries.isEmpty()) {
|
||||
if (menuEntries.get(0) instanceof MenuSpacer) {
|
||||
remove(menuEntries.get(0));
|
||||
}
|
||||
}
|
||||
// now check to see if a spacer is at the top/bottom of the list (and remove it if so. This is a recursive function.
|
||||
if (!menuEntries.isEmpty()) {
|
||||
if (menuEntries.get(menuEntries.size()-1) instanceof MenuSpacer) {
|
||||
remove(menuEntries.get(menuEntries.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SystemTray.logger.error("Error removing menu entry from list.", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This removes a menu entry or sub-menu (via the text label) from the dropdown menu.
|
||||
*
|
||||
@ -435,9 +470,6 @@ class Menu {
|
||||
*/
|
||||
public
|
||||
void remove(final String menuText) {
|
||||
// have to wait for the value
|
||||
final AtomicBoolean hasValue = new AtomicBoolean(true);
|
||||
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
@ -445,18 +477,11 @@ class Menu {
|
||||
synchronized (menuEntries) {
|
||||
MenuEntry menuEntry = get(menuText);
|
||||
|
||||
if (menuEntry == null) {
|
||||
hasValue.set(false);
|
||||
}
|
||||
else {
|
||||
if (menuEntry != null) {
|
||||
remove(menuEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasValue.get()) {
|
||||
throw new NullPointerException("No menu entry exists for string '" + menuText + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ interface MenuEntry {
|
||||
*/
|
||||
Menu getParent();
|
||||
|
||||
/**
|
||||
* Enables, or disables the entry.
|
||||
*/
|
||||
void setEnabled(final boolean enabled);
|
||||
|
||||
/**
|
||||
* @return the text label that the menu entry has assigned
|
||||
*/
|
||||
|
@ -104,7 +104,7 @@ class SystemTray extends Menu {
|
||||
* <p>
|
||||
* This is an advanced feature, and it is recommended to leave at 0.
|
||||
*/
|
||||
public static int FORCE_TRAY_TYPE = 0;
|
||||
public static int FORCE_TRAY_TYPE = 3;
|
||||
|
||||
@Property
|
||||
/**
|
||||
@ -812,6 +812,14 @@ class SystemTray extends Menu {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the attached menu to this system tray
|
||||
*/
|
||||
public
|
||||
Menu getMenu() {
|
||||
return systemTrayMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a spacer to the dropdown menu. When menu entries are removed, any menu spacer that ends up at the top/bottom of the drop-down
|
||||
* menu, will also be removed. For example:
|
||||
@ -825,34 +833,73 @@ class SystemTray extends Menu {
|
||||
* Entry3 (deleted)
|
||||
*/
|
||||
public
|
||||
void addMenuSpacer() {
|
||||
systemTrayMenu.addMenuSpacer();
|
||||
void addSeparator() {
|
||||
systemTrayMenu.addSeparator();
|
||||
}
|
||||
|
||||
|
||||
// NO OP.
|
||||
@Override
|
||||
protected
|
||||
MenuEntry addEntry_(final String menuText, final File imagePath, final SystemTrayMenuAction callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// NO OP.
|
||||
@Override
|
||||
protected
|
||||
Menu addMenu_(final String menuText, final File imagePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// NO OP.
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
}
|
||||
|
||||
// NO OP.
|
||||
@Override
|
||||
protected
|
||||
void dispatch(final Runnable runnable) {
|
||||
}
|
||||
|
||||
// NO OP.
|
||||
@Override
|
||||
protected
|
||||
void dispatchAndWait(final Runnable runnable) {
|
||||
}
|
||||
|
||||
// NO OP.
|
||||
protected
|
||||
void removePrivate() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the menu entry for a specified text
|
||||
*
|
||||
* @param menuText the menu entry text to use to find the menu entry. The first result found is returned
|
||||
*/
|
||||
public final
|
||||
MenuEntry getMenuEntry(final String menuText) {
|
||||
return systemTrayMenu.getMenuEntry(menuText);
|
||||
MenuEntry get(final String menuText) {
|
||||
return systemTrayMenu.get(menuText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first menu entry, ignoring status and spacers
|
||||
*/
|
||||
public final
|
||||
MenuEntry getFirstMenuEntry() {
|
||||
return systemTrayMenu.getFirstMenuEntry();
|
||||
MenuEntry getFirst() {
|
||||
return systemTrayMenu.getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last menu entry, ignoring status and spacers
|
||||
*/
|
||||
public final
|
||||
MenuEntry getLastMenuEntry() {
|
||||
return systemTrayMenu.getLastMenuEntry();
|
||||
MenuEntry getLast() {
|
||||
return systemTrayMenu.getLast();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -861,10 +908,14 @@ class SystemTray extends Menu {
|
||||
* @param menuIndex the menu entry index to use to retrieve the menu entry.
|
||||
*/
|
||||
public final
|
||||
MenuEntry getMenuEntry(final int menuIndex) {
|
||||
return systemTrayMenu.getMenuEntry(menuIndex);
|
||||
MenuEntry get(final int menuIndex) {
|
||||
return systemTrayMenu.get(menuIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a menu entry to the tray icon with text (no image)
|
||||
*
|
||||
@ -872,8 +923,8 @@ class SystemTray extends Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
void addMenuEntry(String menuText, SystemTrayMenuAction callback) {
|
||||
addMenuEntry(menuText, (String) null, callback);
|
||||
MenuEntry addEntry(String menuText, SystemTrayMenuAction callback) {
|
||||
return addEntry(menuText, (String) null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -884,8 +935,8 @@ class SystemTray extends Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
void addMenuEntry(String menuText, String imagePath, SystemTrayMenuAction callback) {
|
||||
systemTrayMenu.addMenuEntry(menuText, imagePath, callback);
|
||||
MenuEntry addEntry(String menuText, String imagePath, SystemTrayMenuAction callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imagePath, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -896,8 +947,8 @@ class SystemTray extends Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
void addMenuEntry(String menuText, URL imageUrl, SystemTrayMenuAction callback) {
|
||||
systemTrayMenu.addMenuEntry(menuText, imageUrl, callback);
|
||||
MenuEntry addEntry(String menuText, URL imageUrl, SystemTrayMenuAction callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imageUrl, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -909,8 +960,8 @@ class SystemTray extends Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public
|
||||
void addMenuEntry(String menuText, String cacheName, InputStream imageStream, SystemTrayMenuAction callback) {
|
||||
systemTrayMenu.addMenuEntry(menuText, cacheName, imageStream, callback);
|
||||
MenuEntry addEntry(String menuText, String cacheName, InputStream imageStream, SystemTrayMenuAction callback) {
|
||||
return systemTrayMenu.addEntry(menuText, cacheName, imageStream, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -921,18 +972,80 @@ class SystemTray extends Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
void addMenuEntry(String menuText, InputStream imageStream, SystemTrayMenuAction callback) {
|
||||
systemTrayMenu.addMenuEntry(menuText, imageStream, callback);
|
||||
MenuEntry addEntry(String menuText, InputStream imageStream, SystemTrayMenuAction callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imageStream, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text (no image)
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
*/
|
||||
public
|
||||
Menu addMenu(String menuText) {
|
||||
return addMenu(menuText, (String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text + image
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param imagePath the image (full path required) to use. If null, no image will be used
|
||||
*/
|
||||
public
|
||||
Menu addMenu(String menuText, String imagePath) {
|
||||
return systemTrayMenu.addMenu(menuText, imagePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text + image
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param imageUrl the URL of the image to use. If null, no image will be used
|
||||
*/
|
||||
public
|
||||
Menu addMenu(String menuText, URL imageUrl) {
|
||||
return systemTrayMenu.addMenu(menuText, imageUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text + image
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param cacheName @param cacheName the name to use for lookup in the cache for the imageStream
|
||||
* @param imageStream the InputStream of the image to use. If null, no image will be used
|
||||
*/
|
||||
public
|
||||
Menu addMenu(String menuText, String cacheName, InputStream imageStream) {
|
||||
return systemTrayMenu.addMenu(menuText, cacheName, imageStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text + image
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param imageStream the InputStream of the image to use. If null, no image will be used
|
||||
*/
|
||||
public
|
||||
Menu addMenu(String menuText, InputStream imageStream) {
|
||||
return systemTrayMenu.addMenu(menuText, imageStream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This removes a menu entry from the dropdown menu.
|
||||
*
|
||||
* @param menuEntry This is the menu entry to remove
|
||||
*/
|
||||
public final
|
||||
void removeMenuEntry(final MenuEntry menuEntry) {
|
||||
systemTrayMenu.removeMenuEntry(menuEntry);
|
||||
void remove(final MenuEntry menuEntry) {
|
||||
systemTrayMenu.remove(menuEntry);
|
||||
}
|
||||
|
||||
|
||||
@ -942,8 +1055,8 @@ class SystemTray extends Menu {
|
||||
* @param menuText This is the label for the menu entry to remove
|
||||
*/
|
||||
public final
|
||||
void removeMenuEntry(final String menuText) {
|
||||
systemTrayMenu.removeMenuEntry(menuText);
|
||||
void remove(final String menuText) {
|
||||
systemTrayMenu.remove(menuText);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,18 @@ class GtkEntry implements MenuEntry {
|
||||
abstract
|
||||
void setImage_(final File imageFile);
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
if (enabled) {
|
||||
Gtk.gtk_widget_set_sensitive(_native, Gtk.TRUE);
|
||||
} else {
|
||||
Gtk.gtk_widget_set_sensitive(_native, Gtk.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
|
@ -57,6 +57,10 @@ class GtkEntrySeparator extends GtkEntry implements MenuSpacer {
|
||||
@Override
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
}
|
||||
}
|
||||
|
@ -53,4 +53,9 @@ class GtkEntryStatus extends GtkEntryItem {
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,19 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
if (enabled) {
|
||||
Gtk.gtk_widget_set_sensitive(menuEntry._native, Gtk.TRUE);
|
||||
} else {
|
||||
Gtk.gtk_widget_set_sensitive(menuEntry._native, Gtk.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void addSeparator() {
|
||||
|
@ -59,6 +59,14 @@ class SwingEntry implements MenuEntry {
|
||||
abstract
|
||||
void setImage_(final File imageFile);
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
_native.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
|
@ -58,11 +58,11 @@ class SwingMenu extends Menu implements MenuEntry {
|
||||
public
|
||||
void run() {
|
||||
if (parent != null) {
|
||||
if (!OS.isLinux()) {
|
||||
_native = new AdjustedJMenu(null);
|
||||
if (OS.isLinux()) {
|
||||
_native = new AdjustedJMenu((SwingSystemTrayLinuxMenuPopup)((SwingMenu) systemTray.getMenu())._native);
|
||||
}
|
||||
else {
|
||||
_native = new AdjustedJMenu((SwingSystemTrayLinuxMenuPopup)((SwingMenu) systemTray.getMenu())._native);
|
||||
_native = new AdjustedJMenu(null);
|
||||
}
|
||||
|
||||
((SwingMenu) parent)._native.add(_native);
|
||||
@ -108,6 +108,15 @@ class SwingMenu extends Menu implements MenuEntry {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
_native.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
*/
|
||||
@ -303,8 +312,27 @@ class SwingMenu extends Menu implements MenuEntry {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
((SwingMenu) getParent())._native.remove(_native);
|
||||
_native.setVisible(false);
|
||||
if (_native instanceof SwingSystemTrayMenuPopup) {
|
||||
((SwingSystemTrayMenuPopup) _native).close();
|
||||
}
|
||||
else if (_native instanceof SwingSystemTrayLinuxMenuPopup) {
|
||||
((SwingSystemTrayLinuxMenuPopup) _native).close();
|
||||
}
|
||||
|
||||
SwingMenu parent = (SwingMenu) getParent();
|
||||
if (parent != null) {
|
||||
parent._native.remove(_native);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when this menu is removed from it's parent menu
|
||||
*/
|
||||
protected
|
||||
void removePrivate() {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ class SwingSystemTray extends SwingMenu {
|
||||
}
|
||||
menuEntries.clear();
|
||||
}
|
||||
|
||||
remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -156,4 +156,9 @@ class SwingSystemTrayLinuxMenuPopup extends JPopupMenu {
|
||||
// restart the timer
|
||||
SwingSystemTrayLinuxMenuPopup.this.timer.delay(POPUP_HIDE_DELAY);
|
||||
}
|
||||
|
||||
public
|
||||
void close() {
|
||||
this.timer.cancel();
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ class SwingSystemTrayMenuPopup extends JPopupMenu {
|
||||
this.hiddenDialog = new JDialog((Frame)null);
|
||||
this.hiddenDialog.setEnabled(false);
|
||||
this.hiddenDialog.setUndecorated(true);
|
||||
this.hiddenDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
|
||||
this.hiddenDialog.setSize(1, 1);
|
||||
|
||||
@ -68,4 +69,10 @@ class SwingSystemTrayMenuPopup extends JPopupMenu {
|
||||
|
||||
super.setVisible(makeVisible);
|
||||
}
|
||||
|
||||
public
|
||||
void close() {
|
||||
this.hiddenDialog.setVisible(false);
|
||||
this.hiddenDialog.dispatchEvent(new WindowEvent(this.hiddenDialog, WindowEvent.WINDOW_CLOSING));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user