# HG changeset patch # User Olaf Wintermann # Date 1727126259 -7200 # Node ID 4efc7c19e31d6156902c803582644d685850f2b9 # Parent 301d6c73087a3b7f4fa64a92bb1e755cda7ce149 simplify gtk button code diff -r 301d6c73087a -r 4efc7c19e31d application/main.c --- 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); diff -r 301d6c73087a -r 4efc7c19e31d ui/gtk/button.c --- 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); diff -r 301d6c73087a -r 4efc7c19e31d ui/gtk/button.h --- 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); diff -r 301d6c73087a -r 4efc7c19e31d ui/gtk/headerbar.c --- 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); }