# HG changeset patch # User Olaf Wintermann # Date 1763154120 -3600 # Node ID 0d488f04078d13807d87cf153a33c6269104735f # Parent ae0ad20122ccaa38cda760ba0399719456a5ed28 add spinbox (Motif) diff -r ae0ad20122cc -r 0d488f04078d application/main.c --- a/application/main.c Thu Nov 13 21:29:00 2025 +0100 +++ b/application/main.c Fri Nov 14 22:02:00 2025 +0100 @@ -995,7 +995,7 @@ */ ui_button(obj, .label = "Next Tab", .onclick = action_next_tab); - ui_tabview_w(obj, wdata->tabview, .tabview = UI_TABVIEW_INVISIBLE, .value = wdata->tab, .fill = UI_ON) { + ui_tabview_w(obj, wdata->tabview, .value = wdata->tab, .fill = UI_ON) { ui_tab(obj, "Tab 1") { ui_textarea(obj, .varname = "text", .fill = UI_ON); } @@ -1009,6 +1009,12 @@ ui_tab(obj, "Tab 3") { ui_button(obj, .label = "Test Tab 3", .onclick = action_remove_tab3); } + + ui_tab(obj, "Tab 4") { + ui_grid(obj, .margin = 10) { + ui_spinbox(obj, .varname = "num1"); + } + } } diff -r ae0ad20122cc -r 0d488f04078d ui/motif/entry.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/motif/entry.c Fri Nov 14 22:02:00 2025 +0100 @@ -0,0 +1,151 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2025 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 "entry.h" + + +UIWIDGET ui_spinbox_create(UiObject *obj, UiSpinBoxArgs *args) { + Arg xargs[16]; + int n = 0; + + double min = args->min; + double max = args->max != 0 ? args->max : 1000; + + UiVar *var = NULL; + UiVarType vartype = 0; + if(args->varname) { + var = uic_get_var(obj->ctx, args->varname); + if(var) { + vartype = var->type; + } else { + var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, args->varname, UI_VAR_RANGE); + vartype = UI_VAR_RANGE; + } + } + + if(!var) { + if(args->intvalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->intvalue, NULL, UI_VAR_INTEGER); + vartype = UI_VAR_INTEGER; + } else if(args->doublevalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE); + vartype = UI_VAR_DOUBLE; + } else if(args->rangevalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, NULL, UI_VAR_RANGE); + vartype = UI_VAR_RANGE; + } + } + + if(vartype == UI_VAR_RANGE) { + UiRange *r = var->value; + min = r->min; + max = r->max; + } + if(args->step == 0) { + args->step = 1; + } + + UiContainerPrivate *ctn = ui_obj_container(obj); + UiLayout layout = UI_ARGS2LAYOUT(args); + + + XtSetArg(xargs[n], XmNminimumValue, 0); n++; + XtSetArg(xargs[n], XmNmaximumValue, 100); n++; + XtSetArg(xargs[n], XmNincrementValue, 1); n++; + XtSetArg(xargs[n], XmNspinBoxChildType, XmNUMERIC); n++; + + Widget parent = ui_container_prepare(ctn, &layout, xargs, &n); + + char *name = args->name ? (char*)args->name : "button"; + Widget spinbox = XmCreateSimpleSpinBox(parent, name, xargs, n); + XtManageChild(spinbox); + ui_container_add(ctn, spinbox); + + ui_set_widget_groups(obj->ctx, spinbox, args->groups); + + WidgetList children; + Cardinal num_children; + unsigned char type; + + Widget textfield = NULL; + XtVaGetValues( + spinbox, + XmNchildren, &children, + XmNnumChildren, &num_children, + NULL); + + for(int i = 0;iobj = obj; + data->textfield = textfield; + data->var = var; + data->vartype = vartype; + data->onchange = args->onchange; + data->onchangedata = args->onchangedata; + data->last_value = 0; + data->min = min; + data->max = max; + data->increment = args->step; + data->digits = args->digits; + + XtAddCallback( + spinbox, + XmNvalueChangedCallback, + (XtCallbackProc)ui_spinbox_value_changed, + data); + + XmTextFieldSetString(textfield, "0"); + + + return spinbox; +} + +void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb) { + char buf[32]; + switch(cb->reason) { + case 62: { + spinbox->last_value += spinbox->increment; + snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); + XmTextFieldSetString(spinbox->textfield, buf); + break; + } + case 63: { + spinbox->last_value -= spinbox->increment; + snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); + XmTextFieldSetString(spinbox->textfield, buf); + break; + } + } +} diff -r ae0ad20122cc -r 0d488f04078d ui/motif/entry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/motif/entry.h Fri Nov 14 22:02:00 2025 +0100 @@ -0,0 +1,63 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2025 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. + */ + +#ifndef ENTRY_H +#define ENTRY_H + +#include "../ui/entry.h" +#include "container.h" +#include "toolkit.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct UiSpinBox { + UiObject *obj; + Widget textfield; + UiVar *var; + UiVarType vartype; + ui_callback onchange; + void* onchangedata; + double last_value; + double min; + double max; + double increment; + int digits; +} UiSpinBox; + +void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb); + +#ifdef __cplusplus +} +#endif + +#endif /* ENTRY_H */ + diff -r ae0ad20122cc -r 0d488f04078d ui/motif/objs.mk --- a/ui/motif/objs.mk Thu Nov 13 21:29:00 2025 +0100 +++ b/ui/motif/objs.mk Fri Nov 14 22:02:00 2025 +0100 @@ -45,6 +45,7 @@ MOTIFOBJ += dnd.o MOTIFOBJ += image.o MOTIFOBJ += Grid.o +MOTIFOBJ += entry.o TOOLKITOBJS += $(MOTIFOBJ:%=$(MOTIF_OBJPRE)%) TOOLKITSOURCE += $(MOTIFOBJ:%.o=motif/%.c)