simplify gtk button code newapi

Mon, 23 Sep 2024 23:17:39 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 23 Sep 2024 23:17:39 +0200
branch
newapi
changeset 308
4efc7c19e31d
parent 307
301d6c73087a
child 309
02c95df91de1

simplify gtk button code

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/button.h file | annotate | diff | comparison | revisions
ui/gtk/headerbar.c file | annotate | diff | comparison | revisions
--- a/application/main.c	Sun Sep 22 21:17:15 2024 +0200
+++ b/application/main.c	Mon Sep 23 23:17:39 2024 +0200
@@ -162,12 +162,12 @@
         ui_menuitem(.label = "Test");
     }
     
-    ui_toolbar_item("Test", .label = "Test", .icon = "terminal", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test2", .label = "Test 2", .icon = "terminal", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test3", .label = "Test 3", .icon = "terminal", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test4", .label = "Test 4", .icon = "terminal", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test5", .label = "Test 5", .icon = "terminal", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test6", .label = "Test 6", .icon = "terminal", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test2", .label = "Test 2", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test3", .label = "Test 3", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test4", .label = "Test 4", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test5", .label = "Test 5", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test6", .label = "Test 6", .onclick = action_toolbar_button);
     ui_toolbar_toggleitem("Toggle", .label = "Toggle", .onchange = action_toolbar_button);
     ui_toolbar_menu("Menu", .label = "Menu") {
         ui_menuitem("Secondary Test", NULL, NULL);
--- a/ui/gtk/button.c	Sun Sep 22 21:17:15 2024 +0200
+++ b/ui/gtk/button.c	Mon Sep 23 23:17:39 2024 +0200
@@ -54,20 +54,21 @@
 #endif
 }
 
-UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) {
-    UiObject* current = uic_current_obj(obj);
-    GtkWidget *button = gtk_button_new();
-    if(args.label) {
-        gtk_button_set_label(GTK_BUTTON(button), args.label);
-    }
-    ui_button_set_icon_name(button, args.icon);
-
+GtkWidget* ui_create_button(
+        UiObject *obj,
+        const char *label,
+        const char *icon,
+        ui_callback onclick,
+        void *userdata)
+{
+    GtkWidget *button = gtk_button_new_with_label(label);
+    ui_button_set_icon_name(button, icon);
     
-    if(args.onclick) {
+    if(onclick) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
-        event->userdata = args.onclickdata;
-        event->callback = args.onclick;
+        event->userdata = userdata;
+        event->callback = onclick;
         event->value = 0;
         event->customdata = NULL;
 
@@ -83,9 +84,14 @@
                 event);
     }
     
+    return button;
+}
+
+UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata);
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, button, FALSE);
-    
     return button;
 }
 
@@ -112,7 +118,7 @@
     gtk_toggle_button_set_active(button, value != 0 ? TRUE : FALSE);
 }
 
