implement list/table contextmenu (GTK) newapi

Thu, 21 Nov 2024 18:45:47 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 21 Nov 2024 18:45:47 +0100
branch
newapi
changeset 390
b130f80ec7f9
parent 389
d15eca5fd8b3
child 391
fc0df448dfbc

implement list/table contextmenu (GTK)

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/image.c file | annotate | diff | comparison | revisions
ui/gtk/list.c file | annotate | diff | comparison | revisions
ui/gtk/menu.c file | annotate | diff | comparison | revisions
ui/ui/menu.h file | annotate | diff | comparison | revisions
ui/ui/tree.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Thu Nov 21 13:17:56 2024 +0100
+++ b/application/main.c	Thu Nov 21 18:45:47 2024 +0100
@@ -40,6 +40,7 @@
     UiText *text;
     UiDouble *progress;
     UiList *list;
+    UiList *list2;
     UiList *menulist;
     UiInteger *radio;
     UiInteger *tabview;
@@ -152,6 +153,10 @@
     ui_list_append(doc->list, "test1");
     ui_list_append(doc->list, "test2");
     ui_list_append(doc->list, "test3");
+    doc->list2 = ui_list_new(docctx, "list2");
+    ui_list_append(doc->list2, "test1");
+    ui_list_append(doc->list2, "test2");
+    ui_list_append(doc->list2, "test3");
     doc->radio = ui_int_new(docctx, "radio");
     doc->tabview = ui_int_new(docctx, "tabview");
     doc->image = ui_generic_new(docctx, "image");
@@ -241,6 +246,10 @@
 
 UiMenuBuilder *menubuilder;
 
+void* table_getvalue(void *row, int col) {
+    return row;
+}
+
 void application_startup(UiEvent *event, void *data) {
     // global list
     UiContext *global = ui_global_context();
@@ -303,6 +312,11 @@
                     ui_radiobutton(obj, .label = "Radio 2", .varname = "radio");
                     ui_radiobutton(obj, .label = "Radio 3", .varname = "radio");
                 }
+                ui_newline(obj);
+                
+                UiModel *model = ui_model(obj->ctx, UI_STRING, "col1", -1);
+                model->getvalue = table_getvalue;
+                ui_table(obj, .model = model, .list = doc->list2, .colspan = 2, .hexpand = TRUE, .contextmenu = menubuilder);
             }
         }
         ui_tab(obj, "Tab 2") {
--- a/ui/gtk/image.c	Thu Nov 21 13:17:56 2024 +0100
+++ b/ui/gtk/image.c	Thu Nov 21 18:45:47 2024 +0100
@@ -73,7 +73,7 @@
     }
     
     if(args.contextmenu) {
-        UIMENU menu = ui_create_menu(args.contextmenu, obj);
+        UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, eventbox);
         ui_widget_set_contextmenu(eventbox, menu);
     }
     
--- a/ui/gtk/list.c	Thu Nov 21 13:17:56 2024 +0100
+++ b/ui/gtk/list.c	Thu Nov 21 18:45:47 2024 +0100
@@ -37,6 +37,7 @@
 
 #include "list.h"
 #include "icon.h"
+#include "menu.h"
 
 
 void* ui_strmodel_getvalue(void *elm, int column) {
@@ -235,6 +236,10 @@
                 G_CALLBACK(ui_listview_selection_event),
                 event);
     }
+    if(args.contextmenu) {
+        UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view);
+        ui_widget_set_contextmenu(view, menu);
+    }
     
     
     // add widget to the current container
@@ -396,7 +401,11 @@
                 event);
     }
     // TODO: destroy callback
-
+    
+    if(args.contextmenu) {
+        UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view);
+        ui_widget_set_contextmenu(view, menu);
+    }
     
     GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
     if(args.multiselection) {
--- a/ui/gtk/menu.c	Thu Nov 21 13:17:56 2024 +0100
+++ b/ui/gtk/menu.c	Thu Nov 21 18:45:47 2024 +0100
@@ -75,12 +75,6 @@
     return mb;
 }
 
-GtkMenu* ui_create_menu(UiMenuBuilder *builder, UiObject *obj) {
-    GtkWidget *menu_widget = gtk_menu_new();
-    ui_add_menu_items(menu_widget, 0, builder->menus_begin, obj);
-    return GTK_MENU(menu_widget);
-}
-
 void ui_add_menu_items(GtkWidget *parent, int i, UiMenu *menu, UiObject *obj) {
     UiMenuItemI *it = menu->items_begin;
     int index = 0;
@@ -361,12 +355,18 @@
  * 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);
+            ui_contextmenu_popup(menu, widget, 0, 0);
             return TRUE;
         }
     }
@@ -377,7 +377,7 @@
     g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, 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
@@ -590,35 +590,40 @@
 
 /* --------------------- context menu / menubuilder --------------------- */
 
-GtkPopoverMenu* ui_create_menu(UiMenuBuilder *builder, UiObject *obj) {
+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_set_pointing_to(GTK_POPOVER(user_data), &(GdkRectangle){ x, y, 0, 0 });
     gtk_popover_popup(GTK_POPOVER(user_data));
 }
 
-static void remove_popover(GtkWidget *object, GtkPopoverMenu *menu) {
-    gtk_widget_unparent(GTK_WIDGET(menu));
-}
-
 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);
-    gtk_widget_set_parent(GTK_WIDGET(menu), widget);
-    g_signal_connect(
-                widget,
-                "destroy",
-                G_CALLBACK(remove_popover),
-                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
--- a/ui/ui/menu.h	Thu Nov 21 13:17:56 2024 +0100
+++ b/ui/ui/menu.h	Thu Nov 21 18:45:47 2024 +0100
@@ -97,7 +97,7 @@
 UIEXPORT void ui_contextmenu_builder(UiMenuBuilder **out_builder);
 UIEXPORT void ui_menubuilder_free(UiMenuBuilder *builder);
 UIEXPORT UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget);
-UIEXPORT void ui_contextmenu_popup(UIMENU menu);
+UIEXPORT void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y);
 
 // used for macro
 UIEXPORT void ui_menu_close(void);
--- a/ui/ui/tree.h	Thu Nov 21 13:17:56 2024 +0100
+++ b/ui/ui/tree.h	Thu Nov 21 18:45:47 2024 +0100
@@ -130,6 +130,7 @@
     ui_callback ondrop;
     void* ondropsdata;
     UiBool multiselection;
+    UiMenuBuilder *contextmenu;
     
     const int *groups;
 };

mercurial