Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / muimaster / classes / numericbutton.c
blob314cd3284ab4c42ff1bb4168a18857d761a11151
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 const struct TagItem *tags;
71 struct TagItem *tag;
73 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
75 switch (tag->ti_Tag)
77 case MUIA_Numeric_Max:
78 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Max))
79 data->needs_to_recalculate_sizes = TRUE;
80 break;
81 case MUIA_Numeric_Min:
82 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Min))
83 data->needs_to_recalculate_sizes = TRUE;
84 break;
85 case MUIA_Numeric_Format:
86 if (tag->ti_Data != XGET(obj, MUIA_Numeric_Format))
87 data->needs_to_recalculate_sizes = TRUE;
88 break;
92 return DoSuperMethodA(cl, obj, (Msg)msg);
95 IPTR Numericbutton__MUIM_Setup(struct IClass *cl, Object *obj, 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, &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Knob]);
106 data->knob_bg = zune_imspec_setup(MUII_ButtonBack, muiRenderInfo(obj));
108 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
110 data->needs_to_recalculate_sizes = TRUE;
113 return retval;
116 IPTR Numericbutton__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
118 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
120 if (data->knob_bg)
122 zune_imspec_cleanup(data->knob_bg);
123 data->knob_bg = NULL;
126 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
128 return DoSuperMethodA(cl, obj, (Msg)msg);
131 /**************************************************************************
132 MUIM_AskMinMax
133 **************************************************************************/
134 IPTR Numericbutton__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
136 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
138 DoSuperMethodA(cl, obj, (Msg)msg);
140 if (data->needs_to_recalculate_sizes)
142 struct RastPort rp;
143 LONG min, max, val, width;
145 InitRastPort(&rp);
146 SetFont(&rp,_font(obj));
148 width = 0;
150 longget(obj, MUIA_Numeric_Min, &min);
151 longget(obj, MUIA_Numeric_Max, &max);
153 /* Determine the width of the knob */
154 for (val=min;val<=max;val++)
156 LONG nw;
157 char *buf;
159 buf = (char*)DoMethod(obj, MUIM_Numeric_Stringify, val);
160 nw = TextLength(&rp, buf, strlen(buf));
162 if (nw > width)
163 width = nw;
166 data->max_text_width = width;
167 data->text_height = _font(obj)->tf_YSize;
169 data->needs_to_recalculate_sizes = FALSE;
172 msg->MinMaxInfo->MinWidth += data->max_text_width;
173 msg->MinMaxInfo->MinHeight += data->text_height;
174 msg->MinMaxInfo->DefWidth += data->max_text_width;
175 msg->MinMaxInfo->DefHeight += data->text_height;
176 msg->MinMaxInfo->MaxWidth += data->max_text_width;
177 msg->MinMaxInfo->MaxHeight += data->text_height;
179 return TRUE;
182 static void DrawKnob(Object *obj, struct Numericbutton_DATA *data, BOOL force)
184 struct RastPort *rp, *saverp;
185 LONG x, val, pixeloffset, textlen, pixellen;
186 STRPTR text;
188 pixeloffset = data->popwin->MouseX - data->pop_innerx - 2 - data->knob_clickoffset_x;
190 val = DoMethod(obj, MUIM_Numeric_ScaleToValue, 0,
191 data->pop_innerw - data->knob_width, pixeloffset);
193 data->knob_left = data->pop_innerx + pixeloffset;
194 data->knob_top = data->pop_innery;
195 data->knob_val = val;
197 if (!force && (data->knob_left == data->knob_prev_left))
199 return;
201 data->knob_prev_left = data->knob_left;
203 if (data->knob_left < data->pop_innerx)
205 data->knob_left = data->pop_innerx;
207 else if (data->knob_left > data->pop_innerx + data->pop_innerw - data->knob_width)
209 data->knob_left = data->pop_innerx + data->pop_innerw - data->knob_width;
212 saverp = _rp(obj);
213 _rp(obj) = rp = data->popwin->RPort;
215 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], 0, JAM1);
216 RectFill(rp, data->knob_left, data->knob_top,
217 data->knob_left, data->knob_top + data->knob_height - 1);
218 RectFill(rp, data->knob_left + 1, data->knob_top,
219 data->knob_left + data->knob_width - 1, data->knob_top);
220 SetAPen(rp, _pens(obj)[MPEN_SHADOW]);
221 RectFill(rp, data->knob_left + data->knob_width - 1, data->knob_top + 1,
222 data->knob_left + data->knob_width - 1, data->knob_top + data->knob_height - 1);
223 RectFill(rp, data->knob_left + 1, data->knob_top + data->knob_height - 1,
224 data->knob_left + data->knob_width - 2, data->knob_top + data->knob_height - 1);
226 if (data->knob_bg)
228 #warning "Ugly hack?"
230 struct IBox old_mad_Box = muiAreaData(obj)->mad_Box;
232 muiAreaData(obj)->mad_Box.Left = data->knob_left + 1;
233 muiAreaData(obj)->mad_Box.Top = data->knob_top + 1;
234 muiAreaData(obj)->mad_Box.Width = data->knob_width - 2;
235 muiAreaData(obj)->mad_Box.Height = data->knob_height - 2;
237 zune_imspec_draw(data->knob_bg, muiRenderInfo(obj),
238 data->knob_left + 1,
239 data->knob_top + 1,
240 data->knob_width - 2,
241 data->knob_height - 2,
246 muiAreaData(obj)->mad_Box = old_mad_Box;
248 else
250 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
251 RectFill(rp, data->knob_left + 1, data->knob_top + 1,
252 data->knob_left + data->knob_width - 2,
253 data->knob_top + data->knob_height - 2);
256 SetFont(rp, _font(obj));
258 text = (STRPTR)DoMethod(obj, MUIM_Numeric_Stringify, val);
259 textlen = strlen(text);
260 pixellen = TextLength(_rp(obj), text, textlen);
262 SetAPen(rp, _pens(obj)[MPEN_TEXT]);
263 Move(rp, data->knob_left + 2 + (data->knob_width - 4 - pixellen) / 2,
264 data->knob_top + 1 + rp->TxBaseline);
265 Text(rp, text, textlen);
267 SetAPen(rp, _pens(obj)[MPEN_BACKGROUND]);
269 if (data->knob_left - 1 >= data->pop_innerx)
271 RectFill(rp, data->pop_innerx, data->pop_innery,
272 data->knob_left - 1, data->pop_innery + data->pop_innerh - 1);
275 x = data->knob_left + data->knob_width;
276 if (x <= data->pop_innerx + data->pop_innerw - 1)
278 RectFill(rp, x, data->pop_innery,
279 data->pop_innerx + data->pop_innerw - 1,
280 data->pop_innery + data->pop_innerh - 1);
283 _rp(obj) = saverp;
286 static void KillPopupWin(Object *obj, struct Numericbutton_DATA *data)
288 if (data->popwin)
290 CloseWindow(data->popwin);
291 data->popwin = NULL;
294 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
296 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
297 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
298 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
303 static BOOL MakePopupWin(Object *obj, struct Numericbutton_DATA *data)
305 const struct ZuneFrameGfx *zframe;
306 struct RastPort *rp, *saverp;
307 LONG winx, winy, winw, winh;
308 LONG framew, frameh;
309 LONG min, max;
311 zframe = zune_zframe_get_with_state(obj, &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider],
312 muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Slider].state);
314 data->pop_innerx = zframe->ileft;
315 data->pop_innery = zframe->itop;
317 data->knob_width = data->max_text_width + 4;
318 data->knob_height = data->text_height + 2;
320 framew = data->pop_innerx + zframe->iright;
321 frameh = data->pop_innery + zframe->ibottom;
323 longget(obj, MUIA_Numeric_Min, &min);
324 longget(obj, MUIA_Numeric_Max, &max);
326 winw = max - min + data->knob_width + framew;
327 winh = data->knob_height + frameh;
329 if (winw > _screen(obj)->Width)
331 winw = _screen(obj)->Width;
334 if ((winw < data->knob_width + framew) || (winh > _screen(obj)->Height))
336 return FALSE;
339 data->pop_innerw = winw - framew;
340 data->pop_innerh = winh - frameh;
342 data->knob_left = DoMethod(obj, MUIM_Numeric_ValueToScale, 0, data->pop_innerw - data->knob_width);
344 winx = _window(obj)->LeftEdge + _mleft(obj) -
345 data->pop_innerx - 2 -
346 data->knob_left;
347 winy = _window(obj)->TopEdge + _mtop(obj) - 1-
348 data->pop_innery;
350 data->popwin = OpenWindowTags(NULL, WA_CustomScreen, (IPTR)_screen(obj),
351 WA_Left, winx,
352 WA_Top, winy,
353 WA_Width, winw,
354 WA_Height, winh,
355 WA_AutoAdjust, TRUE,
356 WA_Borderless, TRUE,
357 WA_Activate, FALSE,
358 WA_BackFill, (IPTR)LAYERS_NOBACKFILL,
359 TAG_DONE);
361 if (!data->popwin)
363 return FALSE;
366 rp = data->popwin->RPort;
368 saverp = _rp(obj);
369 _rp(obj) = rp;
370 zframe->draw(zframe->customframe, muiRenderInfo(obj), 0, 0, winw, winh, 0, 0, winw, winh);
372 DrawKnob(obj, data, TRUE);
375 _rp(obj) = saverp;
377 return TRUE;
381 /**************************************************************************
382 MUIM_Show
383 **************************************************************************/
384 IPTR Numericbutton__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
386 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
387 IPTR retval;
389 retval = DoSuperMethodA(cl, obj, (Msg)msg);
391 if (data->knob_bg)
392 zune_imspec_show(data->knob_bg, obj);
394 return retval;
397 /**************************************************************************
398 MUIM_Hide
399 **************************************************************************/
400 IPTR Numericbutton__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
402 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
404 if (data->popwin)
406 KillPopupWin(obj, data);
409 if (data->knob_bg)
410 zune_imspec_hide(data->knob_bg);
412 return DoSuperMethodA(cl, obj, (Msg)msg);
416 /**************************************************************************
417 MUIM_Draw
418 **************************************************************************/
419 IPTR Numericbutton__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
421 IPTR val;
422 char *buf;
423 int width;
425 DoSuperMethodA(cl,obj,(Msg)msg);
427 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
428 return FALSE;
430 DoMethod(obj,MUIM_DrawBackground,_mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj),
431 _mleft(obj),_mtop(obj),0);
433 SetFont(_rp(obj),_font(obj));
434 SetABPenDrMd(_rp(obj),_pens(obj)[MPEN_TEXT],_pens(obj)[MPEN_BACKGROUND],JAM1);
436 get(obj, MUIA_Numeric_Value, &val);
437 buf = (char*)DoMethod(obj,MUIM_Numeric_Stringify,val);
438 width = TextLength(_rp(obj),buf,strlen(buf));
440 Move(_rp(obj), _mleft(obj) + (_mwidth(obj) - width) / 2,
441 _mtop(obj) + _font(obj)->tf_Baseline);
443 Text(_rp(obj), buf, strlen(buf));
445 return TRUE;
448 /**************************************************************************
449 MUIM_HandleEvent
450 **************************************************************************/
451 IPTR Numericbutton__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
453 struct Numericbutton_DATA *data = INST_DATA(cl, obj);
455 if (!msg->imsg)
457 return 0;
460 switch(msg->imsg->Class)
462 case IDCMP_MOUSEBUTTONS:
463 switch(msg->imsg->Code)
465 case SELECTDOWN:
466 if (_between(_left(obj), msg->imsg->MouseX, _right(obj)) &&
467 _between(_top(obj), msg->imsg->MouseY, _bottom(obj)) &&
468 (muiAreaData(obj)->mad_Flags & MADF_CANDRAW) &&
469 !data->popwin)
471 data->knob_clickoffset_x = msg->imsg->MouseX - _mleft(obj);
473 if (MakePopupWin(obj, data))
475 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
476 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
477 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
479 return 0;
482 break;
484 case SELECTUP:
485 case MENUUP:
486 case MIDDLEUP:
487 default:
488 if (data->popwin)
490 KillPopupWin(obj, data);
491 if ((msg->imsg->Code == SELECTUP))
493 set(obj, MUIA_Numeric_Value, data->knob_val);
495 return 0;
497 break;
500 } /* switch(msg->imsg->Code) */
501 break;
503 case IDCMP_MOUSEMOVE:
504 if (data->popwin)
506 DrawKnob(obj, data, FALSE);
508 return 0;
510 break;
512 } /* switch(msg->imsg->Class) */
514 return 0;
518 #if ZUNE_BUILTIN_NUMERICBUTTON
519 BOOPSI_DISPATCHER(IPTR, Numericbutton_Dispatcher, cl, obj, msg)
521 switch (msg->MethodID)
523 case OM_NEW: return Numericbutton__OM_NEW(cl, obj, (struct opSet *)msg);
524 case OM_SET: return Numericbutton__OM_SET(cl, obj, (struct opSet *)msg);
526 case MUIM_Setup: return Numericbutton__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
527 case MUIM_Cleanup: return Numericbutton__MUIM_Cleanup(cl, obj, (struct MUIP_Cleanup *)msg);
528 case MUIM_Show: return Numericbutton__MUIM_Show(cl, obj, (struct MUIP_Show *)msg);
529 case MUIM_Hide: return Numericbutton__MUIM_Hide(cl, obj, (struct MUIP_Hide *)msg);
530 case MUIM_AskMinMax: return Numericbutton__MUIM_AskMinMax(cl, obj, (struct MUIP_AskMinMax *)msg);
531 case MUIM_Draw: return Numericbutton__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
532 case MUIM_HandleEvent: return Numericbutton__MUIM_HandleEvent(cl, obj, (struct MUIP_HandleEvent *)msg);
533 default: return DoSuperMethodA(cl, obj, msg);
536 BOOPSI_DISPATCHER_END
538 const struct __MUIBuiltinClass _MUI_Numericbutton_desc =
540 MUIC_Numericbutton,
541 MUIC_Numeric,
542 sizeof(struct Numericbutton_DATA),
543 (void*)Numericbutton_Dispatcher
545 #endif /* ZUNE_BUILTIN_NUMERICBUTTON */