Some fix for scrolling with lasso.
[tangerine.git] / workbench / libs / muimaster / classes / numericbutton.c
blob09e2f6e50957e2daaebbc756cae69c487a095a47
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, struct opSet *msg)
42 obj = (Object *)DoSuperNewTags
44 cl, obj, NULL,
45 MUIA_Background, MUII_ButtonBack,
46 MUIA_Frame, MUIV_Frame_Button,
47 TAG_MORE, (IPTR) msg->ops_AttrList
50 if (obj)
52 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
54 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
55 data->ehn.ehn_Priority = 0;
56 data->ehn.ehn_Flags = 0;
57 data->ehn.ehn_Object = obj;
58 data->ehn.ehn_Class = cl;
61 return (IPTR)obj;
64 /**************************************************************************
65 OM_SET
66 **************************************************************************/
67 static ULONG Numericbutton__OM_SET(struct IClass *cl, Object * obj, struct opSet *msg)
69 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
70 struct TagItem *tags, *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, struct MUIP_Setup *msg)
96 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
97 // const struct ZuneFrameGfx *knob_frame;
98 IPTR retval;
100 retval = DoSuperMethodA(cl, obj, (Msg)msg);
101 if (retval)
103 //knob_frame = zune_zframe_get(&muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Knob]);
105 data->knob_bg = zune_imspec_setup(MUII_ButtonBack, muiRenderInfo(obj));
107 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
109 data->needs_to_recalculate_sizes = TRUE;
112 return retval;
115 IPTR Numericbutton__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
117 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
119 if (data->knob_bg)
121 zune_imspec_cleanup(data->knob_bg);
122 data->knob_bg = NULL;
125 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
127 return DoSuperMethodA(cl, obj, (Msg)msg);
130 /**************************************************************************
131 MUIM_AskMinMax
132 **************************************************************************/
133 IPTR Numericbutton__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
135 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
137 DoSuperMethodA(cl, obj, (Msg)msg);
139 if (data->needs_to_recalculate_sizes)
141 struct RastPort rp;
142 LONG min, max, val, width;
144 InitRastPort(&rp);
145 SetFont(&rp,_font(obj));
147 width = 0;
149 longget(obj, MUIA_Numeric_Min, &min);
150 longget(obj, MUIA_Numeric_Max, &max);
152 /* Determine the width of the knob */
153 for (val=min;val<=max;val++)
155 LONG nw;
156 char *buf;
158 buf = (char*)DoMethod(obj, MUIM_Numeric_Stringify, val);
159 nw = TextLength(&rp, buf, strlen(buf));
161 if (nw > width)
162 width = nw;
165 data->max_text_width = width;
166 data->text_height = _font(obj)->tf_YSize;
168 data->needs_to_recalculate_sizes = FALSE;
171 msg->MinMaxInfo->MinWidth += data->max_text_width;
172 msg->MinMaxInfo->MinHeight += data->text_height;
173 msg->MinMaxInfo->DefWidth += data->max_text_width;
174 msg->MinMaxInfo->DefHeight += data->text_height;
175 msg->MinMaxInfo->MaxWidth += data->max_text_width;
176 msg->MinMaxInfo->MaxHeight += data->text_height;
178 return TRUE;
181 static void DrawKnob(Object *obj, struct Numericbutton_DATA *data, BOOL force)
183 struct RastPort *rp, *saverp;
184 LONG x, val, pixeloffset, textlen, pixellen;
185 STRPTR text;
187 pixeloffset = data->popwin->MouseX - data->pop_innerx - 2 - data->knob_clickoffset_x;
189 val = DoMethod(obj, MUIM_Numeric_ScaleToValue, 0,
190 data->pop_innerw - data->knob_width, pixeloffset);
192 data->knob_left = data->pop_innerx + pixeloffset;
193 data->knob_top = data->pop_innery;
194 data->knob_val = val;
196 if (!force && (data->knob_left == data->knob_prev_left))
198 return;
200 data->knob_prev_left = data->knob_left;
202 if (data->knob_left < data->pop_innerx)
204 data->knob_left = data->pop_innerx;
206 else if (data->knob_left > data->pop_innerx + data->pop_innerw - data->knob_width)
208 data->knob_left = data->pop_innerx + data->pop_innerw - data->knob_width;
211 saverp = _rp(obj);
212 _rp(obj) = rp = data->popwin->RPort;
214 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], 0, JAM1);
215 RectFill(rp, data->knob_left, data->knob_top,
216 data->knob_left, data->knob_top + data->knob_height - 1);
217 RectFill(rp, data->knob_left + 1, data->knob_top,
218 data->knob_left + data->knob_width - 1, data->knob_top);
219 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
220 RectFill(rp, data->knob_left + data->knob_width - 1, data->knob_top + 1,
221 data->knob_left + data->knob_width - 1, data->knob_top + data->knob_height - 1);
222 RectFill(rp, data->knob_left + 1, data->knob_top + data->knob_height - 1,
223 data->knob_left + data->knob_width - 2, data->knob_top + data->knob_height - 1);
225 if (data->knob_bg)
227 #warning "Ugly hack?"
229 struct IBox old_mad_Box = muiAreaData(obj)->mad_Box;
231 muiAreaData(obj)->mad_Box.Left = data->knob_left + 1;
232 muiAreaData(obj)->mad_Box.Top = data->knob_top + 1;
233 muiAreaData(obj)->mad_Box.Width = data->knob_width - 2;
234 muiAreaData(obj)->mad_Box.Height = data->knob_height - 2;
236 zune_imspec_draw(data->knob_bg, muiRenderInfo(obj),
237 data->knob_left + 1,
238 data->knob_top + 1,
239 data->knob_width - 2,
240 data->knob_height - 2,
245 muiAreaData(obj)->mad_Box = old_mad_Box;
247 else
249 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
250 RectFill(rp, data->knob_left + 1, data->knob_top + 1,
251 data->knob_left + data->knob_width - 2,
252 data->knob_top + data->knob_height - 2);
255 SetFont(rp, _font(obj));
257 text = (STRPTR)DoMethod(obj, MUIM_Numeric_Stringify, val);
258 textlen = strlen(text);
259 pixellen = TextLength(_rp(obj), text, textlen);
261 SetAPen(rp, _pens(obj)[MPEN_TEXT]);
262 Move(rp, data->knob_left + 2 + (data->knob_width - 4 - pixellen) / 2,
263 data->knob_top + 1 + rp->TxBaseline);
264 Text(rp, text, textlen);
266 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
268 if (data->knob_left - 1 >= data->pop_innerx)
270 RectFill(rp, data->pop_innerx, data->pop_innery,
271 data->knob_left - 1, data->pop_innery + data->pop_innerh - 1);
274 x = data->knob_left + data->knob_width;
275 if (x <= data->pop_innerx + data->pop_innerw - 1)
277 RectFill(rp, x, data->pop_innery,
278 data->pop_innerx + data->pop_innerw - 1,
279 data->pop_innery + data->pop_innerh - 1);
282 _rp(obj) = saverp;
285 static void KillPopupWin(Object *obj, struct Numericbutton_DATA *data)
287 if (data->popwin)
289 CloseWindow(data->popwin);
290 data->popwin = NULL;
293 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
295 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
296 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
297 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
302 static BOOL MakePopupWin(Object *obj, struct Numericbutton_DATA *data)
304 const struct ZuneFrameGfx *zframe;
305 struct RastPort *rp, *saverp;
306 LONG winx, winy, winw, winh;
307 LONG framew, frameh;
308 LONG min, max;
310 zframe = zune_zframe_get_with_state(&muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider],
311 muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider].state);
313 data->pop_innerx = zframe->ileft;
314 data->pop_innery = zframe->itop;
316 data->knob_width = data->max_text_width + 4;
317 data->knob_height = data->text_height + 2;
319 framew = data->pop_innerx + zframe->iright;
320 frameh = data->pop_innery + zframe->ibottom;
322 longget(obj, MUIA_Numeric_Min, &min);
323 longget(obj, MUIA_Numeric_Max, &max);
325 winw = max - min + data->knob_width + framew;
326 winh = data->knob_height + frameh;
328 if (winw > _screen(obj)->Width)
330 winw = _screen(obj)->Width;
333 if ((winw < data->knob_width + framew) || (winh > _screen(obj)->Height))
335 return FALSE;
338 data->pop_innerw = winw - framew;
339 data->pop_innerh = winh - frameh;
341 data->knob_left = DoMethod(obj, MUIM_Numeric_ValueToScale, 0, data->pop_innerw - data->knob_width);
343 winx = _window(obj)->LeftEdge + _mleft(obj) -
344 data->pop_innerx - 2 -
345 data->knob_left;
346 winy = _window(obj)->TopEdge + _mtop(obj) - 1-
347 data->pop_innery;
349 data->popwin = OpenWindowTags(NULL, WA_CustomScreen, (IPTR)_screen(obj),
350 WA_Left, winx,
351 WA_Top, winy,
352 WA_Width, winw,
353 WA_Height, winh,
354 WA_AutoAdjust, TRUE,
355 WA_Borderless, TRUE,
356 WA_Activate, FALSE,
357 WA_BackFill, (IPTR)LAYERS_NOBACKFILL,
358 TAG_DONE);
360 if (!data->popwin)
362 return FALSE;
365 rp = data->popwin->RPort;
367 saverp = _rp(obj);
368 _rp(obj) = rp;
369 zframe->draw(muiRenderInfo(obj), 0, 0, winw, winh);
371 DrawKnob(obj, data, TRUE);
374 _rp(obj) = saverp;
376 return TRUE;
380 /**************************************************************************
381 MUIM_Show
382 **************************************************************************/
383 IPTR Numericbutton__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
385 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
386 IPTR retval;
388 retval = DoSuperMethodA(cl, obj, (Msg)msg);
390 if (data->knob_bg)
391 zune_imspec_show(data->knob_bg, obj);
393 return retval;
396 /**************************************************************************
397 MUIM_Hide
398 **************************************************************************/
399 IPTR Numericbutton__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
401 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
403 if (data->popwin)
405 KillPopupWin(obj, data);
408 if (data->knob_bg)
409 zune_imspec_hide(data->knob_bg);
411 return DoSuperMethodA(cl, obj, (Msg)msg);
415 /**************************************************************************
416 MUIM_Draw
417 **************************************************************************/
418 IPTR Numericbutton__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
420 IPTR val;
421 char *buf;
422 int width;
424 DoSuperMethodA(cl,obj,(Msg)msg);
426 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
427 return FALSE;
429 DoMethod(obj,MUIM_DrawBackground,_mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj),
430 _mleft(obj),_mtop(obj),0);
432 SetFont(_rp(obj),_font(obj));
433 SetABPenDrMd(_rp(obj),_pens(obj)[MPEN_TEXT],_pens(obj)[MPEN_BACKGROUND],JAM1);
435 get(obj, MUIA_Numeric_Value, &val);
436 buf = (char*)DoMethod(obj,MUIM_Numeric_Stringify,val);
437 width = TextLength(_rp(obj),buf,strlen(buf));
439 Move(_rp(obj), _mleft(obj) + (_mwidth(obj) - width) / 2,
440 _mtop(obj) + _font(obj)->tf_Baseline);
442 Text(_rp(obj), buf, strlen(buf));
444 return TRUE;
447 /**************************************************************************
448 MUIM_HandleEvent
449 **************************************************************************/
450 IPTR Numericbutton__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
452 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
454 if (!msg->imsg)
456 return 0;
459 switch(msg->imsg->Class)
461 case IDCMP_MOUSEBUTTONS:
462 switch(msg->imsg->Code)
464 case SELECTDOWN:
465 if (_between(_left(obj), msg->imsg->MouseX, _right(obj)) &&
466 _between(_top(obj), msg->imsg->MouseY, _bottom(obj)) &&
467 (muiAreaData(obj)->mad_Flags & MADF_CANDRAW) &&
468 !data->popwin)
470 data->knob_clickoffset_x = msg->imsg->MouseX - _mleft(obj);
472 if (MakePopupWin(obj, data))
474 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
475 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
476 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
478 return 0;
481 break;
483 case SELECTUP:
484 case MENUUP:
485 case MIDDLEUP:
486 default:
487 if (data->popwin)
489 KillPopupWin(obj, data);
490 if ((msg->imsg->Code == SELECTUP))
492 set(obj, MUIA_Numeric_Value, data->knob_val);
494 return 0;
496 break;
499 } /* switch(msg->imsg->Code) */
500 break;
502 case IDCMP_MOUSEMOVE:
503 if (data->popwin)
505 DrawKnob(obj, data, FALSE);
507 return 0;
509 break;
511 } /* switch(msg->imsg->Class) */
513 return 0;
517 #if ZUNE_BUILTIN_NUMERICBUTTON
518 BOOPSI_DISPATCHER(IPTR, Numericbutton_Dispatcher, cl, obj, msg)
520 switch (msg->MethodID)
522 case OM_NEW: return Numericbutton__OM_NEW(cl, obj, (struct opSet *)msg);
523 case OM_SET: return Numericbutton__OM_SET(cl, obj, (struct opSet *)msg);
525 case MUIM_Setup: return Numericbutton__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
526 case MUIM_Cleanup: return Numericbutton__MUIM_Cleanup(cl, obj, (struct MUIP_Cleanup *)msg);
527 case MUIM_Show: return Numericbutton__MUIM_Show(cl, obj, (struct MUIP_Show *)msg);
528 case MUIM_Hide: return Numericbutton__MUIM_Hide(cl, obj, (struct MUIP_Hide *)msg);
529 case MUIM_AskMinMax: return Numericbutton__MUIM_AskMinMax(cl, obj, (struct MUIP_AskMinMax *)msg);
530 case MUIM_Draw: return Numericbutton__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
531 case MUIM_HandleEvent: return Numericbutton__MUIM_HandleEvent(cl, obj, (struct MUIP_HandleEvent *)msg);
532 default: return DoSuperMethodA(cl, obj, msg);
535 BOOPSI_DISPATCHER_END
537 const struct __MUIBuiltinClass _MUI_Numericbutton_desc =
539 MUIC_Numericbutton,
540 MUIC_Numeric,
541 sizeof(struct Numericbutton_DATA),
542 (void*)Numericbutton_Dispatcher
544 #endif /* ZUNE_BUILTIN_NUMERICBUTTON */