Fri, 12 Dec 2025 12:44:03 +0100
fix uic_store_app_properties
/* * 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->states); WidgetList children; Cardinal num_children; unsigned char type; Widget textfield = NULL; XtVaGetValues( spinbox, XmNchildren, &children, XmNnumChildren, &num_children, NULL); for(int i = 0;i<num_children;i++) { XtVaGetValues(children[i], XmNspinBoxChildType, &type, NULL); Widget w = children[i]; if(type == XmNUMERIC) { textfield = children[i]; } } UiSpinBox *data = malloc(sizeof(UiSpinBox)); data->obj = obj; data->textfield = textfield; data->var = var; data->vartype = vartype; data->obs = NULL; data->onchange = args->onchange; data->onchangedata = args->onchangedata; data->value = 0; data->min = min; data->max = max; data->increment = args->step; data->digits = args->digits; UiObserver **obs = NULL; if(var) { double value = 0; switch(vartype) { default: break; case UI_VAR_INTEGER: { UiInteger *i = var->value; i->get = ui_spinbutton_getint; i->set = ui_spinbutton_setint; i->obj = data; value = (double)i->value; obs = &i->observers; break; } case UI_VAR_DOUBLE: { UiDouble *d = var->value; d->get = ui_spinbutton_getdouble; d->set = ui_spinbutton_setdouble; d->obj = data; value = d->value; obs = &d->observers; break; } case UI_VAR_RANGE: { UiRange *r = var->value; r->get = ui_spinbutton_getrangeval; r->set = ui_spinbutton_setrangeval; r->setrange = ui_spinbutton_setrange; r->setextent = ui_spinbutton_setextent; r->obj = data; value = r->value; obs = &r->observers; break; } } ui_spinbox_set_value(data, value); } data->obs = obs; XtAddCallback( spinbox, XmNvalueChangedCallback, (XtCallbackProc)ui_spinbox_value_changed, data); XtAddCallback( spinbox, XmNdestroyCallback, (XtCallbackProc)ui_destroy_data, data); XmTextFieldSetString(textfield, "0"); return spinbox; } void ui_spinbox_set_value(UiSpinBox *spinbox, double value) { if(value < spinbox->min) { value = spinbox->min; } if(value > spinbox->max) { value = spinbox->max; } char buf[32]; snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->value); XmTextFieldSetString(spinbox->textfield, buf); spinbox->value = value; } void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb) { Boolean update_value = TRUE; double value = spinbox->value; switch(cb->reason) { case XmCR_OK: { update_value = FALSE; break; } case XmCR_SPIN_NEXT: { value += spinbox->increment; break; } case XmCR_SPIN_PRIOR: { value -= spinbox->increment; break; } } if(update_value) { ui_spinbox_set_value(spinbox, value); UiEvent event; event.obj = spinbox->obj; event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = NULL; event.eventdatatype = 0; event.intval = (int64_t)value; event.set = ui_get_setop(); if(spinbox->onchange) { spinbox->onchange(&event, spinbox->onchangedata); } UiObserver *obs = *spinbox->obs; ui_notify_evt(*spinbox->obs, &event); } } int64_t ui_spinbutton_getint(UiInteger *i) { UiSpinBox *spinbox = i->obj; i->value = (int64_t)spinbox->value; return i->value; } void ui_spinbutton_setint(UiInteger *i, int64_t val) { UiSpinBox *spinbox = i->obj; ui_spinbox_set_value(spinbox, (double)val); i->value = spinbox->value; } double ui_spinbutton_getdouble(UiDouble *d) { UiSpinBox *spinbox = d->obj; d->value = spinbox->value; return d->value; } void ui_spinbutton_setdouble(UiDouble *d, double val) { UiSpinBox *spinbox = d->obj; ui_spinbox_set_value(spinbox, val); d->value = spinbox->value; } double ui_spinbutton_getrangeval(UiRange *r) { UiSpinBox *spinbox = r->obj; r->value = spinbox->value; return r->value; } void ui_spinbutton_setrangeval(UiRange *r, double val) { UiSpinBox *spinbox = r->obj; ui_spinbox_set_value(spinbox, val); r->value = spinbox->value; } void ui_spinbutton_setrange(UiRange *r, double min, double max) { UiSpinBox *spinbox = r->obj; spinbox->min = min; spinbox->max = max; r->min = min; r->max = max; } void ui_spinbutton_setextent(UiRange *r, double extent) { UiSpinBox *spinbox = r->obj; spinbox->increment = extent; r->extent = extent; }