--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/motif/button.c Wed Dec 09 11:32:01 2020 +0100 @@ -0,0 +1,207 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "button.h" +#include "container.h" +#include "../common/context.h" +#include <ucx/mempool.h> + + +UIWIDGET ui_button(UiObject *obj, char *label, ui_callback f, void *data) { + UiContainer *ct = uic_get_current_container(obj); + XmString str = XmStringCreateLocalized(label); + + int n = 0; + Arg args[16]; + + XtSetArg(args[n], XmNlabelString, str); + n++; + + Widget parent = ct->prepare(ct, args, &n, FALSE); + Widget button = XmCreatePushButton(parent, "button", args, n); + ct->add(ct, button); + + if(f) { + UiEventData *event = ucx_mempool_malloc( + obj->ctx->mempool, + sizeof(UiEventData)); + event->obj = obj; + event->userdata = data; + event->callback = f; + event->value = 0; + XtAddCallback( + button, + XmNactivateCallback, + (XtCallbackProc)ui_push_button_callback, + event); + } + + XtManageChild(button); + + return button; +} + +// wrapper +int64_t ui_toggle_button_get(UiInteger *i) { + int state = 0; + XtVaGetValues(i->obj, XmNset, &state, NULL); + i->value = state; + return state; +} + +void ui_toggle_button_set(UiInteger *i, int64_t value) { + Arg arg; + XtSetArg(arg, XmNset, value); + XtSetValues(i->obj, &arg, 1); + i->value = value; +} + +void ui_toggle_button_callback( + Widget widget, + UiEventData *event, + XmToggleButtonCallbackStruct *tb) +{ + UiEvent e; + e.obj = event->obj; + e.window = event->obj->window; + // TODO: e.document + e.intval = tb->set; + event->callback(&e, event->userdata); +} + +void ui_push_button_callback(Widget widget, UiEventData *event, XtPointer d) { + UiEvent e; + e.obj = event->obj; + e.window = event->obj->window; + e.document = event->obj->ctx->document; + e.intval = event->value; + event->callback(&e, event->userdata); +} + + +static void radio_callback( + Widget widget, + RadioEventData *event, + XmToggleButtonCallbackStruct *tb) +{ + if(tb->set) { + RadioButtonGroup *group = event->group; + if(group->current) { + Arg arg; + XtSetArg(arg, XmNset, FALSE); + XtSetValues(group->current, &arg, 1); + } + group->current = widget; + } +} + +UIWIDGET ui_radiobutton(UiObject *obj, char *label, UiInteger *rgroup) { + UiContainer *ct = uic_get_current_container(obj); + XmString str = XmStringCreateLocalized(label); + + int n = 0; + Arg args[16]; + + XtSetArg(args[n], XmNlabelString, str); + n++; + XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY_ROUND); + n++; + + Widget parent = ct->prepare(ct, args, &n, FALSE); + Widget button = XmCreateToggleButton(parent, "radiobutton", args, n); + ct->add(ct, button); + + if(rgroup) { + RadioButtonGroup *group; + if(rgroup->obj) { + group = rgroup->obj; + group->buttons = ucx_list_append(group->buttons, button); + group->ref++; + } else { + group = malloc(sizeof(RadioButtonGroup)); + group->buttons = ucx_list_append(NULL, button); + group->current = button; + // this is the first button in the radiobutton group + // so we should enable it + Arg arg; + XtSetArg(arg, XmNset, TRUE); + XtSetValues(button, &arg, 1); + rgroup->obj = group; + + group->current = button; + } + + RadioEventData *event = malloc(sizeof(RadioEventData)); + event->obj = obj; + event->callback = NULL; + event->userdata = NULL; + event->group = group; + XtAddCallback( + button, + XmNvalueChangedCallback, + (XtCallbackProc)radio_callback, + event); + + rgroup->get = ui_radiobutton_get; + rgroup->set = ui_radiobutton_set; + } + + XtManageChild(button); + return button; +} + +int64_t ui_radiobutton_get(UiInteger *value) { + RadioButtonGroup *group = value->obj; + + int i = ucx_list_find(group->buttons, group->current, NULL, NULL); + if (i >= 0) { + value->value = i; + return i; + } else { + return 0; + } +} + +void ui_radiobutton_set(UiInteger *value, int64_t i) { + RadioButtonGroup *group = value->obj; + Arg arg; + + XtSetArg(arg, XmNset, FALSE); + XtSetValues(group->current, &arg, 1); + + UcxList *elm = ucx_list_get(group->buttons, i); + if(elm) { + Widget button = elm->data; + XtSetArg(arg, XmNset, TRUE); + XtSetValues(button, &arg, 1); + group->current = button; + } +}