# HG changeset patch # User Olaf Wintermann # Date 1734299631 -3600 # Node ID 7d15cad351fc5ca7bfbe7e73da67e9a0c8ea7226 # Parent a57268d20ed9ee945fb395f110efe3332aa80ce0 add menu toggle/radio button (Motif) diff -r a57268d20ed9 -r 7d15cad351fc application/main.c --- a/application/main.c Sun Dec 15 22:16:12 2024 +0100 +++ b/application/main.c Sun Dec 15 22:53:51 2024 +0100 @@ -564,6 +564,12 @@ ui_menuitem(.label = "Test 1", .onclick = action_test); ui_menuitem(.label = "Test 2", .onclick = action_test); ui_menuitem(.label = "Test 3", .onclick = action_test); + ui_menu_toggleitem(.label = "Toggle 1"); + ui_menu_toggleitem(.label = "Toggle 2"); + ui_menu_radioitem(.label = "Radio 1", .varname = "menu_radio"); + ui_menu_radioitem(.label = "Radio 2", .varname = "menu_radio"); + ui_menu_radioitem(.label = "Radio 3", .varname = "menu_radio"); + ui_menu_radioitem(.label = "Radio 4", .varname = "menu_radio"); } ui_main(); diff -r a57268d20ed9 -r 7d15cad351fc ui/common/menu.c --- a/ui/common/menu.c Sun Dec 15 22:16:12 2024 +0100 +++ b/ui/common/menu.c Sun Dec 15 22:53:51 2024 +0100 @@ -175,7 +175,7 @@ mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; - item->item.type = UI_MENU_CHECK_ITEM; + item->item.type = UI_MENU_RADIO_ITEM; item->label = nl_strdup(args.label); item->stockid = nl_strdup(args.stockid); diff -r a57268d20ed9 -r 7d15cad351fc ui/common/menu.h --- a/ui/common/menu.h Sun Dec 15 22:16:12 2024 +0100 +++ b/ui/common/menu.h Sun Dec 15 22:53:51 2024 +0100 @@ -101,6 +101,7 @@ char *label; char *stockid; char *icon; + char *varname; ui_callback callback; void *userdata; int *groups; diff -r a57268d20ed9 -r 7d15cad351fc ui/motif/button.c --- a/ui/motif/button.c Sun Dec 15 22:16:12 2024 +0100 +++ b/ui/motif/button.c Sun Dec 15 22:53:51 2024 +0100 @@ -291,6 +291,55 @@ } } +void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, int enable_group) { + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, value, varname, UI_VAR_INTEGER); + if(var) { + UiInteger *value = var->value; + CxList *rb = value->obj; + if(!rb) { + // first button in the radiobutton group + // create a list for all buttons and use the list as value obj + rb = cxArrayListCreateSimple(CX_STORE_POINTERS, 4); + value->obj = rb; + value->get = ui_radiobutton_get; + value->set = ui_radiobutton_set; + + // the first radio button is also responsible for cleanup + XtAddCallback( + rbutton, + XmNdestroyCallback, + (XtCallbackProc)destroy_list, + rb); + } + cxListAdd(rb, rbutton); + + // set the radiobutton state, if the value is already set + if(cxListSize(rb) == value->value) { + XmToggleButtonSetState(rbutton, True, False); + } + } + + // the radio button needs to handle change events to update all + // other buttons in the radio button group + UiVarEventData *event = malloc(sizeof(UiVarEventData)); + event->obj = obj; + event->callback = onchange; + event->userdata = onchangedata; + event->observers = NULL; + event->var = var; + event->value = enable_group; + XtAddCallback( + rbutton, + XmNvalueChangedCallback, + (XtCallbackProc)radiobutton_changed, + event); + XtAddCallback( + rbutton, + XmNdestroyCallback, + (XtCallbackProc)ui_destroy_eventdata, + event); +} + UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) { Arg xargs[16]; int n = 0; diff -r a57268d20ed9 -r 7d15cad351fc ui/motif/button.h --- a/ui/motif/button.h Sun Dec 15 22:16:12 2024 +0100 +++ b/ui/motif/button.h Sun Dec 15 22:53:51 2024 +0100 @@ -50,6 +50,8 @@ int64_t ui_togglebutton_get(UiInteger *i); void ui_togglebutton_set(UiInteger *i, int64_t value); +void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, int enable_group); + int64_t ui_radiobutton_get(UiInteger *i); void ui_radiobutton_set(UiInteger *i, int64_t value); diff -r a57268d20ed9 -r 7d15cad351fc ui/motif/menu.c --- a/ui/motif/menu.c Sun Dec 15 22:16:12 2024 +0100 +++ b/ui/motif/menu.c Sun Dec 15 22:53:51 2024 +0100 @@ -147,6 +147,8 @@ (XtCallbackProc)ui_destroy_eventdata, eventdata); } + + ui_set_widget_groups(obj->ctx, mitem, it->groups); } void add_menuseparator_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { @@ -155,11 +157,48 @@ } void add_checkitem_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { + UiMenuCheckItem *it = (UiMenuCheckItem*)item; + Arg args[4]; + int n = 0; + XmString s = NULL; + if(it->label) { + s = XmStringCreateLocalized(it->label); + XtSetArg(args[n], XmNlabelString, s); n++; + } + + //XtSetArg(args[n], XmNvisibleWhenOff, 0); n++; + Widget checkbox = XtCreateManagedWidget( + "menutogglebutton", + xmToggleButtonWidgetClass, + p, + args, + n); + if(s) { + XmStringFree(s); + } + + ui_bind_togglebutton(obj, checkbox, it->varname, NULL, it->callback, it->userdata, 0); + + ui_set_widget_groups(obj->ctx, checkbox, it->groups); } void add_radioitem_widget(Widget p, int index, UiMenuItemI *item, UiObject *obj) { + UiMenuRadioItem *it = (UiMenuRadioItem*)item; + Arg args[4]; + int n = 0; + XmString s = NULL; + if(it->label) { + s = XmStringCreateLocalized(it->label); + XtSetArg(args[n], XmNlabelString, s); n++; + } + XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY_ROUND); n++; + + Widget button = XmCreateToggleButton(p, "menuradiobutton", args, n); + XtManageChild(button); + + ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, 0); } void add_checkitemnv_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) {