revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / muimaster / classes / numeric.c
bloba5c01e3e639ddf3c88fab74e4fa9c458841e498c
1 /*
2 Copyright © 2002-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <devices/rawkeycodes.h>
7 #include <stdio.h>
9 #include <clib/alib_protos.h>
10 #include <proto/exec.h>
11 #include <proto/intuition.h>
12 #include <proto/graphics.h>
13 #include <proto/utility.h>
14 #include <proto/muimaster.h>
16 #include "debug.h"
17 #include "mui.h"
18 #include "muimaster_intern.h"
19 #include "support.h"
21 struct MUI_NumericData
23 STRPTR format;
24 LONG defvalue;
25 LONG max;
26 LONG min;
27 LONG value;
28 ULONG flags;
29 struct MUI_EventHandlerNode ehn;
30 char buf[50];
33 enum numeric_flags
35 NUMERIC_REVERSE = (1 << 0),
36 NUMERIC_REVLEFTRIGHT = (1 << 1),
37 NUMERIC_REVUPDOWN = (1 << 2),
38 NUMERIC_CHECKALLSIZES = (1 << 3),
41 extern struct Library *MUIMasterBase;
43 /**************************************************************************
44 OM_NEW
45 **************************************************************************/
46 IPTR Numeric__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
48 struct MUI_NumericData *data;
49 struct TagItem *tags, *tag;
51 BOOL value_set = FALSE;
53 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
54 if (!obj)
55 return 0;
57 data = INST_DATA(cl, obj);
58 data->format = "%ld";
59 data->max = 100;
60 data->min = 0;
61 data->flags = 0;
63 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
65 switch (tag->ti_Tag)
67 case MUIA_Numeric_CheckAllSizes:
68 _handle_bool_tag(data->flags, tag->ti_Data,
69 NUMERIC_CHECKALLSIZES);
70 break;
71 case MUIA_Numeric_Default:
72 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
73 data->defvalue = tag->ti_Data;
74 break;
75 case MUIA_Numeric_Format:
76 data->format = (STRPTR) tag->ti_Data;
77 break;
78 case MUIA_Numeric_Max:
79 data->max = tag->ti_Data;
80 break;
81 case MUIA_Numeric_Min:
82 data->min = tag->ti_Data;
83 break;
84 case MUIA_Numeric_Reverse:
85 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
86 break;
87 case MUIA_Numeric_RevLeftRight:
88 _handle_bool_tag(data->flags, tag->ti_Data,
89 NUMERIC_REVLEFTRIGHT);
90 break;
91 case MUIA_Numeric_RevUpDown:
92 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
93 break;
94 case MUIA_Numeric_Value:
95 value_set = TRUE;
96 data->value = (LONG) tag->ti_Data;
97 break;
101 data->value =
102 CLAMP(value_set ? data->value : data->defvalue, data->min,
103 data->max);
105 return (IPTR) obj;
108 /**************************************************************************
109 OM_SET
110 **************************************************************************/
111 IPTR Numeric__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
113 struct MUI_NumericData *data = INST_DATA(cl, obj);
114 struct TagItem *tags, *tag;
115 LONG oldval, oldmin, oldmax;
116 STRPTR oldfmt;
117 IPTR ret;
118 BOOL values_changed = FALSE;
120 oldval = data->value;
121 oldfmt = data->format;
122 oldmin = data->min;
123 oldmax = data->max;
125 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
127 switch (tag->ti_Tag)
129 case MUIA_Numeric_CheckAllSizes:
130 _handle_bool_tag(data->flags, tag->ti_Data,
131 NUMERIC_CHECKALLSIZES);
132 break;
133 case MUIA_Numeric_Default:
134 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
135 data->defvalue = tag->ti_Data;
136 break;
137 case MUIA_Numeric_Format:
138 data->format = (STRPTR) tag->ti_Data;
139 break;
140 case MUIA_Numeric_Max:
141 data->max = tag->ti_Data;
142 data->value = CLAMP(data->value, data->min, data->max);
143 break;
144 case MUIA_Numeric_Min:
145 data->min = tag->ti_Data;
146 data->value = CLAMP(data->value, data->min, data->max);
147 break;
148 case MUIA_Numeric_Reverse:
149 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
150 break;
151 case MUIA_Numeric_RevLeftRight:
152 _handle_bool_tag(data->flags, tag->ti_Data,
153 NUMERIC_REVLEFTRIGHT);
154 break;
155 case MUIA_Numeric_RevUpDown:
156 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
157 break;
158 case MUIA_Numeric_Value:
159 tag->ti_Data = CLAMP((LONG) tag->ti_Data, data->min, data->max);
161 if (data->value == (LONG) tag->ti_Data)
162 tag->ti_Tag = TAG_IGNORE;
163 else
164 data->value = (LONG) tag->ti_Data;
166 break;
170 /* If the max, min or format values changed, then the minimum and maximum
171 sizes of the string output by MUIM_Numeric_Stringify may have changed,
172 so give the subclass a chance to recalculate them and relayout the group
173 accordingly. Basically, the subclass will have to react on changes to
174 these values as well (by setting a notification on them, or by
175 overriding OM_SET) and then recalculate the minimum and maximum sizes
176 for the object. */
177 if (data->format != oldfmt || data->min != oldmin
178 || data->max != oldmax)
180 values_changed = TRUE;
181 Object *parent = _parent(obj);
182 if (parent)
184 DoMethod(parent, MUIM_Group_InitChange);
185 DoMethod(parent, MUIM_Group_ExitChange);
189 ret = DoSuperMethodA(cl, obj, (Msg) msg);
191 if (data->value != oldval || values_changed)
193 MUI_Redraw(obj, MADF_DRAWUPDATE);
196 return ret;
199 /**************************************************************************
200 OM_GET
201 **************************************************************************/
202 IPTR Numeric__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
204 struct MUI_NumericData *data = INST_DATA(cl, obj);
205 IPTR *store = msg->opg_Storage;
206 ULONG tag = msg->opg_AttrID;
208 switch (tag)
210 case MUIA_Numeric_CheckAllSizes:
211 *store = ((data->flags & NUMERIC_CHECKALLSIZES) != 0);
212 return TRUE;
214 case MUIA_Numeric_Default:
215 *store = data->defvalue;
216 return TRUE;
218 case MUIA_Numeric_Format:
219 *store = (IPTR) data->format;
220 return TRUE;
222 case MUIA_Numeric_Max:
223 *store = data->max;
224 return TRUE;
226 case MUIA_Numeric_Min:
227 *store = data->min;
228 return TRUE;
230 case MUIA_Numeric_Reverse:
231 *store = ((data->flags & NUMERIC_REVERSE) != 0);
232 return TRUE;
234 case MUIA_Numeric_RevLeftRight:
235 *store = ((data->flags & NUMERIC_REVLEFTRIGHT) != 0);
236 return TRUE;
238 case MUIA_Numeric_RevUpDown:
239 *store = ((data->flags & NUMERIC_REVUPDOWN) != 0);
240 return TRUE;
242 case MUIA_Numeric_Value:
243 *store = data->value;
244 return TRUE;
247 return DoSuperMethodA(cl, obj, (Msg) msg);
250 /**************************************************************************
251 MUIM_Setup
252 **************************************************************************/
253 IPTR Numeric__MUIM_Setup(struct IClass *cl, Object *obj,
254 struct MUIP_Setup *msg)
256 struct MUI_NumericData *data = INST_DATA(cl, obj);
258 if (!DoSuperMethodA(cl, obj, (Msg) msg))
259 return FALSE;
261 data->ehn.ehn_Events = IDCMP_RAWKEY;
262 data->ehn.ehn_Priority = 0;
263 data->ehn.ehn_Flags = 0;
264 data->ehn.ehn_Object = obj;
265 data->ehn.ehn_Class = cl;
266 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) (&data->ehn));
268 return TRUE;
271 /**************************************************************************
272 MUIM_Cleanup
273 **************************************************************************/
274 IPTR Numeric__MUIM_Cleanup(struct IClass *cl, Object *obj,
275 struct MUIP_Cleanup *msg)
277 struct MUI_NumericData *data = INST_DATA(cl, obj);
279 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) (&data->ehn));
280 return DoSuperMethodA(cl, obj, (Msg) msg);
283 /**************************************************************************
284 MUIM_HandleEvent
285 **************************************************************************/
286 IPTR Numeric__MUIM_HandleEvent(struct IClass *cl, Object *obj,
287 struct MUIP_HandleEvent *msg)
289 struct MUI_NumericData *data = INST_DATA(cl, obj);
290 IPTR result = 0;
291 BOOL increase, change;
293 if (msg->muikey != MUIKEY_NONE)
295 LONG step;
296 BOOL use_absolute = FALSE, is_horizontal = FALSE;
298 result = MUI_EventHandlerRC_Eat;
300 if (data->max - data->min < 10)
301 step = 1;
302 else
303 step = 10;
305 switch (msg->muikey)
307 case MUIKEY_PRESS:
308 return MUI_EventHandlerRC_Eat;
310 case MUIKEY_TOGGLE:
311 DoMethod(obj, MUIM_Numeric_SetDefault);
312 return MUI_EventHandlerRC_Eat;
314 case MUIKEY_RELEASE:
315 return MUI_EventHandlerRC_Eat;
317 case MUIKEY_TOP:
318 case MUIKEY_LINESTART:
319 use_absolute = TRUE;
320 is_horizontal = TRUE;
321 step = -1;
322 break;
324 case MUIKEY_BOTTOM:
325 case MUIKEY_LINEEND:
326 use_absolute = TRUE;
327 is_horizontal = TRUE;
328 step = 1;
329 break;
331 case MUIKEY_LEFT:
332 is_horizontal = TRUE;
333 step = -1;
334 break;
336 case MUIKEY_RIGHT:
337 is_horizontal = TRUE;
338 step = 1;
339 break;
341 case MUIKEY_UP:
342 step = -1;
343 break;
345 case MUIKEY_DOWN:
346 step = 1;
347 break;
349 case MUIKEY_PAGEDOWN:
350 case MUIKEY_WORDRIGHT:
351 break;
353 case MUIKEY_PAGEUP:
354 case MUIKEY_WORDLEFT:
355 step = -step;
356 break;
358 default:
359 return 0;
362 /* Send gadget in proper direction */
363 if (step != 0)
365 if (data->flags & NUMERIC_REVERSE)
366 step = -step;
368 if ((is_horizontal && (data->flags & NUMERIC_REVLEFTRIGHT) != 0)
369 || (!is_horizontal && (data->flags & NUMERIC_REVUPDOWN) != 0))
370 step = -step;
372 if (use_absolute)
374 if (step > 0)
375 step = data->max;
376 else
377 step = data->min;
378 step -= data->value;
381 DoMethod(obj, MUIM_Numeric_Increase, step);
384 else if (msg->imsg->Class == IDCMP_RAWKEY
385 && _isinobject(obj, msg->imsg->MouseX, msg->imsg->MouseY))
387 change = TRUE;
388 switch (msg->imsg->Code)
390 case RAWKEY_NM_WHEEL_UP:
391 increase = FALSE;
392 break;
393 case RAWKEY_NM_WHEEL_DOWN:
394 increase = TRUE;
395 break;
396 default:
397 change = FALSE;
399 if (change)
401 if (data->flags & NUMERIC_REVERSE)
402 increase = !increase;
403 DoMethod(obj, increase ?
404 MUIM_Numeric_Increase : MUIM_Numeric_Decrease, 1);
405 result = MUI_EventHandlerRC_Eat;
409 return result;
413 /**************************************************************************
414 MUIM_Numeric_Decrease
415 **************************************************************************/
416 IPTR Numeric__MUIM_Decrease(struct IClass *cl, Object *obj,
417 struct MUIP_Numeric_Decrease *msg)
419 struct MUI_NumericData *data = INST_DATA(cl, obj);
420 LONG newval = CLAMP(data->value - msg->amount, data->min, data->max);
421 if (newval != data->value)
422 set(obj, MUIA_Numeric_Value, newval);
424 return 1;
427 /**************************************************************************
428 MUIM_Numeric_Increase
429 **************************************************************************/
430 IPTR Numeric__MUIM_Increase(struct IClass *cl, Object *obj,
431 struct MUIP_Numeric_Increase *msg)
433 struct MUI_NumericData *data = INST_DATA(cl, obj);
434 LONG newval = CLAMP(data->value + msg->amount, data->min, data->max);
436 if (newval != data->value)
437 set(obj, MUIA_Numeric_Value, newval);
439 return 1;
443 /**************************************************************************
444 MUIM_Numeric_ScaleToValue
445 **************************************************************************/
446 IPTR Numeric__MUIM_ScaleToValue(struct IClass *cl, Object *obj,
447 struct MUIP_Numeric_ScaleToValue *msg)
449 struct MUI_NumericData *data = INST_DATA(cl, obj);
450 LONG min, max;
451 LONG val;
452 LONG d;
454 min = (data->flags & NUMERIC_REVERSE) ? data->max : data->min;
455 max = (data->flags & NUMERIC_REVERSE) ? data->min : data->max;
457 val = CLAMP(msg->scale - msg->scalemin, msg->scalemin, msg->scalemax);
458 d = msg->scalemax - msg->scalemin;
460 // FIXME: watch out for overflow here.
461 val = val * (max - min);
463 if (d)
464 val /= d;
466 val += min;
468 return val;
471 /**************************************************************************
472 MUIM_Numeric_SetDefault
473 **************************************************************************/
474 IPTR Numeric__MUIM_SetDefault(struct IClass *cl, Object *obj, Msg msg)
476 struct MUI_NumericData *data = INST_DATA(cl, obj);
478 set(obj, MUIA_Numeric_Value, CLAMP(data->defvalue, data->min,
479 data->max));
481 return 0;
484 /**************************************************************************
485 MUIM_Numeric_Stringify
486 **************************************************************************/
487 IPTR Numeric__MUIM_Stringify(struct IClass *cl, Object *obj,
488 struct MUIP_Numeric_Stringify *msg)
490 struct MUI_NumericData *data = INST_DATA(cl, obj);
492 /* TODO: use RawDoFmt() and buffer overrun */
493 snprintf(data->buf, 49, data->format, (long)msg->value);
494 data->buf[49] = 0;
496 return (IPTR) data->buf;
499 /**************************************************************************
500 MUIM_Numeric_ValueToScale
501 **************************************************************************/
502 IPTR Numeric__MUIM_ValueToScale(struct IClass *cl, Object *obj,
503 struct MUIP_Numeric_ValueToScale *msg)
505 LONG val;
506 struct MUI_NumericData *data = INST_DATA(cl, obj);
507 LONG min, max;
509 min = (data->flags & NUMERIC_REVERSE) ? msg->scalemax : msg->scalemin;
510 max = (data->flags & NUMERIC_REVERSE) ? msg->scalemin : msg->scalemax;
512 if (data->max != data->min)
514 val =
515 min + ((data->value - data->min) * (max - min) + (data->max -
516 data->min) / 2) / (data->max - data->min);
518 else
520 val = min;
523 val = CLAMP(val, msg->scalemin, msg->scalemax);
525 return val;
528 /**************************************************************************
529 MUIM_Numeric_ValueToScaleExt
530 **************************************************************************/
531 IPTR Numeric__MUIM_ValueToScaleExt(struct IClass *cl, Object *obj,
532 struct MUIP_Numeric_ValueToScaleExt *msg)
534 LONG scale;
535 LONG value;
536 struct MUI_NumericData *data = INST_DATA(cl, obj);
537 LONG min, max;
539 value = CLAMP(msg->value, data->min, data->max);
540 min = (data->flags & NUMERIC_REVERSE) ? msg->scalemax : msg->scalemin;
541 max = (data->flags & NUMERIC_REVERSE) ? msg->scalemin : msg->scalemax;
543 if (data->max != data->min)
545 scale =
546 min + ((value - data->min) * (max - min) + (data->max -
547 data->min) / 2) / (data->max - data->min);
549 else
551 scale = min;
554 scale = CLAMP(scale, msg->scalemin, msg->scalemax);
556 return scale;
559 /**************************************************************************
560 MUIM_Export - to export an object's "contents" to a dataspace object.
561 **************************************************************************/
562 IPTR Numeric__MUIM_Export(struct IClass *cl, Object *obj,
563 struct MUIP_Export *msg)
565 struct MUI_NumericData *data = INST_DATA(cl, obj);
566 ULONG id;
568 if ((id = muiNotifyData(obj)->mnd_ObjectID))
570 LONG value = data->value;
571 DoMethod(msg->dataspace, MUIM_Dataspace_Add,
572 (IPTR) & value, sizeof(value), (IPTR) id);
574 return 0;
577 /**************************************************************************
578 MUIM_Import - to import an object's "contents" from a dataspace object.
579 **************************************************************************/
580 IPTR Numeric__MUIM_Import(struct IClass *cl, Object *obj,
581 struct MUIP_Import *msg)
583 ULONG id;
584 LONG *s;
586 if ((id = muiNotifyData(obj)->mnd_ObjectID))
588 if ((s = (LONG *) DoMethod(msg->dataspace, MUIM_Dataspace_Find,
589 (IPTR) id)))
591 set(obj, MUIA_Numeric_Value, *s);
595 return 0;
599 BOOPSI_DISPATCHER(IPTR, Numeric_Dispatcher, cl, obj, msg)
601 switch (msg->MethodID)
603 case OM_NEW:
604 return Numeric__OM_NEW(cl, obj, (APTR) msg);
605 case OM_SET:
606 return Numeric__OM_SET(cl, obj, (APTR) msg);
607 case OM_GET:
608 return Numeric__OM_GET(cl, obj, (APTR) msg);
610 case MUIM_Setup:
611 return Numeric__MUIM_Setup(cl, obj, (APTR) msg);
612 case MUIM_Cleanup:
613 return Numeric__MUIM_Cleanup(cl, obj, (APTR) msg);
614 case MUIM_HandleEvent:
615 return Numeric__MUIM_HandleEvent(cl, obj, (APTR) msg);
616 case MUIM_Numeric_Decrease:
617 return Numeric__MUIM_Decrease(cl, obj, (APTR) msg);
618 case MUIM_Numeric_Increase:
619 return Numeric__MUIM_Increase(cl, obj, (APTR) msg);
620 case MUIM_Numeric_ScaleToValue:
621 return Numeric__MUIM_ScaleToValue(cl, obj, (APTR) msg);
622 case MUIM_Numeric_SetDefault:
623 return Numeric__MUIM_SetDefault(cl, obj, (APTR) msg);
624 case MUIM_Numeric_Stringify:
625 return Numeric__MUIM_Stringify(cl, obj, (APTR) msg);
626 case MUIM_Numeric_ValueToScale:
627 return Numeric__MUIM_ValueToScale(cl, obj, (APTR) msg);
628 case MUIM_Numeric_ValueToScaleExt:
629 return Numeric__MUIM_ValueToScaleExt(cl, obj, (APTR) msg);
630 case MUIM_Export:
631 return Numeric__MUIM_Export(cl, obj, (APTR) msg);
632 case MUIM_Import:
633 return Numeric__MUIM_Import(cl, obj, (APTR) msg);
636 return DoSuperMethodA(cl, obj, msg);
638 BOOPSI_DISPATCHER_END
641 * Class descriptor.
643 const struct __MUIBuiltinClass _MUI_Numeric_desc =
645 MUIC_Numeric,
646 MUIC_Area,
647 sizeof(struct MUI_NumericData),
648 (void *) Numeric_Dispatcher