WIP for checkboxes on AppIndicators
This commit is contained in:
parent
e4ff8da145
commit
8dddee95dd
|
@ -226,7 +226,12 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
|||
entry.bind(item, parentMenu, parentMenu.getSystemTray());
|
||||
}
|
||||
else if (entry instanceof Checkbox) {
|
||||
GtkMenuItemCheckbox item = new GtkMenuItemCheckbox(GtkMenu.this);
|
||||
// Additionally, we can ask the SystemTray WHAT KIND of tray it is, since it will know by this point in time.
|
||||
// necessary because of bad layout decisions by AppIndicators for checkbox items
|
||||
|
||||
// WIP. The checkbox (if appIndicator) is always black. This could cause problems depending on theme
|
||||
// boolean isAppIndicator = SystemTray.get().getMenu() instanceof _AppIndicatorNativeTray;
|
||||
GtkMenuItemCheckbox item = new GtkMenuItemCheckbox(GtkMenu.this, false);
|
||||
add(item, index);
|
||||
((Checkbox) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
||||
}
|
||||
|
|
|
@ -26,14 +26,19 @@ 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;
|
||||
|
||||
// ElementaryOS shows the checkbox on the right, everyone else is on the left. With eOS, we CANNOT show the spacer image. It does not work
|
||||
class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCallback {
|
||||
private static String checkedFile;
|
||||
private static String uncheckedFile;
|
||||
|
||||
private final GtkMenu parent;
|
||||
|
||||
// these have to be volatile, because they can be changed from any thread
|
||||
private volatile ActionListener callback;
|
||||
private volatile boolean isChecked = false;
|
||||
private volatile Pointer checkedImage;
|
||||
private volatile Pointer image;
|
||||
|
||||
// The mnemonic will ONLY show-up once a menu entry is selected. IT WILL NOT show up before then!
|
||||
|
@ -41,16 +46,35 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
|||
// GtkStatusIconTray will show on mouse+keyboard movement
|
||||
private volatile char mnemonicKey = 0;
|
||||
private final long handlerId;
|
||||
private final boolean isAppIndicator;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* note: AppIndicator tray's DO NOT show the spacer image for checkboxes so they are "shifted left", which looks awkward.
|
||||
*/
|
||||
GtkMenuItemCheckbox(final GtkMenu parent) {
|
||||
super(Gtk.gtk_check_menu_item_new_with_mnemonic(""));
|
||||
GtkMenuItemCheckbox(final GtkMenu parent, final boolean isAppIndicator) {
|
||||
super(isAppIndicator ? Gtk.gtk_image_menu_item_new_with_mnemonic("") : Gtk.gtk_check_menu_item_new_with_mnemonic(""));
|
||||
this.parent = parent;
|
||||
this.isAppIndicator = isAppIndicator;
|
||||
|
||||
handlerId = Gobject.g_signal_connect_object(_native, "activate", this, null, 0);
|
||||
|
||||
if (checkedFile == null) {
|
||||
// from Brankic1979, public domain
|
||||
checkedFile = ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, ImageUtils.class.getResource("checked_32.png")).getAbsolutePath();
|
||||
uncheckedFile = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE).getAbsolutePath();
|
||||
}
|
||||
|
||||
if (isAppIndicator) {
|
||||
setCheckedIconForAppIndicators();
|
||||
}
|
||||
else {
|
||||
Gobject.g_signal_handler_block(_native, handlerId);
|
||||
Gtk.gtk_check_menu_item_set_active(_native, false);
|
||||
Gobject.g_signal_handler_unblock(_native, handlerId);
|
||||
}
|
||||
}
|
||||
|
||||
// called by native code ONLY
|
||||
|
@ -151,7 +175,7 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
|||
@Override
|
||||
public
|
||||
void setChecked(final Checkbox menuItem) {
|
||||
boolean checked = menuItem.getChecked();
|
||||
final boolean checked = menuItem.getChecked();
|
||||
|
||||
// only dispatch if it's actually different
|
||||
if (checked != this.isChecked) {
|
||||
|
@ -161,18 +185,44 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
|||
@Override
|
||||
public
|
||||
void run() {
|
||||
// note: this will trigger "activate", which will then trigger the callback.
|
||||
// we assume this is consistent across ALL versions and variants of GTK
|
||||
// https://github.com/GNOME/gtk/blob/master/gtk/gtkcheckmenuitem.c#L317
|
||||
// this disables the signal handler, then enables it
|
||||
Gobject.g_signal_handler_block(_native, handlerId);
|
||||
Gtk.gtk_check_menu_item_set_active(_native, isChecked);
|
||||
Gobject.g_signal_handler_unblock(_native, handlerId);
|
||||
if (!isAppIndicator) {
|
||||
// note: this will trigger "activate", which will then trigger the callback.
|
||||
// we assume this is consistent across ALL versions and variants of GTK
|
||||
// https://github.com/GNOME/gtk/blob/master/gtk/gtkcheckmenuitem.c#L317
|
||||
// this disables the signal handler, then enables it
|
||||
Gobject.g_signal_handler_block(_native, handlerId);
|
||||
Gtk.gtk_check_menu_item_set_active(_native, isChecked);
|
||||
Gobject.g_signal_handler_unblock(_native, handlerId);
|
||||
} else {
|
||||
setCheckedIconForAppIndicators();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void setCheckedIconForAppIndicators() {
|
||||
if (checkedImage != null) {
|
||||
Gtk.gtk_container_remove(_native, checkedImage); // will automatically get destroyed if no other references to it
|
||||
checkedImage = null;
|
||||
Gtk.gtk_widget_show_all(_native);
|
||||
}
|
||||
|
||||
|
||||
if (this.isChecked) {
|
||||
checkedImage = Gtk.gtk_image_new_from_file(checkedFile);
|
||||
} else {
|
||||
checkedImage = Gtk.gtk_image_new_from_file(uncheckedFile);
|
||||
}
|
||||
Gtk.gtk_image_menu_item_set_image(_native, checkedImage);
|
||||
|
||||
// must always re-set always-show after setting the image
|
||||
Gtk.gtk_image_menu_item_set_always_show_image(_native, true);
|
||||
|
||||
Gtk.gtk_widget_show_all(_native);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setShortcut(final Checkbox checkbox) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user