--- a/ui/motif/entry.c Fri Nov 14 22:02:00 2025 +0100 +++ b/ui/motif/entry.c Sat Nov 15 09:24:55 2025 +0100 @@ -106,46 +106,160 @@ 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->last_value = 0; + 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) { - char buf[32]; + Boolean update_value = TRUE; + double value = spinbox->value; switch(cb->reason) { - case 62: { - spinbox->last_value += spinbox->increment; - snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); - XmTextFieldSetString(spinbox->textfield, buf); + case XmCR_OK: { + update_value = FALSE; break; } - case 63: { - spinbox->last_value -= spinbox->increment; - snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); - XmTextFieldSetString(spinbox->textfield, buf); + 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); + } } + +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; +}