2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2011, 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 alignment */
44 LONG state
; /* When using mouse */
47 int same_knop_value
; /* 1 if the knob value didn't change
48 * since last call of MUIM_Draw */
54 SLIDER_HORIZ
= (1 << 0),
55 SLIDER_QUIET
= (1 << 1),
58 #define longget(obj,attr,var) \
61 IPTR _iptr_var = *(var); \
62 get(obj,attr,&_iptr_var); \
63 *var = (LONG)_iptr_var; \
67 Slider.mui/MUIA_Slider_Horiz
68 Slider.mui/MUIA_Slider_Level
69 Slider.mui/MUIA_Slider_Max
70 Slider.mui/MUIA_Slider_Min
71 Slider.mui/MUIA_Slider_Quiet
72 Slider.mui/MUIA_Slider_Reverse d
75 /**************************************************************************
77 **************************************************************************/
78 IPTR
Slider__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
80 struct MUI_SliderData
*data
;
81 struct TagItem
*tags
, *tag
;
82 ULONG flags
= SLIDER_HORIZ
;
84 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
88 case MUIA_Group_Horiz
:
89 case MUIA_Slider_Horiz
:
90 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_HORIZ
);
92 case MUIA_Slider_Quiet
:
93 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_QUIET
);
98 obj
= (Object
*) DoSuperNewTags
102 MUIA_Background
, MUII_SliderBack
,
103 MUIA_Font
, MUIV_Font_Knob
,
104 MUIA_Frame
, MUIV_Frame_Slider
,
106 TAG_MORE
, (IPTR
) msg
->ops_AttrList
114 data
= INST_DATA(cl
, obj
);
117 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
118 data
->ehn
.ehn_Priority
= 0;
119 data
->ehn
.ehn_Flags
= 0;
120 data
->ehn
.ehn_Object
= obj
;
121 data
->ehn
.ehn_Class
= cl
;
126 /**************************************************************************
128 **************************************************************************/
129 IPTR
Slider__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
131 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
132 struct TagItem
*tags
, *tag
;
134 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
138 case MUIA_Numeric_Value
:
139 if (!data
->keep_knob_offset
)
141 /* reset the offset */
142 data
->knob_offset
= 0;
147 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
150 /**************************************************************************
152 **************************************************************************/
153 IPTR
Slider__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
154 struct MUIP_Setup
*msg
)
156 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
157 const struct ZuneFrameGfx
*knob_frame
;
164 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
169 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
]);
170 data
->knob_bg
= zune_imspec_setup(MUII_SliderKnob
, muiRenderInfo(obj
));
173 SetFont(&rp
, _font(obj
));
177 longget(obj
, MUIA_Numeric_Min
, &min
);
178 longget(obj
, MUIA_Numeric_Max
, &max
);
180 if ((max
- min
) > MUI_MAXMAX
)
186 /* Determine the width of the knob */
187 for (val
= min
; val
<= max
; val
++)
192 buf
= (char *)DoMethod(obj
, MUIM_Numeric_Stringify
, val
);
193 nw
= TextLength(&rp
, buf
, strlen(buf
));
197 data
->max_text_width
= width
;
198 data
->knob_width
= width
+
201 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerLeft
+
202 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerRight
;
204 data
->knob_height
= _font(obj
)->tf_YSize
+
206 knob_frame
->ibottom
+
207 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerTop
+
208 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerBottom
;
210 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
215 /**************************************************************************
217 **************************************************************************/
218 IPTR
Slider__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
219 struct MUIP_Cleanup
*msg
)
221 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
225 zune_imspec_cleanup(data
->knob_bg
);
226 data
->knob_bg
= NULL
;
228 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
229 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
232 /**************************************************************************
234 **************************************************************************/
235 IPTR
Slider__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
236 struct MUIP_AskMinMax
*msg
)
238 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
239 LONG min
= 0, max
= 0;
241 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
243 longget(obj
, MUIA_Numeric_Min
, &min
);
244 longget(obj
, MUIA_Numeric_Max
, &max
);
246 if (data
->flags
& SLIDER_HORIZ
)
248 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
+ 1;
249 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
;
250 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
* 4 + 2;
251 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
;
252 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
253 msg
->MinMaxInfo
->MaxHeight
+= data
->knob_height
;
257 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
;
258 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
+ 1;
259 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
;
260 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
* 4 + 2;
261 msg
->MinMaxInfo
->MaxWidth
+= data
->knob_width
;
262 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
268 /**************************************************************************
270 **************************************************************************/
271 IPTR
Slider__MUIM_Show(struct IClass
*cl
, Object
*obj
,
272 struct MUIP_Show
*msg
)
274 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
276 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
278 zune_imspec_show(data
->knob_bg
, obj
);
282 /**************************************************************************
284 **************************************************************************/
285 IPTR
Slider__MUIM_Hide(struct IClass
*cl
, Object
*obj
,
286 struct MUIP_Hide
*msg
)
288 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
291 zune_imspec_hide(data
->knob_bg
);
293 /* This may look ugly when window is resized but it is easier than
294 * recalculating the knob offset in Slider_Show */
295 data
->knob_offset
= 0;
297 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
301 /**************************************************************************
303 **************************************************************************/
304 IPTR
Slider__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
305 struct MUIP_Draw
*msg
)
307 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
308 const struct ZuneFrameGfx
*knob_frame
;
309 int knob_frame_state
;
314 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
316 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
)))
319 if (data
->flags
& SLIDER_HORIZ
)
321 data
->knob_top
= _mtop(obj
);
323 DoSuperMethod(cl
, obj
, MUIM_Numeric_ValueToScale
, 0,
324 _mwidth(obj
) - data
->knob_width
) + data
->knob_offset
+
327 if (data
->knob_left
< _mleft(obj
))
328 data
->knob_left
= _mleft(obj
);
331 if (data
->knob_left
+ data
->knob_width
> _mright(obj
))
332 data
->knob_left
= _mright(obj
) - data
->knob_width
;
338 (_mheight(obj
) - data
->knob_height
- DoSuperMethod(cl
, obj
,
339 MUIM_Numeric_ValueToScale
, 0,
340 _mheight(obj
) - data
->knob_height
)) + data
->knob_offset
+
342 data
->knob_left
= _mleft(obj
);
344 if (data
->knob_top
< _mtop(obj
))
345 data
->knob_top
= _mtop(obj
);
348 if (data
->knob_top
+ data
->knob_height
> _mbottom(obj
))
349 data
->knob_top
= _mbottom(obj
) - data
->knob_height
;
353 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
354 _mwidth(obj
), _mheight(obj
), 0, 0, 0);
356 zune_imspec_draw(data
->knob_bg
, muiRenderInfo(obj
),
357 data
->knob_left
, data
->knob_top
, data
->knob_width
,
358 data
->knob_height
, 0, 0, 0);
361 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].state
;
363 knob_frame_state
^= 1;
364 knob_frame
= zune_zframe_get_with_state(obj
,
365 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
],
367 knob_frame
->draw(knob_frame
->customframe
, muiRenderInfo(obj
),
368 data
->knob_left
, data
->knob_top
, data
->knob_width
,
369 data
->knob_height
, data
->knob_left
, data
->knob_top
,
370 data
->knob_width
, data
->knob_height
);
372 if (!(data
->flags
& SLIDER_QUIET
))
374 SetFont(_rp(obj
), _font(obj
));
375 SetABPenDrMd(_rp(obj
), _pens(obj
)[MPEN_TEXT
],
376 _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
377 longget(obj
, MUIA_Numeric_Value
, &val
);
378 buf
= (char *)DoMethod(obj
, MUIM_Numeric_Stringify
, val
);
379 width
= TextLength(_rp(obj
), buf
, strlen(buf
));
382 data
->knob_left
+ knob_frame
->ileft
+
383 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].
384 innerLeft
+ (data
->max_text_width
- width
) / 2,
385 data
->knob_top
+ _font(obj
)->tf_Baseline
+ knob_frame
->itop
+
386 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].
388 Text(_rp(obj
), buf
, strlen(buf
));
391 data
->same_knop_value
= 0;
395 /**************************************************************************
397 **************************************************************************/
398 IPTR
Slider__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
399 struct MUIP_HandleEvent
*msg
)
401 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
405 switch (msg
->imsg
->Class
)
407 case IDCMP_MOUSEBUTTONS
:
408 if (msg
->imsg
->Code
== SELECTDOWN
)
410 if (_isinobject(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
412 if (data
->flags
& SLIDER_HORIZ
)
415 msg
->imsg
->MouseX
- data
->knob_left
+ _mleft(obj
);
420 msg
->imsg
->MouseY
- data
->knob_top
+ _mtop(obj
);
421 D(bug("%p: Y=%ld, mtop=%ld mheight=%ld ktop=%ld "
422 "kheight=%ld knob_click=%ld\n",
423 obj
, msg
->imsg
->MouseY
, _mtop(obj
),
424 _mheight(obj
), data
->knob_top
,
425 data
->knob_height
, data
->knob_click
));
428 if (_between(data
->knob_left
, msg
->imsg
->MouseX
,
429 data
->knob_left
+ data
->knob_width
)
430 && _between(data
->knob_top
, msg
->imsg
->MouseY
,
431 data
->knob_top
+ data
->knob_height
))
433 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
435 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
436 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
439 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
441 else if (((data
->flags
& SLIDER_HORIZ
)
442 && msg
->imsg
->MouseX
< data
->knob_left
)
443 || (!(data
->flags
& SLIDER_HORIZ
)
444 && msg
->imsg
->MouseY
>
445 data
->knob_top
+ data
->knob_height
))
447 DoSuperMethod(cl
, obj
, MUIM_Numeric_Decrease
, 1);
451 DoSuperMethod(cl
, obj
, MUIM_Numeric_Increase
, 1);
459 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
461 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
462 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
465 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
470 case IDCMP_MOUSEMOVE
:
475 LONG oldko
= data
->knob_offset
;
477 if (data
->flags
& SLIDER_HORIZ
)
479 newval
= DoSuperMethod(cl
, obj
, MUIM_Numeric_ScaleToValue
,
480 0, _mwidth(obj
) - data
->knob_width
,
481 msg
->imsg
->MouseX
- data
->knob_click
);
484 DoSuperMethod(cl
, obj
, MUIM_Numeric_ValueToScaleExt
,
486 _mwidth(obj
) - data
->knob_width
) + data
->knob_click
;
487 if (data
->knob_offset
< 0)
488 data
->knob_offset
= 0;
489 data
->knob_offset
= msg
->imsg
->MouseX
- pixel
;
490 data
->keep_knob_offset
= 1;
491 // D(bug("%ld %ld %ld %ld %ld\n", data->knob_offset, pixel,
492 // msg->imsg->MouseX, _mleft(obj), data->knob_click));
499 _mheight(obj
) - data
->knob_height
+ data
->knob_click
-
502 DoSuperMethod(cl
, obj
, MUIM_Numeric_ScaleToValue
, 0,
503 _mheight(obj
) - data
->knob_height
, scale
);
505 (_mheight(obj
) - data
->knob_height
- DoSuperMethod(cl
,
506 obj
, MUIM_Numeric_ValueToScaleExt
, newval
, 0,
507 _mheight(obj
) - data
->knob_height
)) +
509 data
->knob_offset
= msg
->imsg
->MouseY
- pixel
;
510 data
->keep_knob_offset
= 1;
511 // D(bug("%0lx: Y=%ld scale=%ld val=%ld pixel: %ld koff: %ld\n",
512 // obj, msg->imsg->MouseY, scale, newval, pixel,
513 // data->knob_offset));
516 get(obj
, MUIA_Numeric_Value
, &oldval
);
517 if ((LONG
) oldval
!= newval
)
519 set(obj
, MUIA_Numeric_Value
, newval
);
521 else if (oldko
!= data
->knob_offset
)
523 data
->same_knop_value
= 1;
524 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
526 data
->keep_knob_offset
= 0;
534 BOOPSI_DISPATCHER(IPTR
, Slider_Dispatcher
, cl
, obj
, msg
)
536 switch (msg
->MethodID
)
539 return Slider__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
541 return Slider__OM_SET(cl
, obj
, (struct opSet
*)msg
);
543 return Slider__MUIM_Setup(cl
, obj
, (APTR
) msg
);
545 return Slider__MUIM_Cleanup(cl
, obj
, (APTR
) msg
);
547 return Slider__MUIM_Show(cl
, obj
, (APTR
) msg
);
549 return Slider__MUIM_Hide(cl
, obj
, (APTR
) msg
);
551 return Slider__MUIM_AskMinMax(cl
, obj
, (APTR
) msg
);
553 return Slider__MUIM_Draw(cl
, obj
, (APTR
) msg
);
554 case MUIM_HandleEvent
:
555 return Slider__MUIM_HandleEvent(cl
, obj
, (APTR
) msg
);
557 return DoSuperMethodA(cl
, obj
, msg
);
559 BOOPSI_DISPATCHER_END
564 const struct __MUIBuiltinClass _MUI_Slider_desc
=
568 sizeof(struct MUI_SliderData
),
569 (void *) Slider_Dispatcher