diff --git a/CMakeLists.txt b/CMakeLists.txt index f303be4e..262af94f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ cmake_minimum_required(VERSION 2.8.11) # - uname -s for more refined OS control # - Haiku for haiku # - debian DESTDIR? https://github.com/andlabs/libui/pull/10 +# - libui-combined* needs to be deleted so that custom command can run every time # the docs say we need to set this up prior to project() set(CMAKE_OSX_DEPLOYMENT_TARGET "10.8") diff --git a/test/page4.c b/test/page4.c index 00bc16ec..5a448c44 100644 --- a/test/page4.c +++ b/test/page4.c @@ -58,6 +58,23 @@ static void onECBChanged(uiEditableCombobox *c, void *data) uiFreeText(t); } +static void onRBSelected(uiRadioButtons *r, void *data) +{ + printf("radio buttons %d\n", uiRadioButtonsSelected(r)); +} + +static void selectSecond(uiButton *b, void *data) +{ + // TODO combobox, editable + uiRadioButtonsSetSelected(rb, 1); +} + +static void selectNone(uiButton *b, void *data) +{ + // TODO combobox, editable + uiRadioButtonsSetSelected(rb, -1); +} + uiBox *makePage4(void) { uiBox *page4; @@ -123,12 +140,19 @@ uiBox *makePage4(void) uiRadioButtonsAppend(rb, "Item 1"); uiRadioButtonsAppend(rb, "Item 2"); uiRadioButtonsAppend(rb, "Item 3"); + uiRadioButtonsOnSelected(rb, onRBSelected, NULL); uiBoxAppend(page4, uiControl(rb), 0); hbox = newHorizontalBox(); b = uiNewButton("Append"); uiButtonOnClicked(b, appendCBRB, NULL); uiBoxAppend(hbox, uiControl(b), 0); + b = uiNewButton("Second"); + uiButtonOnClicked(b, selectSecond, NULL); + uiBoxAppend(hbox, uiControl(b), 0); + b = uiNewButton("None"); + uiButtonOnClicked(b, selectNone, NULL); + uiBoxAppend(hbox, uiControl(b), 0); uiBoxAppend(page4, uiControl(hbox), 0); uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0); diff --git a/ui.h b/ui.h index aede021b..d3996cb7 100644 --- a/ui.h +++ b/ui.h @@ -213,6 +213,9 @@ _UI_EXTERN uiEditableCombobox *uiNewEditableCombobox(void); typedef struct uiRadioButtons uiRadioButtons; #define uiRadioButtons(this) ((uiRadioButtons *) (this)) _UI_EXTERN void uiRadioButtonsAppend(uiRadioButtons *r, const char *text); +_UI_EXTERN intmax_t uiRadioButtonsSelected(uiRadioButtons *r); +_UI_EXTERN void uiRadioButtonsSetSelected(uiRadioButtons *r, intmax_t n); +_UI_EXTERN void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data); _UI_EXTERN uiRadioButtons *uiNewRadioButtons(void); typedef struct uiDateTimePicker uiDateTimePicker; diff --git a/unix/radiobuttons.c b/unix/radiobuttons.c index 7956f5f6..24bc80b1 100644 --- a/unix/radiobuttons.c +++ b/unix/radiobuttons.c @@ -9,10 +9,31 @@ struct uiRadioButtons { 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); @@ -37,11 +58,50 @@ void uiRadioButtonsAppend(uiRadioButtons *r, const char *text) if (r->buttons->len > 0) 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); } +intmax_t 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; + } + return -1; +} + +void uiRadioButtonsSetSelected(uiRadioButtons *r, intmax_t n) +{ + GtkToggleButton *tb; + gboolean active = TRUE; + + // TODO this doesn't work + if (n == -1) { + n = uiRadioButtonsSelected(r); + if (n == -1) // no selection; keep it that way + return; + active = FALSE; + } + tb = GTK_TOGGLE_BUTTON(g_ptr_array_index(r->buttons, n)); + // this is easier than remembering all the signals + r->changing = TRUE; + gtk_toggle_button_set_active(tb, active); + r->changing = FALSE; +} + +void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data) +{ + r->onSelected = f; + r->onSelectedData = data; +} + uiRadioButtons *uiNewRadioButtons(void) { uiRadioButtons *r; @@ -54,5 +114,7 @@ uiRadioButtons *uiNewRadioButtons(void) r->buttons = g_ptr_array_new(); + uiRadioButtonsOnSelected(r, defaultOnSelected, NULL); + return r; }