ui/gtk/menu.c

changeset 88
e27526429d85
parent 46
31bc86844659
child 95
e92c72705da4
--- a/ui/gtk/menu.c	Sun Nov 17 15:19:32 2024 +0100
+++ b/ui/gtk/menu.c	Tue Nov 26 10:40:45 2024 +0100
@@ -355,34 +355,28 @@
  * widget menu functions
  */
 
+UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget) {
+    GtkWidget *menu_widget = gtk_menu_new();
+    ui_add_menu_items(menu_widget, 0, builder->menus_begin, obj);
+    return GTK_MENU(menu_widget);
+}
+
 static gboolean ui_button_press_event(GtkWidget *widget, GdkEvent *event, GtkMenu *menu) {
     if(event->type == GDK_BUTTON_PRESS) {
         GdkEventButton *e = (GdkEventButton*)event;
         if(e->button == 3) {
             gtk_widget_show_all(GTK_WIDGET(menu));
-            ui_contextmenu_popup(menu);
-            return TRUE;
+            ui_contextmenu_popup(menu, widget, 0, 0);
         }
     }
     return FALSE;
 }
 
-UIMENU ui_contextmenu(UiObject *obj) {
-    UiContainer *ct = uic_get_current_container(obj);
-    return ui_contextmenu_w(obj, ct->current);
+void ui_widget_set_contextmenu(GtkWidget *widget, GtkMenu *menu) {
+    g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu);
 }
 
-UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) {
-    UiContainer *ct = uic_get_current_container(obj);
-    
-    GtkMenu *menu = GTK_MENU(gtk_menu_new());
-    g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu);
-    
-    ct->menu = menu;
-    return menu;
-}
-
-void ui_contextmenu_popup(UIMENU menu) {
+void ui_contextmenu_popup(UIMENU menu, GtkWidget *widget, int x, int y) {
 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16
     gtk_menu_popup_at_pointer(menu, NULL);
 #else
@@ -390,116 +384,6 @@
 #endif
 }
 
-void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) {
-    ui_widget_menuitem_gr(obj, label, f, userdata, -1);
-}
-
-void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
-    }
-    
-    // add groups
-    CxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        if(!groups) {
-            groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
-        }
-        cxListAdd(groups, &group);
-    }
-    va_end(ap);
-    
-    // create menuitem
-    GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label);
-    gtk_widget_show(widget);
-    
-    if(f) {
-        UiEventData *event = malloc(sizeof(UiEventData));
-        event->obj = obj;
-        event->userdata = userdata;
-        event->callback = f;
-        event->value = 0;
-        event->customdata = NULL;
-
-        g_signal_connect(
-                widget,
-                "activate",
-                G_CALLBACK(ui_menu_event_wrapper),
-                event);
-        g_signal_connect(
-                widget,
-                "destroy",
-                G_CALLBACK(ui_destroy_userdata),
-                event);
-    }
-    
-    gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
-    
-    if(groups) {
-        uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
-        cxListDestroy(groups);
-    }
-}
-
-void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) {
-    ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1);
-}
-
-void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
-    }
-    
-    // add groups
-    CxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        if(!groups) {
-            groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
-        }
-        cxListAdd(groups, &group);
-    }
-    va_end(ap);
-    
-    // create menuitem
-    GtkWidget *widget = gtk_image_menu_item_new_from_stock(stockid, obj->ctx->accel_group);
-    gtk_widget_show(widget);
-    
-    if(f) {
-        UiEventData *event = malloc(sizeof(UiEventData));
-        event->obj = obj;
-        event->userdata = userdata;
-        event->callback = f;
-        event->value = 0;
-        event->customdata = NULL;
-
-        g_signal_connect(
-                widget,
-                "activate",
-                G_CALLBACK(ui_menu_event_wrapper),
-                event);
-        g_signal_connect(
-                widget,
-                "destroy",
-                G_CALLBACK(ui_destroy_userdata),
-                event);
-    }
-    
-    gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
-    
-    if(groups) {
-        uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
-        cxListDestroy(groups);
-    }
-}
-
 #endif /* GTK_MAJOR_VERSION <= 3 */
 
 
@@ -548,12 +432,23 @@
     g_menu_append_submenu(parent, mi->label, G_MENU_MODEL(menu));
 }
 
+static void action_enable(GSimpleAction *action, int enabled) {
+    g_simple_action_set_enabled(action, enabled);
+}
+
 void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
     UiMenuItem *i = (UiMenuItem*)item;
-
+     
     GSimpleAction *action = g_simple_action_new(item->id, NULL);
     g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
     
+    if(i->groups) {
+        CxList *groups = cxArrayListCreateSimple(sizeof(int), i->ngroups);
+        cxListAddArray(groups, i->groups, i->ngroups);
+        uic_add_group_widget(obj->ctx, action, (ui_enablefunc)action_enable, groups);
+        cxListDestroy(groups);
+    }
+    
     if(i->callback != NULL) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
@@ -702,4 +597,43 @@
     list->oldcount = i;
 }
 
+
+/* --------------------- context menu / menubuilder --------------------- */
+
+static void remove_popover(GtkWidget *object, GtkPopoverMenu *menu) {
+    gtk_widget_unparent(GTK_WIDGET(menu));
+}
+
+UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, GtkWidget *widget) {
+    GMenu *menu = g_menu_new();
+    ui_gmenu_add_menu_items(menu, 0, builder->menus_begin, obj);
+    GtkWidget *contextmenu = gtk_popover_menu_new_from_model(G_MENU_MODEL(menu));
+    gtk_popover_set_has_arrow(GTK_POPOVER(contextmenu), FALSE);
+    gtk_widget_set_halign(contextmenu, GTK_ALIGN_START);
+    gtk_widget_set_parent(GTK_WIDGET(contextmenu), widget);
+    g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(remove_popover),
+                contextmenu);
+    return GTK_POPOVER_MENU(contextmenu);
+}
+
+static void gesture_button_press(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data) {
+    gtk_popover_set_pointing_to(GTK_POPOVER(user_data), &(GdkRectangle){ x, y, 0, 0 });
+    gtk_popover_popup(GTK_POPOVER(user_data));
+}
+
+void ui_widget_set_contextmenu(GtkWidget *widget, GtkPopoverMenu *menu) {
+    GtkGesture *gesture = gtk_gesture_click_new();
+    gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 3);
+    gtk_widget_add_controller(widget, GTK_EVENT_CONTROLLER(gesture));
+    g_signal_connect(gesture, "pressed", G_CALLBACK(gesture_button_press), menu);
+}
+
+void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y) {
+    gtk_popover_set_pointing_to(GTK_POPOVER(menu), &(GdkRectangle){ x, y, 0, 0 });
+    gtk_popover_popup(GTK_POPOVER(menu));
+}
+
 #endif

mercurial