implement sourcelist item popup menu (GTK)

Fri, 17 Oct 2025 20:18:29 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 17 Oct 2025 20:18:29 +0200
changeset 856
b769e01035a7
parent 855
37f8a9fa8251
child 857
1d9dd72fec15

implement sourcelist item popup menu (GTK)

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/list.c file | annotate | diff | comparison | revisions
--- a/application/main.c	Fri Oct 17 16:02:56 2025 +0200
+++ b/application/main.c	Fri Oct 17 20:18:29 2025 +0200
@@ -460,6 +460,7 @@
 }
 
 UiMenuBuilder *menubuilder;
+UiMenuBuilder *sourcelist_menu;
 
 void* table_getvalue(void *row, int col) {
     switch(col) {
@@ -501,6 +502,7 @@
 void sourcelist_getvalue(UiList *list, void *sublistdata, void *rowdata, int index, UiSubListItem *item, void *userdata) {
     item->label = strdup(rowdata);
     item->button_icon = strdup("view-more-horizontal");
+    item->button_menu = sourcelist_menu;
     item->eventdata = sublistdata;
 }
 
@@ -832,6 +834,11 @@
         }
     }
     
+    ui_contextmenu(&sourcelist_menu) {
+        ui_menuitem(.label = "Item 1");
+        ui_menuitem(.label = "Item 2");
+    }
+    
     ui_menu("Edit") {
         ui_menuitem(.label = "Undo");
         ui_menuseparator();
--- a/ui/gtk/list.c	Fri Oct 17 16:02:56 2025 +0200
+++ b/ui/gtk/list.c	Fri Oct 17 20:18:29 2025 +0200
@@ -2301,7 +2301,7 @@
     }
 }
 
-static void listbox_button_clicked(GtkWidget *widget, UiEventDataExt *data) {
+static void listbox_button_clicked(GtkWidget *button, UiEventDataExt *data) {
     UiListBoxSubList *sublist = data->customdata0;
     
     UiSubListEventData eventdata;
@@ -2324,8 +2324,24 @@
     if(data->callback2) {
         data->callback2(&event, data->userdata2);
     }
+    
+    if(data->customdata3) {
+        UIMENU menu = data->customdata3;
+        g_object_set_data(G_OBJECT(button), "ui-button-popup", menu);
+        gtk_popover_popup(GTK_POPOVER(menu));
+    }
 }
 
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void button_popover_closed(GtkPopover *popover, GtkWidget *button) {
+    g_object_set_data(G_OBJECT(button), "ui-button-popup", NULL);
+    if(g_object_get_data(G_OBJECT(button), "ui-button-invisible")) {
+        g_object_set_data(G_OBJECT(button), "ui-button-invisible", NULL);
+        gtk_widget_set_visible(button, FALSE);
+    }
+}
+#endif
+
 static void listbox_fill_row(UiListBox *listbox, GtkWidget *row, UiListBoxSubList *sublist, UiSubListItem *item, int index) {
     UiBool is_header = index < 0;
     
@@ -2398,6 +2414,13 @@
         gtk_widget_set_visible(button, FALSE);
         
         g_object_set_data(G_OBJECT(row), "ui-listbox-row-button", button);
+        
+        // menu
+        if(item->button_menu) {
+            UIMENU menu = ui_contextmenu_create(item->button_menu, listbox->obj, button);
+            event->customdata3 = menu;
+            g_signal_connect(menu, "closed", G_CALLBACK(button_popover_closed), button);
+        }
     }
 }
 
@@ -2441,8 +2464,12 @@
 
 static void listbox_row_on_leave(GtkWidget *row) {
     GtkWidget *button = g_object_get_data(G_OBJECT(row), "ui-listbox-row-button");
-    if(button) {
-        gtk_widget_set_visible(button, FALSE);
+    if(button) {  
+        if(!g_object_get_data(G_OBJECT(button), "ui-button-popup")) {
+            gtk_widget_set_visible(button, FALSE);
+        } else {
+            g_object_set_data(G_OBJECT(button), "ui-button-invisible", (void*)1);
+        }
     }
 }
 

mercurial