Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / numeric.c
blob6539f491350547346542c3c214fd79074ce04c22
1 /*
2 Copyright © 2002-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <stdio.h>
8 #include <clib/alib_protos.h>
9 #include <proto/exec.h>
10 #include <proto/intuition.h>
11 #include <proto/graphics.h>
12 #include <proto/utility.h>
13 #include <proto/muimaster.h>
15 #include "debug.h"
16 #include "mui.h"
17 #include "muimaster_intern.h"
18 #include "support.h"
20 struct MUI_NumericData
22 STRPTR format;
23 LONG defvalue;
24 LONG max;
25 LONG min;
26 LONG value;
27 ULONG flags;
28 struct MUI_EventHandlerNode ehn;
29 char buf[50];
32 enum numeric_flags
34 NUMERIC_REVERSE = (1 << 0),
35 NUMERIC_REVLEFTRIGHT = (1 << 1),
36 NUMERIC_REVUPDOWN = (1 << 2),
37 NUMERIC_CHECKALLSIZES = (1 << 3),
40 extern struct Library *MUIMasterBase;
42 /**************************************************************************
43 OM_NEW
44 **************************************************************************/
45 IPTR Numeric__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
47 struct MUI_NumericData *data;
48 struct TagItem *tags, *tag;
50 BOOL value_set = FALSE;
52 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
53 if (!obj)
54 return 0;
56 data = INST_DATA(cl, obj);
57 data->format = "%ld";
58 data->max = 100;
59 data->min = 0;
60 data->flags = 0;
62 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
64 switch (tag->ti_Tag)
66 case MUIA_Numeric_CheckAllSizes:
67 _handle_bool_tag(data->flags, tag->ti_Data,
68 NUMERIC_CHECKALLSIZES);
69 break;
70 case MUIA_Numeric_Default:
71 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
72 data->defvalue = tag->ti_Data;
73 break;
74 case MUIA_Numeric_Format:
75 data->format = (STRPTR) tag->ti_Data;
76 break;
77 case MUIA_Numeric_Max:
78 data->max = tag->ti_Data;
79 break;
80 case MUIA_Numeric_Min:
81 data->min = tag->ti_Data;
82 break;
83 case MUIA_Numeric_Reverse:
84 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
85 break;
86 case MUIA_Numeric_RevLeftRight:
87 _handle_bool_tag(data->flags, tag->ti_Data,
88 NUMERIC_REVLEFTRIGHT);
89 break;
90 case MUIA_Numeric_RevUpDown:
91 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
92 break;
93 case MUIA_Numeric_Value:
94 value_set = TRUE;
95 data->value = (LONG) tag->ti_Data;
96 break;
100 data->value =
101 CLAMP(value_set ? data->value : data->defvalue, data->min,
102 data->max);
104 return (IPTR) obj;
107 /**************************************************************************
108 OM_SET
109 **************************************************************************/
110 IPTR Numeric__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
112 struct MUI_NumericData *data = INST_DATA(cl, obj);
113 struct TagItem *tags, *tag;
114 LONG oldval, oldmin, oldmax;
115 STRPTR oldfmt;
116 IPTR ret;
117 BOOL values_changed = FALSE;
119 oldval = data->value;
120 oldfmt = data->format;
121 oldmin = data->min;
122 oldmax = data->max;
124 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
126 switch (tag->ti_Tag)
128 case MUIA_Numeric_CheckAllSizes:
129 _handle_bool_tag(data->flags, tag->ti_Data,
130 NUMERIC_CHECKALLSIZES);
131 break;
132 case MUIA_Numeric_Default:
133 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
134 data->defvalue = tag->ti_Data;
135 break;
136 case MUIA_Numeric_Format:
137 data->format = (STRPTR) tag->ti_Data;
138 break;
139 case MUIA_Numeric_Max:
140 data->max = tag->ti_Data;
141 break;
142 case MUIA_Numeric_Min:
143 data->min = tag->ti_Data;
144 break;
145 case MUIA_Numeric_Reverse:
146 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
147 break;
148 case MUIA_Numeric_RevLeftRight:
149 _handle_bool_tag(data->flags, tag->ti_Data,
150 NUMERIC_REVLEFTRIGHT);
151 break;
152 case MUIA_Numeric_RevUpDown:
153 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
154 break;
155 case MUIA_Numeric_Value:
156 tag->ti_Data = CLAMP((LONG) tag->ti_Data, data->min, data->max);
158 if (data->value == (LONG) tag->ti_Data)
159 tag->ti_Tag = TAG_IGNORE;
160 else
161 data->value = (LONG) tag->ti_Data;
163 break;
167 /* If the max, min or format values changed, then the minimum and maximum
168 sizes of the string output by MUIM_Numeric_Stringify may have changed,
169 so give the subclass a chance to recalculate them and relayout the group
170 accordingly. Basically, the subclass will have to react on changes to
171 these values as well (by setting a notification on them, or by
172 overriding OM_SET) and then recalculate the minimum and maximum sizes
173 for the object. */
174 if (data->format != oldfmt || data->min != oldmin
175 || data->max != oldmax)
177 values_changed = TRUE;
178 Object *parent = _parent(obj);
179 if (parent)
181 DoMethod(parent, MUIM_Group_InitChange);
182 DoMethod(parent, MUIM_Group_ExitChange);
186 ret = DoSuperMethodA(cl, obj, (Msg) msg);
188 if (data->value != oldval || values_changed)
190 MUI_Redraw(obj, MADF_DRAWUPDATE);
193 return ret;
196 /**************************************************************************
197 OM_GET
198 **************************************************************************/
199 IPTR Numeric__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
201 struct MUI_NumericData *data = INST_DATA(cl, obj);
202 IPTR *store = msg->opg_Storage;
203 ULONG tag = msg->opg_AttrID;
205 switch (tag)
207 case MUIA_Numeric_CheckAllSizes:
208 *store = ((data->flags & NUMERIC_CHECKALLSIZES) != 0);
209 return TRUE;
211 case MUIA_Numeric_Default:
212 *store = data->defvalue;
213 return TRUE;
215 case MUIA_Numeric_Format:
216 *store = (IPTR) data->format;
217 return TRUE;
219 case MUIA_Numeric_Max:
220 *store = data->max;
221 return TRUE;
223 case MUIA_Numeric_Min:
224 *store = data->min;
225 return TRUE;
227 case MUIA_Numeric_Reverse:
228 *store = ((data->flags & NUMERIC_REVERSE) != 0);
229 return TRUE;
231 case MUIA_Numeric_RevLeftRight:
232 *store = ((data->flags & NUMERIC_REVLEFTRIGHT) != 0);
233 return TRUE;
235 case MUIA_Numeric_RevUpDown:
236 *store = ((data->flags & NUMERIC_REVUPDOWN) != 0);
237 return TRUE;
239 case MUIA_Numeric_Value:
240 *store = data->value;
241 return TRUE;
244 return DoSuperMethodA(cl, obj, (Msg) msg);
247 /**************************************************************************
248 MUIM_Setup
249 **************************************************************************/
250 IPTR Numeric__MUIM_Setup(struct IClass *cl, Object *obj,
251 struct MUIP_Setup *msg)
253 struct MUI_NumericData *data = INST_DATA(cl, obj);
255 if (!DoSuperMethodA(cl, obj, (Msg) msg))
256 return FALSE;
258 data->ehn.ehn_Events = IDCMP_RAWKEY;
259 data->ehn.ehn_Priority = 0;
260 data->ehn.ehn_Flags = 0;
261 data->ehn.ehn_Object = obj;
262 data->ehn.ehn_Class = cl;
263 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) (&data->ehn));
265 return TRUE;
268 /**************************************************************************
269 MUIM_Cleanup
270 **************************************************************************/
271 IPTR Numeric__MUIM_Cleanup(struct IClass *cl, Object *obj,
272 struct MUIP_Cleanup *msg)
274 struct MUI_NumericData *data = INST_DATA(cl, obj);
276 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) (&data->ehn));
277 return DoSuperMethodA(cl, obj, (Msg) msg);
280 /**************************************************************************
281 MUIM_HandleEvent
282 **************************************************************************/
283 IPTR Numeric__MUIM_HandleEvent(struct IClass *cl, Object *obj,
284 struct MUIP_HandleEvent *msg)
286 struct MUI_NumericData *data = INST_DATA(cl, obj);
288 if (msg->muikey != MUIKEY_NONE)
290 LONG step;
292 if (data->max - data->min < 10)
293 step = 1;
294 else
295 step = 10;
297 switch (msg->muikey)
299 case MUIKEY_PRESS:
300 return MUI_EventHandlerRC_Eat;
302 case MUIKEY_TOGGLE:
303 DoMethod(obj, MUIM_Numeric_SetDefault);
304 return MUI_EventHandlerRC_Eat;
306 case MUIKEY_RELEASE:
307 return MUI_EventHandlerRC_Eat;
309 case MUIKEY_BOTTOM:
310 case MUIKEY_LINEEND:
311 if (data->flags & NUMERIC_REVUPDOWN)
312 set(obj, MUIA_Numeric_Value, data->min);
313 else
314 set(obj, MUIA_Numeric_Value, data->max);
315 return MUI_EventHandlerRC_Eat;
317 case MUIKEY_TOP:
318 case MUIKEY_LINESTART:
319 if (data->flags & NUMERIC_REVUPDOWN)
320 set(obj, MUIA_Numeric_Value, data->max);
321 else
322 set(obj, MUIA_Numeric_Value, data->min);
323 return MUI_EventHandlerRC_Eat;
325 case MUIKEY_LEFT:
326 if (data->flags & NUMERIC_REVLEFTRIGHT)
327 DoMethod(obj, MUIM_Numeric_Increase, 1);
328 else
329 DoMethod(obj, MUIM_Numeric_Decrease, 1);
330 return MUI_EventHandlerRC_Eat;
332 case MUIKEY_RIGHT:
333 if (data->flags & NUMERIC_REVLEFTRIGHT)
334 DoMethod(obj, MUIM_Numeric_Decrease, 1);
335 else
336 DoMethod(obj, MUIM_Numeric_Increase, 1);
337 return MUI_EventHandlerRC_Eat;
339 case MUIKEY_UP:
340 if (data->flags & NUMERIC_REVUPDOWN)
341 DoMethod(obj, MUIM_Numeric_Increase, 1);
342 else
343 DoMethod(obj, MUIM_Numeric_Decrease, 1);
344 return MUI_EventHandlerRC_Eat;
346 case MUIKEY_DOWN:
347 if (data->flags & NUMERIC_REVUPDOWN)
348 DoMethod(obj, MUIM_Numeric_Decrease, 1);
349 else
350 DoMethod(obj, MUIM_Numeric_Increase, 1);
351 return MUI_EventHandlerRC_Eat;
353 case MUIKEY_PAGEDOWN:
354 case MUIKEY_WORDRIGHT:
355 if (data->flags & NUMERIC_REVUPDOWN)
356 DoMethod(obj, MUIM_Numeric_Decrease, step);
357 else
358 DoMethod(obj, MUIM_Numeric_Increase, step);
359 return MUI_EventHandlerRC_Eat;
361 case MUIKEY_PAGEUP:
362 case MUIKEY_WORDLEFT:
363 if (data->flags & NUMERIC_REVUPDOWN)
364 DoMethod(obj, MUIM_Numeric_Increase, step);
365 else
366 DoMethod(obj, MUIM_Numeric_Decrease, step);
367 return MUI_EventHandlerRC_Eat;
369 default:
370 return 0;
374 return 0;
378 /**************************************************************************
379 MUIM_Numeric_Decrease
380 **************************************************************************/
381 IPTR Numeric__MUIM_Decrease(struct IClass *cl, Object *obj,
382 struct MUIP_Numeric_Decrease *msg)
384 struct MUI_NumericData *data = INST_DATA(cl, obj);
385 LONG newval = CLAMP(data->value - msg->amount, data->min, data->max);
386 if (newval != data->value)
387 set(obj, MUIA_Numeric_Value, newval);
389 return 1;
392 /**************************************************************************
393 MUIM_Numeric_Increase
394 **************************************************************************/
395 IPTR Numeric__MUIM_Increase(struct IClass *cl, Object *obj,
396 struct MUIP_Numeric_Increase *msg)
398 struct MUI_NumericData *data = INST_DATA(cl, obj);
399 LONG newval = CLAMP(data->value + msg->amount, data->min, data->max);
401 if (newval != data->value)
402 set(obj, MUIA_Numeric_Value, newval);
404 return 1;
408 /**************************************************************************
409 MUIM_Numeric_ScaleToValue
410 **************************************************************************/
411 IPTR Numeric__MUIM_ScaleToValue(struct IClass *cl, Object *obj,
412 struct MUIP_Numeric_ScaleToValue *msg)
414 struct MUI_NumericData *data = INST_DATA(cl, obj);
415 LONG min, max;
416 LONG val;
417 LONG d;
419 min = (data->flags & NUMERIC_REVERSE) ? data->max : data->min;
420 max = (data->flags & NUMERIC_REVERSE) ? data->min : data->max;
422 val = CLAMP(msg->scale - msg->scalemin, msg->scalemin, msg->scalemax);
423 d = msg->scalemax - msg->scalemin;
425 // FIXME: watch out for overflow here.
426 val = val * (max - min);
428 if (d)
429 val /= d;
431 val += min;
433 return val;
436 /**************************************************************************
437 MUIM_Numeric_SetDefault
438 **************************************************************************/
439 IPTR Numeric__MUIM_SetDefault(struct IClass *cl, Object *obj, Msg msg)
441 struct MUI_NumericData *data = INST_DATA(cl, obj);
443 set(obj, MUIA_Numeric_Value, CLAMP(data->defvalue, data->min,
444 data->max));
446 return 0;
449 /**************************************************************************
450 MUIM_Numeric_Stringify
451 **************************************************************************/
452 IPTR Numeric__MUIM_Stringify(struct IClass *cl, Object *obj,
453 struct MUIP_Numeric_Stringify *msg)
455 struct MUI_NumericData *data = INST_DATA(cl, obj);
457 /* TODO: use RawDoFmt() and buffer overrun */
458 snprintf(data->buf, 49, data->format, (long)msg->value);
459 data->buf[49] = 0;
461 return (IPTR) data->buf;
464 /**************************************************************************
465 MUIM_Numeric_ValueToScale
466 **************************************************************************/
467 IPTR Numeric__MUIM_ValueToScale(struct IClass *cl, Object *obj,
468 struct MUIP_Numeric_ValueToScale *msg)
470 LONG val;
471 struct MUI_NumericData *data = INST_DATA(cl, obj);
472 LONG min, max;
474 min = (data->flags & NUMERIC_REVERSE) ? msg->scalemax : msg->scalemin;
475 max = (data->flags & NUMERIC_REVERSE) ? msg->scalemin : msg->scalemax;
477 if (data->max != data->min)
479 val =
480 min + ((data->value - data->min) * (max - min) + (data->max -
481 data->min) / 2) / (data->max - data->min);
483 else
485 val = min;
488 val = CLAMP(val, min, max);
490 return val;
493 /**************************************************************************
494 MUIM_Numeric_ValueToScaleExt
495 **************************************************************************/
496 IPTR Numeric__MUIM_ValueToScaleExt(struct IClass *cl, Object *obj,
497 struct MUIP_Numeric_ValueToScaleExt *msg)
499 LONG scale;
500 LONG value;
501 struct MUI_NumericData *data = INST_DATA(cl, obj);
502 LONG min, max;
504 value = CLAMP(msg->value, data->min, data->max);
505 min = (data->flags & NUMERIC_REVERSE) ? msg->scalemax : msg->scalemin;
506 max = (data->flags & NUMERIC_REVERSE) ? msg->scalemin : msg->scalemax;
508 if (data->max != data->min)
510 scale =
511 min + ((value - data->min) * (max - min) + (data->max -
512 data->min) / 2) / (data->max - data->min);
514 else
516 scale = min;
519 scale = CLAMP(scale, min, max);
521 return scale;
524 /**************************************************************************
525 MUIM_Export - to export an objects "contents" to a dataspace object.
526 **************************************************************************/
527 IPTR Numeric__MUIM_Export(struct IClass *cl, Object *obj,
528 struct MUIP_Export *msg)
530 struct MUI_NumericData *data = INST_DATA(cl, obj);
531 ULONG id;
533 if ((id = muiNotifyData(obj)->mnd_ObjectID))
535 LONG value = data->value;
536 DoMethod(msg->dataspace, MUIM_Dataspace_Add,
537 (IPTR) & value, sizeof(value), (IPTR) id);
539 return 0;
542 /**************************************************************************
543 MUIM_Import - to import an object's "contents" from a dataspace object.
544 **************************************************************************/
545 IPTR Numeric__MUIM_Import(struct IClass *cl, Object *obj,
546 struct MUIP_Import *msg)
548 ULONG id;
549 LONG *s;
551 if ((id = muiNotifyData(obj)->mnd_ObjectID))
553 if ((s = (LONG *) DoMethod(msg->dataspace, MUIM_Dataspace_Find,
554 (IPTR) id)))
556 set(obj, MUIA_Numeric_Value, *s);
560 return 0;
564 BOOPSI_DISPATCHER(IPTR, Numeric_Dispatcher, cl, obj, msg)
566 switch (msg->MethodID)
568 case OM_NEW:
569 return Numeric__OM_NEW(cl, obj, (APTR) msg);
570 case OM_SET:
571 return Numeric__OM_SET(cl, obj, (APTR) msg);
572 case OM_GET:
573 return Numeric__OM_GET(cl, obj, (APTR) msg);
575 case MUIM_Setup:
576 return Numeric__MUIM_Setup(cl, obj, (APTR) msg);
577 case MUIM_Cleanup:
578 return Numeric__MUIM_Cleanup(cl, obj, (APTR) msg);
579 case MUIM_HandleEvent:
580 return Numeric__MUIM_HandleEvent(cl, obj, (APTR) msg);
581 case MUIM_Numeric_Decrease:
582 return Numeric__MUIM_Decrease(cl, obj, (APTR) msg);
583 case MUIM_Numeric_Increase:
584 return Numeric__MUIM_Increase(cl, obj, (APTR) msg);
585 case MUIM_Numeric_ScaleToValue:
586 return Numeric__MUIM_ScaleToValue(cl, obj, (APTR) msg);
587 case MUIM_Numeric_SetDefault:
588 return Numeric__MUIM_SetDefault(cl, obj, (APTR) msg);
589 case MUIM_Numeric_Stringify:
590 return Numeric__MUIM_Stringify(cl, obj, (APTR) msg);
591 case MUIM_Numeric_ValueToScale:
592 return Numeric__MUIM_ValueToScale(cl, obj, (APTR) msg);
593 case MUIM_Numeric_ValueToScaleExt:
594 return Numeric__MUIM_ValueToScaleExt(cl, obj, (APTR) msg);
595 case MUIM_Export:
596 return Numeric__MUIM_Export(cl, obj, (APTR) msg);
597 case MUIM_Import:
598 return Numeric__MUIM_Import(cl, obj, (APTR) msg);
601 return DoSuperMethodA(cl, obj, msg);
603 BOOPSI_DISPATCHER_END
606 * Class descriptor.
608 const struct __MUIBuiltinClass _MUI_Numeric_desc =
610 MUIC_Numeric,
611 MUIC_Area,
612 sizeof(struct MUI_NumericData),
613 (void *) Numeric_Dispatcher