Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / numericbutton.c
blobe1abe5cc90851af8070f59d5e764532cd0d9b5ef
1 /*
2 Copyright 2002-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <exec/memory.h>
9 #include <clib/alib_protos.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <proto/intuition.h>
13 #include <proto/graphics.h>
14 #include <proto/utility.h>
15 #include <proto/muimaster.h>
17 #include <string.h>
18 #include <stdio.h>
20 #include "mui.h"
21 #include "muimaster_intern.h"
22 #include "support.h"
23 #include "frame.h"
24 #include "support_classes.h"
25 #include "prefs.h"
26 #include "imspec.h"
27 #include "debug.h"
28 #include "numericbutton_private.h"
30 extern struct Library *MUIMasterBase;
32 #define longget(obj,attr,var) \
33 do \
34 { \
35 IPTR _iptr_var = *(var); \
36 get(obj,attr,&_iptr_var); \
37 *var = (LONG)_iptr_var; \
38 } while(0)
40 IPTR Numericbutton__OM_NEW(struct IClass *cl, Object *obj,
41 struct opSet *msg)
43 obj = (Object *) DoSuperNewTags(cl, obj, NULL,
44 MUIA_Background, MUII_ButtonBack,
45 MUIA_Frame, MUIV_Frame_Button,
46 TAG_MORE, (IPTR) msg->ops_AttrList);
48 if (obj)
50 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
52 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
53 data->ehn.ehn_Priority = 0;
54 data->ehn.ehn_Flags = 0;
55 data->ehn.ehn_Object = obj;
56 data->ehn.ehn_Class = cl;
59 return (IPTR) obj;
62 /**************************************************************************
63 OM_SET
64 **************************************************************************/
65 static ULONG Numericbutton__OM_SET(struct IClass *cl, Object *obj,
66 struct opSet *msg)
68 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
69 struct TagItem *tags;
70 struct TagItem *tag;
72 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
74 switch (tag->ti_Tag)
76 case MUIA_Numeric_Max:
77 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Max))
78 data->needs_to_recalculate_sizes = TRUE;
79 break;
80 case MUIA_Numeric_Min:
81 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Min))
82 data->needs_to_recalculate_sizes = TRUE;
83 break;
84 case MUIA_Numeric_Format:
85 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Format))
86 data->needs_to_recalculate_sizes = TRUE;
87 break;
91 return DoSuperMethodA(cl, obj, (Msg) msg);
94 IPTR Numericbutton__MUIM_Setup(struct IClass *cl, Object *obj,
95 struct MUIP_Setup *msg)
97 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
98 // const struct ZuneFrameGfx *knob_frame;
99 IPTR retval;
101 retval = DoSuperMethodA(cl, obj, (Msg) msg);
102 if (retval)
104 //knob_frame = zune_zframe_get(obj,
105 // &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Knob]);
107 data->knob_bg =
108 zune_imspec_setup(MUII_ButtonBack, muiRenderInfo(obj));
110 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
111 (IPTR) & data->ehn);
113 data->needs_to_recalculate_sizes = TRUE;
116 return retval;
119 IPTR Numericbutton__MUIM_Cleanup(struct IClass *cl, Object *obj,
120 struct MUIP_Cleanup *msg)
122 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
124 if (data->knob_bg)
126 zune_imspec_cleanup(data->knob_bg);
127 data->knob_bg = NULL;
130 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) & data->ehn);
132 return DoSuperMethodA(cl, obj, (Msg) msg);
135 /**************************************************************************
136 MUIM_AskMinMax
137 **************************************************************************/
138 IPTR Numericbutton__MUIM_AskMinMax(struct IClass *cl, Object *obj,
139 struct MUIP_AskMinMax *msg)
141 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
143 DoSuperMethodA(cl, obj, (Msg) msg);
145 if (data->needs_to_recalculate_sizes)
147 struct RastPort rp;
148 LONG min = 0, max = 0, val, width;
150 InitRastPort(&rp);
151 SetFont(&rp, _font(obj));
153 width = 0;
155 longget(obj, MUIA_Numeric_Min, &min);
156 longget(obj, MUIA_Numeric_Max, &max);
158 /* Determine the width of the knob */
159 for (val = min; val <= max; val++)
161 LONG nw;
162 char *buf;
164 buf = (char *)DoMethod(obj, MUIM_Numeric_Stringify, val);
165 nw = TextLength(&rp, buf, strlen(buf));
167 if (nw > width)
168 width = nw;
171 data->max_text_width = width;
172 data->text_height = _font(obj)->tf_YSize;
174 data->needs_to_recalculate_sizes = FALSE;
177 msg->MinMaxInfo->MinWidth += data->max_text_width;
178 msg->MinMaxInfo->MinHeight += data->text_height;
179 msg->MinMaxInfo->DefWidth += data->max_text_width;
180 msg->MinMaxInfo->DefHeight += data->text_height;
181 msg->MinMaxInfo->MaxWidth += data->max_text_width;
182 msg->MinMaxInfo->MaxHeight += data->text_height;
184 return TRUE;
187 static void DrawKnob(Object *obj, struct Numericbutton_DATA *data,
188 BOOL force)
190 struct RastPort *rp, *saverp;
191 LONG x, val, pixeloffset, textlen, pixellen;
192 STRPTR text;
194 pixeloffset =
195 data->popwin->MouseX - data->pop_innerx - 2 -
196 data->knob_clickoffset_x;
198 val = DoMethod(obj, MUIM_Numeric_ScaleToValue, 0,
199 data->pop_innerw - data->knob_width, pixeloffset);
201 data->knob_left = data->pop_innerx + pixeloffset;
202 data->knob_top = data->pop_innery;
203 data->knob_val = val;
205 if (!force && (data->knob_left == data->knob_prev_left))
207 return;
209 data->knob_prev_left = data->knob_left;
211 if (data->knob_left < data->pop_innerx)
213 data->knob_left = data->pop_innerx;
215 else if (data->knob_left >
216 data->pop_innerx + data->pop_innerw - data->knob_width)
218 data->knob_left =
219 data->pop_innerx + data->pop_innerw - data->knob_width;
222 saverp = _rp(obj);
223 _rp(obj) = rp = data->popwin->RPort;
225 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], 0, JAM1);
226 RectFill(rp, data->knob_left, data->knob_top,
227 data->knob_left, data->knob_top + data->knob_height - 1);
228 RectFill(rp, data->knob_left + 1, data->knob_top,
229 data->knob_left + data->knob_width - 1, data->knob_top);
230 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
231 RectFill(rp, data->knob_left + data->knob_width - 1, data->knob_top + 1,
232 data->knob_left + data->knob_width - 1,
233 data->knob_top + data->knob_height - 1);
234 RectFill(rp, data->knob_left + 1,
235 data->knob_top + data->knob_height - 1,
236 data->knob_left + data->knob_width - 2,
237 data->knob_top + data->knob_height - 1);
239 if (data->knob_bg)
241 // FIXME: Ugly hack?
243 struct IBox old_mad_Box = muiAreaData(obj)->mad_Box;
245 muiAreaData(obj)->mad_Box.Left = data->knob_left + 1;
246 muiAreaData(obj)->mad_Box.Top = data->knob_top + 1;
247 muiAreaData(obj)->mad_Box.Width = data->knob_width - 2;
248 muiAreaData(obj)->mad_Box.Height = data->knob_height - 2;
250 zune_imspec_draw(data->knob_bg, muiRenderInfo(obj),
251 data->knob_left + 1,
252 data->knob_top + 1,
253 data->knob_width - 2, data->knob_height - 2, 0, 0, 0);
255 muiAreaData(obj)->mad_Box = old_mad_Box;
257 else
259 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
260 RectFill(rp, data->knob_left + 1, data->knob_top + 1,
261 data->knob_left + data->knob_width - 2,
262 data->knob_top + data->knob_height - 2);
265 SetFont(rp, _font(obj));
267 text = (STRPTR) DoMethod(obj, MUIM_Numeric_Stringify, val);
268 textlen = strlen(text);
269 pixellen = TextLength(_rp(obj), text, textlen);
271 SetAPen(rp, _pens(obj)[MPEN_TEXT]);
272 Move(rp, data->knob_left + 2 + (data->knob_width - 4 - pixellen) / 2,
273 data->knob_top + 1 + rp->TxBaseline);
274 Text(rp, text, textlen);
276 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
278 if (data->knob_left - 1 >= data->pop_innerx)
280 RectFill(rp, data->pop_innerx, data->pop_innery,
281 data->knob_left - 1, data->pop_innery + data->pop_innerh - 1);
284 x = data->knob_left + data->knob_width;
285 if (x <= data->pop_innerx + data->pop_innerw - 1)
287 RectFill(rp, x, data->pop_innery,
288 data->pop_innerx + data->pop_innerw - 1,
289 data->pop_innery + data->pop_innerh - 1);
292 _rp(obj) = saverp;
295 static void KillPopupWin(Object *obj, struct Numericbutton_DATA *data)
297 if (data->popwin)
299 CloseWindow(data->popwin);
300 data->popwin = NULL;
303 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
305 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
306 (IPTR) & data->ehn);
307 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
308 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
309 (IPTR) & data->ehn);
314 static BOOL MakePopupWin(Object *obj, struct Numericbutton_DATA *data)
316 const struct ZuneFrameGfx *zframe;
317 struct RastPort *rp, *saverp;
318 LONG winx, winy, winw, winh;
319 LONG framew, frameh;
320 LONG min = 0, max = 0;
322 zframe =
323 zune_zframe_get_with_state(obj,
324 &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider],
325 muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider].state);
327 data->pop_innerx = zframe->ileft;
328 data->pop_innery = zframe->itop;
330 data->knob_width = data->max_text_width + 4;
331 data->knob_height = data->text_height + 2;
333 framew = data->pop_innerx + zframe->iright;
334 frameh = data->pop_innery + zframe->ibottom;
336 longget(obj, MUIA_Numeric_Min, &min);
337 longget(obj, MUIA_Numeric_Max, &max);
339 winw = max - min + data->knob_width + framew;
340 winh = data->knob_height + frameh;
342 if (winw > _screen(obj)->Width)
344 winw = _screen(obj)->Width;
347 if ((winw < data->knob_width + framew) || (winh > _screen(obj)->Height))
349 return FALSE;
352 data->pop_innerw = winw - framew;
353 data->pop_innerh = winh - frameh;
355 data->knob_left =
356 DoMethod(obj, MUIM_Numeric_ValueToScale, 0,
357 data->pop_innerw - data->knob_width);
359 winx = _window(obj)->LeftEdge + _mleft(obj) -
360 data->pop_innerx - 2 - data->knob_left;
361 winy = _window(obj)->TopEdge + _mtop(obj) - 1 - data->pop_innery;
363 data->popwin =
364 OpenWindowTags(NULL, WA_CustomScreen, (IPTR) _screen(obj), WA_Left,
365 winx, WA_Top, winy, WA_Width, winw, WA_Height, winh, WA_AutoAdjust,
366 TRUE, WA_Borderless, TRUE, WA_Activate, FALSE, WA_BackFill,
367 (IPTR) LAYERS_NOBACKFILL, TAG_DONE);
369 if (!data->popwin)
371 return FALSE;
374 rp = data->popwin->RPort;
376 saverp = _rp(obj);
377 _rp(obj) = rp;
378 zframe->draw(zframe->customframe, muiRenderInfo(obj), 0, 0, winw, winh,
379 0, 0, winw, winh);
381 DrawKnob(obj, data, TRUE);
384 _rp(obj) = saverp;
386 return TRUE;
390 /**************************************************************************
391 MUIM_Show
392 **************************************************************************/
393 IPTR Numericbutton__MUIM_Show(struct IClass *cl, Object *obj,
394 struct MUIP_Show *msg)
396 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
397 IPTR retval;
399 retval = DoSuperMethodA(cl, obj, (Msg) msg);
401 if (data->knob_bg)
402 zune_imspec_show(data->knob_bg, obj);
404 return retval;
407 /**************************************************************************
408 MUIM_Hide
409 **************************************************************************/
410 IPTR Numericbutton__MUIM_Hide(struct IClass *cl, Object *obj,
411 struct MUIP_Hide *msg)
413 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
415 if (data->popwin)
417 KillPopupWin(obj, data);
420 if (data->knob_bg)
421 zune_imspec_hide(data->knob_bg);
423 return DoSuperMethodA(cl, obj, (Msg) msg);
427 /**************************************************************************
428 MUIM_Draw
429 **************************************************************************/
430 IPTR Numericbutton__MUIM_Draw(struct IClass *cl, Object *obj,
431 struct MUIP_Draw *msg)
433 IPTR val = 0;
434 char *buf;
435 int width;
437 DoSuperMethodA(cl, obj, (Msg) msg);
439 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
440 return FALSE;
442 DoMethod(obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj),
443 _mwidth(obj), _mheight(obj), _mleft(obj), _mtop(obj), 0);
445 SetFont(_rp(obj), _font(obj));
446 SetABPenDrMd(_rp(obj), _pens(obj)[MPEN_TEXT],
447 _pens(obj)[MPEN_BACKGROUND], JAM1);
449 get(obj, MUIA_Numeric_Value, &val);
450 buf = (char *)DoMethod(obj, MUIM_Numeric_Stringify, val);
451 width = TextLength(_rp(obj), buf, strlen(buf));
453 Move(_rp(obj), _mleft(obj) + (_mwidth(obj) - width) / 2,
454 _mtop(obj) + _font(obj)->tf_Baseline);
456 Text(_rp(obj), buf, strlen(buf));
458 return TRUE;
461 /**************************************************************************
462 MUIM_HandleEvent
463 **************************************************************************/
464 IPTR Numericbutton__MUIM_HandleEvent(struct IClass *cl, Object *obj,
465 struct MUIP_HandleEvent *msg)
467 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
469 if (!msg->imsg)
471 return 0;
474 switch (msg->imsg->Class)
476 case IDCMP_MOUSEBUTTONS:
477 switch (msg->imsg->Code)
479 case SELECTDOWN:
480 if (_between(_left(obj), msg->imsg->MouseX, _right(obj)) &&
481 _between(_top(obj), msg->imsg->MouseY, _bottom(obj)) &&
482 (muiAreaData(obj)->mad_Flags & MADF_CANDRAW) &&
483 !data->popwin)
485 data->knob_clickoffset_x = msg->imsg->MouseX - _mleft(obj);
487 if (MakePopupWin(obj, data))
489 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
490 (IPTR) & data->ehn);
491 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
492 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
493 (IPTR) & data->ehn);
495 return 0;
498 break;
500 case SELECTUP:
501 case MENUUP:
502 case MIDDLEUP:
503 default:
504 if (data->popwin)
506 KillPopupWin(obj, data);
507 if ((msg->imsg->Code == SELECTUP))
509 set(obj, MUIA_Numeric_Value, data->knob_val);
511 return 0;
513 break;
516 } /* switch(msg->imsg->Code) */
517 break;
519 case IDCMP_MOUSEMOVE:
520 if (data->popwin)
522 DrawKnob(obj, data, FALSE);
524 return 0;
526 break;
528 } /* switch(msg->imsg->Class) */
530 return 0;
534 #if ZUNE_BUILTIN_NUMERICBUTTON
535 BOOPSI_DISPATCHER(IPTR, Numericbutton_Dispatcher, cl, obj, msg)
537 switch (msg->MethodID)
539 case OM_NEW:
540 return Numericbutton__OM_NEW(cl, obj, (struct opSet *)msg);
541 case OM_SET:
542 return Numericbutton__OM_SET(cl, obj, (struct opSet *)msg);
544 case MUIM_Setup:
545 return Numericbutton__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
546 case MUIM_Cleanup:
547 return Numericbutton__MUIM_Cleanup(cl, obj,
548 (struct MUIP_Cleanup *)msg);
549 case MUIM_Show:
550 return Numericbutton__MUIM_Show(cl, obj, (struct MUIP_Show *)msg);
551 case MUIM_Hide:
552 return Numericbutton__MUIM_Hide(cl, obj, (struct MUIP_Hide *)msg);
553 case MUIM_AskMinMax:
554 return Numericbutton__MUIM_AskMinMax(cl, obj,
555 (struct MUIP_AskMinMax *)msg);
556 case MUIM_Draw:
557 return Numericbutton__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
558 case MUIM_HandleEvent:
559 return Numericbutton__MUIM_HandleEvent(cl, obj,
560 (struct MUIP_HandleEvent *)msg);
561 default:
562 return DoSuperMethodA(cl, obj, msg);
565 BOOPSI_DISPATCHER_END
567 const struct __MUIBuiltinClass _MUI_Numericbutton_desc =
569 MUIC_Numericbutton,
570 MUIC_Numeric,
571 sizeof(struct Numericbutton_DATA),
572 (void *) Numericbutton_Dispatcher
574 #endif /* ZUNE_BUILTIN_NUMERICBUTTON */