2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2006, The AROS Development Team.
9 #include <exec/types.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/intuition.h>
14 #include <proto/utility.h>
15 #include <proto/graphics.h>
16 #include <proto/muimaster.h>
18 extern struct Library
*MUIMasterBase
;
20 #include "muimaster_intern.h"
25 /* #define MYDEBUG 1 */
28 #define ROUND(x) ((int)(x + 0.5))
29 #define IS_HIDDEN(obj) (! (_flags(obj) & MADF_SHOWME) || (_flags(obj) & MADF_BORDERGADGET))
31 /* Attributes filtered out in OM_SET, before OM_SET gets passed to children.
32 Tested with MUI under UAE/AOS.
44 MUIA_ContextMenuTrigger
61 struct layout2d_elem
{
72 struct Hook
*layout_hook
;
76 struct layout2d_elem
*row_infos
;
77 struct layout2d_elem
*col_infos
;
82 ULONG num_visible_children
; /* for horiz/vert group only */
83 ULONG horiz_weight_sum
;
84 ULONG vert_weight_sum
;
85 ULONG samesize_maxmin_horiz
;
86 ULONG samesize_maxmin_vert
;
87 ULONG update
; /* for MUI_Redraw() 1 - do not redraw the frame, 2 - the virtual pos has changed */
88 struct MUI_EventHandlerNode ehn
;
89 LONG virt_offx
, virt_offy
; /* diplay offsets */
90 LONG old_virt_offx
, old_virt_offy
; /* Saved virtual positions, used for update == 2 */
91 LONG virt_mwidth
,virt_mheight
; /* The complete width */
92 LONG saved_minwidth
,saved_minheight
;
93 LONG dont_forward_get
; /* Setted temporary to 1 so that the get method is not forwarded */
94 LONG dont_forward_methods
; /* Setted temporary to 1, meaning that the methods are not forwarded to the group's children */
97 #define GROUP_HORIZ (1<<1)
98 #define GROUP_SAME_WIDTH (1<<2)
99 #define GROUP_SAME_HEIGHT (1<<3)
100 #define GROUP_CHANGING (1<<4)
101 #define GROUP_PAGEMODE (1<<5)
102 #define GROUP_VIRTUAL (1<<6)
103 #define GROUP_HSPACING (1<<7)
104 #define GROUP_VSPACING (1<<8)
107 /* During minmax calculations objects with a weight of 0 shall
108 be treated like they had identical min/def/max size, ie. fixed size.
110 During layout objects with 0 weight must be treated like fixed-sized
111 too, but for hgroups only in x direction, and for vgroups only in
112 y direction. I think ... */
114 #define w0_defwidth(x) (_hweight(x) ? _defwidth(x) : _minwidth(x))
115 #define w0_maxwidth(x) (_hweight(x) ? _maxwidth(x) : _minwidth(x))
117 #define w0_defheight(x) (_vweight(x) ? _defheight(x) : _minheight(x))
118 #define w0_maxheight(x) (_vweight(x) ? _maxheight(x) : _minheight(x))
120 static const int __version
= 1;
121 static const int __revision
= 1;
123 IPTR
Group__MUIM_Show(struct IClass
*cl
, Object
*obj
, struct MUIP_Show
*msg
);
124 IPTR
Group__MUIM_Hide(struct IClass
*cl
, Object
*obj
, struct MUIP_Hide
*msg
);
126 /******************************************************************************/
127 /******************************************************************************/
130 static ULONG
Group_DispatchMsg(struct IClass
*cl
, Object
*obj
, Msg msg
);
132 static void change_active_page (struct IClass
*cl
, Object
*obj
, LONG page
)
134 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
137 if (!(data
->flags
& GROUP_PAGEMODE
)) return;
141 case MUIV_Group_ActivePage_First
:
144 case MUIV_Group_ActivePage_Last
:
145 newpage
= data
->num_childs
- 1;
147 case MUIV_Group_ActivePage_Prev
:
148 newpage
= data
->active_page
- 1;
150 newpage
= data
->num_childs
- 1;
152 case MUIV_Group_ActivePage_Next
:
153 case MUIV_Group_ActivePage_Advance
:
154 newpage
= (data
->active_page
+ 1) % data
->num_childs
;
161 if (newpage
!= data
->active_page
)
163 if (_flags(obj
) & MADF_CANDRAW
) Group__MUIM_Hide(cl
,obj
,NULL
);
164 data
->active_page
= newpage
;
165 if (_flags(obj
) & MADF_CANDRAW
)
167 DoMethod(obj
,MUIM_Layout
);
168 Group__MUIM_Show(cl
,obj
,NULL
);
170 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
175 /**************************************************************************
176 Returns the number of visible children. Visible children are all children
177 with have MADF_SHOWME and not MADF_BORDERGADGET set.
178 **************************************************************************/
179 static int Group_GetNumVisibleChildren(struct MUI_GroupData
*data
, struct MinList
*children
)
181 int num_visible_children
= data
->num_childs
;
185 /* As there can be unvisible children we have subtract those from the total
186 * number of children */
187 cstate
= (Object
*)children
->mlh_Head
;
188 while ((child
= NextObject(&cstate
)))
190 if (IS_HIDDEN(child
))
191 num_visible_children
--;
193 return num_visible_children
;
196 /**************************************************************************
198 **************************************************************************/
199 IPTR
Group__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
201 struct MUI_GroupData
*data
;
202 struct TagItem
*tags
,*tag
;
203 BOOL bad_childs
= FALSE
;
206 obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
209 /* Initial local instance data */
210 data
= INST_DATA(cl
, obj
);
212 data
->family
= MUI_NewObjectA(MUIC_Family
, NULL
);
215 CoerceMethod(cl
,obj
,OM_DISPOSE
);
219 data
->horiz_spacing
= -1;
220 data
->vert_spacing
= -1;
224 /* parse initial taglist */
225 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem((const struct TagItem
**)&tags
)); )
229 case MUIA_Group_Child
:
230 if (tag
->ti_Data
) DoMethod(obj
, OM_ADDMEMBER
, tag
->ti_Data
);
231 else bad_childs
= TRUE
;
234 case MUIA_Group_ActivePage
:
235 change_active_page(cl
, obj
, (LONG
)tag
->ti_Data
);
238 case MUIA_Group_Columns
:
239 data
->columns
= (tag
->ti_Data
)>1?tag
->ti_Data
:1;
243 case MUIA_Group_Horiz
:
244 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_HORIZ
);
247 case MUIA_Group_HorizSpacing
:
248 data
->flags
|= GROUP_HSPACING
;
249 data
->horiz_spacing
= tag
->ti_Data
;
252 case MUIA_Group_LayoutHook
:
253 data
->layout_hook
= (struct Hook
*)tag
->ti_Data
;
256 case MUIA_Group_PageMode
:
257 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_PAGEMODE
);
260 case MUIA_Group_Rows
:
261 data
->rows
= MAX((ULONG
)tag
->ti_Data
, 1);
265 case MUIA_Group_SameHeight
:
266 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_SAME_HEIGHT
);
269 case MUIA_Group_SameSize
:
270 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_SAME_HEIGHT
);
271 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_SAME_WIDTH
);
274 case MUIA_Group_SameWidth
:
275 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_SAME_WIDTH
);
278 case MUIA_Group_Spacing
:
279 data
->flags
|= (GROUP_HSPACING
| GROUP_VSPACING
);
280 data
->horiz_spacing
= tag
->ti_Data
;
281 data
->vert_spacing
= tag
->ti_Data
;
284 case MUIA_Group_VertSpacing
:
285 data
->flags
|= GROUP_VSPACING
;
286 data
->vert_spacing
= tag
->ti_Data
;
289 case MUIA_Group_Virtual
:
290 _handle_bool_tag(data
->flags
, tag
->ti_Data
, GROUP_VIRTUAL
);
297 CoerceMethod(cl
, obj
, OM_DISPOSE
);
301 /* D(bug("Group_New(0x%lx)\n",obj)); */
303 if (data
->flags
& GROUP_VIRTUAL
)
305 /* This is used by MUI_Render() to determine if group is virtual. It then installs a clip region.
306 * Also MUI_Layout() uses this. Probably for speed up reason */
307 _flags(obj
) |= MADF_ISVIRTUALGROUP
;
310 /* will forward MUIA_Disabled to childs */
311 get(obj
, MUIA_Disabled
, &disabled
);
314 set(obj
, MUIA_Disabled
, TRUE
);
317 /* This is only used for virtual groups */
318 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
; /* Will be filled on demand */
319 data
->ehn
.ehn_Priority
= 10; /* Will hear the click before all other normal objects */
320 data
->ehn
.ehn_Flags
= 0;
321 data
->ehn
.ehn_Object
= obj
;
322 data
->ehn
.ehn_Class
= cl
;
326 /**************************************************************************
328 **************************************************************************/
329 IPTR
Group__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
331 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
333 if (data
->row_infos
!= NULL
)
334 mui_free(data
->row_infos
);
335 if (data
->col_infos
!= NULL
)
336 mui_free(data
->col_infos
);
337 if (data
->family
!= NULL
)
338 MUI_DisposeObject(data
->family
);
339 return DoSuperMethodA(cl
, obj
, msg
);
342 /**************************************************************************
344 **************************************************************************/
345 IPTR
Group__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
347 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
348 struct TagItem
*tags
= msg
->ops_AttrList
;
351 BOOL need_recalc
= FALSE
;
354 int virt_offx
= data
->virt_offx
, virt_offy
= data
->virt_offy
;
356 /* There are many ways to find out what tag items provided by set()
357 ** we do know. The best way should be using NextTagItem() and simply
358 ** browsing through the list.
361 /* Parse group attributes before calling DoSuperMethodA(),
362 ** otherwise if an app for example sets up a notification
363 ** on MUIA_Group_ActivePage which calls a hook, and then
364 ** the hook function calls get(obj, MUIA_Group_ActivePage),
365 ** it would get returned the old active page instead of the new
369 while ((tag
= NextTagItem((const struct TagItem
**)&tags
)) != NULL
)
373 case MUIA_Group_Columns
:
374 data
->columns
= MAX((ULONG
)tag
->ti_Data
, 1);
378 case MUIA_Group_ActivePage
:
379 change_active_page(cl
, obj
, (LONG
)tag
->ti_Data
);
381 case MUIA_Group_Forward
:
382 forward
= tag
->ti_Data
;
384 case MUIA_Group_HorizSpacing
:
385 data
->flags
|= GROUP_HSPACING
;
386 data
->horiz_spacing
= tag
->ti_Data
;
388 case MUIA_Group_Rows
:
389 data
->rows
= MAX((ULONG
)tag
->ti_Data
, 1);
393 case MUIA_Group_Spacing
:
394 data
->flags
|= (GROUP_HSPACING
| GROUP_VSPACING
);
395 data
->horiz_spacing
= tag
->ti_Data
;
396 data
->vert_spacing
= tag
->ti_Data
;
398 case MUIA_Group_VertSpacing
:
399 data
->flags
|= GROUP_VSPACING
;
400 data
->vert_spacing
= tag
->ti_Data
;
402 case MUIA_Virtgroup_Left
:
403 //kprintf("set virtgroup_left: %d\n", tag->ti_Data);
404 virt_offx
= tag
->ti_Data
;
407 case MUIA_Group_LayoutHook
:
409 [ach] Seems like MUI supports setting this attribute after
410 initialization, even though the documentation states
411 otherwise. Atleast some programs use it...
413 data
->layout_hook
= (struct Hook
*)tag
->ti_Data
;
416 case MUIA_Virtgroup_Top
:
417 //kprintf("set virtgroup_top: %d\n", tag->ti_Data);
418 virt_offy
= tag
->ti_Data
;
426 DoMethod(_win(obj
), MUIM_Window_RecalcDisplay
, (IPTR
)obj
);
428 retval
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
430 /* seems to be the documented behaviour, however it should be slow! */
434 /* Attributes which are to be filtered out, so that they are ignored
435 when OM_SET is passed to group's children */
437 tags
= msg
->ops_AttrList
;
438 while ((tag
= NextTagItem((const struct TagItem
**)&tags
)) != NULL
)
447 case MUIA_ContextMenu
:
448 case MUIA_ContextMenuTrigger
:
449 case MUIA_ControlChar
:
450 case MUIA_CycleChain
:
453 case MUIA_Group_ActivePage
:
455 case MUIA_FrameTitle
:
456 case MUIA_HorizWeight
:
460 case MUIA_VertWeight
:
462 case MUIA_Virtgroup_Left
:
463 case MUIA_Virtgroup_Top
:
464 tag
->ti_Tag
= TAG_IGNORE
;
467 /* D(bug("Group_Set(%p) MUIA_Selected forwarded\n", obj)); */
468 /* tag->ti_Tag = TAG_IGNORE; */
473 Group_DispatchMsg(cl
, obj
, (Msg
)msg
);
477 if (virt_offx
!= data
->virt_offx
|| virt_offy
!= data
->virt_offy
)
479 if (_flags(obj
) & MADF_CANDRAW
) Group__MUIM_Hide(cl
,obj
,NULL
);
480 data
->virt_offx
= virt_offx
;
481 data
->virt_offy
= virt_offy
;
482 /* Relayout ourself, this will also relayout all the children */
483 DoMethod(obj
,MUIM_Layout
);
484 if (_flags(obj
) & MADF_CANDRAW
) Group__MUIM_Show(cl
,obj
,NULL
);
486 MUI_Redraw(obj
,MADF_DRAWUPDATE
);
493 /**************************************************************************
495 **************************************************************************/
496 IPTR
Group__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
498 /* small macro to simplify return value storage */
499 #define STORE *(msg->opg_Storage)
501 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
503 switch (msg
->opg_AttrID
)
505 case MUIA_Version
: STORE
= __version
; return 1;
506 case MUIA_Revision
: STORE
= __revision
; return 1;
507 case MUIA_Group_ActivePage
: STORE
= data
->active_page
; return 1;
508 case MUIA_Group_ChildList
: return GetAttr(MUIA_Family_List
, data
->family
, msg
->opg_Storage
);
509 case MUIA_Group_Horiz
: STORE
= (data
->flags
& GROUP_HORIZ
); return 1;
510 case MUIA_Group_HorizSpacing
: STORE
= data
->horiz_spacing
; return 1;
511 case MUIA_Group_VertSpacing
: STORE
= data
->vert_spacing
; return 1;
512 case MUIA_Virtgroup_Left
: STORE
= data
->virt_offx
; return 1;
513 case MUIA_Virtgroup_Top
: STORE
= data
->virt_offy
; return 1;
514 case MUIA_Virtgroup_Width
: STORE
= data
->virt_mwidth
; return 1;
515 case MUIA_Virtgroup_Height
: STORE
= data
->virt_mheight
; return 1;
516 case MUIA_Virtgroup_MinWidth
: STORE
= data
->saved_minwidth
; return 1;
517 case MUIA_Virtgroup_MinHeight
: STORE
= data
->saved_minheight
; return 1;
520 /* our handler didn't understand the attribute, we simply pass
521 ** it to our superclass now
523 if (DoSuperMethodA(cl
, obj
, (Msg
) msg
)) return 1;
525 /* seems to be the documented behaviour, however it should be slow! */
526 // if (!data->dont_forward_get)
530 struct MinList
*ChildList
;
532 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
533 cstate
= (Object
*)ChildList
->mlh_Head
;
534 while ((child
= NextObject(&cstate
)))
535 if (DoMethodA(child
, (Msg
)msg
)) return 1;
542 /**************************************************************************
544 **************************************************************************/
545 IPTR
Group__OM_ADDMEMBER(struct IClass
*cl
, Object
*obj
, struct opMember
*msg
)
547 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
549 /* D(bug("Group_AddMember(0x%lx, 0x%lx)\n",obj, msg->opam_Object)); */
551 DoMethodA(data
->family
, (Msg
)msg
);
554 /* if we are in an application tree, propagate pointers */
555 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
557 /* Only childs of groups can have parents */
559 if ((_flags(obj
) & MADF_INVIRTUALGROUP
) || (data
->flags
& GROUP_VIRTUAL
))
561 _flags(msg
->opam_Object
) |= MADF_INVIRTUALGROUP
;
564 muiNotifyData(msg
->opam_Object
)->mnd_ParentObject
= obj
;
565 DoMethod(msg
->opam_Object
, MUIM_ConnectParent
, (IPTR
)obj
);
568 if (_flags(obj
) & MADF_SETUP
)
570 DoSetupMethod(msg
->opam_Object
, muiRenderInfo(obj
));
572 /* if (_flags(obj) & MADF_CANDRAW) */
573 /* DoShowMethod(msg->opam_Object); */
578 /**************************************************************************
580 **************************************************************************/
581 IPTR
Group__OM_REMMEMBER(struct IClass
*cl
, Object
*obj
, struct opMember
*msg
)
583 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
585 if (_flags(obj
) & MADF_CANDRAW
)
586 DoHideMethod(msg
->opam_Object
);
587 if (_flags(obj
) & MADF_SETUP
)
588 DoMethod(msg
->opam_Object
, MUIM_Cleanup
);
589 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
591 DoMethod(msg
->opam_Object
, MUIM_DisconnectParent
);
592 muiNotifyData(msg
->opam_Object
)->mnd_ParentObject
= NULL
;
594 _flags(msg
->opam_Object
) &= ~MADF_INVIRTUALGROUP
;
598 DoMethodA(data
->family
, (Msg
)msg
);
604 /**************************************************************************
606 **************************************************************************/
607 IPTR
Group__MUIM_ConnectParent(struct IClass
*cl
, Object
*obj
, struct MUIP_ConnectParent
*msg
)
609 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
612 struct MinList
*ChildList
;
614 DoSuperMethodA(cl
,obj
,(Msg
)msg
);
616 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
617 cstate
= (Object
*)ChildList
->mlh_Head
;
618 while ((child
= NextObject(&cstate
)))
620 if ((_flags(obj
) & MADF_INVIRTUALGROUP
) || (data
->flags
& GROUP_VIRTUAL
))
622 _flags(child
) |= MADF_INVIRTUALGROUP
;
625 /* Only childs of groups can have parents */
626 muiNotifyData(child
)->mnd_ParentObject
= obj
;
628 DoMethod(child
, MUIM_ConnectParent
, (IPTR
)obj
);
633 /**************************************************************************
634 MUIM_DisconnectParent
635 **************************************************************************/
636 IPTR
Group__MUIM_DisconnectParent(struct IClass
*cl
, Object
*obj
, struct MUIP_ConnectParent
*msg
)
638 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
641 struct MinList
*ChildList
;
643 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
644 cstate
= (Object
*)ChildList
->mlh_Head
;
645 while ((child
= NextObject(&cstate
)))
647 DoMethodA(child
, (Msg
)msg
);
648 muiNotifyData(child
)->mnd_ParentObject
= NULL
;
649 _flags(child
) &= ~MADF_INVIRTUALGROUP
;
651 DoSuperMethodA(cl
,obj
,(Msg
)msg
);
656 * Put group in exchange state
658 IPTR
Group__MUIM_InitChange(struct IClass
*cl
, Object
*obj
,
659 struct MUIP_Group_InitChange
*msg
)
661 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
663 data
->flags
|= GROUP_CHANGING
;
669 * Will recalculate display after dynamic adding/removing
671 IPTR
Group__MUIM_ExitChange(struct IClass
*cl
, Object
*obj
,
672 struct MUIP_Group_ExitChange
*msg
)
674 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
676 if (data
->flags
& GROUP_CHANGING
)
678 data
->flags
&= ~GROUP_CHANGING
;
680 if ((_flags(obj
) & MADF_SETUP
) && _win(obj
))
681 DoMethod(_win(obj
), MUIM_Window_RecalcDisplay
, (IPTR
)obj
);
691 IPTR
Group__MUIM_Sort(struct IClass
*cl
, Object
*obj
, struct MUIP_Group_Sort
*msg
)
693 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
696 msg
->MethodID
= MUIM_Family_Sort
;
698 DoMethodA(data
->family
, (APTR
)msg
);
700 /* restore original message */
701 msg
->MethodID
= MUIM_Group_Sort
;
705 /**************************************************************************
706 MUIM_Group_DoMethodNoForward
708 Executes the given method but does not forward it to the children
709 **************************************************************************/
710 IPTR
Group__MUIM_DoMethodNoForward(struct IClass
*cl
, Object
*obj
, struct MUIP_Group_DoMethodNoForward
*msg
)
712 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
714 data
->dont_forward_methods
= 1; /* disable forwarding */
715 rc
= DoMethodA(obj
, (Msg
)&msg
->DoMethodID
); /* Probably doesn't not work correctly on AROS? */
716 data
->dont_forward_methods
= 0;
721 * Propagate a method to group childs.
723 static ULONG
Group_DispatchMsg(struct IClass
*cl
, Object
*obj
, Msg msg
)
725 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
728 struct MinList
*ChildList
;
730 if (data
->dont_forward_methods
) return TRUE
;
732 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
733 cstate
= (Object
*)ChildList
->mlh_Head
;
734 while ((child
= NextObject(&cstate
)))
735 DoMethodA(child
, (Msg
)msg
);
740 /**************************************************************************
742 **************************************************************************/
743 IPTR
Group__MUIM_Setup(struct IClass
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
745 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
750 struct MinList
*ChildList
;
752 if (!DoSuperMethodA(cl
, obj
, (Msg
)msg
))
755 ASSERT_VALID_PTR(muiGlobalInfo(obj
));
757 if (!(data
->flags
& GROUP_HSPACING
))
758 data
->horiz_spacing
= muiGlobalInfo(obj
)->mgi_Prefs
->group_hspacing
;
759 if (!(data
->flags
& GROUP_VSPACING
))
760 data
->vert_spacing
= muiGlobalInfo(obj
)->mgi_Prefs
->group_vspacing
;
761 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
762 cstate
= cstate_copy
= (Object
*)ChildList
->mlh_Head
;
763 while ((child
= NextObject(&cstate
)))
765 #if 0 /* SHOWME affects only show/hide */
766 if (! (_flags(child
) & MADF_SHOWME
))
770 if (!DoSetupMethod(child
, msg
->RenderInfo
))
772 /* Send MUIM_Cleanup to all objects that received MUIM_Setup.
775 cstate
= cstate_copy
;
776 while ((child
= NextObject(&cstate
)) && (child
!= childFailed
))
778 #if 0 /* SHOWME affects only show/hide */
779 if (! (_flags(child
) & MADF_SHOWME
))
782 DoMethod(child
, MUIM_Cleanup
);
788 if (data
->flags
& GROUP_VIRTUAL
)
790 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
797 /**************************************************************************
799 **************************************************************************/
800 IPTR
Group__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
, Msg msg
)
802 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
805 struct MinList
*ChildList
;
807 if (data
->flags
& GROUP_VIRTUAL
)
809 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
812 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
813 cstate
= (Object
*)ChildList
->mlh_Head
;
814 while ((child
= NextObject(&cstate
)))
816 #if 0 /* SHOWME affects only show/hide */
817 if (! (_flags(child
) & MADF_SHOWME
))
820 DoMethodA(child
, (Msg
)msg
);
822 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
827 /**************************************************************************
828 MUIM_Draw - draw the group
829 **************************************************************************/
830 IPTR
Group__MUIM_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
832 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
835 struct MinList
*ChildList
;
836 struct Rectangle group_rect
; /* child_rect;*/
838 struct Region
*region
= NULL
;
839 APTR clip
= (APTR
)-1;
841 /* D(bug("Group_Draw(%lx) %ldx%ldx%ldx%ld upd=%d page=%d\n", */
842 /* obj,_left(obj),_top(obj),_right(obj),_bottom(obj), */
843 /* data->update, data->active_page)); */
844 /* D(bug("Group_Draw(%p) msg=0x%08lx flags=0x%08lx\n", obj, msg->flags, _flags(obj))); */
846 if (data
->flags
& GROUP_CHANGING
)
849 if (muiGlobalInfo(obj
)->mgi_Prefs
->window_redraw
== WINDOW_REDRAW_WITHOUT_CLEAR
)
851 region
= NewRegion();
854 struct Rectangle rect
;
856 rect
.MinX
= _left(obj
);
857 rect
.MinY
= _top(obj
);
858 rect
.MaxX
= _right(obj
);
859 rect
.MaxY
= _bottom(obj
);
861 OrRectRegion(region
, &rect
);
863 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
864 cstate
= (Object
*)ChildList
->mlh_Head
;
865 while ((child
= NextObject(&cstate
)))
867 /*page++;*//* redraw problem with colorwheel in coloradjust register */
868 if ((data
->flags
& GROUP_PAGEMODE
) && (page
!= data
->active_page
))
871 if ((muiAreaData(child
)->mad_Flags
& MADF_CANDRAW
)
872 && (_width(child
) > 0)
873 && (_height(child
) > 0))
875 rect
.MinX
= MAX(_left(child
) , _mleft (obj
));
876 rect
.MinY
= MAX(_top(child
) , _mtop (obj
));
877 rect
.MaxX
= MIN(_right(child
) , _mright (obj
));
878 rect
.MaxY
= MIN(_bottom(child
), _mbottom(obj
));
880 if ((rect
.MaxX
>= rect
.MinX
) && (rect
.MaxY
>= rect
.MinY
))
882 ClearRectRegion(region
, &rect
);
887 clip
= MUI_AddClipRegion(muiRenderInfo(obj
), region
);
891 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
895 MUI_RemoveClipRegion(muiRenderInfo(obj
), clip
);
901 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
903 /* D(bug("Group_Draw(%p) (after dsma) msg=0x%08lx flags=0x%08lx\n", */
904 /* obj, msg->flags, _flags(obj))); */
906 if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 1)
909 * update is set when changing active page of a page group
910 * need to redraw background ourself
912 DoMethod(obj
, MUIM_DrawBackground
,
913 _mleft(obj
), _mtop(obj
), _mwidth(obj
), _mheight(obj
), _mleft(obj
), _mtop(obj
), 0);
918 if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 2)
920 LONG left
,top
,right
,bottom
;
921 LONG diff_virt_offx
= data
->virt_offx
- data
->old_virt_offx
;
922 LONG diff_virt_offy
= data
->virt_offy
- data
->old_virt_offy
;
923 struct Rectangle rect
;
924 struct Rectangle
*clip_rect
= &muiRenderInfo(obj
)->mri_ClipRect
;
928 if (!diff_virt_offx
&& !diff_virt_offy
)
933 /* sba: I don't know how MUI handle this but ScrollRasterBF() made problems when scrolling
934 ** a (partly visible) virtual groups in a virtual group, because e.g. _mtop() is then
935 ** smaller than the region. ScrollRasterBF() on AmigaOS then marks the complete region
936 ** as damaged. Using ScrollWindowRaster() solved that problem but it flickers then.
937 ** To avoid this we prevent that the scroll area is out of the region bounds.
938 ** The region bounds are setted in MUI_Redraw() but should probably should go in the
939 ** MUI's clip functions
942 left
= MAX(_mleft(obj
),clip_rect
->MinX
);
943 top
= MAX(_mtop(obj
),clip_rect
->MinY
);
944 right
= MIN(_mright(obj
),clip_rect
->MaxX
);
945 bottom
= MIN(_mbottom(obj
),clip_rect
->MaxY
);
948 ** ScrollRasterBF(_rp(obj), diff_virt_offx, diff_virt_offy, _mleft(obj), _mtop(obj), _mright(obj),_mbottom(obj));
951 ScrollWindowRaster(_window(obj
), diff_virt_offx
, diff_virt_offy
, left
, top
, right
,bottom
);
953 if ((region
= NewRegion()))
960 if (diff_virt_offx
> 0)
962 rect
.MinX
= right
- diff_virt_offx
+ 1;
963 if (rect
.MinX
< left
) rect
.MinX
= left
;
968 rect
.MaxX
= left
- diff_virt_offx
- 1;
969 if (rect
.MaxX
> right
) rect
.MaxX
= right
;
972 if (rect
.MinX
<= rect
.MaxX
)
974 DoMethod(obj
, MUIM_DrawBackground
,
975 rect
.MinX
, rect
.MinY
,
976 rect
.MaxX
- rect
.MinX
+ 1,
977 rect
.MaxY
- rect
.MinY
+ 1,
978 rect
.MinX
, rect
.MinY
, 0);
980 OrRectRegion(region
,&rect
);
989 if (diff_virt_offy
> 0)
991 rect
.MinY
= bottom
- diff_virt_offy
+ 1;
992 if (rect
.MinY
< top
) rect
.MinY
= top
;
997 rect
.MaxY
= top
- diff_virt_offy
- 1;
998 if (rect
.MaxY
> bottom
) rect
.MaxY
= bottom
;
1000 if (rect
.MinY
<= rect
.MaxY
)
1002 DoMethod(obj
, MUIM_DrawBackground
,
1003 rect
.MinX
, rect
.MinY
,
1004 rect
.MaxX
- rect
.MinX
+ 1,
1005 rect
.MaxY
- rect
.MinY
+ 1,
1006 rect
.MinX
, rect
.MinY
, 0);
1008 OrRectRegion(region
,&rect
);
1015 if (!(msg
->flags
& MADF_DRAWOBJECT
) && !(msg
->flags
& MADF_DRAWALL
))
1020 if (data
->flags
& GROUP_VIRTUAL
&& !region
)
1022 /* Not really needed if MUI Draws all the objects, maybe that's where DRAWALL is for??? */
1023 if ((region
= NewRegion()))
1025 struct Rectangle rect
;
1026 rect
.MinX
= _mleft(obj
);
1027 rect
.MinY
= _mtop(obj
);
1028 rect
.MaxX
= _mright(obj
);
1029 rect
.MaxY
= _mbottom(obj
);
1030 OrRectRegion(region
,&rect
);
1034 /* Add clipping region if we have one */
1035 if (region
) clip
= MUI_AddClipRegion(muiRenderInfo(obj
),region
);
1037 group_rect
= muiRenderInfo(obj
)->mri_ClipRect
;
1039 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
1040 cstate
= (Object
*)ChildList
->mlh_Head
;
1041 while ((child
= NextObject(&cstate
)))
1043 if (! (_flags(child
) & MADF_SHOWME
))
1046 if ((data
->flags
& GROUP_PAGEMODE
) && (page
!= data
->active_page
))
1051 // msg->flags |= MADF_DRAWOBJECT; /* yup, do not forget */
1053 // child_rect.MinX = _left(child);
1054 // child_rect.MinY = _top(child);
1055 // child_rect.MaxX = _right(child);
1056 // child_rect.MaxY = _bottom(child);
1057 /* g_print("intersect: a=(%d, %d, %d, %d) b=(%d, %d, %d, %d)\n", */
1058 /* group_rect.x, group_rect.y, */
1059 /* group_rect.width, group_rect.height, */
1060 /* child_rect.x, child_rect.y, */
1061 /* child_rect.width, child_rect.height); */
1063 // if (gdk_rectangle_intersect(&group_rect, &child_rect,
1064 // &muiRenderInfo(obj)->mri_ClipRect))
1065 // DoMethodA(child, (Msg)msg);
1066 /* if (((msg->flags & MADF_DRAWUPDATE) && data->update) || (data->flags & GROUP_PAGEMODE)) */
1067 MUI_Redraw(child
, MADF_DRAWOBJECT
);
1069 /* MUI_Redraw(child, msg->flags); */
1070 muiRenderInfo(obj
)->mri_ClipRect
= group_rect
;
1071 /* g_print("set back clip to (%d, %d, %d, %d)\n", */
1072 /* group_rect.x, group_rect.y, group_rect.width, group_rect.height); */
1074 /* D(bug("Group_Draw(%p) end\n", obj)); */
1076 if (data
->flags
& GROUP_VIRTUAL
&& region
&& clip
!= (APTR
)-1)
1078 MUI_RemoveClipRegion(muiRenderInfo(obj
), clip
);
1081 data
->old_virt_offx
= data
->virt_offx
;
1082 data
->old_virt_offy
= data
->virt_offy
;
1089 #define END_MINMAX() \
1090 tmp.MaxHeight = MAX(tmp.MaxHeight, tmp.MinHeight); \
1091 tmp.MaxWidth = MAX(tmp.MaxWidth, tmp.MinWidth); \
1092 tmp.DefHeight = CLAMP(tmp.DefHeight, tmp.MinHeight, tmp.MaxHeight); \
1093 tmp.DefWidth = CLAMP(tmp.DefWidth, tmp.MinWidth, tmp.MaxWidth); \
1094 msg->MinMaxInfo->MinWidth += tmp.MinWidth; \
1095 msg->MinMaxInfo->MinHeight += tmp.MinHeight; \
1096 msg->MinMaxInfo->MaxWidth += tmp.MaxWidth; \
1097 msg->MinMaxInfo->MaxHeight += tmp.MaxHeight; \
1098 msg->MinMaxInfo->DefWidth += tmp.DefWidth; \
1099 msg->MinMaxInfo->DefHeight += tmp.DefHeight;
1102 * MinMax calculation function. When this is called,
1103 * the children of your group have already been asked
1104 * about their min/max dimension so you can use their
1105 * dimensions to calculate yours.
1108 * - Init minwidth and maxwidth with size needed for total child spacing.
1109 * - 1st pass to find maximum minimum width, to set minwidth of each child
1110 * if they should have the same width (for a row of buttons ...)
1111 * - Adjust minwidth w/o making object bigger than their max size.
1113 static void group_minmax_horiz(struct IClass
*cl
, Object
*obj
,
1114 struct MinList
*children
, struct MUIP_AskMinMax
*msg
)
1116 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
1119 struct MUI_MinMax tmp
;
1120 WORD maxminwidth
= 0;
1121 BOOL found_nonzero_vweight
= FALSE
;
1125 tmp
.MaxHeight
= MUI_MAXMAX
;
1126 tmp
.MinWidth
= tmp
.DefWidth
= tmp
.MaxWidth
=
1127 (data
->num_visible_children
- 1) * data
->horiz_spacing
;
1129 if (data
->flags
& GROUP_SAME_WIDTH
) {
1130 cstate
= (Object
*)children
->mlh_Head
;
1131 while ((child
= NextObject(&cstate
))) {
1132 if (IS_HIDDEN(child
))
1134 maxminwidth
= MAX(maxminwidth
, _minwidth(child
));
1138 data
->samesize_maxmin_horiz
= maxminwidth
;
1139 /* D(bug("group_minmax_horiz(%p) : maxminwidth=%d\n", obj, maxminwidth)); */
1141 data
->horiz_weight_sum
= 0;
1142 cstate
= (Object
*)children
->mlh_Head
;
1143 while ((child
= NextObject(&cstate
))) {
1146 if (IS_HIDDEN(child
))
1148 if (data
->flags
& GROUP_SAME_WIDTH
)
1150 minwidth
= MAX(maxminwidth
, _minwidth(child
));
1151 minwidth
= MIN(minwidth
, _maxwidth(child
));
1154 minwidth
= _minwidth(child
);
1155 tmp
.MinWidth
+= minwidth
;
1156 tmp
.DefWidth
+= w0_defwidth(child
);
1157 tmp
.MaxWidth
+= w0_maxwidth(child
);
1158 tmp
.MaxWidth
= MIN(tmp
.MaxWidth
, MUI_MAXMAX
);
1159 tmp
.MinHeight
= MAX(tmp
.MinHeight
, _minheight(child
));
1160 tmp
.DefHeight
= MAX(tmp
.DefHeight
, _defheight(child
));
1162 if all childs have null weight then maxheight=minheight
1163 if all but some childs have null weights, the maxheight
1164 is the min of all maxheights
1166 tmp
.MaxHeight
= MIN(tmp
.MaxHeight
, _maxheight(child
));
1167 data
->horiz_weight_sum
+= _hweight(child
);
1168 if (_vweight(child
) > 0)
1170 found_nonzero_vweight
= TRUE
;
1173 if (!found_nonzero_vweight
)
1175 tmp
.MaxHeight
= tmp
.MinHeight
;
1178 //if (data->flags & GROUP_VIRTUAL)
1180 //kprintf("# min %d x %d def %d x %d max %d x %d\n",
1181 // tmp.MinWidth, tmp.MinHeight,
1182 // tmp.DefWidth, tmp.DefHeight,
1183 // tmp.MaxWidth, tmp.MaxHeight);
1189 /* minmax calculation for vertical groups (see group_minmax_horiz)
1191 static void group_minmax_vert(struct IClass
*cl
, Object
*obj
,
1192 struct MinList
*children
, struct MUIP_AskMinMax
*msg
)
1194 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
1197 struct MUI_MinMax tmp
;
1198 WORD maxminheight
= 0;
1199 BOOL found_nonzero_hweight
= FALSE
;
1203 tmp
.MaxWidth
= MUI_MAXMAX
;
1204 tmp
.MinHeight
= tmp
.DefHeight
= tmp
.MaxHeight
=
1205 (data
->num_visible_children
- 1) * data
->vert_spacing
;
1207 if (data
->flags
& GROUP_SAME_HEIGHT
)
1209 cstate
= (Object
*)children
->mlh_Head
;
1210 while ((child
= NextObject(&cstate
))) {
1211 if (IS_HIDDEN(child
))
1213 maxminheight
= MAX(maxminheight
, _minheight(child
));
1217 data
->samesize_maxmin_vert
= maxminheight
;
1218 data
->vert_weight_sum
= 0;
1219 cstate
= (Object
*)children
->mlh_Head
;
1220 while ((child
= NextObject(&cstate
)))
1222 if (IS_HIDDEN(child
))
1225 if (data
->flags
& GROUP_SAME_HEIGHT
)
1226 _minheight(child
) = MIN(maxminheight
, w0_maxheight(child
));
1227 tmp
.MinHeight
+= _minheight(child
);
1228 tmp
.DefHeight
+= w0_defheight(child
);
1229 tmp
.MaxHeight
+= w0_maxheight(child
);
1230 tmp
.MaxHeight
= MIN(tmp
.MaxHeight
, MUI_MAXMAX
);
1231 tmp
.MinWidth
= MAX(tmp
.MinWidth
, _minwidth(child
));
1232 tmp
.DefWidth
= MAX(tmp
.DefWidth
, _defwidth(child
));
1233 tmp
.MaxWidth
= MIN(tmp
.MaxWidth
, _maxwidth(child
));
1234 data
->vert_weight_sum
+= _vweight(child
);
1235 if (_hweight(child
) > 0)
1237 found_nonzero_hweight
= TRUE
;
1240 if (!found_nonzero_hweight
)
1242 tmp
.MaxWidth
= tmp
.MinWidth
;
1250 minmax_2d_rows_pass (struct MUI_GroupData
*data
, struct MinList
*children
,
1251 struct MUI_MinMax
*req
, WORD maxmin_height
, WORD maxdef_height
)
1257 /* do not rewind after the while, to process line by line */
1258 cstate
= (Object
*)children
->mlh_Head
;
1260 for (i
= 0; i
< data
->rows
; i
++) {
1261 /* calculate min and max height of this row */
1262 int min_h
= 0, def_h
= 0, max_h
= MUI_MAXMAX
;
1263 BOOL found_nonzero_vweight
= FALSE
;
1265 data
->row_infos
[i
].weight
= 0;
1268 while ((child
= NextObject(&cstate
))) {
1269 if (IS_HIDDEN(child
))
1271 if (data
->flags
& GROUP_SAME_HEIGHT
)
1273 _minheight(child
) = MIN(maxmin_height
, w0_maxheight(child
));
1274 _defheight(child
) = MIN(maxdef_height
, w0_maxheight(child
));
1276 min_h
= MAX(min_h
, _minheight(child
));
1277 def_h
= MAX(def_h
, w0_defheight(child
));
1278 max_h
= MIN(max_h
, _maxheight(child
));
1279 if (_vweight(child
) > 0)
1281 found_nonzero_vweight
= TRUE
;
1282 data
->row_infos
[i
].weight
+= _vweight(child
);
1285 if ((j
% data
->columns
) == 0)
1288 if (!found_nonzero_vweight
)
1291 max_h
= MAX(max_h
, min_h
);
1292 /* D(bug("row %d : min_h=%d max_h=%d\n", i, min_h, max_h)); */
1294 data
->row_infos
[i
].min
= min_h
;
1295 data
->row_infos
[i
].max
= max_h
;
1296 data
->vert_weight_sum
+= data
->row_infos
[i
].weight
;
1298 req
->MinHeight
+= min_h
;
1299 req
->DefHeight
+= def_h
;
1300 req
->MaxHeight
+= max_h
;
1301 if (req
->MaxHeight
> MUI_MAXMAX
)
1302 req
->MaxHeight
= MUI_MAXMAX
;
1308 minmax_2d_columns_pass (struct MUI_GroupData
*data
, struct MinList
*children
,
1309 struct MUI_MinMax
*req
, WORD maxmin_width
, WORD maxdef_width
)
1315 for (i
= 0; i
< data
->columns
; i
++) {
1316 /* calculate min and max width of this column */
1317 int min_w
= 0, def_w
= 0, max_w
= MUI_MAXMAX
;
1318 BOOL found_nonzero_hweight
= FALSE
;
1320 data
->col_infos
[i
].weight
= 0;
1323 /* process all childs to get childs on a column */
1324 cstate
= (Object
*)children
->mlh_Head
;
1325 while ((child
= NextObject(&cstate
))) {
1326 if (IS_HIDDEN(child
))
1329 if (((j
- 1) % data
->columns
) != i
)
1331 if (data
->flags
& GROUP_SAME_WIDTH
)
1333 _minwidth(child
) = MIN(maxmin_width
, w0_maxwidth(child
));
1334 _defwidth(child
) = MIN(maxdef_width
, w0_maxwidth(child
));
1336 min_w
= MAX(min_w
, _minwidth(child
));
1337 def_w
= MAX(def_w
, w0_defwidth(child
));
1339 /* this handles the case of null weight childs, which limit
1340 * the max size if they're alone, but not if they are with
1341 * non-null weight obj
1343 max_w
= MIN(max_w
, _maxwidth(child
));
1344 if (_hweight(child
) > 0)
1346 found_nonzero_hweight
= TRUE
;
1347 data
->col_infos
[i
].weight
+= _hweight(child
);
1350 if (!found_nonzero_hweight
)
1353 max_w
= MAX(max_w
, min_w
);
1354 /* D(bug("col %d : min_w=%d max_w=%d\n", i, min_w, max_w)); */
1356 data
->col_infos
[i
].min
= min_w
;
1357 data
->col_infos
[i
].max
= max_w
;
1358 data
->horiz_weight_sum
+= data
->col_infos
[i
].weight
;
1360 req
->MinWidth
+= min_w
;
1361 req
->DefWidth
+= def_w
;
1362 req
->MaxWidth
+= max_w
;
1363 if (req
->MaxWidth
> MUI_MAXMAX
)
1364 req
->MaxWidth
= MUI_MAXMAX
;
1369 group_minmax_2d(struct IClass
*cl
, Object
*obj
,
1370 struct MinList
*children
, struct MUIP_AskMinMax
*msg
)
1372 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
1375 struct MUI_MinMax tmp
;
1383 if (data
->num_childs
% data
->rows
)
1386 data
->rows
= data
->num_childs
;
1389 data
->columns
= data
->num_childs
/ data
->rows
;
1393 if (data
->num_childs
% data
->columns
)
1396 data
->columns
= data
->num_childs
;
1399 data
->rows
= data
->num_childs
/ data
->columns
;
1402 if (data
->columns
< 1)
1407 if (data
->row_infos
!= NULL
)
1408 mui_free(data
->row_infos
);
1410 data
->row_infos
= mui_alloc(data
->rows
* sizeof(struct layout2d_elem
));
1411 if (NULL
== data
->row_infos
)
1414 if (data
->col_infos
!= NULL
)
1415 mui_free(data
->col_infos
);
1417 data
->col_infos
= mui_alloc(data
->columns
* sizeof(struct layout2d_elem
));
1418 if (NULL
== data
->col_infos
)
1421 data
->horiz_weight_sum
= 0;
1422 data
->vert_weight_sum
= 0;
1424 tmp
.MinHeight
= tmp
.DefHeight
= tmp
.MaxHeight
= (data
->rows
- 1) * data
->vert_spacing
;
1425 tmp
.MinWidth
= tmp
.DefWidth
= tmp
.MaxWidth
= (data
->columns
- 1) * data
->horiz_spacing
;
1426 /* get minimum dims if same dims for all childs are needed */
1432 if ((data
->flags
& GROUP_SAME_WIDTH
) || (data
->flags
& GROUP_SAME_HEIGHT
)) {
1433 cstate
= (Object
*)children
->mlh_Head
;
1434 while ((child
= NextObject(&cstate
))) {
1435 if (! (_flags(child
) & MADF_SHOWME
))
1437 maxmin_width
= MAX(maxmin_width
, _minwidth(child
));
1438 maxmin_height
= MAX(maxmin_height
, _minheight(child
));
1439 maxdef_width
= MAX(maxdef_width
, w0_defwidth(child
));
1440 maxdef_height
= MAX(maxdef_height
, w0_defheight(child
));
1442 /* g_print("2d group: mminw=%d mminh=%d\n", maxmin_width, maxmin_height); */
1444 if (data
->flags
& GROUP_SAME_HEIGHT
)
1445 data
->samesize_maxmin_vert
= maxmin_height
;
1447 data
->samesize_maxmin_vert
= 0;
1449 if (data
->flags
& GROUP_SAME_WIDTH
)
1450 data
->samesize_maxmin_horiz
= maxmin_width
;
1452 data
->samesize_maxmin_horiz
= 0;
1454 minmax_2d_rows_pass (data
, children
, &tmp
, maxmin_height
, maxdef_height
);
1455 minmax_2d_columns_pass (data
, children
, &tmp
, maxmin_width
, maxdef_width
);
1462 group_minmax_pagemode(struct IClass
*cl
, Object
*obj
,
1463 struct MinList
*children
, struct MUIP_AskMinMax
*msg
)
1467 struct MUI_MinMax tmp
= { 0, 0, MUI_MAXMAX
, MUI_MAXMAX
, 0, 0 };
1469 cstate
= (Object
*)children
->mlh_Head
;
1470 /* D(bug("minmax_pagemode(%lx)\n", obj, tmp.DefWidth)); */
1471 while ((child
= NextObject(&cstate
)))
1473 if (! (_flags(child
) & MADF_SHOWME
))
1476 tmp
.MinHeight
= MAX(tmp
.MinHeight
, _minheight(child
));
1477 D(bug("minmax_pagemode(%p) minh child = %d tmpmin=%d\n", obj
, _minheight(child
), tmp
.MinHeight
));
1478 tmp
.MinWidth
= MAX(tmp
.MinWidth
, _minwidth(child
));
1479 tmp
.MaxHeight
= MIN(tmp
.MaxHeight
, w0_maxheight(child
));
1480 tmp
.MaxWidth
= MIN(tmp
.MaxWidth
, w0_maxwidth(child
));
1481 tmp
.DefHeight
= MAX(tmp
.DefHeight
,
1482 ((w0_defheight(child
) < MUI_MAXMAX
) ? w0_defheight(child
) : tmp
.DefHeight
));
1483 tmp
.DefWidth
= MAX(tmp
.DefWidth
,
1484 ((w0_defwidth(child
) < MUI_MAXMAX
) ? w0_defwidth(child
) : tmp
.DefWidth
));
1485 /* D(bug("minmax_pagemode(%lx) defw = %ld\n", obj, tmp.DefWidth)); */
1490 /**************************************************************************
1491 MUIM_AskMinMax : ask childs about min/max sizes, then
1492 either call a hook, or the builtin method, to calculate our minmax
1493 **************************************************************************/
1494 IPTR
Group__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
1496 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
1497 struct MUI_LayoutMsg lm
;
1498 struct MUIP_AskMinMax childMsg
;
1499 struct MUI_MinMax childMinMax
;
1502 LONG super_minwidth
,super_minheight
;
1505 * let our superclass first fill in its size with frame, inner spc etc ...
1507 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
1508 super_minwidth
= msg
->MinMaxInfo
->MinWidth
;
1509 super_minheight
= msg
->MinMaxInfo
->MinHeight
;
1514 childMsg
.MethodID
= msg
->MethodID
;
1515 childMsg
.MinMaxInfo
= &childMinMax
;
1516 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(lm
.lm_Children
));
1518 cstate
= (Object
*)lm
.lm_Children
->mlh_Head
;
1520 while ((child
= NextObject(&cstate
)))
1522 if (! (_flags(child
) & MADF_SHOWME
)) /* BORDERGADGETs should handle this itself */
1525 DoMethodA(child
, (Msg
)&childMsg
);
1526 /* D(bug("*** group %lx, child %lx min=%ld,%ld\n", obj, child, childMinMax.MinWidth, childMinMax.MinHeight)); */
1527 __area_finish_minmax(child
, childMsg
.MinMaxInfo
);
1531 * Use childs infos to calculate group size
1533 if (data
->flags
& GROUP_PAGEMODE
)
1535 D(bug("minmax_pagemode(%p) minh initial = %d\n", obj
, msg
->MinMaxInfo
->MinHeight
));
1536 group_minmax_pagemode(cl
, obj
, lm
.lm_Children
, msg
);
1537 D(bug("minmax_pagemode(%p) minh = %d\n", obj
, msg
->MinMaxInfo
->MinHeight
));
1539 else if (data
->layout_hook
)
1541 lm
.lm_Type
= MUILM_MINMAX
;
1542 CallHookPkt(data
->layout_hook
, obj
, &lm
);
1544 if (lm
.lm_MinMax
.MaxHeight
< lm
.lm_MinMax
.MinHeight
)
1545 lm
.lm_MinMax
.MaxHeight
= lm
.lm_MinMax
.MinHeight
;
1546 if (lm
.lm_MinMax
.DefHeight
< lm
.lm_MinMax
.MinHeight
)
1547 lm
.lm_MinMax
.DefHeight
= lm
.lm_MinMax
.MinHeight
;
1548 if (lm
.lm_MinMax
.MaxWidth
< lm
.lm_MinMax
.MinWidth
)
1549 lm
.lm_MinMax
.MaxWidth
= lm
.lm_MinMax
.MinWidth
;
1550 if (lm
.lm_MinMax
.DefWidth
< lm
.lm_MinMax
.MinWidth
)
1551 lm
.lm_MinMax
.DefWidth
= lm
.lm_MinMax
.MinWidth
;
1553 //kprintf("### min %d x %d def %d x %d max %d x %d\n",
1554 // msg->MinMaxInfo->MinWidth,
1555 // msg->MinMaxInfo->MinHeight,
1556 // msg->MinMaxInfo->DefWidth,
1557 // msg->MinMaxInfo->DefHeight,
1558 // msg->MinMaxInfo->MaxWidth,
1559 // msg->MinMaxInfo->MaxHeight);
1561 msg
->MinMaxInfo
->MinWidth
+= lm
.lm_MinMax
.MinWidth
;
1562 msg
->MinMaxInfo
->MinHeight
+= lm
.lm_MinMax
.MinHeight
;
1563 msg
->MinMaxInfo
->MaxWidth
+= lm
.lm_MinMax
.MaxWidth
;
1564 if (msg
->MinMaxInfo
->MaxWidth
> MUI_MAXMAX
)
1565 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
1566 msg
->MinMaxInfo
->MaxHeight
+= lm
.lm_MinMax
.MaxHeight
;
1567 if (msg
->MinMaxInfo
->MaxHeight
> MUI_MAXMAX
)
1568 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
1569 msg
->MinMaxInfo
->DefWidth
+= lm
.lm_MinMax
.DefWidth
;
1570 msg
->MinMaxInfo
->DefHeight
+= lm
.lm_MinMax
.DefHeight
;
1572 //kprintf("#### min %d x %d def %d x %d max %d x %d\n",
1573 // msg->MinMaxInfo->MinWidth,
1574 // msg->MinMaxInfo->MinHeight,
1575 // msg->MinMaxInfo->DefWidth,
1576 // msg->MinMaxInfo->DefHeight,
1577 // msg->MinMaxInfo->MaxWidth,
1578 // msg->MinMaxInfo->MaxHeight);
1583 if ((data
->rows
== 1) && (data
->columns
== 1))
1585 data
->num_visible_children
= Group_GetNumVisibleChildren(data
, lm
.lm_Children
);
1586 if (data
->flags
& GROUP_HORIZ
)
1587 group_minmax_horiz(cl
, obj
, lm
.lm_Children
, msg
);
1589 group_minmax_vert(cl
, obj
, lm
.lm_Children
, msg
);
1593 group_minmax_2d(cl
, obj
, lm
.lm_Children
, msg
);
1597 if (data
->flags
& GROUP_VIRTUAL
)
1599 data
->saved_minwidth
= msg
->MinMaxInfo
->MinWidth
;
1600 data
->saved_minheight
= msg
->MinMaxInfo
->MinHeight
;
1601 msg
->MinMaxInfo
->MinWidth
= super_minwidth
+ 2;
1602 msg
->MinMaxInfo
->MinHeight
= super_minheight
+ 2;
1604 //kprintf("## min %d x %d def %d x %d max %d x %d\n",
1605 // msg->MinMaxInfo->MinWidth,
1606 // msg->MinMaxInfo->MinHeight,
1607 // msg->MinMaxInfo->DefWidth,
1608 // msg->MinMaxInfo->DefHeight,
1609 // msg->MinMaxInfo->MaxWidth,
1610 // msg->MinMaxInfo->MaxHeight);
1618 // enforce minmax constraint, but also update total growable/shrinkable weights
1619 // while we're at it
1620 static void Layout1D_minmax_constraint (
1621 WORD
*sizep
, WORD minsize
, WORD maxsize
, WORD
*remainp
, WORD
*sizegrowp
,
1622 WORD
*sizeshrinkp
, ULONG
*weightgrowp
, ULONG
*weightshrinkp
, UWORD weight
,
1625 WORD size
= *sizep
, remain
= *remainp
,
1626 sizegrow
= *sizegrowp
, sizeshrink
= *sizeshrinkp
;
1627 ULONG weightgrow
= *weightgrowp
, weightshrink
= *weightshrinkp
;
1629 /* D(bug("L1D_minmax_c size=%d min=%d max=%d w=%d ss=%d\n", size, minsize, maxsize, */
1630 /* weight, samesize)); */
1632 if ((samesize
> 0) && (weight
== 0))
1634 remain
+= size
- samesize
;
1640 if (size
<= minsize
) // too little
1642 remain
+= size
- minsize
;
1645 if (size
== maxsize
)
1648 else if (size
>= maxsize
) // too big
1650 remain
+= size
- maxsize
;
1655 if (!((samesize
> 0) && (weight
== 0)))
1658 weightgrow
+= weight
;
1660 weightshrink
+= weight
;
1663 *sizep
= size
; *remainp
= remain
;
1664 *sizegrowp
= sizegrow
; *sizeshrinkp
= sizeshrink
;
1665 *weightgrowp
= weightgrow
; *weightshrinkp
= weightshrink
;
1669 // redistribute excess size to growable child, or reduce size of a shrinkable
1671 static void Layout1D_redistribution (
1672 WORD
*sizep
, WORD minsize
, WORD maxsize
, WORD
*remainp
, WORD
*sizegrowp
,
1673 WORD
*sizeshrinkp
, ULONG
*weightgrowp
, ULONG
*weightshrinkp
, UWORD weight
1676 WORD size
= *sizep
, remain
= *remainp
,
1677 sizegrow
= *sizegrowp
, sizeshrink
= *sizeshrinkp
;
1678 ULONG weightgrow
= *weightgrowp
, weightshrink
= *weightshrinkp
;
1683 if ((remain
> 0) && (size
< maxsize
))
1687 newsize
= (sizegrow
* weight
+ weightgrow
/ 2) / weightgrow
;
1689 /* D(bug("newsize=%ld == size_growa=%ld * w=%ld / weight_grow=%d\n", */
1690 /* newsize, sizegrow, weight, weightgrow)); */
1692 /* take care of off-by-1 errors that may toggle remainder sign
1693 * by ensuring convergence to 0
1695 if (remain
- newsize
+ size
< 0)
1697 /* D(bug("adding remainder=%d => size = %d\n", */
1698 /* remain, size + remain)); */
1704 remain
-= newsize
- size
;
1707 weightgrow
-= weight
;
1710 else if ((remain
< 0) && (size
> minsize
))
1714 newsize
= (sizeshrink
* weight
+ weightshrink
/ 2) / weightshrink
;
1716 /* D(bug("newsize=%ld == size_shrinkables=%ld * w=%ld / weight_shrinkables=%d\n", */
1717 /* newsize, sizeshrink, weight, weightshrink)); */
1719 if (remain
- newsize
+ size
> 0)
1721 /* D(bug("adding remainder=%d => size = %d\n", */
1722 /* remain, size + remain)); */
1728 remain
-= newsize
- size
;
1731 weightshrink
-= weight
;
1735 *sizep
= size
; *remainp
= remain
;
1736 *sizegrowp
= sizegrow
; *sizeshrinkp
= sizeshrink
;
1737 *weightgrowp
= weightgrow
; *weightshrinkp
= weightshrink
;
1741 // 2 passes at most, less on average (0.5 or 1.5), each does
1742 // - a minmax clamping, evenutally adding to a remainder
1743 // (remainder = missing (underflow) or remaining (overflow) space compared
1744 // to ideal sizes where childs fill the whole group)
1745 // - a redistribution of the remainder, by growing (pos. remainder) or
1746 // shrinking (neg. remainder) childs able to support it.
1748 // Occasionnaly the first time the redistribution is done, the minmax
1749 // constraint can be broken, thus the extra pass to check and eventually
1750 // redistribute. The second redistribution never breaks minmax constraint
1751 // (there should be a mathematical proof, but feel free to prove me wrong
1753 static void Layout1D_minmax_constraints_and_redistrib (
1754 struct MinList
*children
,
1765 for (i
= 0; i
< 2; i
++)
1767 WORD size_growables
= total_size
;
1768 WORD size_shrinkables
= total_size
;
1769 ULONG weight_growables
= 0;
1770 ULONG weight_shrinkables
= 0;
1772 /* D(bug("start : rem=%ld, A=%ld, size_growables=%ld, size_shrinkables=%ld\n", */
1773 /* remainder, total_size, size_growables, size_shrinkables)); */
1775 // minmax constraints
1776 cstate
= (Object
*)children
->mlh_Head
;
1777 while ((child
= NextObject(&cstate
)))
1781 if (IS_HIDDEN(child
))
1786 old_size
= _width(child
);
1788 Layout1D_minmax_constraint(
1789 &_width(child
), _minwidth(child
), _maxwidth(child
),
1791 &size_growables
, &size_shrinkables
,
1792 &weight_growables
, &weight_shrinkables
,
1793 _hweight(child
), samesize
);
1795 /* D(bug("loop1 on %p : width=%d was %d, rem=%d, A=%d, " */
1796 /* "sizegrow=%d, sizeshrink=%d w=%d min=%d max=%d\n", */
1797 /* child, _width(child), old_size, remainder, total_size, */
1798 /* size_growables, size_shrinkables, _hweight(child), */
1799 /* _minwidth(child), _maxwidth(child))); */
1801 else // ! group_horiz
1803 old_size
= _height(child
);
1805 Layout1D_minmax_constraint(
1806 &_height(child
), _minheight(child
), _maxheight(child
),
1808 &size_growables
, &size_shrinkables
,
1809 &weight_growables
, &weight_shrinkables
,
1810 _vweight(child
), samesize
);
1812 /* D(bug("loop1 on %p : h=%ld was %d, rem=%d, A=%d, " */
1813 /* "sizegrow=%d, sizeshrink=%d w=%d min=%d max=%d\n", */
1814 /* child, _height(child), old_size, remainder, total_size, */
1815 /* size_growables, size_shrinkables, _vweight(child), */
1816 /* _minheight(child), _maxheight(child))); */
1817 } // if (group_horiz)
1818 } // while child, minmax constraints
1824 /* D(bug("mid : rem=%d, A=%d, size_grow=%d, size_shrink=%d, " */
1825 /* "wg=%ld, ws=%ld\n", remainder, total_size, size_growables, */
1826 /* size_shrinkables, weight_growables, weight_shrinkables)); */
1828 // distribute remaining space to possible candidates
1829 cstate
= (Object
*)children
->mlh_Head
;
1830 while (((child
= NextObject(&cstate
)) != NULL
) && (remainder
!= 0))
1834 if (IS_HIDDEN(child
))
1839 old_size
= _width(child
);
1841 Layout1D_redistribution(
1842 &_width(child
), _minwidth(child
), _maxwidth(child
),
1844 &size_growables
, &size_shrinkables
,
1845 &weight_growables
, &weight_shrinkables
,
1848 /* D(bug("loop2 on %p : h=%d was %d, rem=%d, A=%d, " */
1849 /* "size_grow=%d, size_shrink=%d\n", child, */
1850 /* _width(child), old_size, remainder, total_size, */
1851 /* size_growables, size_shrinkables)); */
1853 else // ! group_horiz
1855 old_size
= _height(child
);
1857 Layout1D_redistribution(
1858 &_height(child
), _minheight(child
), _maxheight(child
),
1860 &size_growables
, &size_shrinkables
,
1861 &weight_growables
, &weight_shrinkables
,
1864 /* D(bug("loop2 on %p : h=%d was %d, rem=%d, A=%d, " */
1865 /* "size_grow=%d, size_shrink=%d\n", child, */
1866 /* _height(child), old_size, remainder, total_size, */
1867 /* size_growables, size_shrinkables)); */
1868 } // if (group_horiz)
1870 } // while child, redistribution
1872 /* if (remainder != 0) */
1874 /* D(bug("end : rem=%ld, A=%ld, size_grow=%ld, size_shrink=%ld\n", */
1875 /* remainder, total_size, size_growables, size_shrinkables)); */
1877 // dont break here if remainder == 0, some minmax constraints
1878 // may not be respected
1881 // to easily spot layout bugs, nothing like a (division by zero) exception
1882 /* if (remainder != 0) */
1884 /* ASSERT(remainder != 0); */
1885 /* D(bug("gonna crash, remainder = %d\n", remainder)); */
1886 /* remainder /= 0; */
1891 static void Layout1D_weight_constraint (
1893 WORD
*total_init_sizep
,
1894 ULONG
*total_weightp
,
1900 if (*total_weightp
> 0)
1901 *sizep
= (*total_sizep
* weight
+ *total_weightp
/ 2)
1906 *total_weightp
-= weight
;
1907 *total_sizep
-= *sizep
;
1908 *total_init_sizep
+= *sizep
;
1912 static void group_layout_vert(struct IClass
*cl
, Object
*obj
, struct MinList
*children
)
1914 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
1918 WORD remainder
; /* must converge to 0 to succesfully end layout */
1920 WORD total_size_backup
;
1921 WORD total_init_size
; /* total size of the ideally sized childs */
1928 //kprintf("group_layout_vert: virtoff = %d,%d\n", data->virt_offx, data->virt_offy);
1930 if (data
->flags
& GROUP_VIRTUAL
)
1932 data
->virt_mwidth
= CLAMP(_mwidth(obj
), data
->saved_minwidth
- _subwidth(obj
), _maxwidth(obj
) - _subwidth(obj
));
1933 data
->virt_mheight
= CLAMP(_mheight(obj
), data
->saved_minheight
- _subheight(obj
), _maxheight(obj
) - _subheight(obj
));
1935 layout_width
= data
->virt_mwidth
;
1936 layout_height
= data
->virt_mheight
;
1940 layout_width
= _mwidth(obj
);
1941 layout_height
= _mheight(obj
);
1944 total_weight
= data
->vert_weight_sum
;
1945 total_init_size
= 0;
1946 total_size
= layout_height
- (data
->num_visible_children
- 1) * data
->vert_spacing
;
1947 total_size_backup
= total_size
;
1949 /* D(bug("\nvert layout for %p, A=%d W=%ld\n", obj, total_size, total_weight)); */
1951 // weight constraints
1952 // calculate ideal size for each object, and total ideal size
1953 cstate
= (Object
*)children
->mlh_Head
;
1954 while ((child
= NextObject(&cstate
)))
1956 if (IS_HIDDEN(child
))
1959 Layout1D_weight_constraint(
1960 &total_size
, &total_init_size
, &total_weight
,
1961 &_height(child
), _vweight(child
), _minheight(child
));
1962 /* D(bug("child %p : ideal=%d w=%ld\n", */
1963 /* child, _height(child), _vweight(child))); */
1964 } // while child, weight constraints
1966 total_size
= total_size_backup
;
1967 remainder
= total_size
- total_init_size
;
1969 if (data
->flags
& GROUP_VIRTUAL
)
1971 /* This is also true for non virtual groups, but if this would be the case
1972 ** then there is a bug in the layout function
1974 if (total_size
< 0) total_size
= 0;
1977 Layout1D_minmax_constraints_and_redistrib (
1981 (data
->flags
& GROUP_SAME_HEIGHT
) ? data
->samesize_maxmin_vert
: 0,
1985 cstate
= (Object
*)children
->mlh_Head
;
1986 while ((child
= NextObject(&cstate
)))
1988 if (IS_HIDDEN(child
))
1991 width
= MIN(_maxwidth(child
), layout_width
);
1992 width
= MAX(width
, _minwidth(child
));
1993 left
= (layout_width
- width
) / 2;
1995 /* D(bug("child %p -> layout %d x %d\n", child, width, _height(child))); */
1996 if (!MUI_Layout(child
, left
, top
, width
, _height(child
), 0))
1998 top
+= data
->vert_spacing
+ _height(child
);
2004 static void group_layout_horiz(struct IClass
*cl
, Object
*obj
, struct MinList
*children
)
2006 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2010 WORD remainder
; /* must converge to 0 to succesfully end layout */
2012 WORD total_size_backup
;
2013 WORD total_init_size
; /* total size of the ideally sized childs */
2020 //kprintf("group_layout_horiz: virtoff = %d,%d\n", data->virt_offx, data->virt_offy);
2022 if (data
->flags
& GROUP_VIRTUAL
)
2024 data
->virt_mwidth
= CLAMP(_mwidth(obj
), data
->saved_minwidth
- _subwidth(obj
), _maxwidth(obj
) - _subwidth(obj
));
2025 data
->virt_mheight
= CLAMP(_mheight(obj
), data
->saved_minheight
- _subheight(obj
), _maxheight(obj
) - _subheight(obj
));
2027 layout_width
= data
->virt_mwidth
;
2028 layout_height
= data
->virt_mheight
;
2030 //kprintf("group_layout_horiz: layoutsize %d x %d virtsize %d x %d msize %d x %d\n",
2031 // layout_width, layout_height, data->virt_mwidth, data->virt_mheight,
2032 // _mwidth(obj), _mheight(obj));
2037 layout_width
= _mwidth(obj
);
2038 layout_height
= _mheight(obj
);
2041 total_weight
= data
->horiz_weight_sum
;
2042 total_init_size
= 0;
2043 total_size
= layout_width
- (data
->num_visible_children
- 1) * data
->horiz_spacing
;
2044 total_size_backup
= total_size
;
2046 /* D(bug("\nhoriz layout for %p, A=%d W=%ld\n", obj, total_size, total_weight)); */
2048 // weight constraints
2049 // calculate ideal size for each object, and total ideal size
2050 cstate
= (Object
*)children
->mlh_Head
;
2051 while ((child
= NextObject(&cstate
)))
2053 if (IS_HIDDEN(child
))
2056 Layout1D_weight_constraint(
2057 &total_size
, &total_init_size
, &total_weight
,
2058 &_width(child
), _hweight(child
), _minwidth(child
));
2059 /* D(bug("child %p : ideal=%d w=%ld\n", */
2060 /* child, _width(child), _hweight(child))); */
2061 } // while child, weight constraints
2063 total_size
= total_size_backup
;
2064 if (data
->horiz_weight_sum
> 0)
2065 remainder
= total_size
- total_init_size
;
2069 if (data
->flags
& GROUP_VIRTUAL
)
2071 /* This is also true for non virtual groups, but if this would be the case
2072 ** then there is a bug in the layout function
2074 if (total_size
< 0) total_size
= 0;
2077 Layout1D_minmax_constraints_and_redistrib (
2081 (data
->flags
& GROUP_SAME_WIDTH
) ? data
->samesize_maxmin_horiz
: 0,
2085 cstate
= (Object
*)children
->mlh_Head
;
2086 while ((child
= NextObject(&cstate
)))
2088 if (IS_HIDDEN(child
))
2091 height
= MIN(_maxheight(child
), layout_height
);
2092 height
= MAX(height
, _minheight(child
));
2093 top
= (layout_height
- height
) / 2;
2095 /* D(bug("child %p -> layout %d x %d\n", child, _width(child), height)); */
2096 if (!MUI_Layout(child
, left
, top
, _width(child
), height
, 0))
2098 left
+= data
->horiz_spacing
+ _width(child
);
2104 static void Layout2D_weight_constraint (
2105 struct MUI_GroupData
*data
,
2106 struct layout2d_elem
*row_infos
,
2107 struct layout2d_elem
*col_infos
,
2108 WORD total_size_height
, WORD total_size_width
,
2109 WORD
*total_init_height
, WORD
*total_init_width
)
2112 ULONG total_weight_vert
= data
->vert_weight_sum
;
2113 ULONG total_weight_horiz
= data
->horiz_weight_sum
;
2115 *total_init_height
= 0;
2116 *total_init_width
= 0;
2118 /* calc row heights */
2119 for (i
= 0; i
< data
->rows
; i
++)
2121 if (total_weight_vert
> 0)
2122 row_infos
[i
].dim
= (total_size_height
* row_infos
[i
].weight
+ total_weight_vert
/ 2)
2123 / total_weight_vert
;
2125 row_infos
[i
].dim
= row_infos
[i
].min
;
2127 /* D(bug("l2 row %d : ideal = %d with w=%d, A=%d, W=%d\n", i, row_infos[i].dim, */
2128 /* row_infos[i].weight, total_size_height, total_weight_vert)); */
2130 total_weight_vert
-= row_infos
[i
].weight
;
2131 total_size_height
-= row_infos
[i
].dim
;
2132 *total_init_height
+= row_infos
[i
].dim
;
2135 /* calc columns widths */
2136 for (i
= 0; i
< data
->columns
; i
++)
2138 if (total_weight_horiz
)
2139 col_infos
[i
].dim
= (total_size_width
* col_infos
[i
].weight
+ total_weight_horiz
/ 2 )
2140 / total_weight_horiz
;
2142 col_infos
[i
].dim
= col_infos
[i
].min
;
2144 /* D(bug("l2 col %d : ideal = %d with w=%d, A=%d, W=%d\n", i, col_infos[i].dim, */
2145 /* col_infos[i].weight, total_size_width, total_weight_horiz)); */
2147 total_weight_horiz
-= col_infos
[i
].weight
;
2148 total_size_width
-= col_infos
[i
].dim
;
2149 *total_init_width
+= col_infos
[i
].dim
;
2155 static void Layout2D_minmax_constraints_and_redistrib (
2156 struct layout2d_elem
*infos
,
2164 /* D(bug("L2D mc&r n=%d A=%d ss=%d rem=%d\n", nitems, total_size, samesize, remainder)); */
2166 for (j
= 0; j
< 2; j
++)
2168 WORD size_growables
= total_size
;
2169 WORD size_shrinkables
= total_size
;
2170 ULONG weight_growables
= 0;
2171 ULONG weight_shrinkables
= 0;
2175 // minmax constraints
2176 for (i
= 0; i
< nitems
; i
++)
2178 old_size
= infos
[i
].dim
;
2180 /* D(bug("bef loop1 on %d : size=%d, rem=%d, A=%d, " */
2181 /* "sizegrow=%d, sizeshrink=%d w=%d min=%d max=%d\n", */
2182 /* i, infos[i].dim, remainder, total_size, */
2183 /* size_growables, size_shrinkables, infos[i].weight, */
2184 /* infos[i].min, infos[i].max)); */
2186 Layout1D_minmax_constraint(
2187 &infos
[i
].dim
, infos
[i
].min
, infos
[i
].max
,
2189 &size_growables
, &size_shrinkables
,
2190 &weight_growables
, &weight_shrinkables
,
2195 /* D(bug("loop1 on %d : size=%d was %d, rem=%d, A=%d, " */
2196 /* "sizegrow=%d, sizeshrink=%d w=%d min=%d max=%d\n", */
2197 /* i, infos[i].dim, old_size, remainder, total_size, */
2198 /* size_growables, size_shrinkables, infos[i].weight, */
2199 /* infos[i].min, infos[i].max)); */
2205 for (i
= 0; i
< nitems
; i
++)
2207 old_size
= infos
[i
].dim
;
2209 /* D(bug("bef loop2 on %d : size=%d, rem=%d, A=%d, " */
2210 /* "size_grow=%d, size_shrink=%d\n", i, */
2211 /* infos[i].dim, remainder, total_size, */
2212 /* size_growables, size_shrinkables)); */
2214 Layout1D_redistribution(
2215 &infos
[i
].dim
, infos
[i
].min
, infos
[i
].max
,
2217 &size_growables
, &size_shrinkables
,
2218 &weight_growables
, &weight_shrinkables
,
2221 /* D(bug("loop2 on %d : size=%d was %d, rem=%d, A=%d, " */
2222 /* "size_grow=%d, size_shrink=%d\n", i, */
2223 /* infos[i].dim, old_size, remainder, total_size, */
2224 /* size_growables, size_shrinkables)); */
2230 layout_2d_distribute_space (struct MUI_GroupData
*data
,
2231 struct layout2d_elem
*row_infos
,
2232 struct layout2d_elem
*col_infos
,
2233 struct MinList
*children
,
2234 LONG left_start
, LONG top_start
)
2245 * pass 2 : distribute space
2247 cstate
= (Object
*)children
->mlh_Head
;
2250 for (i
= 0; i
< data
->rows
; i
++)
2252 /* left start for child layout in this row */
2255 /* max height for childs in this row */
2256 row_height
= row_infos
[i
].dim
;
2258 /* for each column */
2259 while ((child
= NextObject(&cstate
)))
2266 if (IS_HIDDEN(child
))
2268 /* max width for childs in this column */
2269 col_width
= col_infos
[j
].dim
;
2271 /* center child if col width is bigger than child maxwidth */
2272 cwidth
= MIN(_maxwidth(child
), col_width
);
2273 cwidth
= MAX(cwidth
, _minwidth(child
));
2274 cleft
= left
+ (col_width
- cwidth
) / 2;
2276 /* center child if row height is bigger than child maxheight */
2277 cheight
= MIN(_maxheight(child
), row_height
);
2278 cheight
= MAX(cheight
, _minheight(child
));
2279 ctop
= top
+ (row_height
- cheight
) / 2;
2281 /* g_print("layout %d %d %d %d\n", cleft, ctop, cwidth, cheight); */
2282 /* D(bug("2DL/child %p -> layout %d x %d\n", child, cwidth, cheight)); */
2283 if (!MUI_Layout(child
, cleft
, ctop
, cwidth
, cheight
, 0))
2286 left
+= data
->horiz_spacing
+ col_width
;
2289 if ((j
% data
->columns
) == 0)
2293 top
+= data
->vert_spacing
+ row_height
;
2300 * all childs in the same row have the same maximum height
2301 * all childs in the same column have the same maximum height
2302 * if a child maximum size is smaller than the biggest minimum size,
2303 * the chid will be centered in the remaining space.
2305 * for each row, determine its height allocation
2306 * weight ? the vertical weight of a row, if no fixed-height child
2307 * in the row, is the sum of all vertical weights of childs
2308 * all row members will have the same height
2310 * for each column, determine its width allocation
2311 * all column members will have the same width
2313 /* Write a proper hook function */
2315 group_layout_2d(struct IClass
*cl
, Object
*obj
, struct MinList
*children
)
2317 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2318 WORD left_start
= 0;
2320 WORD total_size_height
= _mheight(obj
) - (data
->rows
- 1) * data
->vert_spacing
;
2321 WORD total_size_width
= _mwidth(obj
) - (data
->columns
- 1) * data
->horiz_spacing
;
2322 WORD total_init_height
;
2323 WORD total_init_width
;
2324 WORD remainder_height
;
2325 WORD remainder_width
;
2329 if (data
->rows
== 0 || data
->columns
== 0)
2331 if (data
->num_childs
% data
->rows
|| data
->num_childs
% data
->columns
)
2333 if (data
->row_infos
== NULL
|| data
->col_infos
== NULL
)
2336 //kprintf("group_layout_horiz: virtoff = %d,%d\n", data->virt_offx, data->virt_offy);
2338 if (data
->flags
& GROUP_VIRTUAL
)
2340 data
->virt_mwidth
= CLAMP(_mwidth(obj
), data
->saved_minwidth
- _subwidth(obj
), _maxwidth(obj
) - _subwidth(obj
));
2341 data
->virt_mheight
= CLAMP(_mheight(obj
), data
->saved_minheight
- _subheight(obj
), _maxheight(obj
) - _subheight(obj
));
2343 layout_width
= data
->virt_mwidth
;
2344 layout_height
= data
->virt_mheight
;
2348 layout_width
= _mwidth(obj
);
2349 layout_height
= _mheight(obj
);
2352 total_size_height
= layout_height
- (data
->rows
- 1) * data
->vert_spacing
;
2353 total_size_width
= layout_width
- (data
->columns
- 1) * data
->horiz_spacing
;
2357 // weight constraints
2358 Layout2D_weight_constraint (
2359 data
, data
->row_infos
, data
->col_infos
,
2360 total_size_height
, total_size_width
,
2361 &total_init_height
, &total_init_width
);
2363 remainder_height
= total_size_height
- total_init_height
;
2364 remainder_width
= total_size_width
- total_init_width
;
2366 Layout2D_minmax_constraints_and_redistrib(
2370 /* (data->flags & GROUP_SAME_HEIGHT) ? data->samesize_maxmin_vert : 0, */
2374 Layout2D_minmax_constraints_and_redistrib(
2378 /* (data->flags & GROUP_SAME_WIDTH) ? data->samesize_maxmin_horiz : 0, */
2382 layout_2d_distribute_space (data
, data
->row_infos
, data
->col_infos
,
2383 children
, left_start
, top_start
);
2387 /* Write a proper hook function */
2388 static void group_layout_pagemode (struct IClass
*cl
, Object
*obj
, struct MinList
*children
)
2390 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2397 if (data
->flags
& GROUP_VIRTUAL
)
2399 data
->virt_mwidth
= CLAMP(_mwidth(obj
), data
->saved_minwidth
- _subwidth(obj
), _maxwidth(obj
) - _subwidth(obj
));
2400 data
->virt_mheight
= CLAMP(_mheight(obj
), data
->saved_minheight
- _subheight(obj
), _maxheight(obj
) - _subheight(obj
));
2402 layout_width
= data
->virt_mwidth
;
2403 layout_height
= data
->virt_mheight
;
2407 layout_width
= _mwidth(obj
);
2408 layout_height
= _mheight(obj
);
2411 cstate
= (Object
*)children
->mlh_Head
;
2412 while ((child
= NextObject(&cstate
)))
2414 w
= MIN(layout_width
, _maxwidth(child
));
2415 h
= MIN(layout_height
, _maxheight(child
));
2417 /* D(bug("PM/child %p -> layout %d x %d\n", child, w, h)); */
2418 MUI_Layout(child
, (layout_width
- w
) / 2, (layout_height
- h
) / 2,
2424 /**************************************************************************
2426 Either use a given layout hook, or the builtin method.
2427 **************************************************************************/
2428 IPTR
Group__MUIM_Layout(struct IClass
*cl
, Object
*obj
, struct MUIP_Layout
*msg
)
2430 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2431 struct MUI_LayoutMsg lm
;
2433 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(lm
.lm_Children
));
2434 if (data
->flags
& GROUP_PAGEMODE
)
2436 group_layout_pagemode(cl
, obj
, lm
.lm_Children
);
2438 else if (data
->layout_hook
)
2440 lm
.lm_Type
= MUILM_LAYOUT
;
2441 lm
.lm_Layout
.Width
= _mwidth(obj
);
2442 lm
.lm_Layout
.Height
= _mheight(obj
);
2444 CallHookPkt(data
->layout_hook
, obj
, &lm
);
2446 if (data
->flags
& GROUP_VIRTUAL
)
2448 data
->virt_mwidth
= lm
.lm_Layout
.Width
;
2449 data
->virt_mheight
= lm
.lm_Layout
.Height
;
2454 if ((data
->rows
== 1) && (data
->columns
== 1))
2456 if (data
->flags
& GROUP_HORIZ
)
2457 group_layout_horiz(cl
, obj
, lm
.lm_Children
);
2459 group_layout_vert(cl
, obj
, lm
.lm_Children
);
2462 group_layout_2d(cl
, obj
, lm
.lm_Children
);
2465 if (data
->flags
& GROUP_VIRTUAL
)
2467 WORD new_virt_offx
, new_virt_offy
;
2469 new_virt_offx
= data
->virt_offx
;
2470 new_virt_offy
= data
->virt_offy
;
2472 if (new_virt_offx
+ _mwidth(obj
) > data
->virt_mwidth
)
2474 new_virt_offx
= data
->virt_mwidth
- _mwidth(obj
);
2476 if (new_virt_offx
< 0) new_virt_offx
= 0;
2478 if (new_virt_offy
+ _mheight(obj
) > data
->virt_mheight
)
2480 new_virt_offy
= data
->virt_mheight
- _mheight(obj
);
2482 if (new_virt_offy
< 0) new_virt_offy
= 0;
2484 if (new_virt_offx
!= data
->virt_offx
)
2486 nfset(obj
, MUIA_Virtgroup_Left
, new_virt_offx
);
2489 if (new_virt_offy
!= data
->virt_offy
)
2491 nfset(obj
, MUIA_Virtgroup_Top
, new_virt_offy
);
2499 /**************************************************************************
2501 **************************************************************************/
2502 IPTR
Group__MUIM_Show(struct IClass
*cl
, Object
*obj
, struct MUIP_Show
*msg
)
2504 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2507 struct MinList
*ChildList
;
2509 /* If msg is NULL, we won't want that the super method actually gets this call */
2510 if (msg
) DoSuperMethodA(cl
,obj
,(Msg
)msg
);
2512 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2513 cstate
= (Object
*)ChildList
->mlh_Head
;
2515 if (data
->flags
& GROUP_PAGEMODE
)
2518 while ((child
= NextObject(&cstate
)))
2520 if (page
== data
->active_page
)
2522 DoShowMethod(child
);
2529 while ((child
= NextObject(&cstate
)))
2531 if (!(data
->flags
& GROUP_VIRTUAL
) ||
2532 IsObjectVisible(child
,MUIMasterBase
))
2534 if (_flags(child
) & MADF_SHOWME
)
2535 DoShowMethod(child
);
2542 /**************************************************************************
2544 **************************************************************************/
2545 IPTR
Group__MUIM_Hide(struct IClass
*cl
, Object
*obj
, struct MUIP_Hide
*msg
)
2547 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2550 struct MinList
*ChildList
;
2552 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2553 cstate
= (Object
*)ChildList
->mlh_Head
;
2555 if (data
->flags
& GROUP_PAGEMODE
)
2558 while ((child
= NextObject(&cstate
)))
2560 if (page
== data
->active_page
)
2562 DoHideMethod(child
);
2569 while ((child
= NextObject(&cstate
)))
2571 if (_flags(child
) & MADF_CANDRAW
)
2572 DoHideMethod(child
);
2576 /* If msg is NULL, we won't want that the super method actually gets this call */
2577 if (msg
) return DoSuperMethodA(cl
,obj
,(Msg
)msg
);
2582 * MUIM_FindUData : tests if the MUIA_UserData of the object
2583 * contains the given <udata> and returns the object pointer in this case.
2585 IPTR
Group__MUIM_FindUData(struct IClass
*cl
, Object
*obj
, struct MUIP_FindUData
*msg
)
2587 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2589 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
2592 return DoMethodA(data
->family
, (Msg
)msg
);
2597 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
2598 * contains the given <udata> and gets <attr> to <storage> for itself
2601 IPTR
Group__MUIM_GetUData(struct IClass
*cl
, Object
*obj
, struct MUIP_GetUData
*msg
)
2603 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2605 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
2607 get(obj
, msg
->attr
, msg
->storage
);
2611 return DoMethodA(data
->family
, (Msg
)msg
);
2616 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
2617 * contains the given <udata> and sets <attr> to <val> for itself in this case.
2619 IPTR
Group__MUIM_SetUData(struct IClass
*cl
, Object
*obj
, struct MUIP_SetUData
*msg
)
2621 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2623 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
2624 set(obj
, msg
->attr
, msg
->val
);
2626 DoMethodA(data
->family
, (Msg
)msg
);
2632 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
2633 * contains the given <udata> and sets <attr> to <val> for itself in this case.
2634 * Stop after the first udata found.
2636 IPTR
Group__MUIM_SetUDataOnce(struct IClass
*cl
, Object
*obj
, struct MUIP_SetUData
*msg
)
2638 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2640 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
2642 set(obj
, msg
->attr
, msg
->val
);
2645 return DoMethodA(data
->family
, (Msg
)msg
);
2648 /**************************************************************************
2649 MUIM_DragQueryExtented
2650 **************************************************************************/
2651 IPTR
Group__MUIM_DragQueryExtended(struct IClass
*cl
, Object
*obj
, struct MUIP_DragQueryExtended
*msg
)
2653 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2657 struct MinList
*ChildList
;
2659 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2660 cstate
= (Object
*)ChildList
->mlh_Head
;
2661 while ((child
= NextObject(&cstate
)))
2663 if (! (_flags(child
) & MADF_CANDRAW
))
2666 if ((found_obj
= (Object
*)DoMethodA(child
, (Msg
)msg
)))
2667 return (IPTR
)found_obj
;
2669 return DoSuperMethodA(cl
,obj
,(Msg
)msg
);
2672 /**************************************************************************
2674 **************************************************************************/
2675 IPTR
Group__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
2677 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2679 /* check this, otherwise a superclass who has IDCMP_MOUSEBUTTONS
2680 eventhandler might call DoSuperMethod, and this function gets
2681 called even when he have not added any eventhandler */
2683 if ((data
->flags
& GROUP_VIRTUAL
) && msg
->imsg
)
2685 switch (msg
->imsg
->Class
)
2687 case IDCMP_MOUSEBUTTONS
:
2688 /* For virtual groups */
2689 if (msg
->imsg
->Code
== SELECTDOWN
)
2691 if (_between(_mleft(obj
),msg
->imsg
->MouseX
,_mright(obj
)) && _between(_mtop(obj
),msg
->imsg
->MouseY
,_mbottom(obj
)))
2693 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
2694 data
->ehn
.ehn_Events
|= IDCMP_INTUITICKS
;
2695 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
2699 if (data
->ehn
.ehn_Events
& IDCMP_INTUITICKS
)
2701 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
2702 data
->ehn
.ehn_Events
&= ~IDCMP_INTUITICKS
;
2703 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
2708 case IDCMP_INTUITICKS
:
2709 if (!(data
->ehn
.ehn_Events
& IDCMP_INTUITICKS
)) break;
2711 if (!(_between(_mleft(obj
),msg
->imsg
->MouseX
,_mright(obj
)) && _between(_mtop(obj
),msg
->imsg
->MouseY
,_mbottom(obj
))))
2713 LONG new_virt_offx
= data
->virt_offx
;
2714 LONG new_virt_offy
= data
->virt_offy
;
2716 if (msg
->imsg
->MouseX
< _mleft(obj
))
2719 if (new_virt_offx
>= 4) new_virt_offx
-= 4;
2720 else new_virt_offx
= 0;
2722 else if (msg
->imsg
->MouseX
> _mright(obj
))
2726 if (new_virt_offx
> data
->virt_mwidth
- _mwidth(obj
)) new_virt_offx
= data
->virt_mwidth
- _mwidth(obj
);
2727 if (new_virt_offx
< 0) new_virt_offx
= 0;
2730 if (msg
->imsg
->MouseY
< _mtop(obj
))
2733 if (new_virt_offy
>= 4) new_virt_offy
-= 4;
2734 else new_virt_offy
= 0;
2736 else if (msg
->imsg
->MouseY
> _mbottom(obj
))
2740 if (new_virt_offy
> data
->virt_mheight
- _mheight(obj
)) new_virt_offy
= data
->virt_mheight
- _mheight(obj
);
2741 if (new_virt_offy
< 0) new_virt_offy
= 0;
2744 if (new_virt_offx
!= data
->virt_offx
|| new_virt_offy
!= data
->virt_offy
)
2747 MUIA_Virtgroup_Left
, new_virt_offx
,
2748 MUIA_Virtgroup_Top
, new_virt_offy
,
2749 MUIA_Group_Forward
, FALSE
,
2760 /**************************************************************************
2762 **************************************************************************/
2763 IPTR
Group__MUIM_DrawBackground(struct IClass
*cl
, Object
*obj
, struct MUIP_DrawBackground
*msg
)
2765 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2767 if (data
->flags
& GROUP_VIRTUAL
)
2769 struct MUIP_DrawBackground msg2
= *msg
;
2771 msg2
.xoffset
+= data
->virt_offx
;
2772 msg2
.yoffset
+= data
->virt_offy
;
2774 return DoSuperMethodA(cl
, obj
, (Msg
)&msg2
);
2777 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
2780 /**************************************************************************
2782 Find the given object or return NULL
2783 **************************************************************************/
2784 IPTR
Group__MUIM_FindAreaObject(struct IClass
*cl
, Object
*obj
,
2785 struct MUIP_FindAreaObject
*msg
)
2787 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2790 struct MinList
*ChildList
;
2793 if (msg
->obj
== obj
)
2796 // it's one of my childs ?
2797 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2798 cstate
= (Object
*)ChildList
->mlh_Head
;
2799 while ((child
= NextObject(&cstate
)))
2801 if (msg
->obj
== child
)
2805 // let the childs find it
2806 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2807 cstate
= (Object
*)ChildList
->mlh_Head
;
2808 while ((child
= NextObject(&cstate
)))
2810 Object
*res
= (Object
*)DoMethodA(child
, (Msg
)msg
);
2818 /**************************************************************************
2819 MUIM_Notify - disabled now because previous Zune versions had a OM_GET
2820 check in MUIM_Notify which is no longer the case
2821 **************************************************************************/
2823 STATIC IPTR
Group_Notify(struct IClass
*cl
, Object
*obj
, struct MUIP_Notify
*msg
)
2825 struct MUI_GroupData
*data
= INST_DATA(cl
, obj
);
2828 struct MinList
*ChildList
;
2830 /* Try at first if understand the message our self
2831 ** We disable the forwarding of the OM_GET message
2832 ** as the MUIM_Notify otherwise would "think" that
2833 ** the group class actually understands the attribute
2834 ** although a child does this only
2836 data
->dont_forward_get
= 1;
2837 if (DoSuperMethodA(cl
,obj
,(Msg
)msg
))
2839 data
->dont_forward_get
= 0;
2843 /* We ourself didn't understand the notify tag so we try the children now */
2844 data
->dont_forward_get
= 0;
2846 get(data
->family
, MUIA_Family_List
, (IPTR
*)&(ChildList
));
2847 cstate
= (Object
*)ChildList
->mlh_Head
;
2848 while ((child
= NextObject(&cstate
)))
2850 if (DoMethodA(child
, (Msg
)msg
)) return 1;
2856 BOOPSI_DISPATCHER(IPTR
, Group_Dispatcher
, cl
, obj
, msg
)
2858 switch (msg
->MethodID
)
2860 case OM_NEW
: return Group__OM_NEW(cl
, obj
, (struct opSet
*) msg
);
2861 case OM_DISPOSE
: return Group__OM_DISPOSE(cl
, obj
, msg
);
2862 case OM_SET
: return Group__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2863 case OM_GET
: return Group__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2864 case OM_ADDMEMBER
: return Group__OM_ADDMEMBER(cl
, obj
, (APTR
)msg
);
2865 case OM_REMMEMBER
: return Group__OM_REMMEMBER(cl
, obj
, (APTR
)msg
);
2866 case MUIM_AskMinMax
: return Group__MUIM_AskMinMax(cl
, obj
, (APTR
)msg
);
2867 case MUIM_Group_ExitChange
: return Group__MUIM_ExitChange(cl
, obj
, (APTR
)msg
);
2868 case MUIM_Group_InitChange
: return Group__MUIM_InitChange(cl
, obj
, (APTR
)msg
);
2869 case MUIM_Group_Sort
: return Group__MUIM_Sort(cl
, obj
, (APTR
)msg
);
2870 case MUIM_Group_DoMethodNoForward
: return Group__MUIM_DoMethodNoForward(cl
, obj
, (APTR
)msg
);
2871 case MUIM_ConnectParent
: return Group__MUIM_ConnectParent(cl
, obj
, (APTR
)msg
);
2872 case MUIM_DisconnectParent
: return Group__MUIM_DisconnectParent(cl
, obj
, (APTR
)msg
);
2873 case MUIM_Layout
: return Group__MUIM_Layout(cl
, obj
, (APTR
)msg
);
2874 case MUIM_Setup
: return Group__MUIM_Setup(cl
, obj
, (APTR
)msg
);
2875 case MUIM_Cleanup
: return Group__MUIM_Cleanup(cl
, obj
, (APTR
)msg
);
2876 case MUIM_Draw
: return Group__MUIM_Draw(cl
, obj
, (APTR
)msg
);
2878 case MUIM_FindUData
: return Group__MUIM_FindUData(cl
, obj
, (APTR
)msg
);
2879 case MUIM_GetUData
: return Group__MUIM_GetUData(cl
, obj
, (APTR
)msg
);
2880 case MUIM_SetUData
: return Group__MUIM_SetUData(cl
, obj
, (APTR
)msg
);
2881 case MUIM_SetUDataOnce
: return Group__MUIM_SetUDataOnce(cl
, obj
, (APTR
)msg
);
2882 case MUIM_Show
: return Group__MUIM_Show(cl
, obj
, (APTR
)msg
);
2883 case MUIM_Hide
: return Group__MUIM_Hide(cl
, obj
, (APTR
)msg
);
2884 case MUIM_HandleEvent
: return Group__MUIM_HandleEvent(cl
,obj
, (APTR
)msg
);
2885 case MUIM_DrawBackground
: return Group__MUIM_DrawBackground(cl
, obj
, (APTR
)msg
);
2886 case MUIM_DragQueryExtended
:return Group__MUIM_DragQueryExtended(cl
, obj
, (APTR
)msg
);
2887 case MUIM_FindAreaObject
: return Group__MUIM_FindAreaObject(cl
, obj
, (APTR
)msg
);
2890 /* Disabled. See above */
2891 case MUIM_Notify
: return Group_Notify(cl
, obj
, (APTR
)msg
);
2896 case MUIM_DrawParentBackground
:
2897 case MUIM_DragBegin
:
2899 case MUIM_DragQuery
:
2900 case MUIM_DragFinish
:
2902 case MUIM_CreateDragImage
:
2903 case MUIM_DeleteDragImage
:
2905 case MUIM_GoInactive
:
2906 case MUIM_CreateBubble
:
2907 case MUIM_DeleteBubble
:
2908 case MUIM_CreateShortHelp
:
2909 case MUIM_DeleteShortHelp
:
2912 return DoSuperMethodA(cl
, obj
, (APTR
)msg
); /* Needs not to be forwarded? */
2915 /* sometimes you want to call a superclass method,
2916 * but not dispatching to child.
2917 * But what to do with list methods in a listview ?
2919 Group_DispatchMsg(cl
, obj
, (APTR
)msg
);
2921 return DoSuperMethodA(cl
, obj
, msg
);
2923 BOOPSI_DISPATCHER_END
2929 const struct __MUIBuiltinClass _MUI_Group_desc
= {
2932 sizeof(struct MUI_GroupData
),
2933 (void*)Group_Dispatcher