--- a/ui/gtk/button.c Wed Jun 17 19:50:57 2026 +0200 +++ b/ui/gtk/button.c Wed Jun 17 20:42:21 2026 +0200 @@ -334,7 +334,7 @@ event); } - if(onchange) { + if(onchange || action) { UiEventData *event = malloc(sizeof(UiEventData)); event->obj = obj; event->userdata = onchangedata; @@ -577,6 +577,148 @@ #endif +static void content_toggle_button_changed(UiContentToggleButton *button) { + if(button->toggled) { + gtk_button_set_label(GTK_BUTTON(button->widget), button->label1); + ui_button_set_icon_name(button->widget, button->icon1); + gtk_widget_set_tooltip_text(button->widget, button->tooltip1); + } else { + gtk_button_set_label(GTK_BUTTON(button->widget), button->label0); + ui_button_set_icon_name(button->widget, button->icon0); + gtk_widget_set_tooltip_text(button->widget, button->tooltip0); + } + + UiEvent e; + e.obj = button->obj; + e.window = button->obj->window; + e.document = button->obj->ctx->document; + e.eventdata = NULL; + e.eventdatatype = 0; + e.intval = button->toggled; + e.set = ui_get_setop(); + + if(button->onchange) { + button->onchange(&e, button->onchangedata); + } + + if(button->onchange_action) { + uic_action_callback(&e, button->onchange_action); + } +} + +static void ui_content_toggle_button_toggled(GtkWidget *widget, UiContentToggleButton *button) { + button->toggled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + if(ui_get_setop() == 0) { + content_toggle_button_changed(button); + } +} + +static void ui_content_toggle_button_clicked(GtkWidget *widget, UiContentToggleButton *button) { + button->toggled = !button->toggled; + content_toggle_button_changed(button); +} + +static void ui_destroy_content_togglebutton(GtkWidget *widget, UiContentToggleButton *button) { + free(button->label0); + free(button->icon0); + free(button->tooltip0); + free(button->label1); + free(button->icon1); + free(button->tooltip1); + free(button->onchange_action); + free(button); +} + +UIWIDGET ui_create_content_togglebutton(UiObject *obj, UiContentToggleArgs *args) { + UiContentToggleButton *button = malloc(sizeof(UiContentToggleButton)); + memset(button, 0, sizeof(UiContentToggleButton)); + button->obj = obj; + button->label0 = args->label0 ? strdup(args->label0) : NULL; + button->icon0 = args->icon0 ? strdup(args->icon0) : NULL; + button->tooltip0 = args->tooltip0 ? strdup(args->tooltip0) : NULL; + button->label1 = args->label1 ? strdup(args->label1) : NULL; + button->icon1 = args->icon1 ? strdup(args->icon1) : NULL; + button->tooltip1 = args->tooltip1 ? strdup(args->tooltip1) : NULL; + button->enable_state = args->enable_state; + button->var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); + button->onchange = args->onchange; + button->onchangedata = args->onchangedata; + button->onchange_action = args->action ? strdup(args->action) : NULL; + + const char *label = args->label0; + const char *icon = args->icon0; + const char *tooltip = args->tooltip0; + if(button->var) { + UiInteger *i = button->var->value; + i->obj = button; + i->get = ui_ctntogglebutton_get; + i->set = ui_ctntogglebutton_set; + + if(i->value) { + label = args->label1; + icon = args->label1; + tooltip = args->tooltip1; + button->toggled = 1; + } + } + + GtkWidget *widget; + if(args->istogglebutton) { + widget = gtk_toggle_button_new_with_label(label); + + g_signal_connect( + widget, + "toggled", + G_CALLBACK(ui_content_toggle_button_toggled), + button); + } else { + widget = gtk_button_new_with_label(label); + + g_signal_connect( + widget, + "clicked", + G_CALLBACK(ui_content_toggle_button_clicked), + button); + } + ui_button_set_icon_name(widget, icon); + gtk_widget_set_tooltip_text(widget, tooltip); + button->widget = widget; + + g_signal_connect( + widget, + "destroy", + G_CALLBACK(ui_destroy_content_togglebutton), + button); + + g_object_set_data(G_OBJECT(widget), "ui_content_togglebutton", button); + return widget; +} + +UIWIDGET ui_content_togglebutton_create(UiObject *obj, UiContentToggleArgs *args) { + GtkWidget *widget = ui_create_content_togglebutton(obj, args); + + ui_set_name_and_style(widget, args->name, args->style_class); + ui_set_widget_states(obj->ctx, widget, args->states); + UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; + UiLayout layout = UI_ARGS2LAYOUT(args); + ct->add(ct, widget, &layout); + uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states); + return widget; +} + +int64_t ui_ctntogglebutton_get(UiInteger *value) { + UiContentToggleButton *button = value->obj; + value->value = button->toggled; + return value->value; +} + +void ui_ctntogglebutton_set(UiInteger *value, int64_t i) { + UiContentToggleButton *button = value->obj; + button->toggled = i != 0; + value->value = button->toggled; + content_toggle_button_changed(button); +} + #if GTK_MAJOR_VERSION >= 4 #define RADIOBUTTON_NEW(group, label) gtk_check_button_new_with_label(label) #define RADIOBUTTON_SET_GROUP(button, group)