2016-09-28 15:33:22 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2014 dorkbox, llc
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
package dorkbox.systemTray;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Iterator;
|
2016-09-29 01:44:11 +02:00
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
2016-09-28 15:33:22 +02:00
|
|
|
|
|
|
|
import dorkbox.systemTray.util.ImageUtils;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a cross-platform menu that is displayed by the tray-icon or as a sub-menu
|
|
|
|
*/
|
|
|
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
2016-10-03 20:13:00 +02:00
|
|
|
public abstract
|
2016-09-28 15:33:22 +02:00
|
|
|
class Menu {
|
2016-09-29 01:44:11 +02:00
|
|
|
public static final AtomicInteger MENU_ID_COUNTER = new AtomicInteger();
|
|
|
|
private final int id = Menu.MENU_ID_COUNTER.getAndIncrement();
|
2016-10-03 23:12:00 +02:00
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
protected final java.util.List<MenuEntry> menuEntries = new ArrayList<MenuEntry>();
|
|
|
|
|
2016-09-29 01:44:11 +02:00
|
|
|
private final SystemTray systemTray;
|
|
|
|
private final Menu parent;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param systemTray the system tray (which is the object that sits in the system tray)
|
|
|
|
* @param parent the parent of this menu, null if the parent is the system tray
|
|
|
|
*/
|
|
|
|
public
|
|
|
|
Menu(final SystemTray systemTray, final Menu parent) {
|
|
|
|
this.systemTray = systemTray;
|
|
|
|
this.parent = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the parent menu (of this menu) or null if we are the root menu
|
|
|
|
*/
|
|
|
|
public
|
|
|
|
Menu getParent() {
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the system tray that this menu is ultimately attached to
|
|
|
|
*/
|
|
|
|
public
|
|
|
|
SystemTray getSystemTray() {
|
|
|
|
return systemTray;
|
|
|
|
}
|
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
/**
|
|
|
|
* 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:
|
|
|
|
*
|
|
|
|
* Original Entry3 deleted Result
|
|
|
|
*
|
|
|
|
* <Status> <Status> <Status>
|
|
|
|
* Entry1 Entry1 Entry1
|
|
|
|
* Entry2 -> Entry2 -> Entry2
|
|
|
|
* <Spacer> (deleted)
|
|
|
|
* Entry3 (deleted)
|
|
|
|
*/
|
2016-10-03 20:13:00 +02:00
|
|
|
public abstract
|
|
|
|
void addSeparator();
|
2016-09-28 15:33:22 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Will add a new menu entry, or update one if it already exists
|
|
|
|
*/
|
2016-10-03 20:13:00 +02:00
|
|
|
protected abstract
|
|
|
|
MenuEntry addEntry_(final String menuText, final File imagePath, final SystemTrayMenuAction callback);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Will add a new sub-menu entry, or update one if it already exists
|
|
|
|
*/
|
|
|
|
protected abstract
|
|
|
|
Menu addMenu_(final String menuText, final File imagePath);
|
2016-09-28 15:33:22 +02:00
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
/*
|
|
|
|
* Called when this menu is removed from it's parent menu
|
|
|
|
*/
|
|
|
|
protected abstract
|
|
|
|
void removePrivate();
|
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
/*
|
|
|
|
* Necessary to guarantee all updates occur on the dispatch thread
|
|
|
|
*/
|
2016-10-03 20:13:00 +02:00
|
|
|
protected abstract
|
|
|
|
void dispatch(Runnable runnable);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Necessary to guarantee all updates occur on the dispatch thread
|
|
|
|
*/
|
|
|
|
protected abstract
|
|
|
|
void dispatchAndWait(Runnable runnable);
|
2016-09-28 15:33:22 +02:00
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
/**
|
|
|
|
* Enables, or disables the sub-menu entry.
|
|
|
|
*/
|
|
|
|
public abstract
|
|
|
|
void setEnabled(final boolean enabled);
|
|
|
|
|
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry get(final String menuText) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (menuText == null || menuText.isEmpty()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Must be wrapped in a synchronized block for object visibility
|
|
|
|
synchronized (menuEntries) {
|
|
|
|
for (MenuEntry entry : menuEntries) {
|
|
|
|
String text = entry.getText();
|
|
|
|
|
|
|
|
// text can be null
|
|
|
|
if (menuText.equals(text)) {
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Gets the first menu entry or sub-menu, ignoring status and spacers
|
2016-09-28 15:33:22 +02:00
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry getFirst() {
|
|
|
|
return get(0);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Gets the last menu entry or sub-menu, ignoring status and spacers
|
2016-09-28 15:33:22 +02:00
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry getLast() {
|
2016-09-28 15:33:22 +02:00
|
|
|
// Must be wrapped in a synchronized block for object visibility
|
|
|
|
synchronized (menuEntries) {
|
|
|
|
if (!menuEntries.isEmpty()) {
|
|
|
|
MenuEntry menuEntry = null;
|
|
|
|
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
|
|
|
menuEntry = menuEntries.get(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(menuEntry instanceof MenuSpacer || menuEntry instanceof MenuStatus)) {
|
|
|
|
return menuEntry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Gets the menu entry or sub-menu for a specified index (zero-index), ignoring status and spacers
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @param menuIndex the menu entry index to use to retrieve the menu entry.
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry get(final int menuIndex) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (menuIndex < 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Must be wrapped in a synchronized block for object visibility
|
|
|
|
synchronized (menuEntries) {
|
|
|
|
if (!menuEntries.isEmpty()) {
|
|
|
|
int count = 0;
|
|
|
|
for (MenuEntry menuEntry : menuEntries) {
|
|
|
|
if (menuEntry instanceof MenuSpacer || menuEntry instanceof MenuStatus) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == menuIndex) {
|
|
|
|
return menuEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Adds a menu entry with text (no image)
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @param menuText string of the text you want to appear
|
|
|
|
* @param callback callback that will be executed when this menu entry is clicked
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry addEntry(String menuText, SystemTrayMenuAction callback) {
|
|
|
|
return addEntry(menuText, (String) null, callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Adds a menu entry with text + image
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
* @param callback callback that will be executed when this menu entry is clicked
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry addEntry(String menuText, String imagePath, SystemTrayMenuAction callback) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (imagePath == null) {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, null, callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imagePath), callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Adds a menu entry with text + image
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
* @param callback callback that will be executed when this menu entry is clicked
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry addEntry(String menuText, URL imageUrl, SystemTrayMenuAction callback) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (imageUrl == null) {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, null, callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Adds a menu entry with text + image
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
* @param callback callback that will be executed when this menu entry is clicked
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry addEntry(String menuText, String cacheName, InputStream imageStream, SystemTrayMenuAction callback) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (imageStream == null) {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, null, callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, cacheName, imageStream), callback);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* Adds a menu entry with text + image
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
* @param callback callback that will be executed when this menu entry is clicked
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry addEntry(String menuText, InputStream imageStream, SystemTrayMenuAction callback) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (imageStream == null) {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addEntry_(menuText, null, callback);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return addEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, 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) {
|
|
|
|
if (imagePath == null) {
|
|
|
|
return addMenu_(menuText, null);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return addMenu_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, 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) {
|
|
|
|
if (imageUrl == null) {
|
|
|
|
return addMenu_(menuText, null);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-03 20:13:00 +02:00
|
|
|
return addMenu_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl));
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 20:13:00 +02:00
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
if (imageStream == null) {
|
|
|
|
return addMenu_(menuText, null);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return addMenu_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, 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) {
|
|
|
|
if (imageStream == null) {
|
|
|
|
return addMenu_(menuText, null);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return addMenu_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
/**
|
|
|
|
* This removes a menu entry from the dropdown menu.
|
|
|
|
*
|
|
|
|
* @param menuEntry This is the menu entry to remove
|
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
void remove(final MenuEntry menuEntry) {
|
2016-09-28 15:33:22 +02:00
|
|
|
if (menuEntry == null) {
|
|
|
|
throw new NullPointerException("No menu entry exists for menuEntry");
|
|
|
|
}
|
|
|
|
|
2016-10-03 20:13:00 +02:00
|
|
|
dispatchAndWait(new Runnable() {
|
2016-09-28 15:33:22 +02:00
|
|
|
@Override
|
|
|
|
public
|
|
|
|
void run() {
|
|
|
|
try {
|
|
|
|
synchronized (menuEntries) {
|
|
|
|
for (Iterator<MenuEntry> iterator = menuEntries.iterator(); iterator.hasNext(); ) {
|
|
|
|
final MenuEntry entry = iterator.next();
|
|
|
|
if (entry == menuEntry) {
|
|
|
|
iterator.remove();
|
|
|
|
|
|
|
|
// this will also reset the menu
|
|
|
|
menuEntry.remove();
|
|
|
|
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) {
|
2016-10-03 20:13:00 +02:00
|
|
|
remove(menuEntries.get(0));
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// 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) {
|
2016-10-03 20:13:00 +02:00
|
|
|
remove(menuEntries.get(menuEntries.size() - 1));
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
SystemTray.logger.error("Error removing menu entry from list.", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-10-03 20:13:00 +02:00
|
|
|
/**
|
|
|
|
* This removes a sub-menu entry or sub-menu from the dropdown menu.
|
|
|
|
*
|
|
|
|
* @param menu This is the menu entry to remove
|
|
|
|
*/
|
2016-10-03 23:12:00 +02:00
|
|
|
@SuppressWarnings("Duplicates")
|
2016-10-03 20:13:00 +02:00
|
|
|
public
|
|
|
|
void remove(final Menu menu) {
|
|
|
|
if (menu == null) {
|
|
|
|
throw new NullPointerException("No menu entry exists for menuEntry");
|
|
|
|
}
|
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
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();
|
2016-10-03 20:13:00 +02:00
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
// this will also reset the menu
|
|
|
|
menu.removePrivate();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-10-03 20:13:00 +02:00
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2016-10-03 20:13:00 +02:00
|
|
|
}
|
|
|
|
|
2016-09-28 15:33:22 +02:00
|
|
|
/**
|
2016-10-03 20:13:00 +02:00
|
|
|
* This removes a menu entry or sub-menu (via the text label) from the dropdown menu.
|
2016-09-28 15:33:22 +02:00
|
|
|
*
|
2016-10-03 20:13:00 +02:00
|
|
|
* @param menuText This is the label for the menu entry or sub-menu to remove
|
2016-09-28 15:33:22 +02:00
|
|
|
*/
|
2016-09-29 01:44:11 +02:00
|
|
|
public
|
2016-10-03 20:13:00 +02:00
|
|
|
void remove(final String menuText) {
|
|
|
|
dispatchAndWait(new Runnable() {
|
2016-09-28 15:33:22 +02:00
|
|
|
@Override
|
|
|
|
public
|
|
|
|
void run() {
|
|
|
|
synchronized (menuEntries) {
|
2016-10-03 20:13:00 +02:00
|
|
|
MenuEntry menuEntry = get(menuText);
|
2016-09-28 15:33:22 +02:00
|
|
|
|
2016-10-03 23:12:00 +02:00
|
|
|
if (menuEntry != null) {
|
2016-10-03 20:13:00 +02:00
|
|
|
remove(menuEntry);
|
2016-09-28 15:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|