// 11 june 2015 #include "uipriv_unix.h" // on GTK+ a uiRadioButtons is a GtkBox with each of the GtkRadioButtons as children struct uiRadioButtons { uiUnixControl c; GtkWidget *widget; GtkContainer *container; GtkBox *box; GPtrArray *buttons; void (*onSelected)(uiRadioButtons *, void *); void *onSelectedData; gboolean changing; }; uiUnixControlAllDefaultsExceptDestroy(uiRadioButtons) static void defaultOnSelected(uiRadioButtons *r, void *data) { // do nothing } static void onToggled(GtkToggleButton *tb, gpointer data) { uiRadioButtons *r = uiRadioButtons(data); // only care if a button is selected if (!gtk_toggle_button_get_active(tb)) return; // ignore programmatic changes if (r->changing) return; (*(r->onSelected))(r, r->onSelectedData); } static void uiRadioButtonsDestroy(uiControl *c) { uiRadioButtons *r = uiRadioButtons(c); GtkWidget *b; while (r->buttons->len != 0) { b = GTK_WIDGET(g_ptr_array_remove_index(r->buttons, 0)); gtk_widget_destroy(b); } g_ptr_array_free(r->buttons, TRUE); // and free ourselves g_object_unref(r->widget); uiFreeControl(uiControl(r)); } void uiRadioButtonsAppend(uiRadioButtons *r, const char *text) { GtkWidget *rb; GtkRadioButton *previous; previous = GTK_RADIO_BUTTON(g_ptr_array_index(r->buttons, 0)); rb = gtk_radio_button_new_with_label_from_widget(previous, text); g_signal_connect(rb, "toggled", G_CALLBACK(onToggled), r); gtk_container_add(r->container, rb); g_ptr_array_add(r->buttons, rb); gtk_widget_show(rb); } int uiRadioButtonsSelected(uiRadioButtons *r) { GtkToggleButton *tb; guint i; for (i = 0; i < r->buttons->len; i++) { tb = GTK_TOGGLE_BUTTON(g_ptr_array_index(r->buttons, i)); if (gtk_toggle_button_get_active(tb)) return i - 1; } return -1; } void uiRadioButtonsSetSelected(uiRadioButtons *r, int n) { GtkToggleButton *tb = GTK_TOGGLE_BUTTON(g_ptr_array_index(r->buttons, n + 1)); // this is easier than remembering all the signals r->changing = TRUE; gtk_toggle_button_set_active(tb, TRUE); r->changing = FALSE; } void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data) { r->onSelected = f; r->onSelectedData = data; } uiRadioButtons *uiNewRadioButtons(void) { uiRadioButtons *r; // Add a hidden button to indicate an empty selection (-1) as GTK does not support this natively GtkWidget *hiddenBtn; uiUnixNewControl(uiRadioButtons, r); r->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); r->container = GTK_CONTAINER(r->widget); r->box = GTK_BOX(r->widget); r->buttons = g_ptr_array_new(); hiddenBtn = gtk_radio_button_new(NULL); gtk_container_add(r->container, hiddenBtn); g_ptr_array_add(r->buttons, hiddenBtn); gtk_widget_hide(hiddenBtn); uiRadioButtonsOnSelected(r, defaultOnSelected, NULL); return r; }