ui/gtk/menu.c

changeset 118
6d0da97105d8
parent 117
b174e721663e
--- a/ui/gtk/menu.c	Sat Dec 27 22:47:56 2025 +0100
+++ b/ui/gtk/menu.c	Thu Jan 08 18:06:04 2026 +0100
@@ -153,29 +153,100 @@
     GtkWidget *widget = gtk_check_menu_item_new_with_mnemonic(ci->label);
     gtk_menu_shell_append(GTK_MENU_SHELL(p), widget);
     
-    if(ci->callback) {
-        UiEventData *event = malloc(sizeof(UiEventData));
-        event->obj = obj;
-        event->userdata = ci->userdata;
-        event->callback = ci->callback;
-        event->value = 0;
-        event->customdata = NULL;
-        
-        g_signal_connect(
-                widget,
-                "toggled",
-                G_CALLBACK(ui_menu_event_toggled),
-                event);
-        g_signal_connect(
-                widget,
-                "destroy",
-                G_CALLBACK(ui_destroy_userdata),
-                event);
+    UiVarEventData *event = malloc(sizeof(UiVarEventData));
+    memset(event, 0, sizeof(UiVarEventData));
+    event->obj = obj;
+    event->userdata = ci->userdata;
+    event->callback = ci->callback;
+    event->var = uic_widget_var(obj->ctx, obj->ctx, NULL, ci->varname, UI_VAR_INTEGER);
+    if(event->var) {
+        UiInteger *v = event->var->value;
+        v->obj = widget;
+        v->get = ui_checkitem_get;
+        v->set = ui_checkitem_set;
+        if(v->value != 0) {
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
+        }
+    }
+
+    g_signal_connect(
+            widget,
+            "toggled",
+            G_CALLBACK(ui_menu_event_toggled),
+            event);
+    g_signal_connect(
+            widget,
+            "destroy",
+            G_CALLBACK(ui_destroy_userdata),
+            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) {
@@ -323,14 +394,23 @@
     uic_set_tmp_eventdata(NULL, 0);
 }
 
-void ui_menu_event_toggled(GtkCheckMenuItem *ci, UiEventData *event) {
+void ui_menu_event_toggled(GtkCheckMenuItem *ci, UiVarEventData *event) {
+    UiInteger *i = event->var ? event->var->value : NULL;
+    
     UiEvent evt;
     evt.obj = event->obj;
     evt.window = event->obj->window;
     evt.document = event->obj->ctx->document;
-    evt.eventdata = NULL;
+    evt.eventdata = i;
+    evt.eventdatatype = i ? UI_EVENT_DATA_INTEGER_VALUE : 0;
     evt.intval = gtk_check_menu_item_get_active(ci);
-    event->callback(&evt, event->userdata);    
+    if(event->callback) {
+        event->callback(&evt, event->userdata);
+    }
+    
+    if(i) {
+        ui_notify_evt(i->observers, &evt);
+    }
 }
 
 int64_t ui_checkitem_get(UiInteger *i) {
@@ -341,7 +421,48 @@
 
 void ui_checkitem_set(UiInteger *i, int64_t value) {
     i->value = value;
-    gtk_check_menu_item_set_active(i->obj, value);
+    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;
 }
 
 

mercurial