forked from dorkbox/SystemTray
Changed action callback to ActionListener. Added checkbox.
This commit is contained in:
parent
4e47c5d263
commit
a07c5e8ab8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 dorkbox, llc
|
||||
* Copyright 2015 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -13,16 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
/**
|
||||
* This represents a common menu-checkbox entry, that is cross platform in nature
|
||||
*/
|
||||
public
|
||||
interface Action {
|
||||
interface Checkbox extends Entry {
|
||||
/**
|
||||
* This method will ALWAYS be called in the swing EDT. If there is work conducted in this method, it will slow-down the GUI.
|
||||
*
|
||||
* @param systemTray this is the parent, system tray object
|
||||
* @param parent this is the parent menu of this menu entry
|
||||
* @param entry this is the menu entry that was clicked
|
||||
* @return true if this checkbox is selected, false if not
|
||||
*/
|
||||
void onClick(SystemTray systemTray, Menu parent, final Entry entry);
|
||||
boolean getState();
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
package dorkbox.systemTray;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
@ -97,7 +98,7 @@ interface Entry {
|
||||
*
|
||||
* @param callback the callback to set. If null, the callback is safely removed.
|
||||
*/
|
||||
void setCallback(Action callback);
|
||||
void setCallback(ActionListener callback);
|
||||
|
||||
/**
|
||||
* Sets a menu entry shortcut key (Mnemonic) so that menu entry can be "selected" via the keyboard while the menu is displayed.
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package dorkbox.systemTray;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
@ -86,7 +87,7 @@ interface Menu extends Entry {
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
Entry addEntry(String menuText, Action callback);
|
||||
Entry addEntry(String menuText, ActionListener callback);
|
||||
|
||||
/**
|
||||
* Adds a menu entry with text + image
|
||||
@ -95,7 +96,7 @@ interface Menu extends Entry {
|
||||
* @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
|
||||
*/
|
||||
Entry addEntry(String menuText, String imagePath, Action callback);
|
||||
Entry addEntry(String menuText, String imagePath, ActionListener callback);
|
||||
|
||||
/**
|
||||
* Adds a menu entry with text + image
|
||||
@ -104,7 +105,7 @@ interface Menu extends Entry {
|
||||
* @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
|
||||
*/
|
||||
Entry addEntry(String menuText, URL imageUrl, Action callback);
|
||||
Entry addEntry(String menuText, URL imageUrl, ActionListener callback);
|
||||
|
||||
/**
|
||||
* Adds a menu entry with text + image
|
||||
@ -114,7 +115,7 @@ interface Menu extends Entry {
|
||||
* @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
|
||||
*/
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, Action callback);
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, ActionListener callback);
|
||||
|
||||
/**
|
||||
* Adds a menu entry with text + image
|
||||
@ -123,10 +124,19 @@ interface Menu extends Entry {
|
||||
* @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
|
||||
*/
|
||||
Entry addEntry(String menuText, InputStream imageStream, Action callback);
|
||||
Entry addEntry(String menuText, InputStream imageStream, ActionListener callback);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a check-box menu entry with text
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
Checkbox addCheckbox(String menuText, ActionListener callback);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a sub-menu entry with text (no image)
|
||||
|
@ -17,6 +17,7 @@ package dorkbox.systemTray;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.HeadlessException;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
@ -924,7 +925,7 @@ class SystemTray implements Menu {
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
// NO OP.
|
||||
}
|
||||
|
||||
@ -992,7 +993,7 @@ class SystemTray implements Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
Entry addEntry(String menuText, Action callback) {
|
||||
Entry addEntry(String menuText, ActionListener callback) {
|
||||
return addEntry(menuText, (String) null, callback);
|
||||
}
|
||||
|
||||
@ -1004,7 +1005,7 @@ class SystemTray implements Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
Entry addEntry(String menuText, String imagePath, Action callback) {
|
||||
Entry addEntry(String menuText, String imagePath, ActionListener callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imagePath, callback);
|
||||
}
|
||||
|
||||
@ -1016,7 +1017,7 @@ class SystemTray implements Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
Entry addEntry(String menuText, URL imageUrl, Action callback) {
|
||||
Entry addEntry(String menuText, URL imageUrl, ActionListener callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imageUrl, callback);
|
||||
}
|
||||
|
||||
@ -1029,7 +1030,7 @@ class SystemTray implements Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, Action callback) {
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, ActionListener callback) {
|
||||
return systemTrayMenu.addEntry(menuText, cacheName, imageStream, callback);
|
||||
}
|
||||
|
||||
@ -1041,11 +1042,22 @@ class SystemTray implements Menu {
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
public final
|
||||
Entry addEntry(String menuText, InputStream imageStream, Action callback) {
|
||||
Entry addEntry(String menuText, InputStream imageStream, ActionListener callback) {
|
||||
return systemTrayMenu.addEntry(menuText, imageStream, callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a check-box menu entry to the tray icon with text
|
||||
*
|
||||
* @param menuText string of the text you want to appear
|
||||
* @param callback callback that will be executed when this menu entry is clicked
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
Checkbox addCheckbox(final String menuText, final ActionListener callback) {
|
||||
return systemTrayMenu.addCheckbox(menuText, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -32,7 +32,6 @@ class Gdi32 {
|
||||
}
|
||||
|
||||
public static final int LOGPIXELSX = 88;
|
||||
public static final int LOGPIXELSY = 90;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,8 @@ package dorkbox.systemTray.jna.linux;
|
||||
|
||||
import static dorkbox.systemTray.SystemTray.logger;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -24,9 +26,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import com.sun.jna.Function;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.jna.JnaHelper;
|
||||
import dorkbox.systemTray.util.JavaFX;
|
||||
@ -422,11 +422,11 @@ class Gtk {
|
||||
* @param callback will never be null.
|
||||
*/
|
||||
public static
|
||||
void proxyClick(final Menu parent, final Entry menuEntry, final Action callback) {
|
||||
void proxyClick(final Entry menuEntry, final ActionListener callback) {
|
||||
Gtk.isDispatch = true;
|
||||
|
||||
try {
|
||||
callback.onClick(parent.getSystemTray(), parent, menuEntry);
|
||||
callback.actionPerformed(new ActionEvent(menuEntry, ActionEvent.ACTION_PERFORMED, ""));
|
||||
} catch (Throwable throwable) {
|
||||
SystemTray.logger.error("Error calling menu entry {} click event.", menuEntry.getText(), throwable);
|
||||
}
|
||||
@ -470,6 +470,9 @@ class Gtk {
|
||||
|
||||
// uses '_' to define which key is the mnemonic
|
||||
public static native Pointer gtk_image_menu_item_new_with_mnemonic(String label);
|
||||
public static native Pointer gtk_check_menu_item_new_with_mnemonic (String label);
|
||||
|
||||
public static native boolean gtk_check_menu_item_get_active (Pointer check_menu_item);
|
||||
|
||||
public static native void gtk_image_menu_item_set_image(Pointer image_menu_item, Pointer image);
|
||||
|
||||
|
104
src/dorkbox/systemTray/nativeUI/AwtEntryCheckbox.java
Normal file
104
src/dorkbox/systemTray/nativeUI/AwtEntryCheckbox.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.CheckboxMenuItem;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
|
||||
class AwtEntryCheckbox extends AwtEntry implements Checkbox {
|
||||
|
||||
private final ActionListener swingCallback;
|
||||
|
||||
private volatile ActionListener callback;
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
AwtEntryCheckbox(final AwtMenu parent, final ActionListener callback) {
|
||||
super(parent, new java.awt.CheckboxMenuItem());
|
||||
this.callback = callback;
|
||||
|
||||
if (callback != null) {
|
||||
_native.setEnabled(true);
|
||||
swingCallback = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(ActionEvent e) {
|
||||
// we want it to run on the EDT
|
||||
handle();
|
||||
}
|
||||
};
|
||||
|
||||
_native.addActionListener(swingCallback);
|
||||
} else {
|
||||
_native.setEnabled(false);
|
||||
swingCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this checkbox is selected, false if not
|
||||
*/
|
||||
public
|
||||
boolean getState() {
|
||||
return ((CheckboxMenuItem) _native).getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
private
|
||||
void handle() {
|
||||
ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
try {
|
||||
cb.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
|
||||
} catch (Throwable throwable) {
|
||||
SystemTray.logger.error("Error calling menu entry {} click event.", getText(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// always called in the EDT
|
||||
@Override
|
||||
void renderText(final String text) {
|
||||
_native.setLabel(text);
|
||||
}
|
||||
|
||||
|
||||
// not supported!
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// not supported!
|
||||
@Override
|
||||
void setImage_(final File imageFile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
void removePrivate() {
|
||||
_native.removeActionListener(swingCallback);
|
||||
}
|
||||
}
|
@ -19,16 +19,16 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
|
||||
class AwtEntryItem extends AwtEntry {
|
||||
|
||||
private final ActionListener swingCallback;
|
||||
|
||||
private volatile Action callback;
|
||||
private volatile ActionListener callback;
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
AwtEntryItem(final AwtMenu parent, final Action callback) {
|
||||
AwtEntryItem(final AwtMenu parent, final ActionListener callback) {
|
||||
super(parent, new java.awt.MenuItem());
|
||||
this.callback = callback;
|
||||
|
||||
@ -53,14 +53,19 @@ class AwtEntryItem extends AwtEntry {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
private
|
||||
void handle() {
|
||||
if (callback != null) {
|
||||
callback.onClick(getParent().getSystemTray(), getParent(), this);
|
||||
ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
try {
|
||||
cb.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
|
||||
} catch (Throwable throwable) {
|
||||
SystemTray.logger.error("Error calling menu entry {} click event.", getText(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,9 @@
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
|
||||
class AwtEntrySeparator extends AwtEntry implements dorkbox.systemTray.Separator {
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
@ -53,6 +52,6 @@ class AwtEntrySeparator extends AwtEntry implements dorkbox.systemTray.Separator
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ import static java.awt.Font.DIALOG;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Status;
|
||||
|
||||
class AwtEntryStatus extends AwtEntry implements Status {
|
||||
@ -70,6 +70,6 @@ class AwtEntryStatus extends AwtEntry implements Status {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,11 @@ package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import java.awt.MenuShortcut;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.Status;
|
||||
@ -97,36 +98,28 @@ class AwtMenu extends MenuBase implements NativeUI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON EDT
|
||||
*/
|
||||
protected final
|
||||
Entry addEntry_(final String menuText, final File imagePath, final Action callback) {
|
||||
Entry addEntry_(final String menuText, final File imagePath, final ActionListener callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Entry> value = new AtomicReference<Entry>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = get(menuText);
|
||||
|
||||
if (entry == null) {
|
||||
// must always be called on the EDT
|
||||
entry = new AwtEntryItem(AwtMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
} else if (entry instanceof AwtEntryItem) {
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
}
|
||||
Entry entry = entry = new AwtEntryItem(AwtMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set(entry);
|
||||
}
|
||||
}
|
||||
@ -136,7 +129,39 @@ class AwtMenu extends MenuBase implements NativeUI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry, or update one if it already exists
|
||||
* Will add a new checkbox menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
@Override
|
||||
protected
|
||||
Checkbox addCheckbox_(final String menuText, final ActionListener callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Checkbox> value = new AtomicReference<Checkbox>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = new AwtEntryCheckbox(AwtMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set((Checkbox) entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry
|
||||
* NOT ALWAYS CALLED ON EDT
|
||||
*/
|
||||
protected final
|
||||
@ -147,28 +172,20 @@ class AwtMenu extends MenuBase implements NativeUI {
|
||||
|
||||
final AtomicReference<Menu> value = new AtomicReference<Menu>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = get(menuText);
|
||||
Entry entry = new AwtMenu(getSystemTray(), AwtMenu.this, new java.awt.Menu());
|
||||
_native.add(((AwtMenu) entry)._native); // have to add it to our native item separately
|
||||
|
||||
if (entry == null) {
|
||||
// must always be called on the EDT
|
||||
entry = new AwtMenu(getSystemTray(), AwtMenu.this, new java.awt.Menu());
|
||||
_native.add(((AwtMenu) entry)._native); // have to add it separately
|
||||
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
value.set((Menu) entry);
|
||||
|
||||
} else if (entry instanceof AwtMenu) {
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
}
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set((Menu) entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
172
src/dorkbox/systemTray/nativeUI/GtkEntryCheckbox.java
Normal file
172
src/dorkbox/systemTray/nativeUI/GtkEntryCheckbox.java
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import com.sun.jna.NativeLong;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.jna.linux.GCallback;
|
||||
import dorkbox.systemTray.jna.linux.Gobject;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
|
||||
class GtkEntryCheckbox extends GtkEntry implements GCallback, Checkbox {
|
||||
private static File transparentIcon = null;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
private final NativeLong nativeLong;
|
||||
|
||||
// these have to be volatile, because they can be changed from any thread
|
||||
private volatile ActionListener callback;
|
||||
private volatile Pointer image;
|
||||
|
||||
// The mnemonic will ONLY show-up once a menu entry is selected. IT WILL NOT show up before then!
|
||||
// AppIndicators will only show if you use the keyboard to navigate
|
||||
// GtkStatusIconTray will show on mouse+keyboard movement
|
||||
private volatile char mnemonicKey = 0;
|
||||
|
||||
/**
|
||||
* called from inside dispatch thread. ONLY creates the menu item, but DOES NOT attach it!
|
||||
* this is a FLOATING reference. See: https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#floating-ref
|
||||
*/
|
||||
GtkEntryCheckbox(final GtkMenu parent, final ActionListener callback) {
|
||||
super(parent, Gtk.gtk_check_menu_item_new_with_mnemonic(""));
|
||||
this.callback = callback;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
Gtk.gtk_widget_set_sensitive(_native, Gtk.TRUE);
|
||||
nativeLong = Gobject.g_signal_connect_object(_native, "activate", this, null, 0);
|
||||
}
|
||||
else {
|
||||
Gtk.gtk_widget_set_sensitive(_native, Gtk.FALSE);
|
||||
nativeLong = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setShortcut(final char key) {
|
||||
this.mnemonicKey = Character.toLowerCase(key);
|
||||
|
||||
Gtk.dispatch(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
renderText(getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this checkbox is selected, false if not
|
||||
*/
|
||||
public
|
||||
boolean getState() {
|
||||
return Gtk.gtk_check_menu_item_get_active(_native);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
// called by native code
|
||||
@Override
|
||||
public
|
||||
int callback(final Pointer instance, final Pointer data) {
|
||||
final ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
Gtk.proxyClick(GtkEntryCheckbox.this, cb);
|
||||
}
|
||||
|
||||
return Gtk.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images.
|
||||
* This is primarily only with AppIndicators, although not always.
|
||||
* <p>
|
||||
* called on the DISPATCH thread
|
||||
*/
|
||||
void setSpacerImage(final boolean everyoneElseHasImages) {
|
||||
// if (true) {
|
||||
// // we have a legit icon, so there is nothing else we can do.
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (image != null) {
|
||||
// Gtk.gtk_widget_destroy(image);
|
||||
// image = null;
|
||||
// Gtk.gtk_widget_show_all(_native);
|
||||
// }
|
||||
//
|
||||
// if (everyoneElseHasImages) {
|
||||
// image = Gtk.gtk_image_new_from_file(transparentIcon.getAbsolutePath());
|
||||
// Gtk.gtk_image_menu_item_set_image(_native, image);
|
||||
//
|
||||
// // must always re-set always-show after setting the image
|
||||
// Gtk.gtk_image_menu_item_set_always_show_image(_native, Gtk.TRUE);
|
||||
// }
|
||||
//
|
||||
// Gtk.gtk_widget_show_all(_native);
|
||||
}
|
||||
|
||||
/**
|
||||
* must always be called in the GTK thread
|
||||
*/
|
||||
void renderText(String text) {
|
||||
if (this.mnemonicKey != 0) {
|
||||
// they are CASE INSENSITIVE!
|
||||
int i = text.toLowerCase()
|
||||
.indexOf(this.mnemonicKey);
|
||||
|
||||
if (i >= 0) {
|
||||
text = text.substring(0, i) + "_" + text.substring(i);
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.gtk_menu_item_set_label(_native, text);
|
||||
Gtk.gtk_widget_show_all(_native);
|
||||
}
|
||||
|
||||
void setImage_(final File imageFile) {
|
||||
}
|
||||
|
||||
void removePrivate() {
|
||||
callback = null;
|
||||
|
||||
if (image != null) {
|
||||
Gtk.gtk_widget_destroy(image);
|
||||
image = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,12 +15,12 @@
|
||||
*/
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import com.sun.jna.NativeLong;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.jna.linux.GCallback;
|
||||
import dorkbox.systemTray.jna.linux.Gobject;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
@ -33,7 +33,7 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
private final NativeLong nativeLong;
|
||||
|
||||
// these have to be volatile, because they can be changed from any thread
|
||||
private volatile Action callback;
|
||||
private volatile ActionListener callback;
|
||||
private volatile Pointer image;
|
||||
|
||||
// these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT
|
||||
@ -48,7 +48,7 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
* called from inside dispatch thread. ONLY creates the menu item, but DOES NOT attach it!
|
||||
* this is a FLOATING reference. See: https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#floating-ref
|
||||
*/
|
||||
GtkEntryItem(final GtkMenu parent, final Action callback) {
|
||||
GtkEntryItem(final GtkMenu parent, final ActionListener callback) {
|
||||
super(parent, Gtk.gtk_image_menu_item_new_with_mnemonic(""));
|
||||
this.callback = callback;
|
||||
|
||||
@ -83,7 +83,7 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@ -91,9 +91,9 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
@Override
|
||||
public
|
||||
int callback(final Pointer instance, final Pointer data) {
|
||||
final Action cb = this.callback;
|
||||
final ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
Gtk.proxyClick(getParent(), GtkEntryItem.this, cb);
|
||||
Gtk.proxyClick(GtkEntryItem.this, cb);
|
||||
}
|
||||
|
||||
return Gtk.TRUE;
|
||||
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Separator;
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
|
||||
@ -56,7 +56,7 @@ class GtkEntrySeparator extends GtkEntry implements Separator {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import dorkbox.systemTray.jna.linux.Gtk;
|
||||
|
||||
// you might wonder WHY this extends MenuEntryItem -- the reason is that an AppIndicator "status" will be offset from everyone else,
|
||||
@ -47,7 +48,7 @@ class GtkEntryStatus extends GtkEntryItem {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,6 +16,7 @@
|
||||
package dorkbox.systemTray.nativeUI;
|
||||
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -23,7 +24,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
@ -62,6 +63,127 @@ class GtkMenu extends MenuBase implements NativeUI {
|
||||
// only needed for AppIndicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
protected
|
||||
Entry addEntry_(final String menuText, final File imagePath, final ActionListener callback) {
|
||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
||||
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
// have to wait for the value
|
||||
final AtomicReference<Entry> value = new AtomicReference<Entry>();
|
||||
|
||||
// must always be called on DISPATCH
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
// some GTK libraries DO NOT let us add items AFTER the menu has been attached to the indicator.
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
Entry menuEntry = new GtkEntryItem(GtkMenu.this, callback);
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(menuEntry);
|
||||
value.set(menuEntry);
|
||||
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new checkbox menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
@Override
|
||||
protected
|
||||
Checkbox addCheckbox_(final String menuText, final ActionListener callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Checkbox> value = new AtomicReference<Checkbox>();
|
||||
|
||||
// must always be called on DISPATCH
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
// some GTK libraries DO NOT let us add items AFTER the menu has been attached to the indicator.
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
Entry entry = new GtkEntryCheckbox(GtkMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set((Checkbox) entry);
|
||||
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
protected
|
||||
Menu addMenu_(final String menuText, final File imagePath) {
|
||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
||||
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Menu> value = new AtomicReference<Menu>();
|
||||
|
||||
// must always be called on DISPATCH
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
// some GTK libraries DO NOT let us add items AFTER the menu has been attached to the indicator.
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
GtkMenu subMenu = new GtkMenu(getSystemTray(), GtkMenu.this);
|
||||
subMenu.setText(menuText);
|
||||
subMenu.setImage(imagePath);
|
||||
|
||||
menuEntries.add(subMenu);
|
||||
value.set(subMenu);
|
||||
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Necessary to guarantee all updates occur on the dispatch thread
|
||||
*/
|
||||
@ -136,10 +258,6 @@ class GtkMenu extends MenuBase implements NativeUI {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// public here so that Swing/Gtk/AppIndicator can override this
|
||||
@Override
|
||||
public
|
||||
@ -336,98 +454,6 @@ class GtkMenu extends MenuBase implements NativeUI {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
*/
|
||||
protected
|
||||
Entry addEntry_(final String menuText, final File imagePath, final Action callback) {
|
||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
||||
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
// have to wait for the value
|
||||
final AtomicReference<Entry> value = new AtomicReference<Entry>();
|
||||
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry menuEntry = get(menuText);
|
||||
if (menuEntry == null) {
|
||||
// some GTK libraries DO NOT let us add items AFTER the menu has been attached to the indicator.
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
menuEntry = new GtkEntryItem(GtkMenu.this, callback);
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
menuEntries.add(menuEntry);
|
||||
|
||||
createMenu();
|
||||
} else if (menuEntry instanceof GtkEntryItem) {
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
}
|
||||
|
||||
value.set(menuEntry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
*/
|
||||
protected
|
||||
Menu addMenu_(final String menuText, final File imagePath) {
|
||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
||||
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Menu> value = new AtomicReference<Menu>();
|
||||
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry menuEntry = get(menuText);
|
||||
if (menuEntry == null) {
|
||||
// some GTK libraries DO NOT let us add items AFTER the menu has been attached to the indicator.
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
GtkMenu subMenu = new GtkMenu(getSystemTray(), GtkMenu.this);
|
||||
subMenu.setText(menuText);
|
||||
subMenu.setImage(imagePath);
|
||||
|
||||
menuEntries.add(subMenu);
|
||||
|
||||
value.set(subMenu);
|
||||
|
||||
createMenu();
|
||||
} else if (menuEntry instanceof GtkMenu) {
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
|
||||
value.set(((GtkMenu) menuEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
// a child will always remove itself from the parent.
|
||||
@Override
|
||||
public
|
||||
|
128
src/dorkbox/systemTray/swingUI/SwingEntryCheckbox.java
Normal file
128
src/dorkbox/systemTray/swingUI/SwingEntryCheckbox.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.swingUI;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.util.ImageUtils;
|
||||
|
||||
class SwingEntryCheckbox extends SwingEntry implements Checkbox {
|
||||
|
||||
private final ActionListener swingCallback;
|
||||
|
||||
private volatile ActionListener callback;
|
||||
|
||||
private static ImageIcon checkedIcon;
|
||||
private static ImageIcon uncheckedIcon;
|
||||
private volatile boolean isChecked = false;
|
||||
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
SwingEntryCheckbox(final SwingMenu parent, final ActionListener callback) {
|
||||
super(parent, new AdjustedJMenuItem());
|
||||
this.callback = callback;
|
||||
|
||||
if (checkedIcon == null) {
|
||||
// from Brankic1979, public domain
|
||||
File checkedFile = ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, ImageUtils.class.getResource("checked_32.png"));
|
||||
checkedIcon = new ImageIcon(checkedFile.getAbsolutePath());
|
||||
|
||||
File uncheckedFile = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE);
|
||||
uncheckedIcon = new ImageIcon(uncheckedFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
((JMenuItem) _native).setIcon(uncheckedIcon);
|
||||
|
||||
if (callback != null) {
|
||||
_native.setEnabled(true);
|
||||
swingCallback = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void actionPerformed(ActionEvent e) {
|
||||
// we want it to run on the EDT
|
||||
if (isChecked) {
|
||||
((JMenuItem) _native).setIcon(uncheckedIcon);
|
||||
} else {
|
||||
((JMenuItem) _native).setIcon(checkedIcon);
|
||||
}
|
||||
isChecked = !isChecked;
|
||||
|
||||
handle();
|
||||
}
|
||||
};
|
||||
|
||||
((JMenuItem) _native).addActionListener(swingCallback);
|
||||
} else {
|
||||
_native.setEnabled(false);
|
||||
swingCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this checkbox is selected, false if not
|
||||
*/
|
||||
public
|
||||
boolean getState() {
|
||||
return isChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
private
|
||||
void handle() {
|
||||
ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
try {
|
||||
cb.actionPerformed(new ActionEvent((Checkbox)this, ActionEvent.ACTION_PERFORMED, ""));
|
||||
} catch (Throwable throwable) {
|
||||
SystemTray.logger.error("Error calling menu entry {} click event.", getText(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkbox image is always present
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void removePrivate() {
|
||||
((JMenuItem) _native).removeActionListener(swingCallback);
|
||||
}
|
||||
|
||||
// always called in the EDT
|
||||
@Override
|
||||
void renderText(final String text) {
|
||||
((JMenuItem) _native).setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setImage_(final File imageFile) {
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import java.io.File;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.util.SwingUtil;
|
||||
|
||||
class SwingEntryItem extends SwingEntry {
|
||||
@ -30,10 +30,10 @@ class SwingEntryItem extends SwingEntry {
|
||||
private final ActionListener swingCallback;
|
||||
|
||||
private volatile boolean hasLegitIcon = false;
|
||||
private volatile Action callback;
|
||||
private volatile ActionListener callback;
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
SwingEntryItem(final SwingMenu parent, final Action callback) {
|
||||
SwingEntryItem(final SwingMenu parent, final ActionListener callback) {
|
||||
super(parent, new AdjustedJMenuItem());
|
||||
this.callback = callback;
|
||||
|
||||
@ -58,14 +58,19 @@ class SwingEntryItem extends SwingEntry {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
private
|
||||
void handle() {
|
||||
if (callback != null) {
|
||||
callback.onClick(getParent().getSystemTray(), getParent(), this);
|
||||
ActionListener cb = this.callback;
|
||||
if (cb != null) {
|
||||
try {
|
||||
cb.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
|
||||
} catch (Throwable throwable) {
|
||||
SystemTray.logger.error("Error calling menu entry {} click event.", getText(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,11 @@
|
||||
*/
|
||||
package dorkbox.systemTray.swingUI;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
|
||||
class SwingEntrySeparator extends SwingEntry implements dorkbox.systemTray.Separator {
|
||||
|
||||
// this is ALWAYS called on the EDT.
|
||||
@ -54,6 +53,6 @@ class SwingEntrySeparator extends SwingEntry implements dorkbox.systemTray.Separ
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,11 @@
|
||||
package dorkbox.systemTray.swingUI;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Status;
|
||||
|
||||
class SwingEntryStatus extends SwingEntry implements Status {
|
||||
@ -65,7 +65,7 @@ class SwingEntryStatus extends SwingEntry implements Status {
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,11 @@
|
||||
*/
|
||||
package dorkbox.systemTray.swingUI;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
|
||||
// TODO: buggy. The menu will **sometimes** stop responding to the "enter" key after this. Mnemonics still work however.
|
||||
class SwingEntryWidget extends SwingEntry implements dorkbox.systemTray.Separator {
|
||||
|
||||
@ -57,6 +56,6 @@ class SwingEntryWidget extends SwingEntry implements dorkbox.systemTray.Separato
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package dorkbox.systemTray.swingUI;
|
||||
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@ -23,7 +24,7 @@ import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.Status;
|
||||
@ -100,36 +101,28 @@ class SwingMenu extends MenuBase implements SwingUI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON EDT
|
||||
*/
|
||||
protected final
|
||||
Entry addEntry_(final String menuText, final File imagePath, final Action callback) {
|
||||
Entry addEntry_(final String menuText, final File imagePath, final ActionListener callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Entry> value = new AtomicReference<Entry>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = get(menuText);
|
||||
|
||||
if (entry == null) {
|
||||
// must always be called on the EDT
|
||||
entry = new SwingEntryItem(SwingMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
} else if (entry instanceof SwingEntryItem) {
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
}
|
||||
Entry entry = new SwingEntryItem(SwingMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set(entry);
|
||||
}
|
||||
}
|
||||
@ -139,7 +132,38 @@ class SwingMenu extends MenuBase implements SwingUI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry, or update one if it already exists
|
||||
* Will add a new checkbox menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
@Override
|
||||
protected
|
||||
Checkbox addCheckbox_(final String menuText, final ActionListener callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
final AtomicReference<Checkbox> value = new AtomicReference<Checkbox>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = new SwingEntryCheckbox(SwingMenu.this, callback);
|
||||
entry.setText(menuText);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set((Checkbox) entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return value.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry
|
||||
* NOT ALWAYS CALLED ON EDT
|
||||
*/
|
||||
protected final
|
||||
@ -150,28 +174,20 @@ class SwingMenu extends MenuBase implements SwingUI {
|
||||
|
||||
final AtomicReference<Menu> value = new AtomicReference<Menu>();
|
||||
|
||||
// must always be called on the EDT
|
||||
dispatchAndWait(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
synchronized (menuEntries) {
|
||||
Entry entry = get(menuText);
|
||||
Entry entry = new SwingMenu(getSystemTray(), SwingMenu.this, new AdjustedJMenu());
|
||||
_native.add(((SwingMenu) entry)._native); // have to add it separately
|
||||
|
||||
if (entry == null) {
|
||||
// must always be called on the EDT
|
||||
entry = new SwingMenu(getSystemTray(), SwingMenu.this, new AdjustedJMenu());
|
||||
_native.add(((SwingMenu) entry)._native); // have to add it separately
|
||||
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
value.set((Menu) entry);
|
||||
|
||||
} else if (entry instanceof SwingMenu) {
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
}
|
||||
entry.setText(menuText);
|
||||
entry.setImage(imagePath);
|
||||
|
||||
menuEntries.add(entry);
|
||||
value.set((Menu) entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -17,7 +17,6 @@ package dorkbox.systemTray.util;
|
||||
|
||||
import static dorkbox.systemTray.jna.Windows.Gdi32.GetDeviceCaps;
|
||||
import static dorkbox.systemTray.jna.Windows.Gdi32.LOGPIXELSX;
|
||||
import static dorkbox.systemTray.jna.Windows.Gdi32.LOGPIXELSY;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
@ -134,8 +133,6 @@ class ImageUtils {
|
||||
} else if (windowsVersion.startsWith("6.3")) {
|
||||
// Windows 8.1
|
||||
// Windows Server 2012 6.3.9200
|
||||
|
||||
|
||||
scalingFactor = 4;
|
||||
|
||||
} else if (windowsVersion.startsWith("6.4")) {
|
||||
@ -154,11 +151,9 @@ class ImageUtils {
|
||||
|
||||
Pointer screen = User32.GetDC(null);
|
||||
int dpiX = GetDeviceCaps (screen, LOGPIXELSX);
|
||||
int dpiY = GetDeviceCaps (screen, LOGPIXELSY);
|
||||
User32.ReleaseDC(null, screen);
|
||||
|
||||
System.err.println("DPI : " + dpiX + "," + dpiY);
|
||||
|
||||
System.err.println("DPI : " + dpiX);
|
||||
|
||||
|
||||
if (SystemTray.DEBUG) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
package dorkbox.systemTray.util;
|
||||
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
@ -23,7 +24,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.Separator;
|
||||
@ -62,14 +63,21 @@ class MenuBase implements Menu {
|
||||
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
* Will add a new menu entry
|
||||
* NOT ALWAYS CALLED ON DISPATCH
|
||||
*/
|
||||
protected abstract
|
||||
Entry addEntry_(final String menuText, final File imagePath, final Action callback);
|
||||
Entry addEntry_(final String menuText, final File imagePath, final ActionListener callback);
|
||||
|
||||
/**
|
||||
* Will add a new sub-menu entry, or update one if it already exists
|
||||
* 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
|
||||
@ -225,13 +233,13 @@ class MenuBase implements Menu {
|
||||
|
||||
@Override
|
||||
public final
|
||||
Entry addEntry(String menuText, Action callback) {
|
||||
Entry addEntry(String menuText, ActionListener callback) {
|
||||
return addEntry(menuText, (String) null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final
|
||||
Entry addEntry(String menuText, String imagePath, Action callback) {
|
||||
Entry addEntry(String menuText, String imagePath, ActionListener callback) {
|
||||
if (imagePath == null) {
|
||||
return addEntry_(menuText, null, callback);
|
||||
}
|
||||
@ -242,7 +250,7 @@ class MenuBase implements Menu {
|
||||
|
||||
@Override
|
||||
public final
|
||||
Entry addEntry(String menuText, URL imageUrl, Action callback) {
|
||||
Entry addEntry(String menuText, URL imageUrl, ActionListener callback) {
|
||||
if (imageUrl == null) {
|
||||
return addEntry_(menuText, null, callback);
|
||||
}
|
||||
@ -253,7 +261,7 @@ class MenuBase implements Menu {
|
||||
|
||||
@Override
|
||||
public final
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, Action callback) {
|
||||
Entry addEntry(String menuText, String cacheName, InputStream imageStream, ActionListener callback) {
|
||||
if (imageStream == null) {
|
||||
return addEntry_(menuText, null, callback);
|
||||
}
|
||||
@ -264,7 +272,7 @@ class MenuBase implements Menu {
|
||||
|
||||
@Override
|
||||
public final
|
||||
Entry addEntry(String menuText, InputStream imageStream, Action callback) {
|
||||
Entry addEntry(String menuText, InputStream imageStream, ActionListener callback) {
|
||||
if (imageStream == null) {
|
||||
return addEntry_(menuText, null, callback);
|
||||
}
|
||||
@ -274,6 +282,11 @@ class MenuBase implements Menu {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
Checkbox addCheckbox(final String menuText, final ActionListener callback) {
|
||||
return addCheckbox_(menuText, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -386,36 +399,12 @@ class MenuBase implements Menu {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final
|
||||
void setCallback(final Action callback) {
|
||||
void setCallback(final ActionListener callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This removes a menu entry from the dropdown menu.
|
||||
*
|
||||
@ -526,27 +515,6 @@ class MenuBase implements Menu {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public final
|
||||
// void remove() {
|
||||
// dispatchAndWait(new Runnable() {
|
||||
// @Override
|
||||
// public
|
||||
// void run() {
|
||||
// _native.setVisible(false);
|
||||
// if (_native instanceof TrayPopup) {
|
||||
// ((TrayPopup) _native).close();
|
||||
// }
|
||||
//
|
||||
// MenuBase parent = (MenuBase) getParent();
|
||||
// if (parent != null) {
|
||||
// parent._native.remove(_native);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
@Override
|
||||
public final
|
||||
void removeAll() {
|
||||
|
BIN
src/dorkbox/systemTray/util/checked_32.png
Normal file
BIN
src/dorkbox/systemTray/util/checked_32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 298 B |
@ -16,9 +16,11 @@
|
||||
|
||||
package dorkbox;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Checkbox;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
@ -49,8 +51,8 @@ class TestTray {
|
||||
}
|
||||
|
||||
private SystemTray systemTray;
|
||||
private Action callbackGreen;
|
||||
private Action callbackGray;
|
||||
private ActionListener callbackGreen;
|
||||
private ActionListener callbackGray;
|
||||
|
||||
public
|
||||
TestTray() {
|
||||
@ -59,13 +61,23 @@ 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 Action() {
|
||||
callbackGreen = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -76,10 +88,11 @@ class TestTray {
|
||||
}
|
||||
};
|
||||
|
||||
callbackGray = new Action() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
@ -94,14 +107,18 @@ class TestTray {
|
||||
// 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 Action() {
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
}
|
||||
});
|
||||
@ -116,26 +133,26 @@ class TestTray {
|
||||
// systemTray.addWidget(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new Action() {
|
||||
submenu.addEntry("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) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new Action() {
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
submenu.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
systemTray.addEntry("Quit", new Action() {
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final ActionEvent e) {
|
||||
systemTray.shutdown();
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
}
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
package dorkbox;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
@ -59,8 +59,8 @@ class TestTrayJavaFX extends Application {
|
||||
}
|
||||
|
||||
private SystemTray systemTray;
|
||||
private Action callbackGreen;
|
||||
private Action callbackGray;
|
||||
private ActionListener callbackGreen;
|
||||
private ActionListener callbackGray;
|
||||
|
||||
public
|
||||
TestTrayJavaFX() {
|
||||
@ -95,10 +95,11 @@ class TestTrayJavaFX extends Application {
|
||||
systemTray.setImage(LT_GRAY_TRAIN);
|
||||
systemTray.setStatus("No Mail");
|
||||
|
||||
callbackGreen = new Action() {
|
||||
callbackGreen = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -109,10 +110,11 @@ class TestTrayJavaFX extends Application {
|
||||
}
|
||||
};
|
||||
|
||||
callbackGray = new Action() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
@ -127,14 +129,18 @@ class TestTrayJavaFX extends Application {
|
||||
// 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 Action() {
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
}
|
||||
});
|
||||
@ -149,25 +155,25 @@ class TestTrayJavaFX extends Application {
|
||||
// systemTray.addWidget(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new Action() {
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new Action() {
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.remove();
|
||||
}
|
||||
});
|
||||
|
||||
systemTray.addEntry("Quit", new Action() {
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
systemTray.shutdown();
|
||||
Platform.exit(); // necessary to close javaFx
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package dorkbox;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
@ -23,7 +24,6 @@ import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import dorkbox.systemTray.Action;
|
||||
import dorkbox.systemTray.Entry;
|
||||
import dorkbox.systemTray.Menu;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
@ -58,8 +58,8 @@ class TestTraySwt {
|
||||
}
|
||||
|
||||
private SystemTray systemTray;
|
||||
private Action callbackGreen;
|
||||
private Action callbackGray;
|
||||
private ActionListener callbackGreen;
|
||||
private ActionListener callbackGray;
|
||||
|
||||
public
|
||||
TestTraySwt() {
|
||||
@ -79,10 +79,11 @@ class TestTraySwt {
|
||||
systemTray.setImage(LT_GRAY_TRAIN);
|
||||
systemTray.setStatus("No Mail");
|
||||
|
||||
callbackGreen = new Action() {
|
||||
callbackGreen = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus("Some Mail!");
|
||||
systemTray.setImage(GREEN_TRAIN);
|
||||
|
||||
@ -93,10 +94,11 @@ class TestTraySwt {
|
||||
}
|
||||
};
|
||||
|
||||
callbackGray = new Action() {
|
||||
callbackGray = new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
final Entry entry = (Entry) e.getSource();
|
||||
systemTray.setStatus(null);
|
||||
systemTray.setImage(BLACK_TRAIN);
|
||||
|
||||
@ -111,14 +113,18 @@ class TestTraySwt {
|
||||
// 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 Action() {
|
||||
submenu.addEntry("Disable menu", BLACK_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.setEnabled(false);
|
||||
}
|
||||
});
|
||||
@ -133,25 +139,25 @@ class TestTraySwt {
|
||||
// systemTray.addWidget(progressBar);
|
||||
// }
|
||||
// });
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new Action() {
|
||||
submenu.addEntry("Hide tray", LT_GRAY_BUS, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
systemTray.setEnabled(false);
|
||||
}
|
||||
});
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new Action() {
|
||||
submenu.addEntry("Remove menu", BLACK_FIRE, new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
submenu.remove();
|
||||
}
|
||||
});
|
||||
|
||||
systemTray.addEntry("Quit", new Action() {
|
||||
systemTray.addEntry("Quit", new ActionListener() {
|
||||
@Override
|
||||
public
|
||||
void onClick(final SystemTray systemTray, final Menu parent, final Entry entry) {
|
||||
void actionPerformed(final java.awt.event.ActionEvent e) {
|
||||
systemTray.shutdown();
|
||||
|
||||
display.asyncExec(new Runnable() {
|
||||
|
Loading…
Reference in New Issue
Block a user