revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / muimaster / classes / title.c
blob7d434a2b5b0f981875200a4fb23b45ffa4f6f363
1 /*
2 Copyright © 2012-2015, 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)))
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;
41 switch (lm->lm_Type)
43 case MUILM_MINMAX:
45 Object *cstate = (Object *) lm->lm_Children->mlh_Head;
46 Object *child;
48 WORD maxminwidth = 0;
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);
68 number_of_children++;
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)
87 mintotalheight +=
88 (number_of_children - 1) * XGET(obj,
89 MUIA_Group_VertSpacing);
90 lm->lm_MinMax.MinWidth = lm->lm_MinMax.DefWidth =
91 maxminwidth;
92 lm->lm_MinMax.MinHeight = lm->lm_MinMax.DefHeight =
93 mintotalheight;
94 lm->lm_MinMax.MaxWidth = lm->lm_MinMax.DefWidth =
95 maxminwidth;
96 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
99 return 0;
101 case MUILM_LAYOUT:
103 APTR cstate;
104 Object *child;
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);
116 WORD childwidth =
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;
132 if (leftovers-- > 0)
133 cwidth++;
134 if (!MUI_Layout(child, left + HORIZ_PADDING, VERT_PADDING, cwidth - (HORIZ_PADDING * 2), cheight , 0))
135 return (FALSE);
137 left += cwidth + horiz_spacing;
140 else if (data->location == MUIV_Tabs_Left)
142 WORD vert_spacing = XGET(obj, MUIA_Group_VertSpacing);
143 WORD top = 0;
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,
150 cheight, 0))
151 return (FALSE);
153 top += cheight + vert_spacing;
156 else
157 return FALSE;
159 return TRUE;
163 return TRUE;
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);
175 if (!layout_hook)
176 return (IPTR) NULL;
178 layout_hook->h_Entry = HookEntry;
179 layout_hook->h_SubEntry = (HOOKFUNC) Tabs_Layout_Function;
181 obj = (Object *) DoSuperNewTags
182 (cl, obj, NULL,
183 MUIA_Group_Horiz, TRUE,
184 MUIA_Group_LayoutHook, (IPTR) layout_hook,
185 MUIA_ShowSelState, FALSE, TAG_MORE, (IPTR) msg->ops_AttrList);
186 if (!obj)
187 return FALSE;
189 data = INST_DATA(cl, obj);
191 layout_hook->h_Data = data;
192 data->layout_hook = layout_hook;
193 data->location = location;
194 data->activetab = 0;
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",
206 obj));
208 return (IPTR) obj;
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;
223 struct TagItem *tag;
225 while ((tag = NextTagItem(&tags)) != NULL)
227 switch (tag->ti_Tag)
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,
237 data->activetab);
239 break;
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 */
254 x1 -= HORIZ_PADDING;
255 y1 -= VERT_PADDING;
256 x2 += HORIZ_PADDING;
257 y2 += 1;
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);
265 if (!active)
267 /* Clear the rounded edges of an inactive tab with default
268 * background */
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);
284 /* top horiz bar */
285 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
286 RectFill(_rp(obj), x1 + 4, y1, x2 - 4, y1);
288 /* left vert bar */
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);
303 if (active)
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);
314 else
316 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
317 RectFill(_rp(obj), x1, y2, x2, y2);
320 /* right vert bar */
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)
336 if (!active)
338 /* Clear the rounded edges of an inactive tab with default
339 * background */
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);
356 /* left vert bar */
357 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
358 RectFill(_rp(obj), x1, y1 + 4, x1, y2 - 4);
360 /* top horiz bar */
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);
375 if (active)
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);
386 else
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);
404 /* Drawing code */
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" */
413 if (active)
414 nnset(child, MUIA_Background, data->background);
415 else
416 nnset(child, MUIA_Background, MUII_BACKGROUND);
418 /* Draw tab frame */
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);
424 return TRUE;
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;
433 APTR cstate;
434 Object *child;
435 WORD horiz_spacing = XGET(obj, MUIA_Group_HorizSpacing);
436 WORD vert_spacing = XGET(obj, MUIA_Group_VertSpacing);
437 LONG tab = 0;
439 /* Draw all the children */
440 DoSuperMethodA(cl, obj, (Msg) msg);
442 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
443 return (0);
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);
460 tab++;
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)
480 WORD lasty = -1;
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);
487 if (lasty > -1)
488 RectFill(_rp(obj), _right(obj), lasty + 1, _right(obj),
489 _bottom(obj));
491 else
492 return FALSE;
494 return TRUE;
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))
503 return FALSE;
505 get(_parent(obj), MUIA_Background, &data->background);
507 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) & data->ehn);
509 return TRUE;
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)
525 if (!msg->imsg)
526 return 0;
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;
537 Object *child;
538 int i;
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);
547 break;
551 break;
553 return 0;
556 #if ZUNE_BUILTIN_TITLE
557 BOOPSI_DISPATCHER(IPTR, Title_Dispatcher, cl, obj, msg)
559 switch (msg->MethodID)
561 case OM_NEW:
562 return Title__OM_NEW(cl, obj, (struct opSet *)msg);
563 case OM_SET:
564 return Title__OM_SET(cl, obj, (struct opSet *)msg);
565 case OM_DISPOSE:
566 return Title_OM_DISPOSE(cl, obj, msg);
567 case MUIM_Draw:
568 return Title__MUIM_Draw(cl, obj, (struct MUIP_Draw *)msg);
569 case MUIM_Setup:
570 return Title__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
571 case MUIM_Cleanup:
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);
576 default:
577 return DoSuperMethodA(cl, obj, msg);
580 BOOPSI_DISPATCHER_END
582 const struct __MUIBuiltinClass _MUI_Title_desc =
584 MUIC_Title,
585 MUIC_Group,
586 sizeof(struct Title_DATA),
587 (void *) Title_Dispatcher
589 #endif /* ZUNE_BUILTIN_TITLE */