#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;
}