2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2013, 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
;
45 CONST_STRPTR text_buffer
;
53 SLIDER_HORIZ
= (1 << 0),
54 SLIDER_QUIET
= (1 << 1),
55 SLIDER_VALIDOFFSET
= (1 << 2),
56 SLIDER_VALIDSTRING
= (1 << 3),
59 #define longget(obj,attr,var) \
62 IPTR _iptr_var = *(var); \
63 get(obj,attr,&_iptr_var); \
64 *var = (LONG)_iptr_var; \
68 static void CalcKnobDimensions(struct IClass
*cl
, Object
*obj
)
70 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
71 const struct ZuneFrameGfx
*knob_frame
;
80 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
]);
83 SetFont(&rp
, _font(obj
));
87 longget(obj
, MUIA_Numeric_Min
, &min
);
88 longget(obj
, MUIA_Numeric_Max
, &max
);
90 if ((max
- min
) > MUI_MAXMAX
)
96 /* Determine the width of the knob */
97 for (val
= min
; val
<= max
; val
++)
102 buf
= (char *)DoMethod(obj
, MUIM_Numeric_Stringify
, val
);
103 nw
= TextLength(&rp
, buf
, strlen(buf
));
107 data
->max_text_width
= width
;
108 data
->knob_width
= width
+
111 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerLeft
+
112 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerRight
;
114 data
->knob_height
= _font(obj
)->tf_YSize
+
116 knob_frame
->ibottom
+
117 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerTop
+
118 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerBottom
;
120 if (data
->flags
& SLIDER_HORIZ
)
121 data
->knob_length
= data
->knob_width
;
123 data
->knob_length
= data
->knob_height
;
126 /**************************************************************************
128 **************************************************************************/
129 IPTR
Slider__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
131 struct MUI_SliderData
*data
;
132 struct TagItem
*tags
, *tag
;
133 ULONG flags
= SLIDER_HORIZ
;
135 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
139 case MUIA_Slider_Horiz
:
140 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_HORIZ
);
142 case MUIA_Slider_Quiet
:
143 _handle_bool_tag(flags
, tag
->ti_Data
, SLIDER_QUIET
);
148 obj
= (Object
*) DoSuperNewTags
152 MUIA_Background
, MUII_SliderBack
,
153 MUIA_Font
, MUIV_Font_Knob
,
154 MUIA_Frame
, MUIV_Frame_Slider
,
156 TAG_MORE
, (IPTR
) msg
->ops_AttrList
164 data
= INST_DATA(cl
, obj
);
167 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
168 data
->ehn
.ehn_Priority
= 0;
169 data
->ehn
.ehn_Flags
= 0;
170 data
->ehn
.ehn_Object
= obj
;
171 data
->ehn
.ehn_Class
= cl
;
176 /**************************************************************************
178 **************************************************************************/
179 IPTR
Slider__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
181 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
182 struct TagItem
*tags
, *tag
;
184 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
188 case MUIA_Slider_Horiz
:
189 _handle_bool_tag(data
->flags
, tag
->ti_Data
, SLIDER_HORIZ
);
190 CalcKnobDimensions(cl
, obj
);
191 data
->flags
&= ~(SLIDER_VALIDOFFSET
| SLIDER_VALIDSTRING
);
192 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
194 case MUIA_Numeric_Value
:
195 case MUIA_Numeric_Min
:
196 case MUIA_Numeric_Max
:
197 case MUIA_Numeric_Format
:
198 /* reset the knob position and string */
199 data
->flags
&= ~(SLIDER_VALIDOFFSET
| SLIDER_VALIDSTRING
);
203 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
206 /**************************************************************************
208 **************************************************************************/
209 IPTR
Slider__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
211 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
212 IPTR
*store
= msg
->opg_Storage
;
214 switch (msg
->opg_AttrID
)
216 case MUIA_Slider_Horiz
:
217 *store
= ((data
->flags
& SLIDER_HORIZ
) != 0);
221 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
224 /**************************************************************************
226 **************************************************************************/
227 IPTR
Slider__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
228 struct MUIP_Setup
*msg
)
230 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
232 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
235 data
->knob_bg
= zune_imspec_setup(MUII_SliderKnob
, muiRenderInfo(obj
));
237 CalcKnobDimensions(cl
, obj
);
239 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
244 /**************************************************************************
246 **************************************************************************/
247 IPTR
Slider__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
248 struct MUIP_Cleanup
*msg
)
250 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
254 zune_imspec_cleanup(data
->knob_bg
);
255 data
->knob_bg
= NULL
;
257 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
259 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
262 /**************************************************************************
264 **************************************************************************/
265 IPTR
Slider__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
266 struct MUIP_AskMinMax
*msg
)
268 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
269 LONG min
= 0, max
= 0;
271 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
273 longget(obj
, MUIA_Numeric_Min
, &min
);
274 longget(obj
, MUIA_Numeric_Max
, &max
);
276 if (data
->flags
& SLIDER_HORIZ
)
278 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
+ 1;
279 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
;
280 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
* 4 + 2;
281 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
;
282 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
283 msg
->MinMaxInfo
->MaxHeight
+= data
->knob_height
;
287 msg
->MinMaxInfo
->MinWidth
+= data
->knob_width
;
288 msg
->MinMaxInfo
->MinHeight
+= data
->knob_height
+ 1;
289 msg
->MinMaxInfo
->DefWidth
+= data
->knob_width
;
290 msg
->MinMaxInfo
->DefHeight
+= data
->knob_height
* 4 + 2;
291 msg
->MinMaxInfo
->MaxWidth
+= data
->knob_width
;
292 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
298 /**************************************************************************
300 **************************************************************************/
301 IPTR
Slider__MUIM_Show(struct IClass
*cl
, Object
*obj
,
302 struct MUIP_Show
*msg
)
304 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
306 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
308 zune_imspec_show(data
->knob_bg
, obj
);
312 /**************************************************************************
314 **************************************************************************/
315 IPTR
Slider__MUIM_Hide(struct IClass
*cl
, Object
*obj
,
316 struct MUIP_Hide
*msg
)
318 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
321 zune_imspec_hide(data
->knob_bg
);
323 /* This may look ugly when window is resized but it is easier than
324 * recalculating the knob offset in the Show method */
325 data
->flags
&= ~SLIDER_VALIDOFFSET
;
327 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
331 /**************************************************************************
333 **************************************************************************/
334 IPTR
Slider__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
335 struct MUIP_Draw
*msg
)
337 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
338 const struct ZuneFrameGfx
*knob_frame
;
339 UWORD knob_frame_state
;
342 D(bug("[slider] %s: obj @ 0x%p\n", __func__
, obj
);)
344 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
346 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
)))
349 D(bug("[slider] %s: %d,%d->%d,%d (%d,%d)\n", __func__
, _mleft(obj
), _mtop(obj
), _mright(obj
), _mbottom(obj
), _mwidth(obj
), _mheight(obj
));)
351 if (data
->flags
& SLIDER_HORIZ
)
352 data
->scale_length
= _mwidth(obj
);
354 data
->scale_length
= _mheight(obj
);
355 data
->scale_length
-= data
->knob_length
;
357 /* Update knob position if not cached */
358 if (!(data
->flags
& SLIDER_VALIDOFFSET
))
361 DoMethod(obj
, MUIM_Numeric_ValueToScale
, 0,
363 data
->flags
|= SLIDER_VALIDOFFSET
;
366 data
->knob_top
= _mtop(obj
);
367 data
->knob_left
= _mleft(obj
);
368 if (data
->flags
& SLIDER_HORIZ
)
369 data
->knob_left
+= data
->knob_offset
;
371 data
->knob_top
+= data
->knob_offset
;
373 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
374 _mwidth(obj
), _mheight(obj
), 0, 0, 0);
376 zune_imspec_draw(data
->knob_bg
, muiRenderInfo(obj
),
377 data
->knob_left
, data
->knob_top
, data
->knob_width
,
378 data
->knob_height
, 0, 0, 0);
381 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].state
;
382 if (XGET(obj
, MUIA_Pressed
))
383 knob_frame_state
^= 1;
384 knob_frame
= zune_zframe_get_with_state(obj
,
385 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
],
387 knob_frame
->draw(knob_frame
->customframe
, muiRenderInfo(obj
),
388 data
->knob_left
, data
->knob_top
, data
->knob_width
,
389 data
->knob_height
, data
->knob_left
, data
->knob_top
,
390 data
->knob_width
, data
->knob_height
);
392 if (!(data
->flags
& SLIDER_QUIET
))
394 SetFont(_rp(obj
), _font(obj
));
395 SetABPenDrMd(_rp(obj
), _pens(obj
)[MPEN_TEXT
],
396 _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
397 if (!(data
->flags
& SLIDER_VALIDSTRING
))
399 longget(obj
, MUIA_Numeric_Value
, &val
);
400 data
->text_buffer
= (CONST_STRPTR
) DoMethod(obj
,
401 MUIM_Numeric_Stringify
, val
);
402 data
->text_length
= strlen(data
->text_buffer
);
404 TextLength(_rp(obj
), data
->text_buffer
, data
->text_length
);
405 data
->flags
|= SLIDER_VALIDSTRING
;
409 data
->knob_left
+ knob_frame
->ileft
+
410 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerLeft
+
411 (data
->max_text_width
- data
->text_width
) / 2,
412 data
->knob_top
+ _font(obj
)->tf_Baseline
+ knob_frame
->itop
+
413 muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Knob
].innerTop
);
414 Text(_rp(obj
), data
->text_buffer
, data
->text_length
);
420 /**************************************************************************
422 **************************************************************************/
423 IPTR
Slider__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
424 struct MUIP_HandleEvent
*msg
)
426 struct MUI_SliderData
*data
= INST_DATA(cl
, obj
);
431 switch (msg
->imsg
->Class
)
433 case IDCMP_MOUSEBUTTONS
:
434 if (msg
->imsg
->Code
== SELECTDOWN
)
436 if (_isinobject(obj
, msg
->imsg
->MouseX
, msg
->imsg
->MouseY
)
437 && (msg
->imsg
->Qualifier
438 & (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
)) == 0)
440 if (data
->flags
& SLIDER_HORIZ
)
443 msg
->imsg
->MouseX
- data
->knob_offset
- _mleft(obj
);
448 msg
->imsg
->MouseY
- data
->knob_offset
- _mtop(obj
);
451 if (_between(data
->knob_left
, msg
->imsg
->MouseX
,
452 data
->knob_left
+ data
->knob_width
)
453 && _between(data
->knob_top
, msg
->imsg
->MouseY
,
454 data
->knob_top
+ data
->knob_height
))
456 /* Clicked on knob */
457 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
459 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
460 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
462 set(obj
, MUIA_Pressed
, TRUE
);
463 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
467 /* Clicked on background */
468 if (data
->flags
& SLIDER_HORIZ
)
469 increase
= msg
->imsg
->MouseX
> data
->knob_left
;
471 increase
= msg
->imsg
->MouseY
> data
->knob_top
;
473 if (XGET(obj
, MUIA_Numeric_Reverse
))
474 increase
= !increase
;
476 DoMethod(obj
, increase
?
477 MUIM_Numeric_Increase
: MUIM_Numeric_Decrease
, 1);
483 if (XGET(obj
, MUIA_Pressed
))
485 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
487 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
488 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
490 set(obj
, MUIA_Pressed
, FALSE
);
491 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
496 case IDCMP_MOUSEMOVE
:
500 LONG old_offset
= data
->knob_offset
;
502 if (data
->flags
& SLIDER_HORIZ
)
504 msg
->imsg
->MouseX
- data
->knob_click
- _mleft(obj
);
507 msg
->imsg
->MouseY
- data
->knob_click
- _mtop(obj
);
509 /* Ensure knob offset is within range */
510 if (data
->knob_offset
< 0)
511 data
->knob_offset
= 0;
512 else if (data
->knob_offset
> data
->scale_length
)
513 data
->knob_offset
= data
->scale_length
;
515 newval
= DoMethod(obj
, MUIM_Numeric_ScaleToValue
,
516 0, data
->scale_length
, data
->knob_offset
);
518 if (data
->knob_offset
!= old_offset
)
520 get(obj
, MUIA_Numeric_Value
, &oldval
);
521 if ((LONG
) oldval
!= newval
)
523 /* Bypass our own set method so that knob position is not
525 data
->flags
&= ~SLIDER_VALIDSTRING
;
526 IPTR tag_list
[] = {MUIA_Numeric_Value
, newval
, TAG_END
};
527 DoSuperMethod(cl
, obj
, OM_SET
, tag_list
, NULL
);
530 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
539 BOOPSI_DISPATCHER(IPTR
, Slider_Dispatcher
, cl
, obj
, msg
)
541 switch (msg
->MethodID
)
544 return Slider__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
546 return Slider__OM_SET(cl
, obj
, (struct opSet
*)msg
);
548 return Slider__OM_GET(cl
, obj
, (struct opGet
*)msg
);
550 return Slider__MUIM_Setup(cl
, obj
, (APTR
) msg
);
552 return Slider__MUIM_Cleanup(cl
, obj
, (APTR
) msg
);
554 return Slider__MUIM_Show(cl
, obj
, (APTR
) msg
);
556 return Slider__MUIM_Hide(cl
, obj
, (APTR
) msg
);
558 return Slider__MUIM_AskMinMax(cl
, obj
, (APTR
) msg
);
560 return Slider__MUIM_Draw(cl
, obj
, (APTR
) msg
);
561 case MUIM_HandleEvent
:
562 return Slider__MUIM_HandleEvent(cl
, obj
, (APTR
) msg
);
564 return DoSuperMethodA(cl
, obj
, msg
);
566 BOOPSI_DISPATCHER_END
571 const struct __MUIBuiltinClass _MUI_Slider_desc
=
575 sizeof(struct MUI_SliderData
),
576 (void *) Slider_Dispatcher