implement menu radio items (GTK3)

Wed, 31 Dec 2025 12:37:09 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 31 Dec 2025 12:37:09 +0100
changeset 1039
6691e007cef7
parent 1038
832e9288f8e2
child 1040
473d8cb58a6c

implement menu radio items (GTK3)

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/menu.c file | annotate | diff | comparison | revisions
ui/gtk/menu.h file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Wed Dec 31 11:36:42 2025 +0100
+++ b/application/main.c	Wed Dec 31 12:37:09 2025 +0100
@@ -627,6 +627,8 @@
     }
     UiInteger *i = event->eventdata;
     printf("action_menu_toggle value: %d\n", ui_get(i));
+    
+    ui_var_set_int(event->obj->ctx, "menu_radio", 5);
 }
 
 void application_startup(UiEvent *event, void *data) {
--- a/ui/gtk/menu.c	Wed Dec 31 11:36:42 2025 +0100
+++ b/ui/gtk/menu.c	Wed Dec 31 12:37:09 2025 +0100
@@ -181,8 +181,72 @@
             event);
 }
 
+static void ui_menu_event_radio_item_toggled(GtkRadioMenuItem *ri, UiVarEventData *event) {
+    UiInteger *i = event->var->value;
+    
+    UiEvent evt;
+    evt.obj = event->obj;
+    evt.window = event->obj->window;
+    evt.document = event->obj->ctx->document;
+    evt.eventdata = i;
+    evt.eventdatatype = i ? UI_EVENT_DATA_INTEGER_VALUE : 0;
+    evt.intval = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(ri));
+    
+    if(event->callback) {
+        event->callback(&evt, event->userdata);
+    }
+    
+    if(evt.intval) {
+        evt.intval = ui_get(i);
+        ui_notify_evt(i->observers, &evt);
+    }
+}
+
+static void ui_destroy_menu_radio_item(GtkWidget *unused, UiVarEventData *event) {
+    if(event->customint1) {
+        uic_unbind_var(event->var);
+    }
+    free(event);
+}
+
 void add_radioitem_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) {
-    // TODO
+    UiMenuRadioItem *ri = (UiMenuRadioItem*)item;
+    
+    UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, ri->varname, UI_VAR_INTEGER);
+    if(!var) {
+        fprintf(stderr, "Error: menu radioitem varname is null\n");
+        return;
+    }
+    int first = 0;
+    UiInteger *i = var->value;
+    GSList *group = i->obj;
+    GtkWidget *widget = gtk_radio_menu_item_new_with_label(group, ri->label);
+    gtk_menu_shell_append(GTK_MENU_SHELL(p), widget);
+    if(!group) {
+        i->get = ui_radioitem_get;
+        i->set = ui_radioitem_set;
+        first = 1;
+    }
+    i->obj = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(widget));
+    
+    UiVarEventData *event = malloc(sizeof(UiVarEventData));
+    memset(event, 0, sizeof(UiVarEventData));
+    event->obj = obj;
+    event->var = var;
+    event->callback = ri->callback;
+    event->userdata = ri->userdata;
+    event->customint1 = first;
+    
+    g_signal_connect(
+            widget,
+            "toggled",
+            G_CALLBACK(ui_menu_event_radio_item_toggled),
+            event);
+    g_signal_connect(
+            widget,
+            "destroy",
+            G_CALLBACK(ui_destroy_menu_radio_item),
+            event);
 }
 
 static void menuitem_list_remove_binding(void *obj) {
@@ -360,6 +424,47 @@
     gtk_check_menu_item_set_active(i->obj, (gboolean)value);
 }
 
+int64_t ui_radioitem_get(UiInteger *value) {
+    int selection = 0;
+    GSList *ls = value->obj;
+    guint len = g_slist_length(ls);
+    int i = 0;
+    while(ls) {
+        if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(ls->data))) {
+            selection = len - i;
+            break;
+        }
+        ls = ls->next;
+        i++;
+    }
+    
+    value->value = selection;
+    return selection;
+}
+
+void ui_radioitem_set(UiInteger *i, int64_t value) {
+    GSList *ls = i->obj;
+    
+    int len = g_slist_length(ls);
+    if(value > len) {
+        value = len;
+    }
+    int s = len - value;
+    int j = 0;
+    int unset = 1;
+    while(ls) {
+        if(j == s) {
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ls->data), TRUE);
+            unset = 0;
+            break;
+        }
+        ls = ls->next;
+        j++;
+    }
+    
+    i->value = value;
+}
+
 
 /*
  * widget menu functions
--- a/ui/gtk/menu.h	Wed Dec 31 11:36:42 2025 +0100
+++ b/ui/gtk/menu.h	Wed Dec 31 12:37:09 2025 +0100
@@ -78,6 +78,8 @@
 void ui_menu_event_toggled(GtkCheckMenuItem *ci, UiVarEventData *event);
 int64_t ui_checkitem_get(UiInteger *i);
 void ui_checkitem_set(UiInteger *i, int64_t value);
+int64_t ui_radioitem_get(UiInteger *i);
+void ui_radioitem_set(UiInteger *i, int64_t value);
 
 #endif /* GTK_MAJOR_VERSION <= 3 */
 
--- a/ui/gtk/toolkit.c	Wed Dec 31 11:36:42 2025 +0100
+++ b/ui/gtk/toolkit.c	Wed Dec 31 12:37:09 2025 +0100
@@ -282,7 +282,7 @@
     free(userdata);
 }
 
-void ui_destroy_vardata(GtkWidget *object, UiVarEventData *data) {
+void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data) {
     if(data->var) {
         ui_destroy_boundvar(data->obj->ctx, data->var);
     }
--- a/ui/gtk/toolkit.h	Wed Dec 31 11:36:42 2025 +0100
+++ b/ui/gtk/toolkit.h	Wed Dec 31 12:37:09 2025 +0100
@@ -190,7 +190,7 @@
 void ui_set_widget_nvisibility_states(UiContext *ctx, GtkWidget *widget, const int *states, size_t ngroups);
 
 void ui_destroy_userdata(GtkWidget *object, void *userdata);
-void ui_destroy_vardata(GtkWidget *object, UiVarEventData *data);
+void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data);
 void ui_destroy_widget_var(GtkWidget *object, UiVar *var);
 void ui_destroy_boundvar(UiContext *ctx, UiVar *var);
 

mercurial