2 Copyright © 2012, 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)))
35 ULONG
Tabs_Layout_Function(struct Hook
*hook
, Object
*obj
,
36 struct MUI_LayoutMsg
*lm
)
38 struct Title_DATA
*data
= (struct Title_DATA
*)hook
->h_Data
;
43 Object
*cstate
= (Object
*) lm
->lm_Children
->mlh_Head
;
47 WORD maxminheight
= 0;
48 WORD mintotalwidth
= 0;
49 WORD mintotalheight
= 0;
50 LONG number_of_children
= 0;
52 /* find out biggest widths & heights of our children */
54 while ((child
= NextObject(&cstate
)))
56 if (maxminwidth
< MUI_MAXMAX
57 && _minwidth(child
) > maxminwidth
)
58 maxminwidth
= _minwidth(child
);
60 if (maxminheight
< MUI_MAXMAX
61 && _minheight(child
) > maxminheight
)
62 maxminheight
= _minheight(child
);
64 mintotalheight
+= _minheight(child
);
69 if (data
->location
== MUIV_Tabs_Top
)
72 number_of_children
* maxminwidth
+ (number_of_children
-
73 1) * XGET(obj
, MUIA_Group_HorizSpacing
);
74 lm
->lm_MinMax
.MinWidth
= lm
->lm_MinMax
.DefWidth
=
76 lm
->lm_MinMax
.MinHeight
= lm
->lm_MinMax
.DefHeight
=
78 lm
->lm_MinMax
.MaxWidth
= MUI_MAXMAX
;
79 lm
->lm_MinMax
.MaxHeight
= lm
->lm_MinMax
.DefHeight
=
82 else if (data
->location
== MUIV_Tabs_Left
)
85 (number_of_children
- 1) * XGET(obj
,
86 MUIA_Group_VertSpacing
);
87 lm
->lm_MinMax
.MinWidth
= lm
->lm_MinMax
.DefWidth
=
89 lm
->lm_MinMax
.MinHeight
= lm
->lm_MinMax
.DefHeight
=
91 lm
->lm_MinMax
.MaxWidth
= lm
->lm_MinMax
.DefWidth
=
93 lm
->lm_MinMax
.MaxHeight
= MUI_MAXMAX
;
102 LONG number_of_children
= 0;
104 cstate
= lm
->lm_Children
->mlh_Head
;
105 while ((child
= NextObject(&cstate
)))
107 number_of_children
++;
110 if (data
->location
== MUIV_Tabs_Top
)
112 WORD horiz_spacing
= XGET(obj
, MUIA_Group_HorizSpacing
);
114 (lm
->lm_Layout
.Width
- (number_of_children
-
115 1) * horiz_spacing
) / number_of_children
;
117 lm
->lm_Layout
.Width
- (number_of_children
-
118 1) * horiz_spacing
- number_of_children
* childwidth
;
120 cstate
= lm
->lm_Children
->mlh_Head
;
121 while ((child
= NextObject(&cstate
)))
123 WORD cwidth
= childwidth
;
124 WORD cheight
= _height(obj
);
127 if (!MUI_Layout(child
, left
,
128 lm
->lm_Layout
.Height
- cheight
, cwidth
,
132 left
+= cwidth
+ horiz_spacing
;
135 else if (data
->location
== MUIV_Tabs_Left
)
137 WORD vert_spacing
= XGET(obj
, MUIA_Group_VertSpacing
);
139 cstate
= lm
->lm_Children
->mlh_Head
;
140 while ((child
= NextObject(&cstate
)))
142 WORD cheight
= _minheight(child
);
144 if (!MUI_Layout(child
, 0, top
, lm
->lm_Layout
.Width
,
148 top
+= cheight
+ vert_spacing
;
161 IPTR
Title__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
163 struct Title_DATA
*data
= NULL
;
164 struct Hook
*layout_hook
;
166 /* Lay tabs horizontally by default */
167 LONG location
= MUIV_Tabs_Top
;
169 layout_hook
= AllocVec(sizeof(struct Hook
), MEMF_ANY
| MEMF_CLEAR
);
173 layout_hook
->h_Entry
= HookEntry
;
174 layout_hook
->h_SubEntry
= (HOOKFUNC
) Tabs_Layout_Function
;
176 obj
= (Object
*) DoSuperNewTags
178 MUIA_Group_Horiz
, TRUE
,
179 MUIA_Group_LayoutHook
, (IPTR
) layout_hook
,
180 MUIA_ShowSelState
, FALSE
, TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
184 data
= INST_DATA(cl
, obj
);
186 layout_hook
->h_Data
= data
;
187 data
->layout_hook
= layout_hook
;
188 data
->location
= location
;
190 data
->oldactivetab
= 0;
192 /* We need tab events to be processed after all objects contained in tabs
193 like for example close button, hence the low priority value */
194 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
195 data
->ehn
.ehn_Priority
= -7;
196 data
->ehn
.ehn_Flags
= 0;
197 data
->ehn
.ehn_Object
= obj
;
198 data
->ehn
.ehn_Class
= cl
;
200 D(bug("muimaster.library/title.c: Title Object created at 0x%lx\n",
206 IPTR
Title__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
208 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
209 FreeVec(data
->layout_hook
);
211 return DoSuperMethodA(cl
, obj
, msg
);
214 IPTR
Title__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
216 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
217 struct TagItem
*tags
= msg
->ops_AttrList
;
220 while ((tag
= NextTagItem(&tags
)) != NULL
)
224 case MUIA_Group_ActivePage
:
226 if (data
->activetab
!= tag
->ti_Data
)
228 data
->oldactivetab
= data
->activetab
;
229 data
->activetab
= tag
->ti_Data
;
230 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
231 set(_parent(obj
), MUIA_Group_ActivePage
,
239 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
242 /* MUIM_Draw helpers */
244 /* Similar like in Register class */
245 static void DrawTopTab(Object
*obj
, struct Title_DATA
*data
, BOOL active
,
246 WORD x1
, WORD y1
, WORD x2
, WORD y2
)
250 /* Clear the rounded edges of an inactive tab with default
253 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
,
254 (IPTR
) 1, (IPTR
) 3, (IPTR
) x1
, (IPTR
) y1
, (IPTR
) 0);
255 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
+ 1, (IPTR
) y1
,
256 (IPTR
) 1, (IPTR
) 2, (IPTR
) x1
+ 1, (IPTR
) y1
, (IPTR
) 0);
257 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
+ 2, (IPTR
) y1
,
258 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
+ 2, (IPTR
) y1
, (IPTR
) 0);
259 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
- 3, (IPTR
) y1
,
260 (IPTR
) 3, (IPTR
) 1, (IPTR
) x2
- 3, (IPTR
) y1
, (IPTR
) 0);
261 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
- 1, (IPTR
) y1
,
262 (IPTR
) 1, (IPTR
) 2, (IPTR
) x2
- 1, (IPTR
) y1
, (IPTR
) 0);
263 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x2
, (IPTR
) y1
,
264 (IPTR
) 1, (IPTR
) 3, (IPTR
) x2
, (IPTR
) y1
, (IPTR
) 0);
268 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
269 RectFill(_rp(obj
), x1
+ 4, y1
, x2
- 4, y1
);
272 RectFill(_rp(obj
), x1
, y1
+ 4, x1
, y2
- (active
? 2 : 1));
273 WritePixel(_rp(obj
), x1
+ 1, y1
+ 3);
274 WritePixel(_rp(obj
), x1
+ 1, y1
+ 2);
275 WritePixel(_rp(obj
), x1
+ 2, y1
+ 1);
276 WritePixel(_rp(obj
), x1
+ 3, y1
+ 1);
277 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHINE
]);
278 WritePixel(_rp(obj
), x1
+ 3, y1
);
279 WritePixel(_rp(obj
), x1
+ 4, y1
+ 1);
280 WritePixel(_rp(obj
), x1
+ 2, y1
+ 2);
281 WritePixel(_rp(obj
), x1
+ 3, y1
+ 2);
282 WritePixel(_rp(obj
), x1
+ 2, y1
+ 3);
283 WritePixel(_rp(obj
), x1
, y1
+ 3);
284 WritePixel(_rp(obj
), x1
+ 1, y1
+ 4);
288 /* bottom horiz bar */
289 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
290 WritePixel(_rp(obj
), x1
, y2
- 1);
291 WritePixel(_rp(obj
), x1
, y2
);
293 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
294 WritePixel(_rp(obj
), x2
, y2
- 1);
295 WritePixel(_rp(obj
), x2
, y2
);
299 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
300 RectFill(_rp(obj
), x1
, y2
, x2
, y2
);
304 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
305 WritePixel(_rp(obj
), x2
- 1, y1
+ 2);
306 RectFill(_rp(obj
), x2
, y1
+ 4, x2
, y2
- (active
? 2 : 1));
307 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHADOW
]);
308 WritePixel(_rp(obj
), x2
- 2, y1
+ 1);
309 WritePixel(_rp(obj
), x2
- 1, y1
+ 3);
310 WritePixel(_rp(obj
), x2
, y1
+ 3);
311 SetAPen(_rp(obj
), _pens(obj
)[MPEN_BACKGROUND
]);
312 WritePixel(_rp(obj
), x2
- 3, y1
+ 1);
315 /* Like above, just symetrically flipped */
316 static void DrawLeftTab(Object
*obj
, struct Title_DATA
*data
, BOOL active
,
317 WORD x1
, WORD y1
, WORD x2
, WORD y2
)
321 /* Clear the rounded edges of an inactive tab with default
324 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
,
325 (IPTR
) 3, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
, (IPTR
) 0);
326 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
+ 1,
327 (IPTR
) 2, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
+ 1, (IPTR
) 0);
328 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y1
+ 2,
329 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y1
+ 2, (IPTR
) 0);
330 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
- 2,
331 (IPTR
) 1, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
- 2, (IPTR
) 0);
332 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
- 1,
333 (IPTR
) 2, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
- 1, (IPTR
) 0);
334 DoMethod(obj
, MUIM_DrawParentBackground
, (IPTR
) x1
, (IPTR
) y2
,
335 (IPTR
) 3, (IPTR
) 1, (IPTR
) x1
, (IPTR
) y2
, (IPTR
) 0);
340 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
341 RectFill(_rp(obj
), x1
, y1
+ 4, x1
, y2
- 4);
344 RectFill(_rp(obj
), x1
+ 4, y1
, x2
- (active
? 2 : 1), y1
);
345 WritePixel(_rp(obj
), x1
+ 1, y1
+ 3);
346 WritePixel(_rp(obj
), x1
+ 1, y1
+ 2);
347 WritePixel(_rp(obj
), x1
+ 2, y1
+ 1);
348 WritePixel(_rp(obj
), x1
+ 3, y1
+ 1);
349 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHINE
]);
350 WritePixel(_rp(obj
), x1
+ 3, y1
);
351 WritePixel(_rp(obj
), x1
+ 4, y1
+ 1);
352 WritePixel(_rp(obj
), x1
+ 2, y1
+ 2);
353 WritePixel(_rp(obj
), x1
+ 3, y1
+ 2);
354 WritePixel(_rp(obj
), x1
+ 2, y1
+ 3);
355 WritePixel(_rp(obj
), x1
, y1
+ 3);
356 WritePixel(_rp(obj
), x1
+ 1, y1
+ 4);
360 /* bottom horiz bar */
361 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
362 WritePixel(_rp(obj
), x2
- 1, y1
);
363 WritePixel(_rp(obj
), x2
, y1
);
365 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
366 WritePixel(_rp(obj
), x2
- 1, y2
);
367 WritePixel(_rp(obj
), x2
, y2
);
371 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
372 RectFill(_rp(obj
), x2
, y1
, x2
, y2
);
375 /* bottom horiz bar */
376 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
377 WritePixel(_rp(obj
), x1
+ 2, y2
- 1);
378 RectFill(_rp(obj
), x1
+ 4, y2
, x2
- (active
? 2 : 1), y2
);
379 SetAPen(_rp(obj
), _pens(obj
)[MPEN_HALFSHADOW
]);
380 WritePixel(_rp(obj
), x1
+ 1, y2
- 2);
381 WritePixel(_rp(obj
), x1
+ 3, y2
- 1);
382 WritePixel(_rp(obj
), x1
+ 3, y2
);
383 SetAPen(_rp(obj
), _pens(obj
)[MPEN_BACKGROUND
]);
384 WritePixel(_rp(obj
), x1
+ 1, y2
- 3);
388 IPTR
Tab__MUIM_Draw(Object
*child
, struct Title_DATA
*data
, LONG active
)
390 WORD x1
= _left(child
);
391 WORD y1
= _top(child
);
392 WORD x2
= _right(child
);
393 WORD y2
= _bottom(child
);
395 /* Setting of background causes redraw of object. We use this "feature" */
398 nnset(child
, MUIA_Background
, data
->background
);
400 else if (active
== 0)
402 nnset(child
, MUIA_Background
, MUII_BACKGROUND
);
406 if (data
->location
== MUIV_Tabs_Top
)
407 DrawTopTab(child
, data
, (active
== 1), x1
, y1
, x2
, y2
);
408 else if (data
->location
== MUIV_Tabs_Left
)
409 DrawLeftTab(child
, data
, (active
== 1), x1
, y1
, x2
, y2
);
413 /* MUIM_Draw helpers */
415 IPTR
Title__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
416 struct MUIP_Draw
*msg
)
418 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
419 struct List
*children
= NULL
;
422 WORD horiz_spacing
= XGET(obj
, MUIA_Group_HorizSpacing
);
423 WORD vert_spacing
= XGET(obj
, MUIA_Group_VertSpacing
);
426 /* Draw all the children */
427 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
429 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
)))
433 /* Now draw missing TabbedGroup border between the spaces */
434 get(obj
, MUIA_Group_ChildList
, &children
);
436 cstate
= children
->lh_Head
;
438 while ((child
= NextObject(&cstate
)))
440 if (tab
== data
->activetab
)
441 Tab__MUIM_Draw(child
, data
, 1);
442 else if (tab
== data
->oldactivetab
)
443 Tab__MUIM_Draw(child
, data
, 0);
445 Tab__MUIM_Draw(child
, data
, -1);
450 cstate
= children
->lh_Head
;
451 child
= NextObject(&cstate
);
453 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
454 if (data
->location
== MUIV_Tabs_Top
)
456 while (child
&& (child
= NextObject(&cstate
)))
458 RectFill(_rp(obj
), _left(child
) - horiz_spacing
, _bottom(child
),
459 _left(child
) - 1, _bottom(child
));
462 else if (data
->location
== MUIV_Tabs_Left
)
465 while (child
&& (child
= NextObject(&cstate
)))
467 RectFill(_rp(obj
), _right(child
), _top(child
) - vert_spacing
,
468 _right(child
), _top(child
) - 1);
469 lasty
= _bottom(child
);
472 RectFill(_rp(obj
), _right(obj
), lasty
+ 1, _right(obj
),
478 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
479 WritePixel(_rp(obj
), _right(obj
), _bottom(obj
));
484 IPTR
Title__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
485 struct MUIP_Setup
*msg
)
487 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
489 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
492 get(_parent(obj
), MUIA_Background
, &data
->background
);
494 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
499 IPTR
Title__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
500 struct MUIP_Cleanup
*msg
)
502 struct Title_DATA
*data
= INST_DATA(cl
, obj
);
504 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
506 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
509 IPTR
Title__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
510 struct MUIP_HandleEvent
*msg
)
515 switch (msg
->imsg
->Class
)
517 case IDCMP_MOUSEBUTTONS
:
518 if (msg
->imsg
->Code
== SELECTDOWN
519 && _isinobj(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
, obj
))
521 struct List
*children
=
522 (struct List
*)XGET(obj
, MUIA_Group_ChildList
);
523 APTR cstate
= children
->lh_Head
;
527 /* Find previous and next tab */
528 for (i
= 0; (child
= NextObject(&cstate
)); i
++)
530 if (_isinobj(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
, child
))
532 /* Activate this tab */
533 set(obj
, MUIA_Group_ActivePage
, i
);
543 #if ZUNE_BUILTIN_TITLE
544 BOOPSI_DISPATCHER(IPTR
, Title_Dispatcher
, cl
, obj
, msg
)
546 switch (msg
->MethodID
)
549 return Title__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
551 return Title__OM_SET(cl
, obj
, (struct opSet
*)msg
);
553 return Title_OM_DISPOSE(cl
, obj
, msg
);
555 return Title__MUIM_Draw(cl
, obj
, (struct MUIP_Draw
*)msg
);
557 return Title__MUIM_Setup(cl
, obj
, (struct MUIP_Setup
*)msg
);
559 return Title__MUIM_Cleanup(cl
, obj
, (struct MUIP_Cleanup
*)msg
);
560 case MUIM_HandleEvent
:
561 return Title__MUIM_HandleEvent(cl
, obj
,
562 (struct MUIP_HandleEvent
*)msg
);
564 return DoSuperMethodA(cl
, obj
, msg
);
567 BOOPSI_DISPATCHER_END
569 const struct __MUIBuiltinClass _MUI_Title_desc
=
573 sizeof(struct Title_DATA
),
574 (void *) Title_Dispatcher
576 #endif /* ZUNE_BUILTIN_TITLE */