Work for issue #42, detecting colors for the checkbox in linux via CSS
theme, RC theme, and raw GTK values.
This commit is contained in:
parent
1bcf51c755
commit
736b098e86
48
src/dorkbox/systemTray/jna/linux/GParamSpecStruct.java
Normal file
48
src/dorkbox/systemTray/jna/linux/GParamSpecStruct.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.jna.linux;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.sun.jna.Structure;
|
||||||
|
|
||||||
|
import dorkbox.util.Keep;
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
public
|
||||||
|
class GParamSpecStruct extends Structure {
|
||||||
|
public
|
||||||
|
class ByValue extends GParamSpecStruct implements Structure.ByValue {}
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
class ByReference extends GParamSpecStruct implements Structure.ByReference {}
|
||||||
|
|
||||||
|
|
||||||
|
public GTypeInstanceStruct g_type_instance;
|
||||||
|
|
||||||
|
public String name; /* interned string */
|
||||||
|
// Pointer flags;
|
||||||
|
// double value_type;
|
||||||
|
// double owner_type; /* class or interface using this property */
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected
|
||||||
|
List<String> getFieldOrder() {
|
||||||
|
return Arrays.asList("g_type_instance", "name");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
* 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.jna.linux;
|
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
|
||||||
|
|
||||||
import dorkbox.util.jna.JnaHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bindings for libgthread
|
|
||||||
*
|
|
||||||
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
|
|
||||||
*/
|
|
||||||
public
|
|
||||||
class GThread {
|
|
||||||
static {
|
|
||||||
JnaHelper.register("gthread-2.0", GThread.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static native void g_thread_init(Pointer GThreadFunctions);
|
|
||||||
}
|
|
34
src/dorkbox/systemTray/jna/linux/GdkColor.java
Normal file
34
src/dorkbox/systemTray/jna/linux/GdkColor.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package dorkbox.systemTray.jna.linux;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.sun.jna.Structure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gnome.org/gdk3/stable/gdk3-Colors.html
|
||||||
|
*
|
||||||
|
* GdkColor has been deprecated since version 3.14 and should not be used in newly-written code.
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class GdkColor extends Structure {
|
||||||
|
|
||||||
|
public int pixel;
|
||||||
|
public short red;
|
||||||
|
public short green;
|
||||||
|
public short blue;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected
|
||||||
|
List<String> getFieldOrder() {
|
||||||
|
return Arrays.asList("pixel", "red", "green", "blue");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
class ByValue extends GdkColor implements Structure.ByValue {}
|
||||||
|
|
||||||
|
|
||||||
|
public static
|
||||||
|
class ByReference extends GdkColor implements Structure.ByReference {}
|
||||||
|
}
|
33
src/dorkbox/systemTray/jna/linux/GdkRGBAColor.java
Normal file
33
src/dorkbox/systemTray/jna/linux/GdkRGBAColor.java
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package dorkbox.systemTray.jna.linux;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.sun.jna.Structure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gnome.org/gdk3/stable/gdk3-RGBA-Colors.html#GdkRGBA
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class GdkRGBAColor extends Structure {
|
||||||
|
|
||||||
|
// these are from 0.0 to 1.0 inclusive
|
||||||
|
public double red;
|
||||||
|
public double green;
|
||||||
|
public double blue;
|
||||||
|
public double alpha;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected
|
||||||
|
List<String> getFieldOrder() {
|
||||||
|
return Arrays.asList("red", "green", "blue", "alpha");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
class ByValue extends GdkRGBAColor implements Structure.ByValue {}
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
class ByReference extends GdkRGBAColor implements Structure.ByReference {}
|
||||||
|
}
|
57
src/dorkbox/systemTray/jna/linux/Glib.java
Normal file
57
src/dorkbox/systemTray/jna/linux/Glib.java
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package dorkbox.systemTray.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Callback;
|
||||||
|
import com.sun.jna.NativeLibrary;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
import dorkbox.util.jna.JnaHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bindings for glib-2.0
|
||||||
|
*
|
||||||
|
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class Glib {
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
NativeLibrary library = JnaHelper.register("glib-2.0", Glib.class);
|
||||||
|
if (library == null) {
|
||||||
|
SystemTray.logger.error("Error loading Glib library, it failed to load.");
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
SystemTray.logger.error("Error loading Glib library, it failed to load {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface GLogLevelFlags {
|
||||||
|
public static final int RECURSION = 1 << 0;
|
||||||
|
public static final int FATAL = 1 << 1;
|
||||||
|
/* GLib log levels */
|
||||||
|
public static final int ERROR = 1 << 2; /* always fatal */
|
||||||
|
public static final int CRITICAL = 1 << 3;
|
||||||
|
public static final int WARNING = 1 << 4;
|
||||||
|
public static final int MESSAGE = 1 << 5;
|
||||||
|
public static final int INFO = 1 << 6;
|
||||||
|
public static final int DEBUG = 1 << 7;
|
||||||
|
public static final int MASK = ~(RECURSION | FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface GLogFunc extends Callback {
|
||||||
|
void callback (String log_domain, int log_level, String message, Pointer data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Glib.GLogFunc nullLogFunc = new Glib.GLogFunc() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
void callback(final String log_domain, final int log_level, final String message, final Pointer data) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static native int g_log_set_handler(String log_domain, int levels, GLogFunc handler, Pointer user_data);
|
||||||
|
public static native void g_log_default_handler (String log_domain, int log_level, String message, Pointer unused_data);
|
||||||
|
public static native GLogFunc g_log_set_default_handler(GLogFunc log_func, Pointer user_data);
|
||||||
|
public static native void g_log_remove_handler (String log_domain, int handler_id);
|
||||||
|
}
|
|
@ -15,13 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package dorkbox.systemTray.jna.linux;
|
package dorkbox.systemTray.jna.linux;
|
||||||
|
|
||||||
import static dorkbox.systemTray.SystemTray.logger;
|
|
||||||
|
|
||||||
import com.sun.jna.Callback;
|
import com.sun.jna.Callback;
|
||||||
import com.sun.jna.NativeLibrary;
|
import com.sun.jna.NativeLibrary;
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
|
||||||
import dorkbox.systemTray.jna.JnaHelper;
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
import dorkbox.util.jna.JnaHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bindings for libgobject-2.0
|
* bindings for libgobject-2.0
|
||||||
|
@ -35,10 +35,10 @@ class Gobject {
|
||||||
try {
|
try {
|
||||||
NativeLibrary library = JnaHelper.register("gobject-2.0", Gobject.class);
|
NativeLibrary library = JnaHelper.register("gobject-2.0", Gobject.class);
|
||||||
if (library == null) {
|
if (library == null) {
|
||||||
logger.error("Error loading GObject library, it failed to load.");
|
SystemTray.logger.error("Error loading GObject library, it failed to load.");
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.error("Error loading GObject library, it failed to load {}", e.getMessage());
|
SystemTray.logger.error("Error loading GObject library, it failed to load {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,4 +54,25 @@ class Gobject {
|
||||||
|
|
||||||
public static native void g_signal_handler_block(Pointer instance, long handlerId);
|
public static native void g_signal_handler_block(Pointer instance, long handlerId);
|
||||||
public static native void g_signal_handler_unblock(Pointer instance, long handlerId);
|
public static native void g_signal_handler_unblock(Pointer instance, long handlerId);
|
||||||
|
|
||||||
|
public static native void g_object_get(Pointer instance, String property_name, PointerByReference value, Pointer terminator);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Types are here https://developer.gnome.org/gobject/stable/gobject-Type-Information.html
|
||||||
|
public static native void g_value_init(Pointer gvalue, double type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the current value in value (if any) and "unsets" the type, this releases all resources associated with this GValue. An unset value is the same as an uninitialized (zero-filled) GValue structure.
|
||||||
|
* @param gvalue
|
||||||
|
*/
|
||||||
|
public static native void g_value_unset(Pointer gvalue);
|
||||||
|
|
||||||
|
public static native String g_value_get_string(Pointer gvalue);
|
||||||
|
public static native int g_value_get_int(Pointer gvalue);
|
||||||
|
|
||||||
|
|
||||||
|
public static native Pointer g_type_class_ref(Pointer widgetType);
|
||||||
|
public static native void g_type_class_unref(Pointer widgetClass);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
72
src/dorkbox/systemTray/jna/linux/Gtk3.java
Normal file
72
src/dorkbox/systemTray/jna/linux/Gtk3.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 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.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bindings for GTK+ 3.
|
||||||
|
*
|
||||||
|
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class Gtk3 {
|
||||||
|
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 | grep gtk
|
||||||
|
// objdump -T /usr/local/lib/libgtk-3.so.0 | grep gtk
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a theme from the usual theme paths
|
||||||
|
*
|
||||||
|
* @param name A theme name
|
||||||
|
* @param variant variant to load, for example, "dark", or NULL for the default.
|
||||||
|
*
|
||||||
|
* @return a GtkCssProvider with the theme loaded. This memory is owned by GTK+, and you must not free it.
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public static native Pointer gtk_css_provider_get_named(String name, String variant);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the provider containing the style settings used as a fallback for all widgets.
|
||||||
|
*
|
||||||
|
* @return a GtkCssProvider with the theme loaded. This memory is owned by GTK+, and you must not free it.
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public static native Pointer gtk_css_provider_get_default();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provider into a string representation in CSS format.
|
||||||
|
*
|
||||||
|
* Using gtk_css_provider_load_from_data() with the return value from this function on a new provider created with
|
||||||
|
* gtk_css_provider_new() will basically create a duplicate of this provider .
|
||||||
|
*
|
||||||
|
* @since 3.2 (released in 2011)
|
||||||
|
*/
|
||||||
|
public static native String gtk_css_provider_to_string(Pointer provider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the foreground color for a given state.
|
||||||
|
*
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public static native void gtk_style_context_get_color(Pointer context, int stateFlags, Pointer color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state used for style matching.
|
||||||
|
*
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public static native int gtk_style_context_get_state(Pointer context);
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import dorkbox.systemTray.Menu;
|
||||||
import dorkbox.systemTray.MenuItem;
|
import dorkbox.systemTray.MenuItem;
|
||||||
import dorkbox.systemTray.Separator;
|
import dorkbox.systemTray.Separator;
|
||||||
import dorkbox.systemTray.Status;
|
import dorkbox.systemTray.Status;
|
||||||
|
import dorkbox.systemTray.SystemTray;
|
||||||
import dorkbox.systemTray.jna.linux.Gtk;
|
import dorkbox.systemTray.jna.linux.Gtk;
|
||||||
import dorkbox.systemTray.peer.MenuPeer;
|
import dorkbox.systemTray.peer.MenuPeer;
|
||||||
|
|
||||||
|
@ -215,7 +216,6 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
if (entry instanceof Menu) {
|
if (entry instanceof Menu) {
|
||||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
// 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
|
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||||
|
|
||||||
GtkMenu item = new GtkMenu(GtkMenu.this);
|
GtkMenu item = new GtkMenu(GtkMenu.this);
|
||||||
add(item, index);
|
add(item, index);
|
||||||
((Menu) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
((Menu) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
@ -229,9 +229,8 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
// Additionally, we can ask the SystemTray WHAT KIND of tray it is, since it will know by this point in time.
|
// 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
|
// 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;
|
||||||
// boolean isAppIndicator = SystemTray.get().getMenu() instanceof _AppIndicatorNativeTray;
|
GtkMenuItemCheckbox item = new GtkMenuItemCheckbox(GtkMenu.this, isAppIndicator);
|
||||||
GtkMenuItemCheckbox item = new GtkMenuItemCheckbox(GtkMenu.this, false);
|
|
||||||
add(item, index);
|
add(item, index);
|
||||||
((Checkbox) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
((Checkbox) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package dorkbox.systemTray.nativeUI;
|
package dorkbox.systemTray.nativeUI;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
@ -26,7 +33,8 @@ import dorkbox.systemTray.jna.linux.GCallback;
|
||||||
import dorkbox.systemTray.jna.linux.Gobject;
|
import dorkbox.systemTray.jna.linux.Gobject;
|
||||||
import dorkbox.systemTray.jna.linux.Gtk;
|
import dorkbox.systemTray.jna.linux.Gtk;
|
||||||
import dorkbox.systemTray.peer.CheckboxPeer;
|
import dorkbox.systemTray.peer.CheckboxPeer;
|
||||||
import dorkbox.systemTray.util.ImageUtils;
|
import dorkbox.systemTray.util.ImageResizeUtil;
|
||||||
|
import dorkbox.util.SwingUtil;
|
||||||
|
|
||||||
// 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
|
// 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 {
|
class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCallback {
|
||||||
|
@ -52,7 +60,12 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
||||||
* called from inside dispatch thread. ONLY creates the menu item, but DOES NOT attach it!
|
* 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
|
* 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.
|
* Because AppIndicator checkbox's DO NOT align correctly (on ubuntu), we use an image_menu_item (instead of a check_menu_item), so that
|
||||||
|
* the alignment is correct for the menu item (with a check_menu_item, they are shifted left - which looks pretty bad)
|
||||||
|
*
|
||||||
|
* For AppIndicators, this is not possible to fix, because we cannot control how the menu's are rendered (this is by design)
|
||||||
|
* Specifically, since it's implementation was copied from GTK, GtkCheckButton and GtkRadioButton allocate only the minimum size
|
||||||
|
* necessary for its child. This causes the child alignment to fail. There is no fix we can apply - so we don't use them.
|
||||||
*/
|
*/
|
||||||
GtkMenuItemCheckbox(final GtkMenu parent, final boolean isAppIndicator) {
|
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(""));
|
super(isAppIndicator ? Gtk.gtk_image_menu_item_new_with_mnemonic("") : Gtk.gtk_check_menu_item_new_with_mnemonic(""));
|
||||||
|
@ -62,9 +75,46 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
||||||
handlerId = Gobject.g_signal_connect_object(_native, "activate", this, null, 0);
|
handlerId = Gobject.g_signal_connect_object(_native, "activate", this, null, 0);
|
||||||
|
|
||||||
if (checkedFile == null) {
|
if (checkedFile == null) {
|
||||||
// from Brankic1979, public domain
|
Color color = Gtk.getCurrentThemeTextColor();
|
||||||
checkedFile = ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, ImageUtils.class.getResource("checked_32.png")).getAbsolutePath();
|
|
||||||
uncheckedFile = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE).getAbsolutePath();
|
try {
|
||||||
|
int iconSize = 32;
|
||||||
|
final File newFile = new File(ImageResizeUtil.TEMP_DIR, iconSize + "_checkMark_" + color.getRGB() + ".png").getAbsoluteFile();
|
||||||
|
|
||||||
|
if (!newFile.canRead()) {
|
||||||
|
JMenuItem jMenuItem = new JMenuItem();
|
||||||
|
|
||||||
|
// do the same modifications that would also happen (if specified) for the actual displayed menu items
|
||||||
|
if (SystemTray.SWING_UI != null) {
|
||||||
|
jMenuItem.setUI(SystemTray.SWING_UI.getItemUI(jMenuItem, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the directory exists
|
||||||
|
if (!newFile.getParentFile()
|
||||||
|
.isDirectory()) {
|
||||||
|
|
||||||
|
boolean mkdirs = newFile.getParentFile()
|
||||||
|
.mkdirs();
|
||||||
|
|
||||||
|
if (!mkdirs) {
|
||||||
|
SystemTray.logger.error("Unable to create directory for check-mark image at: {}", newFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the largest font (based on the orig font) that can be used WITHOUT changing the size of the JMenuItem
|
||||||
|
Font fontForSpecificHeight = SwingUtil.getFontForSpecificHeight(jMenuItem.getFont(), iconSize);
|
||||||
|
|
||||||
|
BufferedImage fontAsImage = SwingUtil.getFontAsImage(fontForSpecificHeight, "✔", color); // or "✓"
|
||||||
|
ImageIO.write(fontAsImage, "png", newFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedFile = newFile.getAbsolutePath();
|
||||||
|
|
||||||
|
// here, it doesn't matter what size the image is, as long as there is an image, the text in the menu will be shifted correctly
|
||||||
|
uncheckedFile = ImageResizeUtil.getTransparentImage().getAbsolutePath();
|
||||||
|
} catch(Exception e) {
|
||||||
|
SystemTray.logger.error("Error creating check-mark image.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAppIndicator) {
|
if (isAppIndicator) {
|
||||||
|
@ -215,6 +265,7 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
||||||
} else {
|
} else {
|
||||||
checkedImage = Gtk.gtk_image_new_from_file(uncheckedFile);
|
checkedImage = Gtk.gtk_image_new_from_file(uncheckedFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk.gtk_image_menu_item_set_image(_native, checkedImage);
|
Gtk.gtk_image_menu_item_set_image(_native, checkedImage);
|
||||||
|
|
||||||
// must always re-set always-show after setting the image
|
// must always re-set always-show after setting the image
|
||||||
|
|
Loading…
Reference in New Issue
Block a user