Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / title.c
blobcbbecc343f4cf6f0eb5b834f5c0604d9193f8d45
1 /*
2 Copyright © 2012, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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>
14 #include "mui.h"
15 #include "muimaster_intern.h"
16 #include "support.h"
17 #include "support_classes.h"
18 #include "title_private.h"
20 /* #define MYDEBUG 1 */
21 #include "debug.h"
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;
39 switch (lm->lm_Type)
41 case MUILM_MINMAX:
43 Object *cstate = (Object *) lm->lm_Children->mlh_Head;
44 Object *child;
46 WORD maxminwidth = 0;
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);
66 number_of_children++;
69 if (data->location == MUIV_Tabs_Top)
71 mintotalwidth =
72 number_of_children * maxminwidth + (number_of_children -
73 1) * XGET(obj, MUIA_Group_HorizSpacing);
74 lm->lm_MinMax.MinWidth = lm->lm_MinMax.DefWidth =
75 mintotalwidth;
76 lm->lm_MinMax.MinHeight = lm->lm_MinMax.DefHeight =
77 maxminheight + 10;
78 lm->lm_MinMax.MaxWidth = MUI_MAXMAX;
79 lm->lm_MinMax.MaxHeight = lm->lm_MinMax.DefHeight =
80 maxminheight + 10;
82 else if (data->location == MUIV_Tabs_Left)
84 mintotalheight +=
85 (number_of_children - 1) * XGET(obj,
86 MUIA_Group_VertSpacing);
87 lm->lm_MinMax.MinWidth = lm->lm_MinMax.DefWidth =
88 maxminwidth;
89 lm->lm_MinMax.MinHeight = lm->lm_MinMax.DefHeight =
90 mintotalheight;
91 lm->lm_MinMax.MaxWidth = lm->lm_MinMax.DefWidth =
92 maxminwidth;
93 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
96 return 0;
98 case MUILM_LAYOUT:
100 APTR cstate;
101 Object *child;
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);
113 WORD childwidth =
114 (lm->lm_Layout.Width - (number_of_children -
115 1) * horiz_spacing) / number_of_children;
116 WORD leftovers =
117 lm->lm_Layout.Width - (number_of_children -
118 1) * horiz_spacing - number_of_children * childwidth;
119 WORD left = 0;
120 cstate = lm->lm_Children->mlh_Head;
121 while ((child = NextObject(&cstate)))
123 WORD cwidth = childwidth;
124 WORD cheight = _height(obj);
125 if (leftovers-- > 0)
126 cwidth++;
127 if (!MUI_Layout(child, left,
128 lm->lm_Layout.Height - cheight, cwidth,
129 cheight - 10, 0))
130 return (FALSE);
132 left += cwidth + horiz_spacing;
135 else if (data->location == MUIV_Tabs_Left)
137 WORD vert_spacing = XGET(obj, MUIA_Group_VertSpacing);
138 WORD top = 0;
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,
145 cheight, 0))
146 return (FALSE);
148 top += cheight + vert_spacing;
151 else
152 return FALSE;
154 return TRUE;
158 return TRUE;
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);
170 if (!layout_hook)
171 return (IPTR) NULL;
173 layout_hook->h_Entry = HookEntry;
174 layout_hook->h_SubEntry = (HOOKFUNC) Tabs_Layout_Function;
176 obj = (Object *) DoSuperNewTags
177 (cl, obj, NULL,
178 MUIA_Group_Horiz, TRUE,
179 MUIA_Group_LayoutHook, (IPTR) layout_hook,
180 MUIA_ShowSelState, FALSE, TAG_MORE, (IPTR) msg->ops_AttrList);
181 if (!obj)
182 return FALSE;
184 data = INST_DATA(cl, obj);
186 layout_hook->h_Data = data;
187 data->layout_hook = layout_hook;
188 data->location = location;
189 data->activetab = 0;
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",
201 obj));
203 return (IPTR) obj;
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;
218 struct TagItem *tag;
220 while ((tag = NextTagItem(&tags)) != NULL)
222 switch (tag->ti_Tag)
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,
232 data->activetab);
234 break;
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)
248 if (!active)
250 /* Clear the rounded edges of an inactive tab with default
251 * background */
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);
267 /* top horiz bar */
268 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
269 RectFill(_rp(obj), x1 + 4, y1, x2 - 4, y1);
271 /* left vert bar */
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);
286 if (active)
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);
297 else
299 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
300 RectFill(_rp(obj), x1, y2, x2, y2);
303 /* right vert bar */
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)
319 if (!active)
321 /* Clear the rounded edges of an inactive tab with default
322 * background */
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);
339 /* left vert bar */
340 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
341 RectFill(_rp(obj), x1, y1 + 4, x1, y2 - 4);
343 /* top horiz bar */
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);
358 if (active)
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);
369 else
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);
387 /* Drawing code */
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" */
396 if (active == 1)
398 nnset(child, MUIA_Background, data->background);
400 else if (active == 0)
402 nnset(child, MUIA_Background, MUII_BACKGROUND);
405 /* Draw tab frame */
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);
411 return TRUE;
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;
420 APTR cstate;
421 Object *child;
422 WORD horiz_spacing = XGET(obj, MUIA_Group_HorizSpacing);
423 WORD vert_spacing = XGET(obj, MUIA_Group_VertSpacing);
424 LONG tab = 0;
426 /* Draw all the children */
427 DoSuperMethodA(cl, obj, (Msg) msg);
429 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
430 return (0);
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);
444 else
445 Tab__MUIM_Draw(child, data, -1);
447 tab++;
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)
464 WORD lasty = -1;
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);
471 if (lasty > -1)
472 RectFill(_rp(obj), _right(obj), lasty + 1, _right(obj),
473 _bottom(obj));
475 else
476 return FALSE;
478 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
479 WritePixel(_rp(obj), _right(obj), _bottom(obj));
481 return TRUE;
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))
490 return FALSE;
492 get(_parent(obj), MUIA_Background, &data->background);
494 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) & data->ehn);
496 return TRUE;
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)
512 if (!msg->imsg)
513 return 0;
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;
524 Object *child;
525 int i;
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);
534 break;
538 break;
540 return 0;
543 #if ZUNE_BUILTIN_TITLE
544 BOOPSI_DISPATCHER(IPTR, Title_Dispatcher, cl, obj, msg)
546 switch (msg->MethodID)
548 case OM_NEW:
549 return Title__OM_NEW(cl, obj, (struct opSet *)msg);
550 case OM_SET:
551 return Title__OM_SET(cl, obj, (struct opSet *)msg);
552 case OM_DISPOSE:
553 return Title_OM_DISPOSE(cl, obj, msg);
554 case MUIM_Draw:
555 return Title__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
556 case MUIM_Setup:
557 return Title__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
558 case MUIM_Cleanup:
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);
563 default:
564 return DoSuperMethodA(cl, obj, msg);
567 BOOPSI_DISPATCHER_END
569 const struct __MUIBuiltinClass _MUI_Title_desc =
571 MUIC_Title,
572 MUIC_Group,
573 sizeof(struct Title_DATA),
574 (void *) Title_Dispatcher
576 #endif /* ZUNE_BUILTIN_TITLE */