Consolidated gtk menu (so the menuentry has the entry+menu)
This commit is contained in:
parent
b1398392c7
commit
ad8cd3709c
@ -39,9 +39,6 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
// these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT
|
||||
private volatile boolean hasLegitIcon = true;
|
||||
|
||||
// only set when this entry has a submenu attached to it. One cannot "unattach" a sub-menu, they must delete+add
|
||||
private GtkMenu subMenu;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -65,20 +62,6 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the sub-menu for an entry, so we can recreate all of the menus when one entry changes (because of how GTK on some systems work
|
||||
*
|
||||
* @param subMenu The submenu that is attached to this menu entry
|
||||
*/
|
||||
void setSubMenu(GtkMenu subMenu) {
|
||||
this.subMenu = subMenu;
|
||||
}
|
||||
|
||||
// only needed for recursive create/delete menus
|
||||
GtkMenu getSubMenu() {
|
||||
return subMenu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
@ -176,9 +159,5 @@ class GtkEntryItem extends GtkEntry implements GCallback {
|
||||
Gtk.gtk_widget_destroy(image);
|
||||
image = null;
|
||||
}
|
||||
|
||||
if (subMenu != null) {
|
||||
subMenu.obliterateMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,19 +34,24 @@ import dorkbox.systemTray.linux.jna.Gobject;
|
||||
import dorkbox.systemTray.linux.jna.Gtk;
|
||||
|
||||
class GtkMenu extends Menu implements MenuEntry {
|
||||
// menu entry that this menu is attached to
|
||||
// menu entry that this menu is attached to. Will be NULL when it's the system tray
|
||||
private final GtkEntryItem menuEntry;
|
||||
|
||||
// must ONLY be created at the end of delete!
|
||||
volatile Pointer _native;
|
||||
|
||||
|
||||
// called on dispatch
|
||||
GtkMenu(SystemTray systemTray, GtkMenu parent, final GtkEntryItem menuEntry) {
|
||||
GtkMenu(final SystemTray systemTray, final GtkMenu parent, final GtkEntryItem menuEntry) {
|
||||
super(systemTray, parent);
|
||||
|
||||
if (menuEntry != null) {
|
||||
// by default, no callback on a menu entry means it's DISABLED. we have to undo that, because we don't have a callback for menus
|
||||
Gtk.gtk_widget_set_sensitive(menuEntry._native, Gtk.TRUE);
|
||||
}
|
||||
this.menuEntry = menuEntry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Necessary to guarantee all updates occur on the dispatch thread
|
||||
*/
|
||||
@ -123,6 +128,75 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
String getText() {
|
||||
return menuEntry.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setText(final String newText) {
|
||||
menuEntry.setText(newText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final File imageFile) {
|
||||
menuEntry.setImage(imageFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String imagePath) {
|
||||
menuEntry.setImage(imagePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final URL imageUrl) {
|
||||
menuEntry.setImage(imageUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String cacheName, final InputStream imageStream) {
|
||||
menuEntry.setImage(cacheName, imageStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final InputStream imageStream) {
|
||||
menuEntry.setImage(imageStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
return menuEntry.hasImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
// NO OP.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when this sub-menu is removed from it's parent menu
|
||||
*/
|
||||
protected
|
||||
void removePrivate() {
|
||||
// delete all of the children
|
||||
obliterateMenu();
|
||||
|
||||
// remove the gtk entry item from our parent menu
|
||||
if (menuEntry != null) {
|
||||
menuEntry.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
/**
|
||||
@ -133,10 +207,20 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
// have to remove all other menu entries
|
||||
synchronized (menuEntries) {
|
||||
for (int i = 0; i < menuEntries.size(); i++) {
|
||||
GtkEntry menuEntry__ = (GtkEntry) menuEntries.get(i);
|
||||
MenuEntry menuEntry__ = menuEntries.get(i);
|
||||
|
||||
Gobject.g_object_force_floating(menuEntry__._native);
|
||||
Gtk.gtk_container_remove(_native, menuEntry__._native);
|
||||
if (menuEntry__ instanceof GtkEntry) {
|
||||
GtkEntry entry = (GtkEntry) menuEntry__;
|
||||
|
||||
Gobject.g_object_force_floating(entry._native);
|
||||
Gtk.gtk_container_remove(_native, entry._native);
|
||||
}
|
||||
else if (menuEntry__ instanceof GtkMenu) {
|
||||
GtkMenu subMenu = (GtkMenu) menuEntry__;
|
||||
|
||||
Gobject.g_object_force_floating(subMenu.menuEntry._native);
|
||||
Gtk.gtk_container_remove(_native, subMenu.menuEntry._native);
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.gtk_widget_destroy(_native);
|
||||
@ -173,23 +257,27 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
}
|
||||
|
||||
for (int i = 0; i < menuEntries.size(); i++) {
|
||||
GtkEntry menuEntry__ = (GtkEntry) menuEntries.get(i);
|
||||
MenuEntry menuEntry__ = menuEntries.get(i);
|
||||
|
||||
// the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images
|
||||
menuEntry__.setSpacerImage(hasImages);
|
||||
if (menuEntry__ instanceof GtkEntry) {
|
||||
GtkEntry entry = (GtkEntry) menuEntry__;
|
||||
entry.setSpacerImage(hasImages);
|
||||
|
||||
// will also get: gsignal.c:2516: signal 'child-added' is invalid for instance '0x7f1df8244080' of type 'GtkMenu'
|
||||
Gtk.gtk_menu_shell_append(this._native, menuEntry__._native);
|
||||
Gobject.g_object_ref_sink(menuEntry__._native); // undoes "floating"
|
||||
// will also get: gsignal.c:2516: signal 'child-added' is invalid for instance '0x7f1df8244080' of type 'GtkMenu'
|
||||
Gtk.gtk_menu_shell_append(this._native, entry._native);
|
||||
Gobject.g_object_ref_sink(entry._native); // undoes "floating"
|
||||
}
|
||||
else if (menuEntry__ instanceof GtkMenu) {
|
||||
GtkMenu subMenu = (GtkMenu) menuEntry__;
|
||||
|
||||
if (menuEntry__ instanceof GtkEntryItem) {
|
||||
GtkMenu subMenu = ((GtkEntryItem) menuEntry__).getSubMenu();
|
||||
if (subMenu != null) {
|
||||
// will also get: gsignal.c:2516: signal 'child-added' is invalid for instance '0x7f1df8244080' of type 'GtkMenu'
|
||||
Gtk.gtk_menu_shell_append(this._native, subMenu.menuEntry._native);
|
||||
Gobject.g_object_ref_sink(subMenu.menuEntry._native); // undoes "floating"
|
||||
|
||||
if (subMenu.getParent() != GtkMenu.this) {
|
||||
// we don't want to "createMenu" on our sub-menu that is assigned to us directly, as they are already doing it
|
||||
if (subMenu.getParent() != GtkMenu.this) {
|
||||
subMenu.createMenu();
|
||||
} else {
|
||||
Gtk.gtk_widget_set_sensitive(menuEntry__._native, Gtk.TRUE);
|
||||
}
|
||||
subMenu.createMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,8 +302,14 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
// have to remove all other menu entries
|
||||
synchronized (menuEntries) {
|
||||
for (int i = 0; i < menuEntries.size(); i++) {
|
||||
GtkEntry menuEntry__ = (GtkEntry) menuEntries.get(i);
|
||||
menuEntry__.removePrivate();
|
||||
MenuEntry menuEntry__ = menuEntries.get(i);
|
||||
|
||||
if (menuEntry__ instanceof GtkEntry) {
|
||||
((GtkEntry) menuEntry__).removePrivate();
|
||||
}
|
||||
else if (menuEntry__ instanceof GtkMenu) {
|
||||
((GtkMenu) menuEntry__).removePrivate();
|
||||
}
|
||||
}
|
||||
menuEntries.clear();
|
||||
|
||||
@ -295,29 +389,20 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||
deleteMenu();
|
||||
|
||||
GtkMenu subMenu = new GtkMenu(getSystemTray(), GtkMenu.this, new GtkEntryItem(GtkMenu.this, null));
|
||||
subMenu.setText(menuText);
|
||||
subMenu.setImage(imagePath);
|
||||
|
||||
menuEntry = new GtkEntryItem(GtkMenu.this, null);
|
||||
Gtk.gtk_widget_set_sensitive(_native, Gtk.TRUE); // submenu needs to be active
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
menuEntries.add(menuEntry);
|
||||
|
||||
GtkMenu subMenu = new GtkMenu(getSystemTray(), GtkMenu.this, (GtkEntryItem) menuEntry);
|
||||
|
||||
((GtkEntryItem) menuEntry).setSubMenu(subMenu);
|
||||
menuEntries.add(subMenu);
|
||||
|
||||
value.set(subMenu);
|
||||
|
||||
createMenu();
|
||||
} else if (menuEntry instanceof GtkEntryItem) {
|
||||
GtkMenu subMenu = ((GtkEntryItem) menuEntry).getSubMenu();
|
||||
if (subMenu != null) {
|
||||
} else if (menuEntry instanceof GtkMenu) {
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
|
||||
menuEntry.setText(menuText);
|
||||
menuEntry.setImage(imagePath);
|
||||
|
||||
value.set(subMenu);
|
||||
}
|
||||
value.set(((GtkMenu) menuEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,63 +411,20 @@ class GtkMenu extends Menu implements MenuEntry {
|
||||
return value.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
String getText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setText(final String newText) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final File imageFile) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String imagePath) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final URL imageUrl) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String cacheName, final InputStream imageStream) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final InputStream imageStream) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean hasImage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
GtkMenu parent = (GtkMenu) getParent();
|
||||
|
||||
Gtk.gtk_container_remove(parent._native, _native);
|
||||
Gtk.gtk_menu_shell_deactivate(parent._native, _native);
|
||||
|
||||
removePrivate();
|
||||
|
||||
Gtk.gtk_widget_destroy(_native);
|
||||
|
||||
// have to rebuild the menu now...
|
||||
parent.deleteMenu();
|
||||
parent.createMenu();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user