2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2006, The AROS Development Team.
11 #include <clib/alib_protos.h>
12 #include <clib/macros.h>
14 #include <proto/exec.h>
15 #include <proto/intuition.h>
16 #include <proto/graphics.h>
17 #include <proto/utility.h>
18 #include <proto/muimaster.h>
25 #include "muimaster_intern.h"
29 extern struct Library
*MUIMasterBase
;
34 struct MUI_EventHandlerNode ehn
;
35 struct MUI_ImageSpec_intern
*knob_bg
;
36 LONG knob_offset
; /* current pixel offest for fine algiment */
44 LONG state
; /* When using mouse */
47 int same_knop_value
; /* 1 if the knob value didn't change in since last call of MUIM_Draw */
52 SLIDER_HORIZ
= (1<<0),
53 SLIDER_QUIET
= (1<<1),
56 #define longget(obj,attr,var) \
59 IPTR _iptr_var = *(var); \
60 get(obj,attr,&_iptr_var); \
61 *var = (LONG)_iptr_var; \
65 Slider.mui/MUIA_Slider_Horiz
66 Slider.mui/MUIA_Slider_Level
67 Slider.mui/MUIA_Slider_Max
68 Slider.mui/MUIA_Slider_Min
69 Slider.mui/MUIA_Slider_Quiet
70 Slider.mui/MUIA_Slider_Reverse d
73 /**************************************************************************
75 **************************************************************************/
76 IPTR
Slider__OM_NEW(struct IClass
*cl
, Object
* obj
, struct opSet
*msg
)
78 struct MUI_SliderData
*data
;
79 struct TagItem
*tags
, *tag
;
80 ULONG flags
= SLIDER_HORIZ
;
82 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem((const struct TagItem
**)&tags
));)
86 case MUIA_Group_Horiz
:
87 case MUIA_Slider_Horiz
:
88 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_HORIZ
);
90 case MUIA_Slider_Quiet
:
91 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_QUIET
);
96 obj
= (Object
*) DoSuperNewTags
100 MUIA_Background
, MUII_SliderBack
,
101 MUIA_Font
, MUIV_Font_Knob
,
102 MUIA_Frame
, MUIV_Frame_Slider
,
104 TAG_MORE
, (IPTR
) msg
->ops_AttrList
112 data
= INST_DATA(cl
, obj
);
115 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
116 data
->ehn
.ehn_Priority
= 0;
117 data
->ehn
.ehn_Flags
= 0;
118 data
->ehn
.ehn_Object
= obj
;
119 data
->ehn
.ehn_Class
= cl
;
124 /**************************************************************************
126 **************************************************************************/
127 IPTR
Slider__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
129 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
130 struct TagItem
*tags
, *tag
;
132 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem((const struct TagItem
**)&tags
));)
136 case MUIA_Numeric_Value
:
137 if (!data
->keep_knob_offset
)
139 /* reset the offset */
140 data
->knob_offset
= 0;
145 return DoSuperMethodA(cl
,obj
,(Msg
)msg
);
148 /**************************************************************************
150 **************************************************************************/
151 IPTR
Slider__MUIM_Setup(struct IClass
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
153 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
154 const struct ZuneFrameGfx
*knob_frame
;
161 if (!DoSuperMethodA(cl
,obj
,(Msg
)msg
))
164 knob_frame
= zune_zframe_get(obj
, &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
]);
165 data
->knob_bg
= zune_imspec_setup(MUII_SliderKnob
, muiRenderInfo(obj
));
168 SetFont(&rp
,_font(obj
));
172 longget(obj
,MUIA_Numeric_Min
,&min
);
173 longget(obj
,MUIA_Numeric_Max
,&max
);
175 if ((max
- min
) > MUI_MAXMAX
)
181 /* Determine the width of the knob */
182 for (val
=min
;val
<=max
;val
++)
187 buf
= (char*)DoMethod(obj
,MUIM_Numeric_Stringify
,val
);
188 nw
= TextLength(&rp
,buf
,strlen(buf
));
189 if (nw
> width
) width
= nw
;
191 data
->max_text_width
= width
;
192 data
->knob_width
= width
+
195 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerLeft
+
196 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerRight
;
198 data
->knob_height
= _font(obj
)->tf_YSize
+
200 knob_frame
->ibottom
+
201 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerTop
+
202 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerBottom
;
204 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
211 /**************************************************************************
213 **************************************************************************/
214 IPTR
Slider__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
, struct MUIP_Cleanup
*msg
)
216 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
220 zune_imspec_cleanup(data
->knob_bg
);
221 data
->knob_bg
= NULL
;
223 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
224 return DoSuperMethodA(cl
,obj
,(Msg
)msg
);
227 /**************************************************************************
229 **************************************************************************/
230 IPTR
Slider__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
232 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
235 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
237 longget(obj
,MUIA_Numeric_Min
,&min
);
238 longget(obj
,MUIA_Numeric_Max
,&max
);
240 if (data
->flags
& SLIDER_HORIZ
)
242 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
+ 1;
243 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
;
244 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
* 4 + 2;
245 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
;
246 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
247 msg
->MinMaxInfo
->MaxHeight
+= data
->knob_height
;
251 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
;
252 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
+ 1;
253 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
;
254 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
* 4 + 2;
255 msg
->MinMaxInfo
->MaxWidth
+= data
->knob_width
;
256 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
262 /**************************************************************************
264 **************************************************************************/
265 IPTR
Slider__MUIM_Show(struct IClass
*cl
, Object
*obj
, struct MUIP_Show
*msg
)
267 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
269 DoSuperMethodA(cl
,obj
,(Msg
)msg
);
271 zune_imspec_show(data
->knob_bg
, obj
);
275 /**************************************************************************
277 **************************************************************************/
278 IPTR
Slider__MUIM_Hide(struct IClass
*cl
, Object
*obj
,struct MUIP_Hide
*msg
)
280 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
283 zune_imspec_hide(data
->knob_bg
);
285 /* This may look ugly when window is resized but it is easier than recalculating
286 * the knob offset in Slider_Show */
287 data
->knob_offset
= 0;
289 return DoSuperMethodA(cl
,obj
,(Msg
)msg
);
293 /**************************************************************************
295 **************************************************************************/
296 IPTR
Slider__MUIM_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
298 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
299 const struct ZuneFrameGfx
*knob_frame
;
300 int knob_frame_state
;
305 DoSuperMethodA(cl
,obj
,(Msg
)msg
);
307 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
)))
310 if (data
->flags
& SLIDER_HORIZ
)
312 data
->knob_top
= _mtop(obj
);
313 data
->knob_left
= DoSuperMethod(cl
, obj
,MUIM_Numeric_ValueToScale
, 0, _mwidth(obj
) - data
->knob_width
) + data
->knob_offset
+ _mleft(obj
);
315 if (data
->knob_left
< _mleft(obj
)) data
->knob_left
= _mleft(obj
);
318 if (data
->knob_left
+ data
->knob_width
> _mright(obj
))
319 data
->knob_left
= _mright(obj
) - data
->knob_width
;
324 data
->knob_top
= (_mheight(obj
) - data
->knob_height
- DoSuperMethod(cl
, obj
,MUIM_Numeric_ValueToScale
, 0, _mheight(obj
) - data
->knob_height
)) + data
->knob_offset
+ _mtop(obj
);
325 data
->knob_left
= _mleft(obj
);
327 if (data
->knob_top
< _mtop(obj
)) data
->knob_top
= _mtop(obj
);
330 if (data
->knob_top
+ data
->knob_height
> _mbottom(obj
))
331 data
->knob_top
= _mbottom(obj
) - data
->knob_height
;
335 DoMethod(obj
,MUIM_DrawBackground
,_mleft(obj
),_mtop(obj
),_mwidth(obj
),_mheight(obj
),0,0,0);
337 zune_imspec_draw(data
->knob_bg
, muiRenderInfo(obj
),
338 data
->knob_left
, data
->knob_top
, data
->knob_width
, data
->knob_height
,
341 knob_frame_state
= muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].state
;
343 knob_frame_state
^= 1;
344 knob_frame
= zune_zframe_get_with_state(obj
,
345 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
], knob_frame_state
);
346 knob_frame
->draw(knob_frame
->customframe
, muiRenderInfo(obj
), data
->knob_left
, data
->knob_top
, data
->knob_width
,
347 data
->knob_height
, data
->knob_left
, data
->knob_top
, data
->knob_width
,
350 SetFont(_rp(obj
),_font(obj
));
351 SetABPenDrMd(_rp(obj
),_pens(obj
)[MPEN_TEXT
],_pens(obj
)[MPEN_BACKGROUND
],JAM1
);
352 longget(obj
, MUIA_Numeric_Value
, &val
);
353 buf
= (char*)DoMethod(obj
,MUIM_Numeric_Stringify
,val
);
354 width
= TextLength(_rp(obj
),buf
,strlen(buf
));
357 data
->knob_left
+ knob_frame
->ileft
+
358 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerLeft
+
359 (data
->max_text_width
- width
) / 2,
360 data
->knob_top
+ _font(obj
)->tf_Baseline
+ knob_frame
->itop
+
361 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerTop
);
362 Text(_rp(obj
), buf
, strlen(buf
));
364 data
->same_knop_value
= 0;
368 /**************************************************************************
370 **************************************************************************/
371 IPTR
Slider__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
373 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
377 switch (msg
->imsg
->Class
)
379 case IDCMP_MOUSEBUTTONS
:
380 if (msg
->imsg
->Code
== SELECTDOWN
)
382 if (_isinobject(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
384 if (data
->flags
& SLIDER_HORIZ
)
386 data
->knob_click
= msg
->imsg
->MouseX
- data
->knob_left
+ _mleft(obj
);
390 data
->knob_click
= msg
->imsg
->MouseY
- data
->knob_top
+ _mtop(obj
) ;
391 D(bug("%p: Y=%ld, mtop=%ld mheight=%ld ktop=%ld kheight=%ld knob_click=%ld\n",
392 obj
, msg
->imsg
->MouseY
, _mtop(obj
), _mheight(obj
),
393 data
->knob_top
, data
->knob_height
, data
->knob_click
));
396 if (_between(data
->knob_left
, msg
->imsg
->MouseX
, data
->knob_left
+ data
->knob_width
)
397 && _between(data
->knob_top
, msg
->imsg
->MouseY
, data
->knob_top
+ data
->knob_height
))
399 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
400 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
401 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
403 MUI_Redraw(obj
,MADF_DRAWUPDATE
);
405 else if (((data
->flags
& SLIDER_HORIZ
)
406 && msg
->imsg
->MouseX
< data
->knob_left
)
407 || (!(data
->flags
& SLIDER_HORIZ
)
408 && msg
->imsg
->MouseY
> data
->knob_top
+ data
->knob_height
))
410 DoSuperMethod(cl
, obj
, MUIM_Numeric_Decrease
, 1);
414 DoSuperMethod(cl
, obj
, MUIM_Numeric_Increase
, 1);
418 else /* msg->imsg->Code != SELECTDOWN */
422 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
423 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
424 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
426 MUI_Redraw(obj
,MADF_DRAWUPDATE
);
428 } /* if (msg->imsg->Code == SELECTDOWN) */
431 case IDCMP_MOUSEMOVE
:
436 LONG oldko
= data
->knob_offset
;
438 if (data
->flags
& SLIDER_HORIZ
)
440 newval
= DoSuperMethod(cl
, obj
, MUIM_Numeric_ScaleToValue
,
441 0, _mwidth(obj
) - data
->knob_width
,
442 msg
->imsg
->MouseX
- data
->knob_click
);
444 pixel
= DoSuperMethod(cl
, obj
,MUIM_Numeric_ValueToScaleExt
, newval
, 0, _mwidth(obj
) - data
->knob_width
) + data
->knob_click
;
445 if (data
->knob_offset
< 0) data
->knob_offset
= 0;
446 data
->knob_offset
= msg
->imsg
->MouseX
- pixel
;
447 data
->keep_knob_offset
= 1;
448 // D(bug("%ld %ld %ld %ld %ld\n",data->knob_offset, pixel, msg->imsg->MouseX, _mleft(obj), data->knob_click));
454 scale
= _mheight(obj
) - data
->knob_height
+ data
->knob_click
- msg
->imsg
->MouseY
;
455 newval
= DoSuperMethod(cl
, obj
, MUIM_Numeric_ScaleToValue
,
456 0, _mheight(obj
) - data
->knob_height
,
458 pixel
= (_mheight(obj
) - data
->knob_height
- DoSuperMethod(cl
, obj
, MUIM_Numeric_ValueToScaleExt
, newval
, 0, _mheight(obj
) - data
->knob_height
)) + data
->knob_click
;
459 data
->knob_offset
= msg
->imsg
->MouseY
- pixel
;
460 data
->keep_knob_offset
= 1;
461 // D(bug("%0lx: Y=%ld scale=%ld val=%ld pixel: %ld koff: %ld\n", obj, msg->imsg->MouseY, scale, newval, pixel, data->knob_offset));
464 get(obj
, MUIA_Numeric_Value
, &oldval
);
465 if ((LONG
)oldval
!= newval
)
467 set(obj
, MUIA_Numeric_Value
, newval
);
468 } else if (oldko
!= data
->knob_offset
)
470 data
->same_knop_value
= 1;
471 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
473 data
->keep_knob_offset
= 0;
481 BOOPSI_DISPATCHER(IPTR
, Slider_Dispatcher
, cl
, obj
, msg
)
483 switch (msg
->MethodID
)
485 case OM_NEW
: return Slider__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
486 case OM_SET
: return Slider__OM_SET(cl
, obj
, (struct opSet
*)msg
);
487 case MUIM_Setup
: return Slider__MUIM_Setup(cl
, obj
, (APTR
)msg
);
488 case MUIM_Cleanup
: return Slider__MUIM_Cleanup(cl
, obj
, (APTR
)msg
);
489 case MUIM_Show
: return Slider__MUIM_Show(cl
, obj
, (APTR
)msg
);
490 case MUIM_Hide
: return Slider__MUIM_Hide(cl
, obj
, (APTR
)msg
);
491 case MUIM_AskMinMax
: return Slider__MUIM_AskMinMax(cl
, obj
, (APTR
)msg
);
492 case MUIM_Draw
: return Slider__MUIM_Draw(cl
, obj
, (APTR
)msg
);
493 case MUIM_HandleEvent
: return Slider__MUIM_HandleEvent(cl
, obj
, (APTR
)msg
);
495 return DoSuperMethodA(cl
, obj
, msg
);
497 BOOPSI_DISPATCHER_END
503 const struct __MUIBuiltinClass _MUI_Slider_desc
= {
506 sizeof(struct MUI_SliderData
),
507 (void*)Slider_Dispatcher