-void ui_toggled_obs(GtkToggleButton *widget, UiVarEventData *event) {
+void ui_toggled_obs(void *widget, UiVarEventData *event) {
     UiInteger *i = event->var->value;
     UiEvent e;
     e.obj = event->obj;
@@ -124,20 +130,61 @@
     ui_notify_evt(i->observers, &e);
 }
 
-static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) {
-    UiObject* current = uic_current_obj(obj);
+static void ui_toggled_callback(GtkToggleButton *widget, UiEventData *event) {
+    UiEvent e;
+    e.obj = event->obj;
+    e.window = event->obj->window;
+    e.document = event->obj->ctx->document;
+    e.eventdata = NULL;
+    e.intval = gtk_toggle_button_get_active(widget);
+    event->callback(&e, event->userdata);    
+}
+
+void ui_setup_togglebutton(
+        UiObject *obj,
+        GtkWidget *togglebutton,
+        const char *label,
+        const char *icon,
+        const char *varname,
+        UiInteger *value,
+        ui_callback onchange,
+        void *onchangedata)
+{
+    if(label) {
+        gtk_button_set_label(GTK_BUTTON(togglebutton), label);
+    }
+    ui_button_set_icon_name(togglebutton, icon);
     
-    if(args.label) {
-        gtk_button_set_label(GTK_BUTTON(widget), args.label);
-    }
-    ui_button_set_icon_name(widget, args.icon);
-    
-    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+    ui_bind_togglebutton(
+            obj,
+            togglebutton,
+            ui_toggle_button_get,
+            ui_toggle_button_set,
+            varname,
+            value,
+            (ui_toggled_func)ui_toggled_callback,
+            onchange,
+            onchangedata);
+}
+
+void ui_bind_togglebutton(
+        UiObject *obj,
+        GtkWidget *widget,
+        int64_t (*getfunc)(UiInteger*),
+        void (*setfunc)(UiInteger*, int64_t),
+        const char *varname,
+        UiInteger *value,
+        void (*toggled_callback)(void*, void*),
+        ui_callback onchange,
+        void *onchangedata)
+{
+    UiObject* current = uic_current_obj(obj);
+    UiVar* var = uic_widget_var(obj->ctx, current->ctx, value, varname, UI_VAR_INTEGER);
     if (var) {
         UiInteger* value = (UiInteger*)var->value;
         value->obj = widget;
-        value->get = ui_toggle_button_get;
-        value->set = ui_toggle_button_set;
+        value->get = getfunc;
+        value->set = setfunc;
         
         UiVarEventData *event = malloc(sizeof(UiVarEventData));
         event->obj = obj;
@@ -148,7 +195,7 @@
 
         g_signal_connect(
                 widget,
-                "clicked",
+                "toggled",
                 G_CALLBACK(ui_toggled_obs),
                 event);
         g_signal_connect(
@@ -158,6 +205,32 @@
                 event);
     }
     
+    if(onchange) {
+        UiEventData *event = malloc(sizeof(UiEventData));
+        event->obj = obj;
+        event->userdata = onchangedata;
+        event->callback = onchange;
+        event->value = 0;
+        event->customdata = NULL;
+        
+        g_signal_connect(
+                widget,
+                "toggled",
+                G_CALLBACK(toggled_callback),
+                event);
+        g_signal_connect(
+                widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
+    }
+}
+
+static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    ui_setup_togglebutton(current, widget, args.label, args.icon, args.varname, args.value, args.onchange, args.onchangedata);
+    
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, widget, FALSE);
     
@@ -182,36 +255,30 @@
     gtk_check_button_set_active(button, value != 0 ? TRUE : FALSE);
 }
 
+static void ui_checkbox_callback(GtkCheckButton *widget, UiEventData *event) {
+    UiEvent e;
+    e.obj = event->obj;
+    e.window = event->obj->window;
+    e.document = event->obj->ctx->document;
+    e.eventdata = NULL;
+    e.intval = gtk_check_button_get_active(widget);
+    event->callback(&e, event->userdata);    
+}
+
 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) {
     UiObject* current = uic_current_obj(obj);
     
-    GtkWidget *widget = gtk_check_button_new_with_label(args.label);
-    
-    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
-    if (var) {
-        UiInteger* value = (UiInteger*)var->value;
-        value->obj = widget;
-        value->get = ui_check_button_get;
-        value->set = ui_check_button_set;
-        
-        UiVarEventData *event = malloc(sizeof(UiVarEventData));
-        event->obj = obj;
-        event->var = var;
-        event->observers = NULL;
-        event->callback = NULL;
-        event->userdata = NULL;
-
-        g_signal_connect(
-                widget,
-                "toggled",
-                G_CALLBACK(ui_toggled_obs),
-                event);
-        g_signal_connect(
-                widget,
-                "destroy",
-                G_CALLBACK(ui_destroy_vardata),
-                event);
-    }
+    GtkWidget *widget = gtk_check_button_new_with_label(args.label); 
+    ui_bind_togglebutton(
+            obj,
+            widget,
+            ui_check_button_get,
+            ui_check_button_set,
+            args.varname,
+            args.value,
+            (ui_toggled_func)ui_checkbox_callback,
+            args.onchange,
+            args.onchangedata);
     
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, widget, FALSE);
@@ -237,24 +304,31 @@
 #define RADIOBUTTON_NEW(group, label) gtk_check_button_new_with_label(label)
 #define RADIOBUTTON_SET_GROUP(button, group) 
 #define RADIOBUTTON_GET_GROUP(button) GTK_CHECK_BUTTON(button)
+#define RADIOBUTTON_GET_ACTIVE(button) gtk_check_button_get_active(GTK_CHECK_BUTTON(button))
 #else
 #define RADIOBUTTON_NEW(group, label) gtk_radio_button_new_with_label(group, label)
 #define RADIOBUTTON_SET_GROUP(button, group) /* noop */
 #define RADIOBUTTON_GET_GROUP(button) gtk_radio_button_get_group(GTK_RADIO_BUTTON(button))
