From 34588de6b7371109e17ce1c616cc199a43ad495f Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 27 Sep 2016 00:50:51 +0200 Subject: [PATCH] Added 'hasImage()' to menu-entry. Fixed text entry alignment issues for GTK menus --- src/dorkbox/systemTray/MenuEntry.java | 6 +- .../systemTray/linux/GtkMenuEntry.java | 58 ++++++++++++++++--- .../systemTray/linux/GtkTypeSystemTray.java | 14 ++++- .../systemTray/swing/SwingMenuEntry.java | 11 +++- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/dorkbox/systemTray/MenuEntry.java b/src/dorkbox/systemTray/MenuEntry.java index e51ba49..f8c61a0 100644 --- a/src/dorkbox/systemTray/MenuEntry.java +++ b/src/dorkbox/systemTray/MenuEntry.java @@ -66,9 +66,13 @@ interface MenuEntry { * * @param imageStream the InputStream of the image to use */ - @Deprecated void setImage(InputStream imageStream); + /** + * @return true if this menu entry has an image assigned to it, or is just text. + */ + boolean hasImage(); + /** * Sets a callback for a menu entry. This is the action that occurs when one clicks the menu entry * diff --git a/src/dorkbox/systemTray/linux/GtkMenuEntry.java b/src/dorkbox/systemTray/linux/GtkMenuEntry.java index bb38489..f7994d0 100644 --- a/src/dorkbox/systemTray/linux/GtkMenuEntry.java +++ b/src/dorkbox/systemTray/linux/GtkMenuEntry.java @@ -45,6 +45,10 @@ class GtkMenuEntry implements MenuEntry, GCallback { private volatile SystemTrayMenuAction 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 + private volatile boolean hasLegitIcon = true; + private static File transparentIcon = null; + /** * 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 @@ -56,13 +60,19 @@ class GtkMenuEntry implements MenuEntry, GCallback { menuItem = Gtk.gtk_image_menu_item_new_with_label(label); - if (imagePath != null) { + if (transparentIcon == null) { + transparentIcon = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE); + } + + hasLegitIcon = imagePath != null; + if (hasLegitIcon) { // NOTE: XFCE used to use appindicator3, which DOES NOT support images in the menu. This change was reverted. // see: https://ask.fedoraproject.org/en/question/23116/how-to-fix-missing-icons-in-program-menus-and-context-menus/ // see: https://git.gnome.org/browse/gtk+/commit/?id=627a03683f5f41efbfc86cc0f10e1b7c11e9bb25 image = Gtk.gtk_image_new_from_file(imagePath.getAbsolutePath()); Gtk.gtk_image_menu_item_set_image(menuItem, image); + // must always re-set always-show after setting the image Gtk.gtk_image_menu_item_set_always_show_image(menuItem, Gtk.TRUE); } @@ -70,6 +80,34 @@ class GtkMenuEntry implements MenuEntry, GCallback { nativeLong = Gobject.g_signal_connect_object(menuItem, "activate", this, null, 0); } + /** + * the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images + * + * called on the DISPATCH thread + */ + void setSpacerImage(final boolean everyoneElseHasImages) { + if (hasLegitIcon) { + // 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(menuItem); + } + + if (everyoneElseHasImages) { + image = Gtk.gtk_image_new_from_file(transparentIcon.getAbsolutePath()); + + Gtk.gtk_image_menu_item_set_image(menuItem, image); + + // must always re-set always-show after setting the image + Gtk.gtk_image_menu_item_set_always_show_image(menuItem, Gtk.TRUE); + } + + Gtk.gtk_widget_show_all(menuItem); + } // called by native code @Override @@ -105,7 +143,9 @@ class GtkMenuEntry implements MenuEntry, GCallback { } private - void setImage_(final File imagePath) { + void setImage_(final File imageFile) { + hasLegitIcon = imageFile != null; + Gtk.dispatch(new Runnable() { @Override public @@ -113,12 +153,11 @@ class GtkMenuEntry implements MenuEntry, GCallback { if (image != null) { Gtk.gtk_widget_destroy(image); image = null; + Gtk.gtk_widget_show_all(menuItem); } - Gtk.gtk_widget_show_all(menuItem); - - if (imagePath != null) { - image = Gtk.gtk_image_new_from_file(imagePath.getAbsolutePath()); + if (hasLegitIcon) { + image = Gtk.gtk_image_new_from_file(imageFile.getAbsolutePath()); Gtk.gtk_image_menu_item_set_image(menuItem, image); Gobject.g_object_ref_sink(image); @@ -165,7 +204,6 @@ class GtkMenuEntry implements MenuEntry, GCallback { } @Override - @Deprecated public void setImage(final InputStream imageStream) { if (imageStream == null) { @@ -176,6 +214,12 @@ class GtkMenuEntry implements MenuEntry, GCallback { } } + @Override + public + boolean hasImage() { + return hasLegitIcon; + } + @Override public void setCallback(final SystemTrayMenuAction callback) { diff --git a/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java b/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java index 3b1130d..2f314cd 100644 --- a/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java +++ b/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java @@ -163,11 +163,22 @@ class GtkTypeSystemTray extends SystemTray { Gobject.g_object_ref_sink(connectionStatusItem); } + boolean hasImages = false; + // now add back other menu entries synchronized (menuEntries) { for (int i = 0; i < menuEntries.size(); i++) { GtkMenuEntry menuEntry__ = (GtkMenuEntry) menuEntries.get(i); + hasImages |= menuEntry__.hasImage(); + } + + + for (int i = 0; i < menuEntries.size(); i++) { + GtkMenuEntry menuEntry__ = (GtkMenuEntry) menuEntries.get(i); + // the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images + menuEntry__.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.menu, menuEntry__.menuItem); Gobject.g_object_ref_sink(menuEntry__.menuItem); @@ -264,8 +275,7 @@ class GtkTypeSystemTray extends SystemTray { addMenuEntry_(menuText, null, callback); } else { -// addMenuEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback); - addMenuEntry_(menuText, ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE), callback); + addMenuEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback); } } diff --git a/src/dorkbox/systemTray/swing/SwingMenuEntry.java b/src/dorkbox/systemTray/swing/SwingMenuEntry.java index 8ebd312..8de4de8 100644 --- a/src/dorkbox/systemTray/swing/SwingMenuEntry.java +++ b/src/dorkbox/systemTray/swing/SwingMenuEntry.java @@ -37,6 +37,7 @@ class SwingMenuEntry implements MenuEntry { private final JMenuItem menuItem; private final ActionListener swingCallback; + private volatile boolean hasLegitIcon = false; private volatile String text; private volatile SystemTrayMenuAction callback; @@ -61,6 +62,7 @@ class SwingMenuEntry implements MenuEntry { menuItem.addActionListener(swingCallback); if (imagePath != null) { + hasLegitIcon = true; setImageIcon(imagePath); } @@ -110,10 +112,12 @@ class SwingMenuEntry implements MenuEntry { private void setImageIcon(final File imagePath) { if (imagePath != null) { + hasLegitIcon = true; ImageIcon origIcon = new ImageIcon(imagePath.getAbsolutePath()); menuItem.setIcon(origIcon); } else { + hasLegitIcon = false; menuItem.setIcon(null); } } @@ -152,7 +156,6 @@ class SwingMenuEntry implements MenuEntry { } @Override - @Deprecated public void setImage(final InputStream imageStream) { if (imageStream == null) { @@ -163,6 +166,12 @@ class SwingMenuEntry implements MenuEntry { } } + @Override + public + boolean hasImage() { + return hasLegitIcon; + } + @Override public void setCallback(final SystemTrayMenuAction callback) {