| |
1 /* |
| |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| |
3 * |
| |
4 * Copyright 2025 Olaf Wintermann. All rights reserved. |
| |
5 * |
| |
6 * Redistribution and use in source and binary forms, with or without |
| |
7 * modification, are permitted provided that the following conditions are met: |
| |
8 * |
| |
9 * 1. Redistributions of source code must retain the above copyright |
| |
10 * notice, this list of conditions and the following disclaimer. |
| |
11 * |
| |
12 * 2. Redistributions in binary form must reproduce the above copyright |
| |
13 * notice, this list of conditions and the following disclaimer in the |
| |
14 * documentation and/or other materials provided with the distribution. |
| |
15 * |
| |
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| |
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| |
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| |
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| |
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| |
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| |
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| |
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| |
26 * POSSIBILITY OF SUCH DAMAGE. |
| |
27 */ |
| |
28 |
| |
29 #include "entry.h" |
| |
30 |
| |
31 |
| |
32 UIWIDGET ui_spinbox_create(UiObject *obj, UiSpinBoxArgs *args) { |
| |
33 Arg xargs[16]; |
| |
34 int n = 0; |
| |
35 |
| |
36 double min = args->min; |
| |
37 double max = args->max != 0 ? args->max : 1000; |
| |
38 |
| |
39 UiVar *var = NULL; |
| |
40 UiVarType vartype = 0; |
| |
41 if(args->varname) { |
| |
42 var = uic_get_var(obj->ctx, args->varname); |
| |
43 if(var) { |
| |
44 vartype = var->type; |
| |
45 } else { |
| |
46 var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, args->varname, UI_VAR_RANGE); |
| |
47 vartype = UI_VAR_RANGE; |
| |
48 } |
| |
49 } |
| |
50 |
| |
51 if(!var) { |
| |
52 if(args->intvalue) { |
| |
53 var = uic_widget_var(obj->ctx, obj->ctx, args->intvalue, NULL, UI_VAR_INTEGER); |
| |
54 vartype = UI_VAR_INTEGER; |
| |
55 } else if(args->doublevalue) { |
| |
56 var = uic_widget_var(obj->ctx, obj->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE); |
| |
57 vartype = UI_VAR_DOUBLE; |
| |
58 } else if(args->rangevalue) { |
| |
59 var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, NULL, UI_VAR_RANGE); |
| |
60 vartype = UI_VAR_RANGE; |
| |
61 } |
| |
62 } |
| |
63 |
| |
64 if(vartype == UI_VAR_RANGE) { |
| |
65 UiRange *r = var->value; |
| |
66 min = r->min; |
| |
67 max = r->max; |
| |
68 } |
| |
69 if(args->step == 0) { |
| |
70 args->step = 1; |
| |
71 } |
| |
72 |
| |
73 UiContainerPrivate *ctn = ui_obj_container(obj); |
| |
74 UiLayout layout = UI_ARGS2LAYOUT(args); |
| |
75 |
| |
76 |
| |
77 XtSetArg(xargs[n], XmNminimumValue, 0); n++; |
| |
78 XtSetArg(xargs[n], XmNmaximumValue, 100); n++; |
| |
79 XtSetArg(xargs[n], XmNincrementValue, 1); n++; |
| |
80 XtSetArg(xargs[n], XmNspinBoxChildType, XmNUMERIC); n++; |
| |
81 |
| |
82 Widget parent = ui_container_prepare(ctn, &layout, xargs, &n); |
| |
83 |
| |
84 char *name = args->name ? (char*)args->name : "button"; |
| |
85 Widget spinbox = XmCreateSimpleSpinBox(parent, name, xargs, n); |
| |
86 XtManageChild(spinbox); |
| |
87 ui_container_add(ctn, spinbox); |
| |
88 |
| |
89 ui_set_widget_groups(obj->ctx, spinbox, args->groups); |
| |
90 |
| |
91 WidgetList children; |
| |
92 Cardinal num_children; |
| |
93 unsigned char type; |
| |
94 |
| |
95 Widget textfield = NULL; |
| |
96 XtVaGetValues( |
| |
97 spinbox, |
| |
98 XmNchildren, &children, |
| |
99 XmNnumChildren, &num_children, |
| |
100 NULL); |
| |
101 |
| |
102 for(int i = 0;i<num_children;i++) { |
| |
103 XtVaGetValues(children[i], XmNspinBoxChildType, &type, NULL); |
| |
104 Widget w = children[i]; |
| |
105 if(type == XmNUMERIC) { |
| |
106 textfield = children[i]; |
| |
107 } |
| |
108 } |
| |
109 |
| |
110 UiSpinBox *data = malloc(sizeof(UiSpinBox)); |
| |
111 data->obj = obj; |
| |
112 data->textfield = textfield; |
| |
113 data->var = var; |
| |
114 data->vartype = vartype; |
| |
115 data->onchange = args->onchange; |
| |
116 data->onchangedata = args->onchangedata; |
| |
117 data->last_value = 0; |
| |
118 data->min = min; |
| |
119 data->max = max; |
| |
120 data->increment = args->step; |
| |
121 data->digits = args->digits; |
| |
122 |
| |
123 XtAddCallback( |
| |
124 spinbox, |
| |
125 XmNvalueChangedCallback, |
| |
126 (XtCallbackProc)ui_spinbox_value_changed, |
| |
127 data); |
| |
128 |
| |
129 XmTextFieldSetString(textfield, "0"); |
| |
130 |
| |
131 |
| |
132 return spinbox; |
| |
133 } |
| |
134 |
| |
135 void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb) { |
| |
136 char buf[32]; |
| |
137 switch(cb->reason) { |
| |
138 case 62: { |
| |
139 spinbox->last_value += spinbox->increment; |
| |
140 snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); |
| |
141 XmTextFieldSetString(spinbox->textfield, buf); |
| |
142 break; |
| |
143 } |
| |
144 case 63: { |
| |
145 spinbox->last_value -= spinbox->increment; |
| |
146 snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value); |
| |
147 XmTextFieldSetString(spinbox->textfield, buf); |
| |
148 break; |
| |
149 } |
| |
150 } |
| |
151 } |