+#define RADIOBUTTON_GET_ACTIVE(button) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))
 #endif
 
+static void radiobutton_toggled(void *widget, UiEventData *event) {
+    UiEvent e;
+    e.obj = event->obj;
+    e.window = event->obj->window;
+    e.document = event->obj->ctx->document;
+    e.eventdata = NULL;
+    e.intval = RADIOBUTTON_GET_ACTIVE(widget);
+    event->callback(&e, event->userdata);    
+}
+
 UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) {
     UiObject* current = uic_current_obj(obj);
     
     GSList *rg = NULL;
     UiInteger *rgroup;
     
-    UiVar* var = NULL;
-    if (args.value) {
-        var = uic_create_value_var(current->ctx, args.value);
-    } else if (args.varname) {
-        var = uic_create_var(obj->ctx, args.varname, UI_VAR_INTEGER);
-    }
+    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
     
     UiBool first = FALSE;
     if(var) {
@@ -304,6 +378,26 @@
         }
     }
     
+    if(args.onchange) {
+        UiEventData *event = malloc(sizeof(UiEventData));
+        event->obj = obj;
+        event->userdata = args.onchangedata;
+        event->callback = args.onchange;
+        event->value = 0;
+        event->customdata = NULL;
+        
+        g_signal_connect(
+                rbutton,
+                "toggled",
+                G_CALLBACK(radiobutton_toggled),
+                event);
+        g_signal_connect(
+                rbutton,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
+    }
+    
     UiContainer *ct = uic_get_current_container(obj);
     ct->add(ct, rbutton, FALSE);
     
--- a/ui/gtk/button.h	Sun Sep 22 21:17:15 2024 +0200
+++ b/ui/gtk/button.h	Mon Sep 23 23:17:39 2024 +0200
@@ -36,14 +36,44 @@
 #ifdef	__cplusplus
 extern "C" {
 #endif
+    
+void ui_button_set_icon_name(GtkWidget *button, const char *icon_name);
 
-void ui_button_set_icon_name(GtkWidget *button, const char *icon_name);
+typedef void (*ui_toggled_func)(void*, void*);
+
+GtkWidget* ui_create_button(
+        UiObject *obj,
+        const char *label,
+        const char *icon,
+        ui_callback onclick,
+        void *userdata);
+
+void ui_setup_togglebutton(
+        UiObject *obj,
+        GtkWidget *togglebutton,
+        const char *label,
+        const char *icon,
+        const char *varname,
+        UiInteger *value,
+        ui_callback onchange,
+        void *onchangedata);
+
+void ui_bind_togglebutton(
+        UiObject *obj,
+        GtkWidget *widget,
+        int64_t (*getfunc)(UiInteger*),
+        void (*setfunc)(UiInteger*, int64_t),
+        const char *varname,
+        UiInteger *value,
+        void (*toggled_callback)(void*, void*),
+        ui_callback onchange,
+        void *onchangedata);
     
 // event wrapper
 void ui_button_clicked(GtkWidget *widget, UiEventData *event);
 
 
-void ui_toggled_obs(GtkToggleButton *widget, UiVarEventData *event);
+void ui_toggled_obs(void *widget, UiVarEventData *event);
 
 UIWIDGET ui_checkbox_var(UiObject *obj, char *label, UiVar *var);
 
--- a/ui/gtk/headerbar.c	Sun Sep 22 21:17:15 2024 +0200
+++ b/ui/gtk/headerbar.c	Mon Sep 23 23:17:39 2024 +0200
@@ -28,7 +28,7 @@
 
 #include "headerbar.h"
 
-
+#include "button.h"
 
 #if GTK_MAJOR_VERSION >= 3
 
@@ -117,7 +117,7 @@
 }
 
 void ui_add_headerbar_item(GtkWidget *headerbar, GtkWidget *box, UiToolbarItem *item, UiObject *obj, enum UiToolbarPos pos) {
-    GtkWidget *button = gtk_button_new_with_label(item->args.label);
+    GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.onclick, item->args.onclickdata);
     WIDGET_ADD_CSS_CLASS(button, "flat");
     headerbar_add(headerbar, box, button, pos);
 }

mercurial