forked from dorkbox/SystemTray
Code polish, documentation, cleanup for API changes
This commit is contained in:
parent
daff5a8e48
commit
599dabf4ef
@ -34,5 +34,7 @@
|
||||
<orderEntry type="module" module-name="JavaLauncher-Util" />
|
||||
<orderEntry type="library" name="jna" level="application" />
|
||||
<orderEntry type="library" name="SWT" level="project" />
|
||||
<orderEntry type="library" name="asm" level="application" />
|
||||
<orderEntry type="library" name="javassist" level="application" />
|
||||
</component>
|
||||
</module>
|
@ -13,92 +13,104 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import dorkbox.systemTray.util.MenuCheckboxHook;
|
||||
import dorkbox.systemTray.peer.CheckboxPeer;
|
||||
|
||||
/**
|
||||
* This represents a common menu-checkbox entry, that is cross platform in nature
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public
|
||||
class Checkbox extends Entry {
|
||||
private volatile boolean isChecked = false;
|
||||
private volatile String text;
|
||||
private volatile ActionListener callback;
|
||||
private boolean isChecked = false;
|
||||
private String text;
|
||||
private ActionListener callback;
|
||||
|
||||
private volatile boolean enabled = true;
|
||||
private volatile char mnemonicKey;
|
||||
private boolean enabled = true;
|
||||
private char mnemonicKey;
|
||||
|
||||
public
|
||||
Checkbox() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public
|
||||
Checkbox(final String text) {
|
||||
this(text, null);
|
||||
}
|
||||
|
||||
public
|
||||
Checkbox(final String text, final ActionListener callback) {
|
||||
this.text = text;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public
|
||||
Checkbox(final String text) {
|
||||
this(text, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hook the platform specific implementation for all actions for this type
|
||||
* @param peer the platform specific implementation for all actions for this type
|
||||
* @param parent the parent of this menu, null if the parent is the system tray
|
||||
* @param systemTray the system tray (which is the object that sits in the system tray)
|
||||
*/
|
||||
public synchronized
|
||||
void bind(final MenuCheckboxHook hook, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(hook, parent, systemTray);
|
||||
void bind(final CheckboxPeer peer, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(peer, parent, systemTray);
|
||||
|
||||
hook.setEnabled(this);
|
||||
hook.setText(this);
|
||||
hook.setCallback(this);
|
||||
hook.setShortcut(this);
|
||||
hook.setChecked(this);
|
||||
peer.setEnabled(this);
|
||||
peer.setText(this);
|
||||
peer.setCallback(this);
|
||||
peer.setShortcut(this);
|
||||
peer.setChecked(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this checkbox is selected, false if not.
|
||||
*/
|
||||
public synchronized
|
||||
boolean getChecked() {
|
||||
return isChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the checked status for this entry
|
||||
*
|
||||
* @param checked true to show the checkbox, false to hide it
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setChecked(boolean checked) {
|
||||
this.isChecked = checked;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuCheckboxHook) hook).setChecked(this);
|
||||
if (peer != null) {
|
||||
((CheckboxPeer) peer).setChecked(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this checkbox is selected, false if not.
|
||||
*/
|
||||
public final
|
||||
boolean getChecked() {
|
||||
return isChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the callback assigned to this menu entry
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
ActionListener getCallback() {
|
||||
return callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback for a menu entry. This is the action that occurs when one clicks the menu entry
|
||||
*
|
||||
* @param callback the callback to set. If null, the callback is safely removed.
|
||||
*/
|
||||
public synchronized
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
if (peer != null) {
|
||||
((CheckboxPeer) peer).setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this item is enabled, or false if it is disabled.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
boolean getEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@ -106,19 +118,19 @@ class Checkbox extends Entry {
|
||||
/**
|
||||
* Enables, or disables the entry.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuCheckboxHook) hook).setEnabled(this);
|
||||
if (peer != null) {
|
||||
((CheckboxPeer) peer).setEnabled(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the text label that the menu entry has assigned
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
String getText() {
|
||||
return text;
|
||||
}
|
||||
@ -128,54 +140,41 @@ class Checkbox extends Entry {
|
||||
*
|
||||
* @param text the new text to set
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setText(final String text) {
|
||||
this.text = text;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuCheckboxHook) hook).setText(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback for a menu entry. This is the action that occurs when one clicks the menu entry
|
||||
*
|
||||
* @param callback the callback to set. If null, the callback is safely removed.
|
||||
*/
|
||||
public
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
if (hook != null) {
|
||||
((MenuCheckboxHook) hook).setCallback(this);
|
||||
if (peer != null) {
|
||||
((CheckboxPeer) peer).setText(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shortcut key for this menu entry (Mnemonic) which is what menu entry uses to be "selected" via the keyboard while the
|
||||
* menu is displayed.
|
||||
*
|
||||
* <p>
|
||||
* Mnemonics are case-insensitive, and if the character defined by the mnemonic is found within the text, the first occurrence
|
||||
* of it will be underlined.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
char getShortcut() {
|
||||
return this.mnemonicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a menu entry shortcut key (Mnemonic) so that menu entry can be "selected" via the keyboard while the menu is displayed.
|
||||
*
|
||||
* <p>
|
||||
* Mnemonics are case-insensitive, and if the character defined by the mnemonic is found within the text, the first occurrence
|
||||
* of it will be underlined.
|
||||
*
|
||||
* @param key this is the key to set as the mnemonic
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setShortcut(final char key) {
|
||||
this.mnemonicKey = key;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuCheckboxHook) hook).setShortcut(this);
|
||||
if (peer != null) {
|
||||
((CheckboxPeer) peer).setShortcut(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import dorkbox.systemTray.util.EntryHook;
|
||||
import dorkbox.systemTray.peer.EntryPeer;
|
||||
|
||||
/**
|
||||
* This represents a common menu-entry, that is cross platform in nature
|
||||
@ -32,7 +31,7 @@ class Entry {
|
||||
private Menu parent;
|
||||
private SystemTray systemTray;
|
||||
|
||||
protected volatile EntryHook hook;
|
||||
protected volatile EntryPeer peer;
|
||||
|
||||
public
|
||||
Entry() {
|
||||
@ -42,16 +41,16 @@ class Entry {
|
||||
// called internally when an entry/menu is attached
|
||||
|
||||
/**
|
||||
* @param hook the platform specific implementation for all actions for this type
|
||||
* @param peer the platform specific implementation for all actions for this type
|
||||
* @param parent the parent of this menu, null if the parent is the system tray
|
||||
* @param systemTray the system tray (which is the object that sits in the system tray)
|
||||
*/
|
||||
public synchronized
|
||||
void bind(final EntryHook hook, final Menu parent, final SystemTray systemTray) {
|
||||
void bind(final EntryPeer peer, final Menu parent, final SystemTray systemTray) {
|
||||
this.parent = parent;
|
||||
this.systemTray = systemTray;
|
||||
|
||||
this.hook = hook;
|
||||
this.peer = peer;
|
||||
}
|
||||
|
||||
// END methods for hooking into the system tray, menu's, and entries.
|
||||
@ -78,12 +77,12 @@ class Entry {
|
||||
*/
|
||||
public synchronized
|
||||
void remove() {
|
||||
if (hook != null) {
|
||||
hook.remove();
|
||||
if (peer != null) {
|
||||
peer.remove();
|
||||
|
||||
this.parent = null;
|
||||
this.systemTray = null;
|
||||
hook = null;
|
||||
peer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import dorkbox.systemTray.util.MenuHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.peer.MenuPeer;
|
||||
|
||||
/**
|
||||
* Represents a cross-platform menu that is displayed by the tray-icon or as a sub-menu
|
||||
@ -33,7 +32,7 @@ import dorkbox.systemTray.util.Status;
|
||||
@SuppressWarnings("unused")
|
||||
public
|
||||
class Menu extends MenuItem {
|
||||
protected final List<Entry> menuEntries = new ArrayList<Entry>();
|
||||
final List<Entry> menuEntries = new ArrayList<Entry>();
|
||||
|
||||
public
|
||||
Menu() {
|
||||
@ -100,19 +99,17 @@ class Menu extends MenuItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hook the platform specific implementation for all actions for this type
|
||||
* @param peer the platform specific implementation for all actions for this type
|
||||
* @param parent the parent of this menu, null if the parent is the system tray
|
||||
* @param systemTray the system tray (which is the object that sits in the system tray)
|
||||
*/
|
||||
public synchronized
|
||||
void bind(final MenuHook hook, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(hook, parent, systemTray);
|
||||
void bind(final MenuPeer peer, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(peer, parent, systemTray);
|
||||
|
||||
synchronized (menuEntries) {
|
||||
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
final Entry menuEntry = menuEntries.get(i);
|
||||
hook.add(this, menuEntry, i);
|
||||
}
|
||||
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
final Entry menuEntry = menuEntries.get(i);
|
||||
peer.add(this, menuEntry, i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,22 +132,20 @@ class Menu extends MenuItem {
|
||||
/**
|
||||
* Adds a menu entry, separator, or sub-menu to this menu.
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
<T extends Entry> T add(final T entry, int index) {
|
||||
synchronized (menuEntries) {
|
||||
if (index == -1) {
|
||||
menuEntries.add(entry);
|
||||
} else {
|
||||
if (!menuEntries.isEmpty() && menuEntries.get(0) instanceof Status) {
|
||||
// the "status" menu entry is ALWAYS first
|
||||
index++;
|
||||
}
|
||||
menuEntries.add(index, entry);
|
||||
if (index == -1) {
|
||||
menuEntries.add(entry);
|
||||
} else {
|
||||
if (!menuEntries.isEmpty() && menuEntries.get(0) instanceof Status) {
|
||||
// the "status" menu entry is ALWAYS first
|
||||
index++;
|
||||
}
|
||||
menuEntries.add(index, entry);
|
||||
}
|
||||
|
||||
if (hook != null) {
|
||||
((MenuHook) hook).add(this, entry, index);
|
||||
if (peer != null) {
|
||||
((MenuPeer) peer).add(this, entry, index);
|
||||
}
|
||||
|
||||
return entry;
|
||||
@ -167,18 +162,16 @@ class Menu extends MenuItem {
|
||||
/**
|
||||
* Gets the last menu entry or sub-menu, ignoring status and separators
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
Entry getLast() {
|
||||
// Must be wrapped in a synchronized block for object visibility
|
||||
synchronized (menuEntries) {
|
||||
if (!menuEntries.isEmpty()) {
|
||||
Entry entry;
|
||||
for (int i = menuEntries.size()-1; i >= 0; i--) {
|
||||
entry = menuEntries.get(i);
|
||||
if (!menuEntries.isEmpty()) {
|
||||
Entry entry;
|
||||
for (int i = menuEntries.size()-1; i >= 0; i--) {
|
||||
entry = menuEntries.get(i);
|
||||
|
||||
if (!(entry instanceof Separator || entry instanceof Status)) {
|
||||
return entry;
|
||||
}
|
||||
if (!(entry instanceof Separator || entry instanceof Status)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,27 +184,25 @@ class Menu extends MenuItem {
|
||||
*
|
||||
* @param menuIndex the menu entry index to use to retrieve the menu entry.
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
Entry get(final int menuIndex) {
|
||||
if (menuIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Must be wrapped in a synchronized block for object visibility
|
||||
synchronized (menuEntries) {
|
||||
if (!menuEntries.isEmpty()) {
|
||||
int count = 0;
|
||||
for (Entry entry : menuEntries) {
|
||||
if (entry instanceof Separator || entry instanceof Status) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count == menuIndex) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
count++;
|
||||
if (!menuEntries.isEmpty()) {
|
||||
int count = 0;
|
||||
for (Entry entry : menuEntries) {
|
||||
if (entry instanceof Separator || entry instanceof Status) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count == menuIndex) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,19 +214,30 @@ class Menu extends MenuItem {
|
||||
*
|
||||
* @param entry This is the menu entry to remove
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
void remove(final Entry entry) {
|
||||
// null is passed in when a sub-menu is removing itself from us (because they have already called "remove" and have also
|
||||
// removed themselves from the menuEntries)
|
||||
if (entry != null) {
|
||||
synchronized (menuEntries) {
|
||||
for (Iterator<Entry> iterator = menuEntries.iterator(); iterator.hasNext(); ) {
|
||||
final Entry entry__ = iterator.next();
|
||||
if (entry__ == entry) {
|
||||
iterator.remove();
|
||||
entry.remove();
|
||||
break;
|
||||
}
|
||||
for (Iterator<Entry> iterator = menuEntries.iterator(); iterator.hasNext(); ) {
|
||||
final Entry entry__ = iterator.next();
|
||||
if (entry__ == entry) {
|
||||
iterator.remove();
|
||||
entry.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 dorkbox.systemTray.Separator) {
|
||||
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 dorkbox.systemTray.Separator) {
|
||||
remove(menuEntries.get(menuEntries.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,16 +246,14 @@ class Menu extends MenuItem {
|
||||
/**
|
||||
* This removes all menu entries from this menu
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
void removeAll() {
|
||||
synchronized (menuEntries) {
|
||||
// have to make copy because we are deleting all of them, and sub-menus remove themselves from parents
|
||||
ArrayList<Entry> menuEntriesCopy = new ArrayList<Entry>(this.menuEntries);
|
||||
for (Entry entry : menuEntriesCopy) {
|
||||
entry.remove();
|
||||
}
|
||||
menuEntries.clear();
|
||||
// have to make copy because we are deleting all of them, and sub-menus remove themselves from parents
|
||||
ArrayList<Entry> menuEntriesCopy = new ArrayList<Entry>(this.menuEntries);
|
||||
for (Entry entry : menuEntriesCopy) {
|
||||
entry.remove();
|
||||
}
|
||||
menuEntries.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
import java.awt.Image;
|
||||
@ -22,8 +21,8 @@ import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.peer.MenuItemPeer;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
import dorkbox.systemTray.util.MenuItemHook;
|
||||
|
||||
/**
|
||||
* This represents a common menu-entry, that is cross platform in nature
|
||||
@ -31,13 +30,13 @@ import dorkbox.systemTray.util.MenuItemHook;
|
||||
@SuppressWarnings({"unused", "SameParameterValue", "WeakerAccess"})
|
||||
public
|
||||
class MenuItem extends Entry {
|
||||
private volatile String text;
|
||||
private volatile File imageFile;
|
||||
private volatile ActionListener callback;
|
||||
private String text;
|
||||
private File imageFile;
|
||||
private ActionListener callback;
|
||||
|
||||
// default enabled is always true
|
||||
private volatile boolean enabled = true;
|
||||
private volatile char mnemonicKey;
|
||||
private boolean enabled = true;
|
||||
private char mnemonicKey;
|
||||
|
||||
public
|
||||
MenuItem() {
|
||||
@ -113,27 +112,27 @@ class MenuItem extends Entry {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hook the platform specific implementation for all actions for this type
|
||||
* @param peer the platform specific implementation for all actions for this type
|
||||
* @param parent the parent of this menu, null if the parent is the system tray
|
||||
* @param systemTray the system tray (which is the object that sits in the system tray)
|
||||
*/
|
||||
public synchronized
|
||||
void bind(final MenuItemHook hook, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(hook, parent, systemTray);
|
||||
void bind(final MenuItemPeer peer, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(peer, parent, systemTray);
|
||||
|
||||
hook.setImage(this);
|
||||
hook.setEnabled(this);
|
||||
hook.setText(this);
|
||||
hook.setCallback(this);
|
||||
hook.setShortcut(this);
|
||||
peer.setImage(this);
|
||||
peer.setEnabled(this);
|
||||
peer.setText(this);
|
||||
peer.setCallback(this);
|
||||
peer.setShortcut(this);
|
||||
}
|
||||
|
||||
private
|
||||
private synchronized
|
||||
void setImage_(final File imageFile) {
|
||||
this.imageFile = imageFile;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuItemHook) hook).setImage(this);
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setImage(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +141,7 @@ class MenuItem extends Entry {
|
||||
* <p>
|
||||
* This file can also be a cached file, depending on how the image was assigned to this entry.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
File getImage() {
|
||||
return imageFile;
|
||||
}
|
||||
@ -150,7 +149,7 @@ class MenuItem extends Entry {
|
||||
/**
|
||||
* Gets the callback assigned to this menu entry
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
ActionListener getCallback() {
|
||||
return callback;
|
||||
}
|
||||
@ -158,7 +157,7 @@ class MenuItem extends Entry {
|
||||
/**
|
||||
* @return true if this item is enabled, or false if it is disabled.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
boolean getEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@ -166,19 +165,19 @@ class MenuItem extends Entry {
|
||||
/**
|
||||
* Enables, or disables the entry.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuItemHook) hook).setEnabled(this);
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setEnabled(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the text label that the menu entry has assigned
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
String getText() {
|
||||
return text;
|
||||
}
|
||||
@ -188,12 +187,12 @@ class MenuItem extends Entry {
|
||||
*
|
||||
* @param text the new text to set
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setText(final String text) {
|
||||
this.text = text;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuItemHook) hook).setText(this);
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setText(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +314,7 @@ class MenuItem extends Entry {
|
||||
/**
|
||||
* @return true if this menu entry has an image assigned to it, or is just text.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
boolean hasImage() {return imageFile != null;}
|
||||
|
||||
/**
|
||||
@ -323,12 +322,12 @@ class MenuItem extends Entry {
|
||||
*
|
||||
* @param callback the callback to set. If null, the callback is safely removed.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuItemHook) hook).setCallback(this);
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +338,7 @@ class MenuItem extends Entry {
|
||||
* Mnemonics are case-insensitive, and if the character defined by the mnemonic is found within the text, the first occurrence
|
||||
* of it will be underlined.
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
char getShortcut() {
|
||||
return this.mnemonicKey;
|
||||
}
|
||||
@ -352,19 +351,19 @@ class MenuItem extends Entry {
|
||||
*
|
||||
* @param key this is the key to set as the mnemonic
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setShortcut(final char key) {
|
||||
this.mnemonicKey = key;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuItemHook) hook).setShortcut(this);
|
||||
if (peer != null) {
|
||||
((MenuItemPeer) peer).setShortcut(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized
|
||||
void remove() {
|
||||
if (hook != null) {
|
||||
if (peer != null) {
|
||||
setImage_(null);
|
||||
setText(null);
|
||||
setCallback(null);
|
||||
|
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
/**
|
||||
|
@ -13,12 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.systemTray;
|
||||
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.peer.StatusPeer;
|
||||
|
||||
/**
|
||||
* This represents a common menu-status entry, that is cross platform in nature
|
||||
@ -32,21 +29,21 @@ class Status extends Entry {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hook the platform specific implementation for all actions for this type
|
||||
* @param peer the platform specific implementation for all actions for this type
|
||||
* @param parent the parent of this menu, null if the parent is the system tray
|
||||
* @param systemTray the system tray (which is the object that sits in the system tray)
|
||||
*/
|
||||
public synchronized
|
||||
void bind(final MenuStatusHook hook, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(hook, parent, systemTray);
|
||||
void bind(final StatusPeer peer, final Menu parent, final SystemTray systemTray) {
|
||||
super.bind(peer, parent, systemTray);
|
||||
|
||||
hook.setText(this);
|
||||
peer.setText(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the text label that the menu entry has assigned
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
String getText() {
|
||||
return text;
|
||||
}
|
||||
@ -56,12 +53,12 @@ class Status extends Entry {
|
||||
*
|
||||
* @param text the new text to set
|
||||
*/
|
||||
public
|
||||
public synchronized
|
||||
void setText(final String text) {
|
||||
this.text = text;
|
||||
|
||||
if (hook != null) {
|
||||
((MenuStatusHook) hook).setText(this);
|
||||
if (peer != null) {
|
||||
((StatusPeer) peer).setText(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,20 @@
|
||||
/*
|
||||
* 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 dorkbox.systemTray.util.Status;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
class Tray extends Menu {
|
||||
|
||||
@ -22,7 +32,7 @@ class Tray extends Menu {
|
||||
/**
|
||||
* Gets the 'status' string assigned to the system tray
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
String getStatus() {
|
||||
return statusText;
|
||||
}
|
||||
@ -32,37 +42,35 @@ class Tray extends Menu {
|
||||
*
|
||||
* @param statusText the text you want displayed, null if you want to remove the 'status' string
|
||||
*/
|
||||
public final
|
||||
public synchronized
|
||||
void setStatus(final String statusText) {
|
||||
this.statusText = statusText;
|
||||
|
||||
synchronized (menuEntries) {
|
||||
// status is ALWAYS at 0 index...
|
||||
Entry menuEntry = null;
|
||||
if (!menuEntries.isEmpty()) {
|
||||
menuEntry = menuEntries.get(0);
|
||||
}
|
||||
|
||||
if (menuEntry instanceof Status) {
|
||||
// set the text or delete...
|
||||
|
||||
if (statusText == null) {
|
||||
// delete
|
||||
remove(menuEntry);
|
||||
}
|
||||
else {
|
||||
// set text
|
||||
((Status) menuEntry).setText(statusText);
|
||||
}
|
||||
} else {
|
||||
// create a new one
|
||||
Status status = new Status();
|
||||
status.setText(statusText);
|
||||
|
||||
// status is ALWAYS at 0 index...
|
||||
Entry menuEntry = null;
|
||||
if (!menuEntries.isEmpty()) {
|
||||
menuEntry = menuEntries.get(0);
|
||||
}
|
||||
|
||||
if (menuEntry instanceof Status) {
|
||||
// set the text or delete...
|
||||
|
||||
if (statusText == null) {
|
||||
// delete
|
||||
remove(menuEntry);
|
||||
}
|
||||
else {
|
||||
// set text
|
||||
((Status) menuEntry).setText(statusText);
|
||||
}
|
||||
} else {
|
||||
// create a new one
|
||||
Status status = new Status();
|
||||
status.setText(statusText);
|
||||
|
||||
// status is ALWAYS at 0 index...
|
||||
// also calls the hook to add it, so we don't need anything special
|
||||
add(status, 0);
|
||||
}
|
||||
// also calls the hook to add it, so we don't need anything special
|
||||
add(status, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* 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.nativeUI;
|
||||
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.MenuShortcut;
|
||||
import java.awt.PopupMenu;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.swingUI.SwingUI;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
abstract
|
||||
class AwtEntry extends Entry implements SwingUI {
|
||||
private final AwtMenu parent;
|
||||
final MenuItem _native;
|
||||
|
||||
// this have to be volatile, because they can be changed from any thread
|
||||
private volatile String text;
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
AwtEntry(final AwtMenu parent, final MenuItem menuItem) {
|
||||
this.parent = parent;
|
||||
this._native = menuItem;
|
||||
|
||||
parent._native.add(menuItem);
|
||||
}
|
||||
|
||||
// public
|
||||
// Menu getParent() {
|
||||
// return parent;
|
||||
// }
|
||||
|
||||
/**
|
||||
* must always be called in the EDT thread
|
||||
*/
|
||||
abstract
|
||||
void renderText(final String text);
|
||||
|
||||
/**
|
||||
* Not always called on the EDT thread
|
||||
*/
|
||||
abstract
|
||||
void setImage_(final File imageFile);
|
||||
|
||||
/**
|
||||
* Enables, or disables the sub-menu entry.
|
||||
*/
|
||||
public
|
||||
void setEnabled(final boolean enabled) {
|
||||
_native.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public
|
||||
void setShortcut(final char key) {
|
||||
if (!(_native instanceof PopupMenu)) {
|
||||
// yikes...
|
||||
final int vKey = SystemTrayFixes.getVirtualKey(key);
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
_native.setShortcut(new MenuShortcut(vKey));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public
|
||||
String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public
|
||||
void setText(final String newText) {
|
||||
this.text = newText;
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
renderText(newText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public
|
||||
void setImage(final File imageFile) {
|
||||
if (imageFile == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
// setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageFile));
|
||||
}
|
||||
}
|
||||
|
||||
public final
|
||||
void setImage(final String imagePath) {
|
||||
if (imagePath == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
// setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imagePath));
|
||||
}
|
||||
}
|
||||
|
||||
public final
|
||||
void setImage(final URL imageUrl) {
|
||||
if (imageUrl == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
// setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl));
|
||||
}
|
||||
}
|
||||
|
||||
public final
|
||||
void setImage(final String cacheName, final InputStream imageStream) {
|
||||
if (imageStream == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
// setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, cacheName, imageStream));
|
||||
}
|
||||
}
|
||||
|
||||
public final
|
||||
void setImage(final InputStream imageStream) {
|
||||
if (imageStream == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
// setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream));
|
||||
}
|
||||
}
|
||||
|
||||
public final
|
||||
void remove() {
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
removePrivate();
|
||||
parent._native.remove(_native);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// called when this item is removed. Necessary to cleanup/remove itself
|
||||
abstract
|
||||
void removePrivate();
|
||||
}
|
@ -24,14 +24,14 @@ import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.util.MenuHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.peer.MenuPeer;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
// this is a weird composite class, because it must be a Menu, but ALSO a Entry -- so it has both
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
class AwtMenu implements MenuHook {
|
||||
class AwtMenu implements MenuPeer {
|
||||
|
||||
volatile java.awt.Menu _native;
|
||||
private final AwtMenu parent;
|
||||
|
@ -21,11 +21,11 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.util.MenuItemHook;
|
||||
import dorkbox.systemTray.peer.MenuItemPeer;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class AwtMenuItem implements MenuItemHook {
|
||||
class AwtMenuItem implements MenuItemPeer {
|
||||
|
||||
private final AwtMenu parent;
|
||||
private final MenuItem _native = new java.awt.MenuItem();
|
||||
@ -116,6 +116,7 @@ class AwtMenuItem implements MenuItemHook {
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
|
@ -21,18 +21,17 @@ import java.awt.event.ActionListener;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.util.MenuCheckboxHook;
|
||||
import dorkbox.systemTray.peer.CheckboxPeer;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class AwtMenuItemCheckbox implements MenuCheckboxHook {
|
||||
class AwtMenuItemCheckbox implements CheckboxPeer {
|
||||
|
||||
private final AwtMenu parent;
|
||||
private final java.awt.CheckboxMenuItem _native = new java.awt.CheckboxMenuItem();
|
||||
|
||||
private volatile ActionListener swingCallback;
|
||||
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
AwtMenuItemCheckbox(final AwtMenu parent) {
|
||||
this.parent = parent;
|
||||
|
@ -17,10 +17,10 @@ package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import java.awt.MenuItem;
|
||||
|
||||
import dorkbox.systemTray.util.EntryHook;
|
||||
import dorkbox.systemTray.peer.EntryPeer;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class AwtMenuItemSeparator implements EntryHook {
|
||||
class AwtMenuItemSeparator implements EntryPeer {
|
||||
|
||||
private final AwtMenu parent;
|
||||
private final MenuItem _native = new MenuItem("-");
|
||||
|
@ -20,11 +20,11 @@ import static java.awt.Font.DIALOG;
|
||||
import java.awt.Font;
|
||||
import java.awt.MenuItem;
|
||||
|
||||
import dorkbox.systemTray.util.MenuStatusHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.peer.StatusPeer;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class AwtMenuItemStatus implements MenuStatusHook {
|
||||
class AwtMenuItemStatus implements StatusPeer {
|
||||
|
||||
private final AwtMenu parent;
|
||||
private final MenuItem _native = new MenuItem();
|
||||
|
@ -21,11 +21,11 @@ import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.jna.linux.Gobject;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.EntryHook;
|
||||
import dorkbox.systemTray.peer.EntryPeer;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
|
||||
abstract
|
||||
class GtkMenuBaseItem implements EntryHook {
|
||||
class GtkBaseMenuItem implements EntryPeer {
|
||||
private static File transparentIcon = null;
|
||||
// these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT
|
||||
private volatile boolean hasLegitImage = true;
|
||||
@ -33,7 +33,7 @@ class GtkMenuBaseItem implements EntryHook {
|
||||
// these have to be volatile, because they can be changed from any thread
|
||||
private volatile Pointer spacerImage;
|
||||
|
||||
GtkMenuBaseItem() {
|
||||
GtkBaseMenuItem() {
|
||||
// cannot be done in a static initializer, because the tray icon size might not yet have been determined
|
||||
if (transparentIcon == null) {
|
||||
transparentIcon = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE);
|
||||
@ -45,7 +45,6 @@ class GtkMenuBaseItem implements EntryHook {
|
||||
return hasLegitImage;
|
||||
}
|
||||
|
||||
public
|
||||
void setLegitImage(boolean isLegit) {
|
||||
hasLegitImage = isLegit;
|
||||
}
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -27,13 +26,13 @@ import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.MenuHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.peer.MenuPeer;
|
||||
|
||||
class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||
// this is a list (that mirrors the actual list) BECAUSE we have to create/delete the entire menu in GTK every time something is changed
|
||||
private final List<GtkMenuBaseItem> menuEntries = new LinkedList<GtkMenuBaseItem>();
|
||||
private final List<GtkBaseMenuItem> menuEntries = new LinkedList<GtkBaseMenuItem>();
|
||||
|
||||
private final GtkMenu parent;
|
||||
volatile Pointer _nativeMenu; // must ONLY be created at the end of delete!
|
||||
@ -55,7 +54,7 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
this.parent = parent;
|
||||
|
||||
if (parent != null) {
|
||||
_nativeEntry = Gtk.gtk_image_menu_item_new_with_mnemonic(""); // is what is added to the parent menu
|
||||
_nativeEntry = Gtk.gtk_image_menu_item_new_with_mnemonic(""); // is what is added to the parent menu (so images work)
|
||||
} else {
|
||||
_nativeEntry = null;
|
||||
}
|
||||
@ -66,7 +65,7 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
}
|
||||
|
||||
private
|
||||
void add(final GtkMenuBaseItem item, final int index) {
|
||||
void add(final GtkBaseMenuItem item, final int index) {
|
||||
if (index > 0) {
|
||||
menuEntries.add(index, item);
|
||||
} else {
|
||||
@ -98,7 +97,7 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
// have to remove all other menu entries
|
||||
synchronized (menuEntries) {
|
||||
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
final GtkMenuBaseItem menuEntry__ = menuEntries.get(i);
|
||||
final GtkBaseMenuItem menuEntry__ = menuEntries.get(i);
|
||||
menuEntry__.onDeleteMenu(_nativeMenu);
|
||||
}
|
||||
|
||||
@ -136,13 +135,13 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
// now add back other menu entries
|
||||
synchronized (menuEntries) {
|
||||
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
final GtkMenuBaseItem menuEntry__ = menuEntries.get(i);
|
||||
final GtkBaseMenuItem menuEntry__ = menuEntries.get(i);
|
||||
hasImages |= menuEntry__.hasImage();
|
||||
}
|
||||
|
||||
for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
// the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images
|
||||
final GtkMenuBaseItem menuEntry__ = menuEntries.get(i);
|
||||
final GtkBaseMenuItem menuEntry__ = menuEntries.get(i);
|
||||
menuEntry__.onCreateMenu(_nativeMenu, hasImages);
|
||||
|
||||
if (menuEntry__ instanceof GtkMenu) {
|
||||
@ -173,10 +172,10 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
synchronized (menuEntries) {
|
||||
// a copy is made because sub-menus remove themselves from parents when .remove() is called. If we don't
|
||||
// do this, errors will be had because indices don't line up anymore.
|
||||
ArrayList<GtkMenuBaseItem> menuEntriesCopy = new ArrayList<GtkMenuBaseItem>(this.menuEntries);
|
||||
ArrayList<GtkBaseMenuItem> menuEntriesCopy = new ArrayList<GtkBaseMenuItem>(this.menuEntries);
|
||||
|
||||
for (int i = 0, menuEntriesSize = menuEntriesCopy.size(); i < menuEntriesSize; i++) {
|
||||
final GtkMenuBaseItem menuEntry__ = menuEntriesCopy.get(i);
|
||||
final GtkBaseMenuItem menuEntry__ = menuEntriesCopy.get(i);
|
||||
menuEntry__.remove();
|
||||
}
|
||||
this.menuEntries.clear();
|
||||
@ -354,7 +353,7 @@ class GtkMenu extends GtkMenuBaseItem implements MenuHook {
|
||||
|
||||
// called when a child removes itself from the parent menu. Does not work for sub-menus
|
||||
public
|
||||
void remove(final GtkMenuBaseItem item) {
|
||||
void remove(final GtkBaseMenuItem item) {
|
||||
synchronized (menuEntries) {
|
||||
menuEntries.remove(item);
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.jna.linux.GCallback;
|
||||
import dorkbox.systemTray.jna.linux.Gobject;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.MenuItemHook;
|
||||
import dorkbox.systemTray.peer.MenuItemPeer;
|
||||
|
||||
class GtkMenuItem extends GtkMenuBaseItem implements MenuItemHook, GCallback {
|
||||
class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
private final NativeLong nativeLong;
|
||||
|
||||
|
@ -26,10 +26,10 @@ import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.jna.linux.GCallback;
|
||||
import dorkbox.systemTray.jna.linux.Gobject;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.peer.CheckboxPeer;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
import dorkbox.systemTray.util.MenuCheckboxHook;
|
||||
|
||||
class GtkMenuItemCheckbox extends GtkMenuBaseItem implements MenuCheckboxHook, GCallback {
|
||||
class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCallback {
|
||||
private static File transparentIcon = null;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
|
@ -18,9 +18,9 @@ package dorkbox.systemTray.nativeUI;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.EntryHook;
|
||||
import dorkbox.systemTray.peer.EntryPeer;
|
||||
|
||||
class GtkMenuItemSeparator extends GtkMenuBaseItem implements EntryHook {
|
||||
class GtkMenuItemSeparator extends GtkBaseMenuItem implements EntryPeer {
|
||||
|
||||
private final GtkMenu parent;
|
||||
private final Pointer _native = Gtk.gtk_separator_menu_item_new();
|
||||
|
@ -17,13 +17,13 @@ package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.MenuStatusHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.peer.StatusPeer;
|
||||
|
||||
// you might wonder WHY this extends MenuEntryItem -- the reason is that an AppIndicator "status" will be offset from everyone else,
|
||||
// where a GtkStatusIconTray + SwingUI will have everything lined up. (with or without icons). This is to normalize how it looks
|
||||
class GtkMenuItemStatus extends GtkMenuBaseItem implements MenuStatusHook {
|
||||
class GtkMenuItemStatus extends GtkBaseMenuItem implements StatusPeer {
|
||||
|
||||
private final GtkMenu parent;
|
||||
private final Pointer _native = Gtk.gtk_image_menu_item_new_with_mnemonic("");
|
||||
|
@ -23,9 +23,8 @@ package dorkbox.systemTray.nativeUI;
|
||||
* the system (with the exception of Windows, whose native menu looks absolutely terrible).
|
||||
* <p>
|
||||
* Noticeable differences that are limitations for the NativeUI only:
|
||||
* - AppIndicator Status entries must be plain text (they are not bold as they are everywhere else).
|
||||
* - MacOS cannot have images in their menu or sub-menu's -- only plain text is possible
|
||||
* - AppIndicator Status entries must be plain text (they are not bold as they are everywhere else).
|
||||
* - MacOS cannot have images in their menu or sub-menu's -- only plain text is possible
|
||||
*/
|
||||
public
|
||||
interface NativeUI
|
||||
{}
|
||||
interface NativeUI {}
|
||||
|
@ -157,13 +157,13 @@ class _AppIndicatorNativeTray extends Tray implements NativeUI {
|
||||
@Override
|
||||
public
|
||||
void setText(final MenuItem menuItem) {
|
||||
// no op
|
||||
// no op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setShortcut(final MenuItem menuItem) {
|
||||
// no op
|
||||
// no op.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,7 +38,7 @@ import dorkbox.util.SwingUtil;
|
||||
* http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6453521
|
||||
* https://stackoverflow.com/questions/331407/java-trayicon-using-image-with-transparent-background/3882028#3882028
|
||||
*
|
||||
* Also, on linux, this WILL NOT CLOSE properly -- there is a frame handle that keeps the JVM open
|
||||
* Also, on linux, this WILL NOT CLOSE properly -- there is a frame handle that keeps the JVM open. MacOS does not have this problem.
|
||||
*/
|
||||
@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter", "WeakerAccess"})
|
||||
public
|
||||
@ -157,7 +157,7 @@ class _AwtTray extends Tray implements NativeUI {
|
||||
@Override
|
||||
public
|
||||
void setText(final MenuItem menuItem) {
|
||||
// no op
|
||||
// no op.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
35
src/dorkbox/systemTray/peer/CheckboxPeer.java
Normal file
35
src/dorkbox/systemTray/peer/CheckboxPeer.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2016 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.peer;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
|
||||
/**
|
||||
* Internal component used to bind the API to the implementation
|
||||
*/
|
||||
public
|
||||
interface CheckboxPeer extends EntryPeer {
|
||||
|
||||
void setEnabled(Checkbox menuItem);
|
||||
|
||||
void setText(Checkbox menuItem);
|
||||
|
||||
void setCallback(Checkbox menuItem);
|
||||
|
||||
void setShortcut(Checkbox menuItem);
|
||||
|
||||
void setChecked(Checkbox checkbox);
|
||||
}
|
24
src/dorkbox/systemTray/peer/EntryPeer.java
Normal file
24
src/dorkbox/systemTray/peer/EntryPeer.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2016 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.peer;
|
||||
|
||||
/**
|
||||
* Internal component used to bind the API to the implementation
|
||||
*/
|
||||
public
|
||||
interface EntryPeer {
|
||||
void remove();
|
||||
}
|
34
src/dorkbox/systemTray/peer/MenuItemPeer.java
Normal file
34
src/dorkbox/systemTray/peer/MenuItemPeer.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2016 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.peer;
|
||||
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
|
||||
/**
|
||||
* Internal component used to bind the API to the implementation
|
||||
*/
|
||||
public
|
||||
interface MenuItemPeer extends EntryPeer {
|
||||
void setImage(MenuItem menuItem);
|
||||
|
||||
void setEnabled(MenuItem menuItem);
|
||||
|
||||
void setText(MenuItem menuItem);
|
||||
|
||||
void setCallback(MenuItem menuItem);
|
||||
|
||||
void setShortcut(MenuItem menuItem);
|
||||
}
|
27
src/dorkbox/systemTray/peer/MenuPeer.java
Normal file
27
src/dorkbox/systemTray/peer/MenuPeer.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2016 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.peer;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
|
||||
/**
|
||||
* Internal component used to bind the API to the implementation
|
||||
*/
|
||||
public
|
||||
interface MenuPeer extends MenuItemPeer {
|
||||
void add(Menu parentMenu, Entry entry, int index);
|
||||
}
|
26
src/dorkbox/systemTray/peer/StatusPeer.java
Normal file
26
src/dorkbox/systemTray/peer/StatusPeer.java
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2016 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.peer;
|
||||
|
||||
import dorkbox.systemTray.Status;
|
||||
|
||||
/**
|
||||
* Internal component used to bind the API to the implementation
|
||||
*/
|
||||
public
|
||||
interface StatusPeer extends EntryPeer {
|
||||
void setText(Status menuItem);
|
||||
}
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package dorkbox.systemTray.swingUI;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
@ -26,15 +25,14 @@ import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.util.MenuHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.peer.MenuPeer;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
// this is a weird composite class, because it must be a Menu, but ALSO a Entry -- so it has both (and duplicate code)
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
class SwingMenu implements MenuHook {
|
||||
class SwingMenu implements MenuPeer {
|
||||
|
||||
final JComponent _native;
|
||||
private final SwingMenu parent;
|
||||
@ -89,12 +87,11 @@ class SwingMenu implements MenuHook {
|
||||
@Override
|
||||
public
|
||||
void setImage(final MenuItem menuItem) {
|
||||
final File imageFile = menuItem.getImage();
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
File imageFile = menuItem.getImage();
|
||||
if (imageFile != null) {
|
||||
ImageIcon origIcon = new ImageIcon(imageFile.getAbsolutePath());
|
||||
((AdjustedJMenu) _native).setIcon(origIcon);
|
||||
@ -179,41 +176,4 @@ class SwingMenu implements MenuHook {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// NOT ALWAYS CALLED ON EDT
|
||||
protected
|
||||
void remove__(final Object menuEntry) {
|
||||
try {
|
||||
// synchronized (menuEntries) {
|
||||
// // null is passed in when a sub-menu is removing itself from us (because they have already called "remove" and have also
|
||||
// // removed themselves from the menuEntries)
|
||||
// if (menuEntry != null) {
|
||||
// for (Iterator<Entry> iterator = menuEntries.iterator(); iterator.hasNext(); ) {
|
||||
// final Entry entry = iterator.next();
|
||||
// if (entry == menuEntry) {
|
||||
// iterator.remove();
|
||||
// entry.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 dorkbox.systemTray.Separator) {
|
||||
// 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 dorkbox.systemTray.Separator) {
|
||||
// remove(menuEntries.get(menuEntries.size() - 1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
SystemTray.logger.error("Error removing entry from menu.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,11 @@ import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.util.MenuItemHook;
|
||||
import dorkbox.systemTray.peer.MenuItemPeer;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class SwingMenuItem implements MenuItemHook {
|
||||
class SwingMenuItem implements MenuItemPeer {
|
||||
|
||||
private final SwingMenu parent;
|
||||
private final JMenuItem _native = new AdjustedJMenuItem();
|
||||
@ -44,12 +44,11 @@ class SwingMenuItem implements MenuItemHook {
|
||||
@Override
|
||||
public
|
||||
void setImage(final MenuItem menuItem) {
|
||||
final File imageFile = menuItem.getImage();
|
||||
|
||||
SwingUtil.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
File imageFile = menuItem.getImage();
|
||||
if (imageFile != null) {
|
||||
ImageIcon origIcon = new ImageIcon(imageFile.getAbsolutePath());
|
||||
_native.setIcon(origIcon);
|
||||
|
@ -24,12 +24,12 @@ import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.peer.CheckboxPeer;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
import dorkbox.systemTray.util.MenuCheckboxHook;
|
||||
import dorkbox.systemTray.util.SystemTrayFixes;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class SwingMenuItemCheckbox implements MenuCheckboxHook {
|
||||
class SwingMenuItemCheckbox implements CheckboxPeer {
|
||||
|
||||
private final SwingMenu parent;
|
||||
private final JMenuItem _native = new AdjustedJMenuItem();
|
||||
|
@ -17,10 +17,10 @@ package dorkbox.systemTray.swingUI;
|
||||
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import dorkbox.systemTray.util.EntryHook;
|
||||
import dorkbox.systemTray.peer.EntryPeer;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class SwingMenuItemSeparator implements EntryHook {
|
||||
class SwingMenuItemSeparator implements EntryPeer {
|
||||
|
||||
private final SwingMenu parent;
|
||||
private final JSeparator _native = new JSeparator(JSeparator.HORIZONTAL);
|
||||
|
@ -19,11 +19,11 @@ import java.awt.Font;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.util.MenuStatusHook;
|
||||
import dorkbox.systemTray.util.Status;
|
||||
import dorkbox.systemTray.Status;
|
||||
import dorkbox.systemTray.peer.StatusPeer;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class SwingMenuItemStatus implements MenuStatusHook {
|
||||
class SwingMenuItemStatus implements StatusPeer {
|
||||
|
||||
private final SwingMenu parent;
|
||||
private final JMenuItem _native = new AdjustedJMenuItem();
|
||||
|
@ -22,9 +22,8 @@ package dorkbox.systemTray.swingUI;
|
||||
* one loses the native L&F of the system (with the exception of Windows, whose native menu looks absolutely terrible).
|
||||
* <p>
|
||||
* Noticeable differences that are limitations for the NativeUI only:
|
||||
* - AppIndicator Status entries must be plain text (they are not bold as they are everywhere else).
|
||||
* - MacOS cannot have images in their menu or sub-menu's -- only plain text is possible
|
||||
* - AppIndicator Status entries must be plain text (they are not bold as they are everywhere else).
|
||||
* - MacOS cannot have images in their menu or sub-menu's -- only plain text is possible
|
||||
*/
|
||||
public
|
||||
interface SwingUI
|
||||
{}
|
||||
interface SwingUI {}
|
||||
|
@ -40,7 +40,7 @@ import dorkbox.util.ScreenUtil;
|
||||
/**
|
||||
* This custom popup is required if we want to be able to show images on the menu,
|
||||
*
|
||||
* This is our "golden standard" since we have 100% control over it.
|
||||
* This is our "golden standard" since we have 100% control over it on all platforms
|
||||
*/
|
||||
class TrayPopup extends JPopupMenu {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -41,15 +41,15 @@ import dorkbox.util.SwingUtil;
|
||||
* <p/>
|
||||
* This is the "old" way to do it, and does not work with some desktop environments. This is a hybrid class, because we want to show the
|
||||
* swing menu popup INSTEAD of GTK menu popups. The "golden standard" is our swing menu popup, since we have 100% control over it.
|
||||
*
|
||||
* http://code.metager.de/source/xref/gnome/Platform/gtk%2B/gtk/deprecated/gtkstatusicon.c
|
||||
* https://github.com/djdeath/glib/blob/master/gobject/gobject.c
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public
|
||||
class _GtkStatusIconTray extends Tray implements SwingUI {
|
||||
private volatile Pointer trayIcon;
|
||||
|
||||
// http://code.metager.de/source/xref/gnome/Platform/gtk%2B/gtk/deprecated/gtkstatusicon.c
|
||||
// https://github.com/djdeath/glib/blob/master/gobject/gobject.c
|
||||
|
||||
// have to save these in a field to prevent GC on the objects (since they go out-of-scope from java)
|
||||
private final List<Object> gtkCallbacks = new ArrayList<Object>();
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface EntryHook {
|
||||
void remove();
|
||||
}
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
|
||||
import dorkbox.systemTray.Menu;
|
||||
|
||||
// this is a weird composite class, because it must be a Menu, but ALSO a Entry -- so it has both
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public abstract
|
||||
class MenuBase extends Menu {
|
||||
// /**
|
||||
// * Called in the EDT/GTK dispatch threads
|
||||
// *
|
||||
// * @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
|
||||
// MenuBase(final SystemTray systemTray, final Menu parent) {
|
||||
// setSystemTray(systemTray);
|
||||
// setParent(parent);
|
||||
// }
|
||||
|
||||
protected abstract
|
||||
void dispatch(final Runnable runnable);
|
||||
|
||||
protected abstract
|
||||
void dispatchAndWait(final Runnable runnable);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
// protected abstract
|
||||
// Entry addEntry_(final String menuText, final File imagePath, final ActionListener callback);
|
||||
|
||||
/**
|
||||
* Will add a new checkbox menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
// protected abstract
|
||||
// Checkbox addCheckbox_(final String menuText, final ActionListener callback);
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
// protected abstract
|
||||
// Menu addMenu_(final String menuText, final File imagePath);
|
||||
|
||||
|
||||
// // public here so that Swing/Gtk/AppIndicator can override this
|
||||
// protected abstract
|
||||
// void setImage_(final File imageFile);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: buggy. The menu will **sometimes** stop responding to the "enter" key after this. Mnemonics still work however.
|
||||
// public
|
||||
// Entry addWidget(final JComponent widget) {
|
||||
// if (widget == null) {
|
||||
// throw new NullPointerException("Widget cannot be null");
|
||||
// }
|
||||
//
|
||||
// final AtomicReference<Entry> value = new AtomicReference<Entry>();
|
||||
//
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// synchronized (menuEntries) {
|
||||
// // must always be called on the EDT
|
||||
// Entry entry = new EntryWidget(MenuImpl.this, widget);
|
||||
// value.set(entry);
|
||||
// menuEntries.add(entry);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// return value.get();
|
||||
// }
|
||||
|
||||
|
||||
// public final
|
||||
// Entry get(final String menuText) {
|
||||
// if (menuText == null || menuText.isEmpty()) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// // Must be wrapped in a synchronized block for object visibility
|
||||
// synchronized (menuEntries) {
|
||||
// for (int i = 0, menuEntriesSize = menuEntries.size(); i < menuEntriesSize; i++) {
|
||||
// final Entry entry = menuEntries.get(i);
|
||||
//
|
||||
// if (entry instanceof Separator || entry instanceof Status) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//// String text = entry.getText();
|
||||
//
|
||||
// // text can be null
|
||||
//// if (menuText.equals(text)) {
|
||||
//// return entry;
|
||||
//// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * This removes a menu entry from the dropdown menu.
|
||||
// *
|
||||
// * @param entry This is the menu entry to remove
|
||||
// */
|
||||
// @Override
|
||||
// public final
|
||||
// void remove(final Entry entry) {
|
||||
// if (entry == null) {
|
||||
// throw new NullPointerException("No menu entry exists for entry");
|
||||
// }
|
||||
//
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// remove__(entry);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * This removes a sub-menu entry from the dropdown menu.
|
||||
// *
|
||||
// * @param menu This is the menu entry to remove
|
||||
// */
|
||||
// @Override
|
||||
// public final
|
||||
// void remove(final Menu menu) {
|
||||
// final Menu parent = getParent();
|
||||
// if (parent == null) {
|
||||
// // we are the system tray menu, so we just remove from ourselves
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// remove__(menu);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// final Menu _this = this;
|
||||
// // we are a submenu
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// ((MenuBase) parent).remove__(_this);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * This removes a menu entry or sub-menu (via the text label) from the dropdown menu.
|
||||
// *
|
||||
// * @param menuText This is the label for the menu entry or sub-menu to remove
|
||||
// */
|
||||
// public final
|
||||
// void remove(final String menuText) {
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// synchronized (menuEntries) {
|
||||
// Entry entry = get(menuText);
|
||||
//
|
||||
// if (entry != null) {
|
||||
// remove(entry);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public final
|
||||
// void removeAll() {
|
||||
// dispatch(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// synchronized (menuEntries) {
|
||||
// // have to make copy because we are deleting all of them, and sub-menus remove themselves from parents
|
||||
// ArrayList<Entry> menuEntriesCopy = new ArrayList<Entry>(MenuBase.this.menuEntries);
|
||||
// for (Entry entry : menuEntriesCopy) {
|
||||
// entry.remove();
|
||||
// }
|
||||
// menuEntries.clear();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface MenuCheckboxHook extends EntryHook {
|
||||
|
||||
void setEnabled(Checkbox menuItem);
|
||||
|
||||
void setText(Checkbox menuItem);
|
||||
|
||||
void setCallback(Checkbox menuItem);
|
||||
|
||||
void setShortcut(Checkbox menuItem);
|
||||
|
||||
void setChecked(Checkbox checkbox);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface MenuHook extends MenuItemHook {
|
||||
void add(Menu parentMenu, Entry entry, int index);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface MenuItemHook extends EntryHook {
|
||||
void setImage(MenuItem menuItem);
|
||||
|
||||
void setEnabled(MenuItem menuItem);
|
||||
|
||||
void setText(MenuItem menuItem);
|
||||
|
||||
void setCallback(MenuItem menuItem);
|
||||
|
||||
void setShortcut(MenuItem menuItem);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface MenuStatusHook extends EntryHook {
|
||||
void setText(Status menuItem);
|
||||
}
|
@ -21,8 +21,9 @@ import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
|
||||
/**
|
||||
@ -51,7 +52,6 @@ class TestTray {
|
||||
}
|
||||
|
||||
private SystemTray systemTray;
|
||||
private ActionListener callbackGreen;
|
||||
private ActionListener callbackGray;
|
||||
|
||||
public
|
||||
@ -61,23 +61,32 @@ class TestTray {
|
||||
throw new RuntimeException("Unable to load SystemTray!");
|
||||
}
|
||||
|
||||
// final JPopupMenu popupMenu = new JPopupMenu();
|
||||
// JMenu submenu2 = new JMenu("SubMenu1");
|
||||
// submenu2.add("asdf");
|
||||
// submenu2.add("asdf");
|
||||
//
|
||||
// // Add submenu to popup menu
|
||||
// popupMenu.add(submenu2);
|
||||
|
||||
|
||||
systemTray.setImage(LT_GRAY_TRAIN);
|
||||
systemTray.setStatus("No Mail");
|
||||
|
||||
callbackGreen = new ActionListener() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.getMenu().remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Menu mainMenu = systemTray.getMenu();
|
||||
|
||||
MenuItem greenEntry = new MenuItem("Green Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -86,76 +95,79 @@ class TestTray {
|
||||
entry.setText("Delete Mail");
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
};
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
callbackGray = new ActionListener() {
|
||||
|
||||
Checkbox checkbox = new Checkbox("Euro € Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
Entry menuEntry = this.systemTray.addEntry("Green Mail", GREEN_MAIL, callbackGreen);
|
||||
// case does not matter
|
||||
menuEntry.setShortcut('G');
|
||||
|
||||
final Checkbox menuCheckbox = this.systemTray.addCheckbox("Euro € Mail", callbackGreen);
|
||||
// case does not matter
|
||||
// menuCheckbox.setShortcut('€');
|
||||
|
||||
this.systemTray.addSeparator();
|
||||
|
||||
final Menu submenu = this.systemTray.addMenu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
System.err.println("Am i checked? " + ((Checkbox) e.getSource()).getChecked());
|
||||
}
|
||||
});
|
||||
checkbox.setShortcut('€');
|
||||
mainMenu.add(checkbox);
|
||||
|
||||
mainMenu.add(new Separator());
|
||||
|
||||
|
||||
Menu submenu = new Menu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
mainMenu.add(submenu);
|
||||
|
||||
MenuItem disableMenu = new MenuItem("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.add(disableMenu);
|
||||
|
||||
|
||||
// TODO: buggy. The menu will **sometimes** stop responding to the "enter" key after this. Mnemonics still work however.
|
||||
// submenu.addEntry("Add widget", GREEN_BUS, new Action() {
|
||||
// submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// @Override
|
||||
// public
|
||||
// void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
// void actionPerformed(final ActionEvent e) {
|
||||
// MenuItem source = (MenuItem) e.getSource();
|
||||
// JProgressBar progressBar = new JProgressBar(0, 100);
|
||||
// progressBar.setValue(new Random().nextInt(101));
|
||||
// progressBar.setStringPainted(true);
|
||||
// systemTray.addWidget(progressBar);
|
||||
// source.getSystemTray().add(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// }));
|
||||
|
||||
|
||||
submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
}));
|
||||
submenu.add(new MenuItem("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
submenu.remove();
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().remove();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
systemTray.getMenu().add(new MenuItem("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
systemTray.shutdown();
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
}
|
||||
}).setShortcut('q'); // case does not matter
|
||||
})).setShortcut('q'); // case does not matter
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,10 @@ package dorkbox;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
@ -95,11 +97,29 @@ class TestTrayJavaFX extends Application {
|
||||
systemTray.setImage(LT_GRAY_TRAIN);
|
||||
systemTray.setStatus("No Mail");
|
||||
|
||||
callbackGreen = new ActionListener() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.getMenu().remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Menu mainMenu = systemTray.getMenu();
|
||||
|
||||
MenuItem greenEntry = new MenuItem("Green Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -108,69 +128,73 @@ class TestTrayJavaFX extends Application {
|
||||
entry.setText("Delete Mail");
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
};
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
callbackGray = new ActionListener() {
|
||||
|
||||
Checkbox checkbox = new Checkbox("Euro € Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
Entry menuEntry = this.systemTray.addEntry("Green Mail", GREEN_MAIL, callbackGreen);
|
||||
// case does not matter
|
||||
menuEntry.setShortcut('G');
|
||||
|
||||
menuEntry = this.systemTray.addEntry("Euro € Mail", GREEN_MAIL, callbackGreen);
|
||||
// case does not matter
|
||||
menuEntry.setShortcut('€');
|
||||
|
||||
this.systemTray.addSeparator();
|
||||
|
||||
final Menu submenu = this.systemTray.addMenu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
System.err.println("Am i checked? " + ((Checkbox) e.getSource()).getChecked());
|
||||
}
|
||||
});
|
||||
checkbox.setShortcut('€');
|
||||
mainMenu.add(checkbox);
|
||||
|
||||
mainMenu.add(new Separator());
|
||||
|
||||
|
||||
Menu submenu = new Menu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
mainMenu.add(submenu);
|
||||
|
||||
MenuItem disableMenu = new MenuItem("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.add(disableMenu);
|
||||
|
||||
|
||||
// TODO: buggy. The menu will **sometimes** stop responding to the "enter" key after this. Mnemonics still work however.
|
||||
// submenu.addEntry("Add widget", GREEN_BUS, new Action() {
|
||||
// submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// @Override
|
||||
// public
|
||||
// void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
// void actionPerformed(final ActionEvent e) {
|
||||
// MenuItem source = (MenuItem) e.getSource();
|
||||
// JProgressBar progressBar = new JProgressBar(0, 100);
|
||||
// progressBar.setValue(new Random().nextInt(101));
|
||||
// progressBar.setStringPainted(true);
|
||||
// systemTray.addWidget(progressBar);
|
||||
// source.getSystemTray().add(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// }));
|
||||
|
||||
|
||||
submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
}));
|
||||
submenu.add(new MenuItem("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.remove();
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().remove();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
|
||||
systemTray.getMenu().add(new MenuItem("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
@ -178,6 +202,6 @@ class TestTrayJavaFX extends Application {
|
||||
Platform.exit(); // necessary to close javaFx
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
}
|
||||
}).setShortcut('q'); // case does not matter
|
||||
})).setShortcut('q'); // case does not matter
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package dorkbox;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
@ -24,8 +25,10 @@ import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.MenuItem;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
|
||||
/**
|
||||
@ -79,11 +82,29 @@ class TestTraySwt {
|
||||
systemTray.setImage(LT_GRAY_TRAIN);
|
||||
systemTray.setStatus("No Mail");
|
||||
|
||||
callbackGreen = new ActionListener() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.getMenu().remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Menu mainMenu = systemTray.getMenu();
|
||||
|
||||
MenuItem greenEntry = new MenuItem("Green Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final MenuItem entry = (MenuItem) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -92,84 +113,86 @@ class TestTraySwt {
|
||||
entry.setText("Delete Mail");
|
||||
// systemTray.remove(menuEntry);
|
||||
}
|
||||
};
|
||||
});
|
||||
greenEntry.setImage(GREEN_MAIL);
|
||||
// case does not matter
|
||||
greenEntry.setShortcut('G');
|
||||
mainMenu.add(greenEntry);
|
||||
|
||||
callbackGray = new ActionListener() {
|
||||
|
||||
Checkbox checkbox = new Checkbox("Euro € Mail", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
entry.setCallback(null);
|
||||
// systemTray.setStatus("Mail Empty");
|
||||
systemTray.remove(entry);
|
||||
System.err.println("POW");
|
||||
}
|
||||
};
|
||||
|
||||
Entry menuEntry = this.systemTray.addEntry("Green Mail", GREEN_MAIL, callbackGreen);
|
||||
// case does not matter
|
||||
menuEntry.setShortcut('G');
|
||||
|
||||
menuEntry = this.systemTray.addEntry("Euro € Mail", GREEN_MAIL, callbackGreen);
|
||||
// case does not matter
|
||||
menuEntry.setShortcut('€');
|
||||
|
||||
this.systemTray.addSeparator();
|
||||
|
||||
final Menu submenu = this.systemTray.addMenu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
System.err.println("Am i checked? " + ((Checkbox) e.getSource()).getChecked());
|
||||
}
|
||||
});
|
||||
checkbox.setShortcut('€');
|
||||
mainMenu.add(checkbox);
|
||||
|
||||
mainMenu.add(new Separator());
|
||||
|
||||
|
||||
Menu submenu = new Menu("Options", BLUE_CAMPING);
|
||||
submenu.setShortcut('t');
|
||||
mainMenu.add(submenu);
|
||||
|
||||
MenuItem disableMenu = new MenuItem("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.add(disableMenu);
|
||||
|
||||
|
||||
// TODO: buggy. The menu will **sometimes** stop responding to the "enter" key after this. Mnemonics still work however.
|
||||
// submenu.addEntry("Add widget", GREEN_BUS, new Action() {
|
||||
// submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// @Override
|
||||
// public
|
||||
// void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
// void actionPerformed(final ActionEvent e) {
|
||||
// MenuItem source = (MenuItem) e.getSource();
|
||||
// JProgressBar progressBar = new JProgressBar(0, 100);
|
||||
// progressBar.setValue(new Random().nextInt(101));
|
||||
// progressBar.setStringPainted(true);
|
||||
// systemTray.addWidget(progressBar);
|
||||
// source.getSystemTray().add(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
// }));
|
||||
|
||||
|
||||
submenu.add(new MenuItem("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
}));
|
||||
submenu.add(new MenuItem("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.remove();
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
MenuItem source = (MenuItem) e.getSource();
|
||||
source.getParent().remove();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
|
||||
systemTray.getMenu().add(new MenuItem("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
systemTray.shutdown();
|
||||
|
||||
// necessary to shut down SWT
|
||||
display.asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
shell.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
}
|
||||
}).setShortcut('q'); // case does not matter
|
||||
|
||||
})).setShortcut('q'); // case does not matter
|
||||
|
||||
|
||||
shell.pack();
|
||||
|
Loading…
Reference in New Issue
Block a user