2 Copyright © 2002-2013, The AROS Development Team. All rights reserved.
6 #include <devices/rawkeycodes.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>
18 #include "muimaster_intern.h"
21 struct MUI_NumericData
29 struct MUI_EventHandlerNode ehn;
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 /**************************************************************************
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);
57 data = INST_DATA(cl, obj);
63 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
67 case MUIA_Numeric_CheckAllSizes:
68 _handle_bool_tag(data->flags, tag->ti_Data,
69 NUMERIC_CHECKALLSIZES);
71 case MUIA_Numeric_Default:
72 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
73 data->defvalue = tag->ti_Data;
75 case MUIA_Numeric_Format:
76 data->format = (STRPTR) tag->ti_Data;
78 case MUIA_Numeric_Max:
79 data->max = tag->ti_Data;
81 case MUIA_Numeric_Min:
82 data->min = tag->ti_Data;
84 case MUIA_Numeric_Reverse:
85 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
87 case MUIA_Numeric_RevLeftRight:
88 _handle_bool_tag(data->flags, tag->ti_Data,
89 NUMERIC_REVLEFTRIGHT);
91 case MUIA_Numeric_RevUpDown:
92 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
94 case MUIA_Numeric_Value:
96 data->value = (LONG) tag->ti_Data;
102 CLAMP(value_set ? data->value : data->defvalue, data->min,
108 /**************************************************************************
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;
118 BOOL values_changed = FALSE;
120 oldval = data->value;
121 oldfmt = data->format;
125 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
129 case MUIA_Numeric_CheckAllSizes:
130 _handle_bool_tag(data->flags, tag->ti_Data,
131 NUMERIC_CHECKALLSIZES);
133 case MUIA_Numeric_Default:
134 /* data->defvalue = CLAMP(tag->ti_Data, data->min, data->max); */
135 data->defvalue = tag->ti_Data;
137 case MUIA_Numeric_Format:
138 data->format = (STRPTR) tag->ti_Data;
140 case MUIA_Numeric_Max:
141 data->max = tag->ti_Data;
142 data->value = CLAMP(data->value, data->min, data->max);
144 case MUIA_Numeric_Min:
145 data->min = tag->ti_Data;
146 data->value = CLAMP(data->value, data->min, data->max);
148 case MUIA_Numeric_Reverse:
149 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVERSE);
151 case MUIA_Numeric_RevLeftRight:
152 _handle_bool_tag(data->flags, tag->ti_Data,
153 NUMERIC_REVLEFTRIGHT);
155 case MUIA_Numeric_RevUpDown:
156 _handle_bool_tag(data->flags, tag->ti_Data, NUMERIC_REVUPDOWN);
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;
164 data->value = (LONG) tag->ti_Data;
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
177 if (data->format != oldfmt || data->min != oldmin
178 || data->max != oldmax)
180 values_changed = TRUE;
181 Object *parent = _parent(obj);
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);
199 /**************************************************************************
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;
210 case MUIA_Numeric_CheckAllSizes:
211 *store = ((data->flags & NUMERIC_CHECKALLSIZES) != 0);
214 case MUIA_Numeric_Default:
215 *store = data->defvalue;
218 case MUIA_Numeric_Format:
219 *store = (IPTR) data->format;
222 case MUIA_Numeric_Max:
226 case MUIA_Numeric_Min:
230 case MUIA_Numeric_Reverse:
231 *store = ((data->flags & NUMERIC_REVERSE) != 0);
234 case MUIA_Numeric_RevLeftRight:
235 *store = ((data->flags & NUMERIC_REVLEFTRIGHT) != 0);
238 case MUIA_Numeric_RevUpDown:
239 *store = ((data->flags & NUMERIC_REVUPDOWN) != 0);
242 case MUIA_Numeric_Value:
243 *store = data->value;
247 return DoSuperMethodA(cl, obj, (Msg) msg);
250 /**************************************************************************
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))
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));
271 /**************************************************************************
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 /**************************************************************************
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);
291 BOOL increase, change;
293 if (msg->muikey != MUIKEY_NONE)
296 BOOL use_absolute = FALSE, is_horizontal = FALSE;
298 result = MUI_EventHandlerRC_Eat;
300 if (data->max - data->min < 10)
308 return MUI_EventHandlerRC_Eat;
311 DoMethod(obj, MUIM_Numeric_SetDefault);
312 return MUI_EventHandlerRC_Eat;
315 return MUI_EventHandlerRC_Eat;
318 case MUIKEY_LINESTART:
320 is_horizontal = TRUE;
327 is_horizontal = TRUE;
332 is_horizontal = TRUE;
337 is_horizontal = TRUE;
349 case MUIKEY_PAGEDOWN:
350 case MUIKEY_WORDRIGHT:
354 case MUIKEY_WORDLEFT:
362 /* Send gadget in proper direction */
365 if (data->flags & NUMERIC_REVERSE)
368 if ((is_horizontal && (data->flags & NUMERIC_REVLEFTRIGHT) != 0)
369 || (!is_horizontal && (data->flags & NUMERIC_REVUPDOWN) != 0))
381 DoMethod(obj, MUIM_Numeric_Increase, step);
384 else if (msg->imsg->Class == IDCMP_RAWKEY
385 && _isinobject(obj, msg->imsg->MouseX, msg->imsg->MouseY))
388 switch (msg->imsg->Code)
390 case RAWKEY_NM_WHEEL_UP:
393 case RAWKEY_NM_WHEEL_DOWN:
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;
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);
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);
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);
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);
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,
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);
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)
506 struct MUI_NumericData *data = INST_DATA(cl, obj);
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)
515 min + ((data->value - data->min) * (max - min) + (data->max -
516 data->min) / 2) / (data->max - data->min);
523 val = CLAMP(val, msg->scalemin, msg->scalemax);
528 /**************************************************************************
529 MUIM_Numeric_ValueToScaleExt
530 **************************************************************************/
531 IPTR Numeric__MUIM_ValueToScaleExt(struct IClass *cl, Object *obj,
532 struct MUIP_Numeric_ValueToScaleExt *msg)
536 struct MUI_NumericData *data = INST_DATA(cl, obj);
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)
546 min + ((value - data->min) * (max - min) + (data->max -
547 data->min) / 2) / (data->max - data->min);
554 scale = CLAMP(scale, msg->scalemin, msg->scalemax);
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);
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);
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)
586 if ((id = muiNotifyData(obj)->mnd_ObjectID))
588 if ((s = (LONG *) DoMethod(msg->dataspace, MUIM_Dataspace_Find,
591 set(obj, MUIA_Numeric_Value, *s);
599 BOOPSI_DISPATCHER(IPTR, Numeric_Dispatcher, cl, obj, msg)
601 switch (msg->MethodID)
604 return Numeric__OM_NEW(cl, obj, (APTR) msg);
606 return Numeric__OM_SET(cl, obj, (APTR) msg);
608 return Numeric__OM_GET(cl, obj, (APTR) msg);
611 return Numeric__MUIM_Setup(cl, obj, (APTR) msg);
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);
631 return Numeric__MUIM_Export(cl, obj, (APTR) msg);
633 return Numeric__MUIM_Import(cl, obj, (APTR) msg);
636 return DoSuperMethodA(cl, obj, msg);
638 BOOPSI_DISPATCHER_END
643 const struct __MUIBuiltinClass _MUI_Numeric_desc =
647 sizeof(struct MUI_NumericData),
648 (void *) Numeric_Dispatcher