2 Copyright © 2012-2015, The AROS Development Team. All rights reserved.
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <clib/alib_protos.h>
9 #include <proto/intuition.h>
10 #include <proto/muimaster.h>
11 #include <proto/graphics.h>
12 #include <proto/utility.h>
15 #include "muimaster_intern.h"
17 #include "support_classes.h"
18 #include "title_private.h"
20 /* #define MYDEBUG 1 */
23 extern struct Library
*MUIMasterBase
;
25 /* Note: Code taken from OWB's tabs handling */
27 #define MUIB_Tabs (TAG_USER | 0x10000000)
28 #define MUIV_Tabs_Top (MUIB_Tabs | 0x00000000)
29 #define MUIV_Tabs_Left (MUIB_Tabs | 0x00000001)
31 #define _isinobj(x,y,obj) (_between(_left(obj),(x),_right (obj)) \
32 && _between(_top(obj) ,(y),_bottom(obj)))
34 #define VERT_PADDING (4)
35 #define HORIZ_PADDING (4)
37 ULONG
Tabs_Layout_Function(struct Hook
*hook
, Object
*obj
,
38 struct MUI_LayoutMsg
*lm
)
40 struct Title_DATA
*data
= (struct Title_DATA
*)hook
->h_Data
;
45 Object
*cstate
= (Object
*) lm
->lm_Children
->mlh_Head
;
49 WORD maxminheight
= 0;
50 WORD mintotalwidth
= 0;
51 WORD mintotalheight
= 0;
52 LONG number_of_children
= 0;
54 /* find out biggest widths & heights of our children */
56 while ((child
= NextObject(&cstate
)))
58 if (maxminwidth
< MUI_MAXMAX
59 && _minwidth(child
) > maxminwidth
)
60 maxminwidth
= _minwidth(child
);
62 if (maxminheight
< MUI_MAXMAX
63 && _minheight(child
) > maxminheight
)
64 maxminheight
= _minheight(child
);
66 mintotalheight
+= _minheight(child
);
71 if (data
->location
== MUIV_Tabs_Top
)
73 WORD horiz_spacing
= XGET(obj
, MUIA_Group_HorizSpacing
);
75 mintotalwidth
= (number_of_children
* maxminwidth
) +
76 ((number_of_children
- 1) * horiz_spacing
) + horiz_spacing
;
78 lm
->lm_MinMax
.MinWidth
= lm
->lm_MinMax
.DefWidth
= mintotalwidth
;
79 lm
->lm_MinMax
.MaxWidth
= MUI_MAXMAX
;
81 lm
->lm_MinMax
.MinHeight
=
82 lm
->lm_MinMax
.MaxHeight
=
83 lm
->lm_MinMax
.DefHeight
= maxminheight
+ (VERT_PADDING
* 2);
85 else if (data
->location
== MUIV_Tabs_Left
)
88 (number_of_children
- 1) * XGET(obj
,
89 MUIA_Group_VertSpacing
);
90 lm
->lm_MinMax
.MinWidth
= lm
->lm_MinMax
.DefWidth
=
92 lm
->lm_MinMax
.MinHeight
= lm
->lm_MinMax
.DefHeight
=
94 lm
->lm_MinMax
.MaxWidth
= lm
->lm_MinMax
.DefWidth
=
96 lm
->lm_MinMax
.MaxHeight
= MUI_MAXMAX
;
105 LONG number_of_children
= 0;
107 cstate
= lm
->lm_Children
->mlh_Head
;
108 while ((child
= NextObject(&cstate
)))
110 number_of_children
++;
113 if (data
->location
== MUIV_Tabs_Top
)
115 WORD horiz_spacing
= XGET(obj
, MUIA_Group_HorizSpacing
);
117 (lm
->lm_Layout
.Width
- ((number_of_children
- 1) * horiz_spacing
) - horiz_spacing
)
118 / number_of_children
;
120 WORD leftovers
= lm
->lm_Layout
.Width
-
121 ((number_of_children
- 1) * horiz_spacing
) - horiz_spacing
-
122 (number_of_children
* childwidth
);
124 WORD left
= horiz_spacing
/ 2;
125 WORD cheight
= _height(obj
) - (VERT_PADDING
* 2);
127 cstate
= lm
->lm_Children
->mlh_Head
;
128 while ((child
= NextObject(&cstate
)))
130 WORD cwidth
= childwidth
;
134 if (!MUI_Layout(child
, left
+ HORIZ_PADDING
, VERT_PADDING
, cwidth
- (HORIZ_PADDING
* 2), cheight
, 0))
137 left
+= cwidth
+ horiz_spacing
;
140 else if (data
->location
== MUIV_Tabs_Left
)
142 WORD vert_spacing
= XGET(obj
, MUIA_Group_VertSpacing
);
144 cstate
= lm
->lm_Children
->mlh_Head
;
145 while ((child
= NextObject(&cstate
)))
147 WORD cheight
= _minheight(child
);
149 if (!MUI_Layout(child
, 0, top
, lm
->lm_Layout
.Width
,
153 top
+= cheight
+ vert_spacing
;
166 IPTR
Title__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
168 struct Title_DATA
*data
= NULL
;
169 struct Hook
*layout_hook
;
171 /* Lay tabs horizontally by default */
172 LONG location
= MUIV_Tabs_Top
;
174 layout_hook
= AllocVec(sizeof(struct Hook
), MEMF_ANY
| MEMF_CLEAR
);
178 layout_hook
->h_Entry
= HookEntry
;
179 layout_hook
->h_SubEntry
= (HOOKFUNC
) Tabs_Layout_Function
;
181 obj
= (Object
*) DoSuperNewTags
183 MUIA_Group_Horiz
, TRUE
,
184 MUIA_Group_LayoutHook
, (IPTR
) layout_hook
,
185 MUIA_ShowSelState
, FALSE
, TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
189 data
= INST_DATA(cl
, obj
);
191 layout_hook
->h_Data
= data
;
192 data
->layout_hook
= layout_hook
;
193 data
->location
= location
;
195 data
->oldactivetab
= 0;
197 /* We need tab events to be processed after all objects contained in tabs
198 like for example close button, hence the low priority value */
199 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
200 data
->ehn
.ehn_Priority
= -7;
201 data
->ehn
.ehn_Flags
= 0;
202 data
->ehn
.ehn_Object
= obj
;
203 data
->ehn
.ehn_Class
= cl
;
205 D(bug("muimaster.library/title.c: Title Object created at 0x%lx\n",
211 IPTR
Title__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
213 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
214 FreeVec(data
->layout_hook
);
216 return DoSuperMethodA(cl
, obj
, msg
);
219 IPTR
Title__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
221 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
222 struct TagItem
*tags
= msg
->ops_AttrList
;
225 while ((tag
= NextTagItem(&tags
)) != NULL
)
229 case MUIA_Group_ActivePage
:
231 if (data
->activetab
!= tag
->ti_Data
)
233 data
->oldactivetab
= data
->activetab
;
234 data
->activetab
= tag
->ti_Data
;
235 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
236 set(_parent(obj
), MUIA_Group_ActivePage
,
244 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
247 /* MUIM_Draw helpers */
249 /* Similar like in Register class */
250 static void DrawTopTab(Object
*obj
, struct Title_DATA
*data
, BOOL active
,
251 WORD x1
, WORD y1
, WORD x2
, WORD y2
)
253 /* Correct for padding */
259 /* Fill the padding area */
260 DoMethod(obj
, MUIM_DrawBackground
, x1
, y1
, x2
- x1
, VERT_PADDING
, 0, 0, 0);
261 DoMethod(obj
, MUIM_DrawBackground
, x1
, y1
, HORIZ_PADDING
, y2
- y1
, 0, 0, 0);
262 DoMethod(obj
, MUIM_DrawBackground
, x2
- VERT_PADDING
+ 1, y1
, HORIZ_PADDING
, y2
- y1
, 0, 0, 0);
263 DoMethod(obj
, MUIM_DrawBackground
, x1
, y2
, x2
- x1
, 1, 0, 0, 0);
267 /* Clear the rounded edges of an inactive tab with default
270 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
,
271 (IPTR
) 1, (IPTR
) 3, (IPTR
) x1
, (IPTR
) y1
, (IPTR
) 0);
272 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
+ 1, (IPTR
) y1
,
273 (IPTR
) 1, (IPTR
) 2, (IPTR
) x1
+ 1, (IPTR
) y1
, (IPTR
) 0);
274 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
+ 2, (IPTR
) y1
,
275 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
+ 2, (IPTR
) y1
, (IPTR
) 0);
276 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
- 3, (IPTR
) y1
,
277 (IPTR
) 3, (IPTR
) 1, (IPTR
) x2
- 3, (IPTR
) y1
, (IPTR
) 0);
278 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
- 1, (IPTR
) y1
,
279 (IPTR
) 1, (IPTR
) 2, (IPTR
) x2
- 1, (IPTR
) y1
, (IPTR
) 0);
280 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
, (IPTR
) y1
,
281 (IPTR
) 1, (IPTR
) 3, (IPTR
) x2
, (IPTR
) y1
, (IPTR
) 0);
285 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
286 RectFill(_rp(obj
), x1
+ 4, y1
, x2
- 4, y1
);
289 RectFill(_rp(obj
), x1
, y1
+ 4, x1
, y2
- (active
? 2 : 1));
290 WritePixel(_rp(obj
), x1
+ 1, y1
+ 3);
291 WritePixel(_rp(obj
), x1
+ 1, y1
+ 2);
292 WritePixel(_rp(obj
), x1
+ 2, y1
+ 1);
293 WritePixel(_rp(obj
), x1
+ 3, y1
+ 1);
294 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHINE
]);
295 WritePixel(_rp(obj
), x1
+ 3, y1
);
296 WritePixel(_rp(obj
), x1
+ 4, y1
+ 1);
297 WritePixel(_rp(obj
), x1
+ 2, y1
+ 2);
298 WritePixel(_rp(obj
), x1
+ 3, y1
+ 2);
299 WritePixel(_rp(obj
), x1
+ 2, y1
+ 3);
300 WritePixel(_rp(obj
), x1
, y1
+ 3);
301 WritePixel(_rp(obj
), x1
+ 1, y1
+ 4);
305 /* bottom horiz bar */
306 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
307 WritePixel(_rp(obj
), x1
, y2
- 1);
308 WritePixel(_rp(obj
), x1
, y2
);
310 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
311 WritePixel(_rp(obj
), x2
, y2
- 1);
312 WritePixel(_rp(obj
), x2
, y2
);
316 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
317 RectFill(_rp(obj
), x1
, y2
, x2
, y2
);
321 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
322 WritePixel(_rp(obj
), x2
- 1, y1
+ 2);
323 RectFill(_rp(obj
), x2
, y1
+ 4, x2
, y2
- (active
? 2 : 1));
324 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHADOW
]);
325 WritePixel(_rp(obj
), x2
- 2, y1
+ 1);
326 WritePixel(_rp(obj
), x2
- 1, y1
+ 3);
327 WritePixel(_rp(obj
), x2
, y1
+ 3);
328 SetAPen(_rp(obj
), _pens(obj
)[MPEN_BACKGROUND
]);
329 WritePixel(_rp(obj
), x2
- 3, y1
+ 1);
332 /* Like above, just symetrically flipped */
333 static void DrawLeftTab(Object
*obj
, struct Title_DATA
*data
, BOOL active
,
334 WORD x1
, WORD y1
, WORD x2
, WORD y2
)
338 /* Clear the rounded edges of an inactive tab with default
341 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
,
342 (IPTR
) 3, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
, (IPTR
) 0);
343 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
+ 1,
344 (IPTR
) 2, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
+ 1, (IPTR
) 0);
345 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
+ 2,
346 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
+ 2, (IPTR
) 0);
347 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
- 2,
348 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
- 2, (IPTR
) 0);
349 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
- 1,
350 (IPTR
) 2, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
- 1, (IPTR
) 0);
351 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
,
352 (IPTR
) 3, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
, (IPTR
) 0);
357 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
358 RectFill(_rp(obj
), x1
, y1
+ 4, x1
, y2
- 4);
361 RectFill(_rp(obj
), x1
+ 4, y1
, x2
- (active
? 2 : 1), y1
);
362 WritePixel(_rp(obj
), x1
+ 1, y1
+ 3);
363 WritePixel(_rp(obj
), x1
+ 1, y1
+ 2);
364 WritePixel(_rp(obj
), x1
+ 2, y1
+ 1);
365 WritePixel(_rp(obj
), x1
+ 3, y1
+ 1);
366 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHINE
]);
367 WritePixel(_rp(obj
), x1
+ 3, y1
);
368 WritePixel(_rp(obj
), x1
+ 4, y1
+ 1);
369 WritePixel(_rp(obj
), x1
+ 2, y1
+ 2);
370 WritePixel(_rp(obj
), x1
+ 3, y1
+ 2);
371 WritePixel(_rp(obj
), x1
+ 2, y1
+ 3);
372 WritePixel(_rp(obj
), x1
, y1
+ 3);
373 WritePixel(_rp(obj
), x1
+ 1, y1
+ 4);
377 /* bottom horiz bar */
378 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
379 WritePixel(_rp(obj
), x2
- 1, y1
);
380 WritePixel(_rp(obj
), x2
, y1
);
382 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
383 WritePixel(_rp(obj
), x2
- 1, y2
);
384 WritePixel(_rp(obj
), x2
, y2
);
388 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
389 RectFill(_rp(obj
), x2
, y1
, x2
, y2
);
392 /* bottom horiz bar */
393 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
394 WritePixel(_rp(obj
), x1
+ 2, y2
- 1);
395 RectFill(_rp(obj
), x1
+ 4, y2
, x2
- (active
? 2 : 1), y2
);
396 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHADOW
]);
397 WritePixel(_rp(obj
), x1
+ 1, y2
- 2);
398 WritePixel(_rp(obj
), x1
+ 3, y2
- 1);
399 WritePixel(_rp(obj
), x1
+ 3, y2
);
400 SetAPen(_rp(obj
), _pens(obj
)[MPEN_BACKGROUND
]);
401 WritePixel(_rp(obj
), x1
+ 1, y2
- 3);
405 IPTR
Tab__MUIM_Draw(Object
*child
, struct Title_DATA
*data
, BOOL active
)
407 WORD x1
= _left(child
);
408 WORD y1
= _top(child
);
409 WORD x2
= _right(child
);
410 WORD y2
= _bottom(child
);
412 /* Setting of background (to a different value!) causes redraw of object. We use this "feature" */
414 nnset(child
, MUIA_Background
, data
->background
);
416 nnset(child
, MUIA_Background
, MUII_BACKGROUND
);
419 if (data
->location
== MUIV_Tabs_Top
)
420 DrawTopTab(child
, data
, active
, x1
, y1
, x2
, y2
);
421 else if (data
->location
== MUIV_Tabs_Left
)
422 DrawLeftTab(child
, data
, active
, x1
, y1
, x2
, y2
);
426 /* MUIM_Draw helpers */
428 IPTR
Title__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
429 struct MUIP_Draw
*msg
)
431 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
432 struct List
*children
= NULL
;
435 WORD horiz_spacing
= XGET(obj
, MUIA_Group_HorizSpacing
);
436 WORD vert_spacing
= XGET(obj
, MUIA_Group_VertSpacing
);
439 /* Draw all the children */
440 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
442 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
)))
446 /* Now draw missing TabbedGroup border between the spaces */
447 get(obj
, MUIA_Group_ChildList
, &children
);
449 cstate
= children
->lh_Head
;
451 while ((child
= NextObject(&cstate
)))
453 if (tab
== data
->activetab
)
454 Tab__MUIM_Draw(child
, data
, TRUE
);
455 else if (tab
== data
->oldactivetab
)
456 Tab__MUIM_Draw(child
, data
, FALSE
);
457 else if (msg
->flags
& MADF_DRAWOBJECT
)
458 Tab__MUIM_Draw(child
, data
, FALSE
);
463 cstate
= children
->lh_Head
;
464 child
= NextObject(&cstate
);
466 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
467 if (data
->location
== MUIV_Tabs_Top
)
469 RectFill(_rp(obj
), _left(obj
), _bottom(child
) + 1, _left(obj
) + horiz_spacing
/ 2, _bottom(child
) + 1);
470 RectFill(_rp(obj
), _right(obj
) - horiz_spacing
/ 2, _bottom(child
) + 1, _right(obj
), _bottom(child
) + 1);
472 while (child
&& (child
= NextObject(&cstate
)))
474 RectFill(_rp(obj
), _left(child
) - horiz_spacing
- HORIZ_PADDING
, _bottom(child
) + 1,
475 _left(child
) - 1 - HORIZ_PADDING
, _bottom(child
) + 1);
478 else if (data
->location
== MUIV_Tabs_Left
)
481 while (child
&& (child
= NextObject(&cstate
)))
483 RectFill(_rp(obj
), _right(child
), _top(child
) - vert_spacing
,
484 _right(child
), _top(child
) - 1);
485 lasty
= _bottom(child
);
488 RectFill(_rp(obj
), _right(obj
), lasty
+ 1, _right(obj
),
497 IPTR
Title__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
498 struct MUIP_Setup
*msg
)
500 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
502 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
505 get(_parent(obj
), MUIA_Background
, &data
->background
);
507 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
512 IPTR
Title__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
513 struct MUIP_Cleanup
*msg
)
515 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
517 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
519 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
522 IPTR
Title__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
523 struct MUIP_HandleEvent
*msg
)
528 switch (msg
->imsg
->Class
)
530 case IDCMP_MOUSEBUTTONS
:
531 if (msg
->imsg
->Code
== SELECTDOWN
532 && _isinobj(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
, obj
))
534 struct List
*children
=
535 (struct List
*)XGET(obj
, MUIA_Group_ChildList
);
536 APTR cstate
= children
->lh_Head
;
540 /* Find previous and next tab */
541 for (i
= 0; (child
= NextObject(&cstate
)); i
++)
543 if (_isinobj(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
, child
))
545 /* Activate this tab */
546 set(obj
, MUIA_Group_ActivePage
, i
);
556 #if ZUNE_BUILTIN_TITLE
557 BOOPSI_DISPATCHER(IPTR
, Title_Dispatcher
, cl
, obj
, msg
)
559 switch (msg
->MethodID
)
562 return Title__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
564 return Title__OM_SET(cl
, obj
, (struct opSet
*)msg
);
566 return Title_OM_DISPOSE(cl
, obj
, msg
);
568 return Title__MUIM_Draw(cl
, obj
, (struct MUIP_Draw
*)msg
);
570 return Title__MUIM_Setup(cl
, obj
, (struct MUIP_Setup
*)msg
);
572 return Title__MUIM_Cleanup(cl
, obj
, (struct MUIP_Cleanup
*)msg
);
573 case MUIM_HandleEvent
:
574 return Title__MUIM_HandleEvent(cl
, obj
,
575 (struct MUIP_HandleEvent
*)msg
);
577 return DoSuperMethodA(cl
, obj
, msg
);
580 BOOPSI_DISPATCHER_END
582 const struct __MUIBuiltinClass _MUI_Title_desc
=
586 sizeof(struct Title_DATA
),
587 (void *) Title_Dispatcher
589 #endif /* ZUNE_BUILTIN_TITLE */