diff options
author | Paul D'Pong | 2021-05-13 20:18:19 +0000 |
---|---|---|
committer | Alexander Kurtakov | 2021-07-15 13:09:01 +0000 |
commit | 1cdf6ba2a7deeb6c460b72fff42f89b6259ef714 (patch) | |
tree | 656a810a1cca2b04ddc63ca0e44549021deebcb5 | |
parent | c3467d0e91d24b386f87e3ec0802d3fb02fdd9e7 (diff) | |
download | eclipse.platform.swt-1cdf6ba2a7deeb6c460b72fff42f89b6259ef714.tar.gz eclipse.platform.swt-1cdf6ba2a7deeb6c460b72fff42f89b6259ef714.tar.xz eclipse.platform.swt-1cdf6ba2a7deeb6c460b72fff42f89b6259ef714.zip |
Bug 567258 - [GTK4] Convert Menus, GtkMenuBar, MenuItems to
GtkPopoverMenuBar - GTK4 dynamic addition fixes
- Added Section class in order to keep track of menu separators in GTK4
- Fix previous GTK4 port by taking into account indexed insertion for
both items & separators
- Added SWT.CHECK menu item
- Proper GTK4 deletion, taking account separators
- One prominent problem is the SHOW and HIDE signals which doesn't exist
with the model system
Change-Id: I0130c7aab32c1998d7c204b73a23b97856004a31
Signed-off-by: Paul D'Pong <sdamrong@redhat.com>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/182420
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Alexander Kurtakov <akurtako@redhat.com>
9 files changed, 252 insertions, 126 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c index 26172e7bd5..d2275c0553 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c @@ -11359,6 +11359,20 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1action_1map_1add_1action) } #endif +#ifndef NO_g_1action_1map_1remove_1action +JNIEXPORT void JNICALL OS_NATIVE(g_1action_1map_1remove_1action) + (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + OS_NATIVE_ENTER(env, that, g_1action_1map_1remove_1action_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; + g_action_map_remove_action((GActionMap *)arg0, (const gchar *)lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + OS_NATIVE_EXIT(env, that, g_1action_1map_1remove_1action_FUNC); +} +#endif + #ifndef NO_g_1app_1info_1create_1from_1commandline JNIEXPORT jlong JNICALL OS_NATIVE(g_1app_1info_1create_1from_1commandline) (JNIEnv *env, jclass that, jbyteArray arg0, jbyteArray arg1, jlong arg2, jlong arg3) @@ -12725,18 +12739,6 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1menu_1item_1set_1submenu) } #endif -#ifndef NO_g_1menu_1model_1get_1n_1items -JNIEXPORT jint JNICALL OS_NATIVE(g_1menu_1model_1get_1n_1items) - (JNIEnv *env, jclass that, jlong arg0) -{ - jint rc = 0; - OS_NATIVE_ENTER(env, that, g_1menu_1model_1get_1n_1items_FUNC); - rc = (jint)g_menu_model_get_n_items((GMenuModel *)arg0); - OS_NATIVE_EXIT(env, that, g_1menu_1model_1get_1n_1items_FUNC); - return rc; -} -#endif - #ifndef NO_g_1menu_1new JNIEXPORT jlong JNICALL OS_NATIVE(g_1menu_1new) (JNIEnv *env, jclass that) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c index 949de4d580..29cba343cf 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c @@ -965,6 +965,7 @@ char * OS_nativeFunctionNames[] = { "g_1action_1get_1enabled", "g_1action_1get_1state", "g_1action_1map_1add_1action", + "g_1action_1map_1remove_1action", "g_1app_1info_1create_1from_1commandline", "g_1app_1info_1get_1all", "g_1app_1info_1get_1default_1for_1type", @@ -1062,7 +1063,6 @@ char * OS_nativeFunctionNames[] = { "g_1menu_1item_1set_1attribute", "g_1menu_1item_1set_1label", "g_1menu_1item_1set_1submenu", - "g_1menu_1model_1get_1n_1items", "g_1menu_1new", "g_1menu_1remove", "g_1object_1get__J_3B_3IJ", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h index 1870a76e40..bc6c632dce 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h @@ -939,6 +939,7 @@ typedef enum { g_1action_1get_1enabled_FUNC, g_1action_1get_1state_FUNC, g_1action_1map_1add_1action_FUNC, + g_1action_1map_1remove_1action_FUNC, g_1app_1info_1create_1from_1commandline_FUNC, g_1app_1info_1get_1all_FUNC, g_1app_1info_1get_1default_1for_1type_FUNC, @@ -1036,7 +1037,6 @@ typedef enum { g_1menu_1item_1set_1attribute_FUNC, g_1menu_1item_1set_1label_FUNC, g_1menu_1item_1set_1submenu_FUNC, - g_1menu_1model_1get_1n_1items_FUNC, g_1menu_1new_FUNC, g_1menu_1remove_FUNC, g_1object_1get__J_3B_3IJ_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java index c83814ea62..9444eb4b1a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java @@ -87,7 +87,8 @@ public class GTK extends OS { public static final int GTK_PHASE_CAPTURE = 1; public static final int GTK_PHASE_BUBBLE = 2; public static final int GTK_PHASE_TARGET = 3; - public static final int GTK_POPOVER_MENU_NESTED = 1; + public static final int GTK_PROGRESS_LEFT_TO_RIGHT = 0x0; + public static final int GTK_PROGRESS_BOTTOM_TO_TOP = 0x2; public static final int GTK_RESPONSE_CANCEL = 0xfffffffa; public static final int GTK_RESPONSE_OK = 0xfffffffb; public static final int GTK_RESPONSE_ACCEPT = -3; diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java index 436ddd60cc..4b905b498c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java @@ -2385,14 +2385,10 @@ public static final native void g_menu_item_set_label(long menu_item, byte[] lab */ public static final native void g_menu_item_set_attribute(long menu_item, byte[] attribute, byte[] format_string, long data); - -/* GMenuModel */ -/** @param model cast=(GMenuModel *) */ -public static final native int g_menu_model_get_n_items(long model); - - -/* GAction */ +/* GSimpleActionGroup */ public static final native long g_simple_action_group_new(); + +/* GSimpleAction */ /** * @param name cast=(const gchar *) * @param parameter_type cast=(const GVariantType *) @@ -2405,22 +2401,30 @@ public static final native long g_simple_action_new(byte[] name, long parameter_ */ public static final native long g_simple_action_new_stateful(byte[] name, long parameter_type, long initial_state); /** - * @param action_map cast=(GActionMap *) - * @param action cast=(GAction *) + * @param simple_action cast=(GSimpleAction *) + * @param value cast=(GVariant *) */ -public static final native void g_action_map_add_action(long action_map, long action); -/** @param action cast=(GAction *) */ -public static final native boolean g_action_get_enabled(long action); +public static final native void g_simple_action_set_state(long simple_action, long value); /** @param simple_action cast=(GSimpleAction *) */ public static final native void g_simple_action_set_enabled(long simple_action, boolean enabled); + +/* GAction */ +/** @param action cast=(GAction *) */ +public static final native boolean g_action_get_enabled(long action); /** @param action cast=(GAction *) */ public static final native long g_action_get_state(long action); + +/* GActionMap */ /** - * @param simple_action cast=(GSimpleAction *) - * @param value cast=(GVariant *) + * @param action_map cast=(GActionMap *) + * @param action cast=(GAction *) */ -public static final native void g_simple_action_set_state(long simple_action, long value); - +public static final native void g_action_map_add_action(long action_map, long action); +/** + * @param action_map cast=(GActionMap *) + * @param action_name cast=(const gchar *) + */ +public static final native void g_action_map_remove_action(long action_map, byte[] action_name); /* GListModel */ /** @param list cast=(GListModel *) */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java index eceff5cdf3..fcfe80a81c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java @@ -17,6 +17,9 @@ package org.eclipse.swt.internal.gtk4; * This class contains native functions that are present in GTK4 only. */ public class GTK4 { + + public static final int GTK_POPOVER_MENU_NESTED = 1 << 0; + /** * @param context cast=(GtkIMContext *) * @param event cast=(GdkEvent *) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java index fe5e7e92c8..db560c04e5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java @@ -5792,8 +5792,11 @@ public boolean setParent (Composite parent) { Menu [] menus = oldShell.findMenus (this); if (oldShell != newShell || oldDecorations != newDecorations) { fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus); - newDecorations.fixAccelGroup (); - oldDecorations.fixAccelGroup (); + + if (!GTK.GTK4) { + newDecorations.fixAccelGroup (); + oldDecorations.fixAccelGroup (); + } } long newParent = parent.parentingHandle(); gtk_widget_reparent(this, newParent); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java index 89430d5420..b072f5e3d5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java @@ -54,8 +54,47 @@ public class Menu extends Widget { int poppedUpCount; /** GTK4 only fields */ - long modelHandle, actionGroup, shortcutController, sectionModelHandle; - ArrayList<MenuItem> items; + long modelHandle, actionGroup, shortcutController; + + class Section { + LinkedList<MenuItem> sectionItems; + private MenuItem separator; + private long sectionHandle; + + public Section() { + this.sectionItems = new LinkedList<>(); + } + + public Section(MenuItem separator) { + this(); + this.separator = separator; + } + + public Section(long sectionHandle) { + this(); + + this.sectionHandle = sectionHandle; + } + + public long getSectionHandle() { + return sectionHandle != 0 ? sectionHandle : separator.modelHandle; + } + + public int getItemPosition(MenuItem item) { + return sectionItems.indexOf(item); + } + + public int getSectionSize() { + return sectionItems.size(); + } + + public int getSectionPosition() { + return items.indexOf(separator); + } + } + + LinkedList<Section> sections; + LinkedList<MenuItem> items; /** * Constructs a new instance of this class given its parent, @@ -451,7 +490,8 @@ void createHandle (int index) { modelHandle = OS.g_menu_new(); if (modelHandle == 0) error(SWT.ERROR_NO_HANDLES); - items = new ArrayList<>(); + items = new LinkedList<>(); + sections = new LinkedList<>(); switch (style & bits) { case SWT.BAR: @@ -465,7 +505,7 @@ void createHandle (int index) { break; case SWT.POP_UP: default: - handle = GTK4.gtk_popover_menu_new_from_model_full(modelHandle, GTK.GTK_POPOVER_MENU_NESTED); + handle = GTK4.gtk_popover_menu_new_from_model_full(modelHandle, GTK4.GTK_POPOVER_MENU_NESTED); GTK.gtk_widget_set_parent(handle, parent.handle); GTK.gtk_popover_set_position(handle, GTK.GTK_POS_BOTTOM); GTK4.gtk_popover_set_has_arrow(handle, false); @@ -473,20 +513,20 @@ void createHandle (int index) { if (handle == 0) error(SWT.ERROR_NO_HANDLES); } - sectionModelHandle = OS.g_menu_new(); - if (sectionModelHandle == 0) error(SWT.ERROR_NO_HANDLES); + // Create first section + long firstSection = OS.g_menu_new(); + if (firstSection == 0) error(SWT.ERROR_NO_HANDLES); + sections.add(new Section(firstSection)); - long defaultSection = OS.g_menu_item_new_section(null, sectionModelHandle); - OS.g_menu_insert_item(modelHandle, index, defaultSection); + long defaultSection = OS.g_menu_item_new_section(null, firstSection); + OS.g_menu_insert_item(modelHandle, 0, defaultSection); OS.g_object_unref(defaultSection); - if ((style & SWT.DROP_DOWN) == 0) { - actionGroup = OS.g_simple_action_group_new(); - if (actionGroup == 0) error(SWT.ERROR_NO_HANDLES); + actionGroup = OS.g_simple_action_group_new(); + if (actionGroup == 0) error(SWT.ERROR_NO_HANDLES); - long shellHandle = parent.getShell().topHandle(); - GTK.gtk_widget_insert_action_group(shellHandle, Converter.javaStringToCString(String.valueOf(this.hashCode())), actionGroup); - } + long shellHandle = parent.getShell().topHandle(); + GTK.gtk_widget_insert_action_group(shellHandle, Converter.javaStringToCString(String.valueOf(this.hashCode())), actionGroup); } else { if ((style & SWT.BAR) != 0) { handle = GTK3.gtk_menu_bar_new(); @@ -623,7 +663,7 @@ public int getItemCount () { checkWidget(); if (GTK.GTK4) { - return OS.g_menu_model_get_n_items(sectionModelHandle); + return items.size(); } else { int count = 0; long list = GTK3.gtk_container_get_children (handle); @@ -896,6 +936,12 @@ void hookEvents() { if (shortcutController == 0) error(SWT.ERROR_NO_HANDLES); GTK4.gtk_shortcut_controller_set_scope(shortcutController, GTK.GTK_SHORTCUT_SCOPE_GLOBAL); GTK4.gtk_widget_add_controller(parent.handle, shortcutController); + + if ((style & SWT.DROP_DOWN) == 0) { + OS.g_signal_connect_closure_by_id(handle, display.signalIds[SHOW], 0, display.getClosure(SHOW), false); + OS.g_signal_connect_closure_by_id(handle, display.signalIds[HIDE], 0, display.getClosure(HIDE), false); + } + } else { OS.g_signal_connect_closure_by_id(handle, display.signalIds[SHOW_HELP], 0, display.getClosure(SHOW_HELP), false); @@ -903,10 +949,10 @@ void hookEvents() { if (GTK.GTK_VERSION >= OS.VERSION(3, 22, 0) && OS.SWT_MENU_LOCATION_DEBUGGING) { OS.g_signal_connect_closure_by_id(handle, display.signalIds[POPPED_UP], 0, display.getClosure(POPPED_UP), false); } - } - OS.g_signal_connect_closure_by_id(handle, display.signalIds[SHOW], 0, display.getClosure(SHOW), false); - OS.g_signal_connect_closure_by_id(handle, display.signalIds[HIDE], 0, display.getClosure(HIDE), false); + OS.g_signal_connect_closure_by_id(handle, display.signalIds[SHOW], 0, display.getClosure(SHOW), false); + OS.g_signal_connect_closure_by_id(handle, display.signalIds[HIDE], 0, display.getClosure(HIDE), false); + } } /** diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java index ede812b657..14dcc50e6b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java @@ -21,6 +21,7 @@ import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.gtk3.*; import org.eclipse.swt.internal.gtk4.*; +import org.eclipse.swt.widgets.Menu.*; /** * Instances of this class represent a selectable user interface object @@ -63,7 +64,7 @@ public class MenuItem extends Item { /** GTK4 only fields */ long modelHandle, actionHandle, shortcutHandle; - int parentMenuPosition; + Section section; String actionName; /** @@ -261,61 +262,90 @@ protected void checkSubclass () { } @Override -void createHandle (int index) { +void createHandle(int index) { state |= HANDLE; - byte [] buffer = new byte [1]; int bits = SWT.CHECK | SWT.RADIO | SWT.PUSH | SWT.SEPARATOR | SWT.CASCADE; if (GTK.GTK4) { - modelHandle = OS.g_menu_new(); - switch (style & bits) { case SWT.SEPARATOR: + modelHandle = OS.g_menu_new(); handle = OS.g_menu_item_new_section(null, modelHandle); - parent.sectionModelHandle = modelHandle; break; case SWT.RADIO: - Menu popoverMenuWidget = parent; - while (popoverMenuWidget.actionGroup == 0) { - popoverMenuWidget = popoverMenuWidget.cascade.parent; - } - long stringVariantType = OS.g_variant_type_new(OS.G_VARIANT_TYPE_STRING); actionHandle = OS.g_simple_action_new_stateful( - Converter.javaStringToCString(String.valueOf(this.hashCode())), - stringVariantType, - OS.g_variant_new_string(Converter.javaStringToCString("untoggled"))); - OS.g_action_map_add_action(popoverMenuWidget.actionGroup, actionHandle); - actionName = String.valueOf(popoverMenuWidget.hashCode()) + "." + String.valueOf(this.hashCode()) + "::toggled"; + Converter.javaStringToCString(String.valueOf(this.hashCode())), + stringVariantType, + OS.g_variant_new_string(Converter.javaStringToCString("untoggled"))); + OS.g_action_map_add_action(parent.actionGroup, actionHandle); + actionName = String.valueOf(parent.hashCode()) + "." + String.valueOf(this.hashCode()) + "::toggled"; handle = OS.g_menu_item_new(null, Converter.javaStringToCString(actionName)); OS.g_variant_type_free(stringVariantType); break; + case SWT.CHECK: + long boolVariantType = OS.g_variant_type_new(OS.G_VARIANT_TYPE_BOOLEAN); + actionHandle = OS.g_simple_action_new_stateful( + Converter.javaStringToCString(String.valueOf(this.hashCode())), + 0, + OS.g_variant_new_boolean(false)); + OS.g_action_map_add_action(parent.actionGroup, actionHandle); + actionName = String.valueOf(parent.hashCode()) + "." + String.valueOf(this.hashCode()); + handle = OS.g_menu_item_new(null, Converter.javaStringToCString(actionName)); + OS.g_variant_type_free(boolVariantType); + break; case SWT.CASCADE: - handle = OS.g_menu_item_new_submenu(null, modelHandle); + modelHandle = OS.g_menu_new(); + handle = OS.g_menu_item_new_submenu(Converter.javaStringToCString(""), modelHandle); break; case SWT.PUSH: default: - popoverMenuWidget = parent; - while (popoverMenuWidget.actionGroup == 0) { - popoverMenuWidget = popoverMenuWidget.cascade.parent; - } - actionHandle = OS.g_simple_action_new(Converter.javaStringToCString(String.valueOf(this.hashCode())), 0); - OS.g_action_map_add_action(popoverMenuWidget.actionGroup, actionHandle); - actionName = String.valueOf(popoverMenuWidget.hashCode()) + "." + String.valueOf(this.hashCode()); + OS.g_action_map_add_action(parent.actionGroup, actionHandle); + actionName = String.valueOf(parent.hashCode()) + "." + String.valueOf(this.hashCode()); handle = OS.g_menu_item_new(null, Converter.javaStringToCString(actionName)); break; } + + Section selectedSection = parent.sections.getLast(); + for (Section section : parent.sections) { + int sectionPosition = section.getSectionPosition(); + int sectionLength = section.getSectionSize(); + + if (index > sectionPosition && index <= sectionPosition + sectionLength + 1) { + selectedSection = section; + break; + } + } + + int sectionRelativeIndex = index - (selectedSection.getSectionPosition() + 1); if ((style & SWT.SEPARATOR) != 0) { - OS.g_menu_insert_item(parent.modelHandle, index, handle); + section = parent.new Section(this); + + int itemsToMove = selectedSection.sectionItems.size() - sectionRelativeIndex; + for (int i = 0; i < itemsToMove; i++) { + MenuItem removedItem = selectedSection.sectionItems.remove(sectionRelativeIndex); + section.sectionItems.add(removedItem); + + OS.g_menu_remove(selectedSection.getSectionHandle(), sectionRelativeIndex); + OS.g_menu_insert_item(modelHandle, section.sectionItems.indexOf(removedItem), removedItem.handle); + removedItem.section = section; + } + + int sectionInsertIndex = parent.sections.indexOf(selectedSection) + 1; + parent.sections.add(sectionInsertIndex, section); + OS.g_menu_insert_item(parent.modelHandle, sectionInsertIndex, handle); } else { - OS.g_menu_insert_item(parent.sectionModelHandle, index, handle); + section = selectedSection; + selectedSection.sectionItems.add(sectionRelativeIndex, this); + OS.g_menu_insert_item(selectedSection.getSectionHandle(), sectionRelativeIndex, handle); } - parentMenuPosition = index; - parent.items.add(this); + parent.items.add(index, this); } else { + byte[] buffer = new byte[1]; + switch (style & bits) { case SWT.SEPARATOR: handle = GTK3.gtk_separator_menu_item_new (); @@ -403,37 +433,35 @@ void createHandle (int index) { } break; } + if (imageHandle != 0) { if (OS.SWT_PADDED_MENU_ITEMS) { GTK.gtk_image_set_pixel_size (imageHandle, 16); } - if (GTK.GTK4) { - GTK4.gtk_box_append(boxHandle, imageHandle); - } else { - GTK3.gtk_container_add (boxHandle, imageHandle); - GTK.gtk_widget_show (imageHandle); - } + + GTK3.gtk_container_add (boxHandle, imageHandle); + GTK.gtk_widget_show (imageHandle); } + if (labelHandle != 0) { GTK.gtk_label_set_xalign (labelHandle, 0); GTK.gtk_widget_set_halign (labelHandle, GTK.GTK_ALIGN_FILL); gtk_box_pack_end (boxHandle, labelHandle, true, true, 0); GTK.gtk_widget_show (labelHandle); } + if (boxHandle != 0) { - if (GTK.GTK4) { - // TODO: need to implement how menu items will be populated, currently no value for handle - } else { - GTK3.gtk_container_add (handle, boxHandle); - GTK.gtk_widget_show (boxHandle); - } + GTK3.gtk_container_add (handle, boxHandle); + GTK.gtk_widget_show (boxHandle); } + if ((style & SWT.SEPARATOR) == 0) { if (boxHandle == 0) { labelHandle = GTK3.gtk_bin_get_child (handle); } GTK3.gtk_accel_label_set_accel_widget (labelHandle, 0); } + long parentHandle = parent.handle; boolean enabled = GTK.gtk_widget_get_sensitive (parentHandle); if (!enabled) GTK.gtk_widget_set_sensitive (parentHandle, true); @@ -477,20 +505,6 @@ long getAccelGroup () { return shell.menuBar == menu ? shell.accelGroup : 0; } -/*public*/ Rectangle getBounds () { - checkWidget(); - if (!GTK.gtk_widget_get_mapped (handle)) { - return new Rectangle (0, 0, 0, 0); - } - GtkAllocation allocation = new GtkAllocation (); - GTK.gtk_widget_get_allocation (handle, allocation); - int x = allocation.x; - int y = allocation.y; - int width = allocation.width; - int height = allocation.height; - return new Rectangle (x, y, width, height); -} - /** * Returns <code>true</code> if the receiver is enabled, and * <code>false</code> otherwise. A disabled menu item is typically @@ -510,6 +524,10 @@ public boolean getEnabled () { checkWidget(); if (GTK.GTK4) { + if ((style & SWT.CASCADE) != 0) { + return true; + } + return OS.g_action_get_enabled(actionHandle); } else { return GTK.gtk_widget_get_sensitive(handle); @@ -593,8 +611,12 @@ public boolean getSelection () { if (GTK.GTK4) { long gVariantState = OS.g_action_get_state(actionHandle); - String stateString = Converter.cCharPtrToJavaString(OS.g_variant_get_string(gVariantState, null), false); - return stateString.equals("toggled"); + if ((style & SWT.CHECK) != 0) { + return OS.g_variant_get_boolean(gVariantState); + } else { + String stateString = Converter.cCharPtrToJavaString(OS.g_variant_get_string(gVariantState, null), false); + return stateString.equals("toggled"); + } } else { return GTK3.gtk_check_menu_item_get_active(handle); } @@ -669,8 +691,7 @@ void hookEvents() { super.hookEvents(); if (GTK.GTK4) { - // Bind activate signal only for menu items with actions (SWT.CHECK and SWT.RADIO) - if (actionHandle != 0) { + if ((style & SWT.PUSH) != 0 || (style & SWT.RADIO) != 0) { OS.g_signal_connect(actionHandle, OS.activate, display.activateProc, handle); } } else { @@ -709,24 +730,64 @@ void releaseChildren (boolean destroy) { } @Override -void releaseParent () { - super.releaseParent (); +void releaseParent() { + super.releaseParent(); + if (menu != null) { if (menu.selectedItem == this) menu.selectedItem = null; - menu.dispose (); + menu.dispose(); + + menu = null; } - menu = null; } @Override -void releaseWidget () { - super.releaseWidget (); - long accelGroup = getAccelGroup (); - if (accelGroup != 0) removeAccelerator (accelGroup); - if (groupHandle != 0) OS.g_object_unref (groupHandle); - groupHandle = 0; +void releaseWidget() { + super.releaseWidget(); + + if (GTK.GTK4) { + if (parent.actionGroup != 0 && actionName != null) OS.g_action_map_remove_action(parent.actionGroup, Converter.javaStringToCString(actionName)); + } else { + long accelGroup = getAccelGroup(); + if (accelGroup != 0) removeAccelerator(accelGroup); + + if (groupHandle != 0) OS.g_object_unref(groupHandle); + groupHandle = 0; + parent = null; + } + accelerator = 0; - parent = null; +} + +@Override +void destroyWidget() { + if (GTK.GTK4) { + if ((style & SWT.SEPARATOR) != 0) { + Section aboveSection = parent.sections.get(parent.sections.indexOf(section) - 1); + aboveSection.sectionItems.addAll(section.sectionItems); + + for (MenuItem item : section.sectionItems) { + OS.g_menu_insert_item(aboveSection.getSectionHandle(), aboveSection.sectionItems.indexOf(item), item.handle); + } + + OS.g_menu_remove(parent.modelHandle, parent.sections.indexOf(section)); + + parent.sections.remove(section); + } else { + OS.g_menu_remove(section.getSectionHandle(), section.sectionItems.indexOf(this)); + section.sectionItems.remove(this); + } + + parent.items.remove(this); + parent = null; + + if (modelHandle != 0) OS.g_object_unref(modelHandle); + OS.g_object_unref(handle); + + releaseHandle(); + } else { + super.destroyWidget(); + } } void removeAccelerator (long accelGroup) { @@ -908,7 +969,7 @@ public void setEnabled (boolean enabled) { checkWidget(); if (GTK.GTK4) { - OS.g_simple_action_set_enabled(actionHandle, enabled); + if (actionHandle != 0) OS.g_simple_action_set_enabled(actionHandle, enabled); } else { if (GTK.gtk_widget_get_sensitive(handle) == enabled) return; long accelGroup = getAccelGroup(); @@ -1065,8 +1126,8 @@ public void setMenu (Menu menu) { OS.g_menu_item_set_submenu(handle, 0); } - OS.g_menu_remove(parent.sectionModelHandle, parentMenuPosition); - OS.g_menu_insert_item(parent.sectionModelHandle, parentMenuPosition, handle); + OS.g_menu_remove(section.getSectionHandle(), section.getItemPosition(this)); + OS.g_menu_insert_item(section.getSectionHandle(), section.getItemPosition(this), handle); } else { long accelGroup = getAccelGroup (); if (accelGroup != 0) removeAccelerators (accelGroup); @@ -1125,7 +1186,11 @@ public void setSelection (boolean selected) { if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return; if (GTK.GTK4) { - OS.g_simple_action_set_state(actionHandle, OS.g_variant_new_string(Converter.javaStringToCString(selected ? "toggled" : "untoggled"))); + if ((style & SWT.CHECK) != 0) { + OS.g_simple_action_set_state(actionHandle, OS.g_variant_new_boolean(selected)); + } else { + OS.g_simple_action_set_state(actionHandle, OS.g_variant_new_string(Converter.javaStringToCString(selected ? "toggled" : "untoggled"))); + } } else { OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, ACTIVATE); GTK3.gtk_check_menu_item_set_active (handle, selected); @@ -1196,8 +1261,8 @@ public void setText (String string) { GTK.gtk_accelerator_name(maskKeysym.keysym, maskKeysym.mask) ); } - OS.g_menu_remove(parent.sectionModelHandle, parentMenuPosition); - OS.g_menu_insert_item(parent.sectionModelHandle, parentMenuPosition, handle); + OS.g_menu_remove(section.getSectionHandle(), section.getItemPosition(this)); + OS.g_menu_insert_item(section.getSectionHandle(), section.getItemPosition(this), handle); } else { if (labelHandle != 0 && GTK.GTK_IS_LABEL (labelHandle)) { GTK.gtk_label_set_text_with_mnemonic (labelHandle, buffer); @@ -1247,6 +1312,8 @@ public void setText (String string) { */ public void setToolTipText(String toolTip) { checkWidget(); + if (GTK.GTK4) return; // GTK4 does not support tooltips within menus + if (toolTip != null && (toolTip.trim().length() == 0 || toolTip.equals(toolTipText))) return; toolTipText = toolTip; |