7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
14 * Revision 42.4 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.3 2000/08/10 17:52:47 stegerg
18 * temp fix for relayout refresh bug which only happens in AROS. temp. solved
19 * by doing a RefreshGList in windowclass.c/WindowClassRelease method.
21 * Revision 42.2 2000/05/15 19:27:01 stegerg
22 * another hundreds of REG() macro replacements in func headers/protos.
24 * Revision 42.1 2000/05/14 23:32:47 stegerg
25 * changed over 200 function headers which all use register
26 * parameters (oh boy ...), because the simple REG() macro
27 * doesn't work with AROS. And there are still hundreds
28 * of headers left to be fixed :(
30 * Many of these functions would also work with stack
31 * params, but since i have fixed every single one
32 * I encountered up to now, I guess will have to do
33 * the same for the rest.
35 * Revision 42.0 2000/05/09 22:09:07 mlemos
36 * Bumped to revision 42.0 before handing BGUI to AROS team
38 * Revision 41.11 2000/05/09 19:54:22 mlemos
39 * Merged with the branch Manuel_Lemos_fixes.
41 * Revision 41.10.2.11 1999/08/30 04:57:41 mlemos
42 * Made the methods that change group members on-fly setup the gadget
43 * attributes using the window WINDOW_SETUPGADGET method.
45 * Revision 41.10.2.10 1999/08/29 20:21:59 mlemos
46 * Renamed the GRM_RELAYOUT to BASE_RELAYOUT.
48 * Revision 41.10.2.9 1999/08/29 18:58:51 mlemos
49 * Added support to the LGO_Relayout attribute to be able to not relayout a
50 * when calling GRM_ADDMEMBER, GRM_INSERTMEMBER, GRM_REPLACEMEMBER.
52 * Revision 41.10.2.8 1998/10/14 04:07:55 mlemos
53 * Fixed the computation of group members minimum, maximum and nominam sizes.
55 * Revision 41.10.2.7 1998/07/05 19:19:26 mlemos
56 * Fixed bug of Group node instance data pointer be passed instead of the
59 * Revision 41.10.2.6 1998/03/02 01:31:21 mlemos
60 * Fixed members list memory leak when group has no members.
61 * Added functions to obtain and release the members list.
63 * Revision 41.10.2.5 1998/03/02 00:22:18 mlemos
64 * Fixed extention determination when a group is empty.
66 * Revision 41.10.2.4 1998/03/01 17:36:48 mlemos
67 * Fixed memory leaks from group member list allocations.
68 * Prevented nest calls to retrieve copies of the group members list.
70 * Revision 41.10.2.3 1998/02/28 02:44:06 mlemos
71 * Made GRM_DIMENSIONS method obtain the group members list.
73 * Revision 41.10.2.2 1998/02/26 22:37:53 mlemos
74 * Commented out unused variables.
75 * Added casts to GadgetInfo structure where BaseInfo is passed.
76 * Fixed Group Node Class RM_REMOVE call.
78 * Revision 41.10.2.1 1998/02/26 17:45:40 mlemos
79 * Added support for getting a group node object
81 * Revision 41.10 1998/02/25 21:12:11 mlemos
84 * Revision 1.1 1998/02/25 17:08:29 mlemos
92 #include "include/classdefs.h"
94 /// Class definitions.
99 Object
*md_Object
; /* The object itself. */
100 struct IBox md_Bounds
; /* Bounds relative to group. */
101 ULONG md_Weight
; /* The object weight. */
102 WORD md_FixedWidth
; /* Fixed width. */
103 WORD md_FixedHeight
; /* Fixed height. */
104 UWORD md_AspectX
, md_AspectY
; /* Fixed Aspect ratio. */
105 UWORD md_MinWidth
, md_MinHeight
; /* Minimum width and height. */
106 UWORD md_MaxWidth
, md_MaxHeight
; /* Maximum width and height. */
107 UWORD md_NomWidth
, md_NomHeight
; /* Nominal width and height. */
108 UWORD md_HBLeft
; /* Hit-box leftedge. */
109 UWORD md_ScaledSize
; /* Scaled size. */
110 UWORD md_Flags
; /* See below. */
111 UBYTE md_HAlign
, md_VAlign
; /* Alignment. */
112 Object
*md_Group
; /* The group we are in. */
115 #define MDF_FIXEDWIDTH (1<<0) /* Fix width. */
116 #define MDF_FIXEDHEIGHT (1<<1) /* Fix height. */
117 #define MDF_SPACING (1<<2) /* This is a spacing object. */
118 #define MDF_NO_ALIGN (1<<3) /* Object must not be aligned. */
119 #define MDF_RESERVED (1<<4) /* Reserved bit. */
120 #define MDF_NO_NO_ALIGN (1<<5) /* Force alignment. */
121 #define MDF_HIDDEN (1<<6) /* Member hidden? */
124 /// SetGroupNodeAttrs
126 METHOD(SetGroupNodeAttrs
, struct opSet
*, ops
)
128 MD
*md
= INST_DATA(cl
, obj
);
129 struct TagItem
*tstate
= ops
->ops_AttrList
, *tag
;
131 BOOL relayout
= FALSE
;
134 * Scan LGO attributes.
136 while (tag
= NextTagItem(&tstate
))
142 md
->md_Bounds
.Left
= data
;
146 md
->md_Bounds
.Top
= data
;
150 md
->md_Bounds
.Width
= data
;
154 md
->md_Bounds
.Height
= data
;
158 md
->md_Object
= (Object
*)data
;
162 md
->md_Group
= (Object
*)data
;
165 case LGO_SpaceObject
:
166 md
->md_Object
= BGUI_NewObjectA(BGUI_SPACING_OBJECT
, NULL
);
167 md
->md_Weight
= data
;
168 md
->md_Flags
|= MDF_SPACING
;
172 if (data
< 1) data
= 1;
173 if (md
->md_Weight
!= data
)
175 md
->md_Weight
= data
;
181 md
->md_FixedWidth
= (WORD
)data
;
185 md
->md_FixedHeight
= (WORD
)data
;
188 case LGO_FixMinWidth
:
189 md
->md_FixedWidth
= data
? 0 : -1;
192 case LGO_FixMinHeight
:
193 md
->md_FixedHeight
= data
? 0 : -1;
198 md
->md_Flags
|= MDF_NO_NO_ALIGN
;
203 md
->md_Flags
|= MDF_NO_ALIGN
;
207 if (*(ULONG
*)&md
->md_AspectX
!= data
)
209 *(ULONG
*)&md
->md_AspectX
= data
;
217 if (md
->md_Flags
& MDF_HIDDEN
)
219 md
->md_Flags
&= ~MDF_HIDDEN
;
225 if (!(md
->md_Flags
& MDF_HIDDEN
))
227 md
->md_Flags
|= MDF_HIDDEN
;
234 if (relayout
&& md
->md_Group
) RelayoutGroup(md
->md_Group
);
243 * Create a shiny new object.
245 METHOD(GroupNodeClassNew
, struct opSet
*, ops
)
251 * First we let the superclass
254 if (rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)ops
))
256 md
= INST_DATA(cl
, rc
);
257 md
->md_Weight
= DEFAULT_WEIGHT
;
258 md
->md_FixedWidth
= -1;
259 md
->md_FixedHeight
= -1;
262 * Setup user attributes.
264 SetGroupNodeAttrs(cl
, (Object
*)rc
, ops
);
266 if (md
->md_Object
&& md
->md_Group
)
268 DoSetMethodNG(md
->md_Object
, BT_GroupMember
, rc
,
269 BT_ParentGroup
, md
->md_Group
,
270 BT_ParentWindow
, BASE_DATA(md
->md_Group
)->bc_Window
,
276 AsmCoerceMethod(cl
, (Object
*)rc
, OM_DISPOSE
);
284 * Change one or more of the object
287 METHOD(GroupNodeClassSet
, struct opSet
*, ops
)
289 AsmDoSuperMethodA(cl
, obj
, (Msg
)ops
);
291 return SetGroupNodeAttrs(cl
, obj
, ops
);
297 * Give one of the attributes.
299 METHOD(GroupNodeClassGet
, struct opGet
*, opg
)
301 MD
*md
= INST_DATA(cl
, obj
);
302 ULONG rc
= 1, *store
= opg
->opg_Storage
;
304 switch (opg
->opg_AttrID
)
307 STORE md
->md_MinWidth
;
310 STORE md
->md_MinHeight
;
313 STORE md
->md_MaxWidth
;
316 STORE md
->md_MaxHeight
;
319 STORE md
->md_NomWidth
;
322 STORE md
->md_NomHeight
;
328 rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)opg
);
339 METHOD(GroupNodeClassRemove
, Msg
, msg
)
341 MD
*md
= INST_DATA(cl
, obj
);
344 DoSetMethodNG(md
->md_Object
, BT_ParentWindow
, NULL
, BT_ParentGroup
, NULL
, BT_GroupMember
, NULL
, TAG_DONE
);
346 return AsmDoSuperMethodA(cl
, obj
, msg
);
351 /// Class initialization.
355 STATIC DPFUNC ClassFuncNode
[] = {
356 OM_NEW
, (FUNCPTR
)GroupNodeClassNew
,
357 OM_SET
, (FUNCPTR
)GroupNodeClassSet
,
358 OM_GET
, (FUNCPTR
)GroupNodeClassGet
,
359 RM_REMOVE
, (FUNCPTR
)GroupNodeClassRemove
,
363 static Class
*GMClass
= NULL
;
364 #define MEMBER_DATA(m) ((MD *)INST_DATA(GMClass, ((Object *)m)))
367 * Simple class initialization.
369 makeproto Class
*InitGroupNodeClass(void)
371 return GMClass
= BGUI_MakeClass(CLASS_SuperClassBGUI
, BGUI_ROOT_OBJECT
,
372 CLASS_ObjectSize
, sizeof(MD
),
373 CLASS_DFTable
, ClassFuncNode
,
379 /// Class definitions.
392 * Object instance data.
395 struct SignalSemaphore gd_Lock
; /* Semaphore for safety purposes. */
396 Object
**gd_MD
; /* Array of object pointers. */
397 struct MinList gd_Members
; /* Group members. */
398 UWORD gd_NumMembers
; /* Number of members. */
399 UWORD gd_Rows
; /* Rows in HGroup. */
400 UWORD gd_Columns
; /* Columns in VGroup. */
401 UBYTE gd_HAlign
; /* Horizontal alignment. */
402 UBYTE gd_VAlign
; /* Vertical alignment. */
403 UWORD gd_SpaceX
; /* Inner-object spacing. */
404 UWORD gd_SpaceY
; /* Inner-object spacing. */
405 TD
*gd_RD
, *gd_CD
; /* Row and column descriptors. */
406 Object
*gd_Active
; /* Active member. */
407 UBYTE gd_Flags
; /* See below. */
408 UBYTE gd_Style
; /* Style. */
411 #define GDF_ADD_FAILURE (1<<0) /* Error flag. */
412 #define GDF_HAS_TITLE (1<<1) /* Group is framed with a title. */
413 #define GDF_IS_MASTER (1<<2) /* This is the master group. */
414 #define GDF_EQUAL_MINWIDTH (1<<3) /* All objects have the same min width. */
415 #define GDF_EQUAL_MINHEIGHT (1<<4) /* All objects have the same min height.*/
416 #define GDF_BUFFER (1<<5) /* Buffer rendering. */
421 //static ASM MD *NextGroupNode(REG(a0) GD *gd, REG(a1) Object **node, REG(d0) ULONG flags)
422 static ASM
REGFUNC3(MD
*, NextGroupNode
,
423 REGPARAM(A0
, GD
*, gd
),
424 REGPARAM(A1
, Object
**, node
),
425 REGPARAM(D0
, ULONG
, flags
))
432 if (*node
) next
= (Object
*)AsmDoMethod(*node
, RM_NEXT
);
433 else next
= ListHeadObject((struct List
*)&gd
->gd_Members
);
435 if (!(*node
= next
)) return NULL
;
437 md
= MEMBER_DATA(next
);
439 } while (md
->md_Flags
& flags
);
447 //STATIC ASM Object *GroupNode(REG(a0) GD *gd, REG(d0) int i, REG(d1) int j)
448 STATIC ASM
REGFUNC3(Object
*, GroupNode
,
449 REGPARAM(A0
, GD
*, gd
),
450 REGPARAM(D0
, int, i
),
451 REGPARAM(D1
, int, j
))
453 switch (gd
->gd_Style
)
455 case GRSTYLE_HORIZONTAL
:
456 j
= (i
* gd
->gd_Columns
) + j
;
458 case GRSTYLE_VERTICAL
:
459 j
= (j
* gd
->gd_Rows
) + i
;
465 if (j
< gd
->gd_NumMembers
) return gd
->gd_MD
[j
];
473 static UWORD
VSpace(UWORD space
)
477 case (UWORD
)GRSPACE_NARROW
:
478 return (UWORD
)GetTagData(GROUP_DefVSpaceNarrow
, 2, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
479 case (UWORD
)GRSPACE_NORMAL
:
480 return (UWORD
)GetTagData(GROUP_DefVSpaceNormal
, 4, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
481 case (UWORD
)GRSPACE_WIDE
:
482 return (UWORD
)GetTagData(GROUP_DefVSpaceWide
, 8, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
486 static UWORD
HSpace(UWORD space
)
490 case (UWORD
)GRSPACE_NARROW
:
491 return (UWORD
)GetTagData(GROUP_DefHSpaceNarrow
, 2, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
492 case (UWORD
)GRSPACE_NORMAL
:
493 return (UWORD
)GetTagData(GROUP_DefHSpaceNormal
, 4, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
494 case (UWORD
)GRSPACE_WIDE
:
495 return (UWORD
)GetTagData(GROUP_DefHSpaceWide
, 8, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
502 //STATIC ASM Object *FindObNode(REG(a0) GD *gd, REG(a1) Object *find)
503 STATIC ASM
REGFUNC2(Object
*, FindObNode
,
504 REGPARAM(A0
, GD
*, gd
),
505 REGPARAM(A1
, Object
*, find
))
513 * Try to locate the object.
515 while (md
= NextGroupNode(gd
, &m
, 0))
520 if (md
->md_Object
== find
) return m
;
530 METHOD(GroupClassNewMember
, struct opSet
*, ops
)
532 return (ULONG
)BGUI_NewObjectA(BGUI_GROUP_NODE
, ops
->ops_AttrList
);
538 * Allocate and initialize a member structure.
540 STATIC Object
*NewGroupMember(Object
*obj
, Object
*member
, struct TagItem
*attrs
)
542 ULONG tags
[6], *t
= tags
;
544 *t
++ = LGO_Group
; *t
++ = (ULONG
)obj
;
545 *t
++ = LGO_Object
; *t
++ = (ULONG
)member
;
546 *t
++ = TAG_MORE
; *t
++ = (ULONG
)attrs
;
548 return (Object
*)AsmDoMethod(obj
, GROUPM_NEWMEMBER
, tags
, NULL
);
553 * Add a spacing object.
555 STATIC Object
*NewSpaceObject(Object
*obj
, ULONG weight
)
557 ULONG tags
[6], *t
= tags
;
559 *t
++ = LGO_Group
; *t
++ = (ULONG
)obj
;
560 *t
++ = LGO_SpaceObject
; *t
++ = (ULONG
)weight
;
563 return (Object
*)AsmDoMethod(obj
, GROUPM_NEWMEMBER
, tags
, NULL
);
568 * Pass an attribute on to the members.
570 //STATIC ASM void PassAttr(REG(a0) GD *gd, REG(a1) struct TagItem *tag, REG(a2) struct GadgetInfo *gi)
571 STATIC ASM
REGFUNC3(void, PassAttr
,
572 REGPARAM(A0
, GD
*, gd
),
573 REGPARAM(A1
, struct TagItem
*, tag
),
574 REGPARAM(A2
, struct GadgetInfo
*, gi
))
581 T
[0].ti_Tag
= tag
->ti_Tag
;
582 T
[0].ti_Data
= tag
->ti_Data
;
583 T
[1].ti_Tag
= TAG_DONE
;
585 ops
.MethodID
= OM_SET
;
586 ops
.ops_AttrList
= T
;
590 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
))
591 AsmDoMethodA(md
->md_Object
, (Msg
)&ops
);
596 * Set one or more attributes.
598 METHOD(GroupSetAttrs
, struct opSet
*, ops
)
600 GD
*gd
= INST_DATA(cl
, obj
);
601 BC
*bc
= BASE_DATA(obj
);
602 struct TagItem
*tstate
= ops
->ops_AttrList
, *tag
;
604 struct GadgetInfo
*gi
= ops
->ops_GInfo
;
607 * Make sure we stay with the correct activation flags.
609 GADGET(obj
)->Activation
|= GACT_RELVERIFY
;
614 while (tag
= BGUI_NextTagItem(&tstate
))
620 if (data
) gd
->gd_Flags
|= GDF_HAS_TITLE
;
621 else gd
->gd_Flags
&= ~GDF_HAS_TITLE
;
625 if (data
== FRTYPE_DEFAULT
)
627 data
= GetTagData(FRM_DefaultType
, FRTYPE_NEXT
, BGUI_GetDefaultTags(BGUI_GROUP_GADGET
));
628 DoSetMethodNG(bc
->bc_Frame
, FRM_Type
, data
, TAG_DONE
);
633 case GA_BottomBorder
:
637 case BT_ParentWindow
:
641 PassAttr(gd
, tag
, gi
);
648 if (data
) gd
->gd_Flags
|= GDF_IS_MASTER
;
649 else gd
->gd_Flags
&= ~GDF_IS_MASTER
;
653 gd
->gd_SpaceX
= gd
->gd_SpaceY
= data
;
656 case GROUP_HorizSpacing
:
657 gd
->gd_SpaceX
= data
;
660 case GROUP_VertSpacing
:
661 gd
->gd_SpaceY
= data
;
669 gd
->gd_Columns
= data
;
676 case GROUP_HorizAlign
:
677 gd
->gd_HAlign
= data
;
680 case GROUP_VertAlign
:
681 gd
->gd_VAlign
= data
;
684 case GROUP_EqualWidth
:
685 if (data
) gd
->gd_Flags
|= GDF_EQUAL_MINWIDTH
;
686 else gd
->gd_Flags
&= ~GDF_EQUAL_MINWIDTH
;
689 case GROUP_EqualHeight
:
690 if (data
) gd
->gd_Flags
|= GDF_EQUAL_MINHEIGHT
;
691 else gd
->gd_Flags
&= ~GDF_EQUAL_MINHEIGHT
;
702 case GROUP_BackDriPen
:
703 attr
= FRM_BackDriPen
;
707 DoSuperSetMethodNG(cl
, obj
, bc
->bc_Frame
? TAG_IGNORE
: FRM_Type
, FRTYPE_NONE
, attr
, data
, TAG_DONE
);
718 * Create a new object.
720 METHOD(GroupClassNew
, struct opSet
*, ops
)
723 struct TagItem
*tags
= ops
->ops_AttrList
, *tstate
, *tag
;
728 struct Node
*n1
, *n2
;
729 int l
= 0, r
= 0, t
= 0, b
= 0;
732 * Let the superclass make an object.
734 if (rc
= NewSuperObject(cl
, obj
, tags
))
737 * Obtain instance data.
739 gd
= INST_DATA(cl
, rc
);
742 * Initialize member list and other data.
744 NewList((struct List
*)&gd
->gd_Members
);
745 InitSemaphore(&gd
->gd_Lock
);
751 * Initialize the rest of the instance data.
753 while (tag
= BGUI_NextTagItem(&tstate
))
760 l
= r
= t
= b
= data
;
763 case GROUP_HorizOffset
:
767 case GROUP_VertOffset
:
771 case GROUP_LeftOffset
:
775 case GROUP_TopOffset
:
779 case GROUP_RightOffset
:
783 case GROUP_BottomOffset
:
791 case GROUP_SpaceObject
:
792 if (m
= NewSpaceObject((Object
*)rc
, data
))
794 AsmDoMethod(m
, RM_ADDTAIL
, &gd
->gd_Members
);
797 gd
->gd_Flags
|= GDF_ADD_FAILURE
;
803 if (m
= NewGroupMember((Object
*)rc
, (Object
*)data
, tag
+ 1))
805 AsmDoMethod(m
, RM_ADDTAIL
, &gd
->gd_Members
);
809 * Dispose of the member.
811 AsmDoMethod((Object
*)data
, OM_DISPOSE
);
816 gd
->gd_Flags
|= GDF_ADD_FAILURE
;
823 n1
= ((struct List
*)&gd
->gd_Members
)->lh_Head
;
825 while ((n2
= n1
->ln_Succ
)->ln_Succ
)
828 AddHead((struct List
*)&gd
->gd_Members
, n2
);
835 if (!(gd
->gd_Flags
& GDF_ADD_FAILURE
))
837 if (GADGET(rc
)->Activation
& GACT_TOPBORDER
) l
++;
839 DoSuperSetMethodNG(cl
, (Object
*)rc
, BT_LeftOffset
, HSpace(l
), BT_RightOffset
, HSpace(r
),
840 BT_TopOffset
, VSpace(t
), BT_BottomOffset
, VSpace(b
), TAG_DONE
);
842 GroupSetAttrs(cl
, (Object
*)rc
, ops
);
847 * Noop... dump the object.
849 AsmCoerceMethod(cl
, (Object
*)rc
, OM_DISPOSE
);
859 * Set one or more attributes.
861 METHOD(GroupClassSet
, struct opSet
*, ops
)
864 * First we let the superclass have a go at it.
866 AsmDoSuperMethodA(cl
, obj
, (Msg
)ops
);
868 return GroupSetAttrs(cl
, obj
, ops
);
873 METHOD(GroupClassGet
, struct opGet
*, opg
)
875 GD
*gd
= INST_DATA(cl
, obj
);
876 ULONG rc
= 1, *store
= opg
->opg_Storage
;
878 switch (opg
->opg_AttrID
)
885 STORE gd
->gd_Columns
;
888 case GROUP_HorizSpacing
:
892 case GROUP_VertSpacing
:
896 case GROUP_HorizAlign
:
900 case GROUP_VertAlign
:
908 case GROUP_NumMembers
:
909 STORE gd
->gd_NumMembers
;
917 rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)opg
);
924 static Object
**ObtainMembers(Object
*obj
,GD
*gd
,BOOL
*got_members_list
)
928 if (!(gd
->gd_MD
= (Object
**)AsmDoMethod(obj
, GROUPM_OBTAINMEMBERS
, GROMF_WAIT
|GROMF_VISIBLE
, &gd
->gd_NumMembers
)))
930 *got_members_list
=TRUE
;
933 *got_members_list
=FALSE
;
937 static VOID
ReleaseMembers(Object
*obj
,GD
*gd
,BOOL got_members_list
)
941 AsmDoMethod(obj
, GROUPM_RELEASEMEMBERS
, gd
->gd_MD
);
952 METHOD(GroupClassLayout
, struct bmLayout
*, bml
)
954 GD
*gd
= INST_DATA(cl
, obj
);
955 BC
*bc
= BASE_DATA(obj
);
959 BOOL changed
,got_members_list
;
960 ULONG totalweight
, totalsize
, tw
, th
;
962 int r
, c
, size
, last
;
963 int x
, y
, dx
, dy
, w
, h
;
966 * Layout the baseclass.
968 AsmDoSuperMethodA(cl
, obj
, (Msg
)bml
);
970 if (!(bml
->bml_Flags
& BLF_CUSTOM_GROUP
))
972 w
= bc
->bc_InnerBox
.Width
- (HSpace(gd
->gd_SpaceX
) * (gd
->gd_Columns
- 1));
973 h
= bc
->bc_InnerBox
.Height
- (VSpace(gd
->gd_SpaceY
) * (gd
->gd_Rows
- 1));
975 if(ObtainMembers(obj
,gd
,&got_members_list
)==NULL
)
977 if (!gd
->gd_NumMembers
)
979 ReleaseMembers(obj
,gd
,got_members_list
);
984 * Set starting values.
987 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
989 tw
+= (td
->td_Size
= td
->td_Nom
);
996 * First loop to get total weight.
1000 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
1002 if (td
->td_Size
< td
->td_Max
)
1003 totalweight
+= td
->td_Weight
;
1005 totalsize
-= td
->td_Size
;
1008 if ((totalweight
== 0) || (totalsize
<= 0)) break;
1011 * Loop to get all scaled sizes.
1014 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
1016 if (td
->td_Size
< td
->td_Max
)
1018 size
= ScaleWeight(totalsize
, totalweight
, td
->td_Weight
);
1019 td
->td_Size
= range(size
, td
->td_Min
, td
->td_Max
);
1023 * Keep track of the total size.
1027 if (tw
== last
) break;
1032 * Constantly adjust the size of objects which where scaled larger
1033 * than their minimum size when the total scaled size was larger than
1034 * the area the objects must fit in.
1039 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
1042 * Was the size bigger than the minimum size?
1044 if (td
->td_Size
> td
->td_Min
)
1056 if (!changed
) break;
1060 * Set starting values.
1063 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1065 th
+= (td
->td_Size
= td
->td_Nom
);
1072 * First loop to get total weight.
1077 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1079 if (td
->td_Size
< td
->td_Max
)
1080 totalweight
+= td
->td_Weight
;
1082 totalsize
-= td
->td_Size
;
1085 if ((totalweight
== 0) || (totalsize
<= 0)) break;
1088 * Loop to get all scaled sizes.
1091 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1093 if (td
->td_Size
< td
->td_Max
)
1095 size
= ScaleWeight(totalsize
, totalweight
, td
->td_Weight
);
1096 td
->td_Size
= range(size
, td
->td_Min
, td
->td_Max
);
1100 * Keep track of the total size.
1104 if (th
== last
) break;
1109 * Constantly adjust the size of objects which where scaled larger
1110 * than their minimum size when the total scaled size was larger than
1111 * the area the objects must fit in.
1116 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1119 * Was the size bigger than the minimum size?
1121 if (td
->td_Size
> td
->td_Min
)
1133 if (!changed
) break;
1137 * Scan through the members.
1139 x
= bc
->bc_InnerBox
.Left
;
1141 for (c
= 0, cd
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, cd
++)
1143 y
= bc
->bc_InnerBox
.Top
;
1145 for (r
= 0, rd
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, rd
++)
1147 if (m
= GroupNode(gd
, r
, c
))
1149 md
= MEMBER_DATA(m
);
1151 md
->md_Bounds
.Width
= range(cd
->td_Size
- md
->md_HBLeft
, md
->md_MinWidth
, md
->md_MaxWidth
);
1152 md
->md_Bounds
.Height
= range(rd
->td_Size
, md
->md_MinHeight
, md
->md_MaxHeight
);
1154 switch (md
->md_HAlign
? md
->md_HAlign
: gd
->gd_HAlign
)
1160 case GRALIGN_CENTER
:
1161 dx
= max(0, cd
->td_Size
- md
->md_Bounds
.Width
) >> 1;
1164 dx
= max(0, cd
->td_Size
- md
->md_Bounds
.Width
);
1168 switch (md
->md_VAlign
? md
->md_VAlign
: gd
->gd_VAlign
)
1174 case GRALIGN_CENTER
:
1175 dy
= max(0, rd
->td_Size
- md
->md_Bounds
.Height
) >> 1;
1177 case GRALIGN_BOTTOM
:
1178 dy
= max(0, rd
->td_Size
- md
->md_Bounds
.Height
);
1182 md
->md_Bounds
.Left
= x
+ dx
;
1183 md
->md_Bounds
.Top
= y
+ dy
;
1185 y
+= rd
->td_Size
+ VSpace(gd
->gd_SpaceY
);
1187 x
+= cd
->td_Size
+ HSpace(gd
->gd_SpaceX
);
1189 ReleaseMembers(obj
,gd
,got_members_list
);
1200 struct Message sr_Message
;
1202 struct GadgetInfo
*sr_GInfo
;
1203 struct RastPort
*sr_RPort
;
1206 VOID SAVEDS
subrender_task(void)
1208 struct Process
*proc
= (struct Process
*)FindTask(NULL
);
1209 struct SubRender
*sr
;
1211 WaitPort(&proc
->pr_MsgPort
);
1212 sr
= (struct SubRender
*)GetMsg(&proc
->pr_MsgPort
);
1214 AsmDoMethod(sr
->sr_Object
, GM_RENDER
, sr
->sr_GInfo
, sr
->sr_RPort
, GREDRAW_REDRAW
);
1216 ReplyMsg((struct Message
*)sr
);
1222 METHOD(GroupClassRender
, struct bmRender
*, bmr
)
1224 GD
*gd
= INST_DATA(cl
, obj
);
1225 BC
*bc
= BASE_DATA(obj
);
1228 struct BaseInfo
*bi
= bmr
->bmr_BInfo
;
1229 struct RastPort
*rp
= bi
->bi_RPort
;
1230 struct Process
*proc
;
1231 struct MsgPort
*msgport
= NULL
;
1232 struct SubRender
*sr
;
1234 BOOL subrender
= FALSE
; // no multitasking yet
1235 int render_count
= 0;
1237 if (gd
->gd_Flags
& GDF_IS_MASTER
)
1241 BSetDPenA(bi
, BACKGROUNDPEN
);
1242 BBoxFillA(bi
, &bc
->bc_OuterBox
);
1246 WW(kprintf("***GroupClassRender*** obj = %x\n", obj
));
1249 * Render the baseclass.
1251 AsmDoSuperMethodA(cl
, obj
, (Msg
)bmr
);
1254 * Top-border group hack...
1256 if (GADGET(obj
)->Activation
& GACT_TOPBORDER
)
1258 BSetDPenA(bi
, SHADOWPEN
);
1259 Move(rp
, bc
->bc_OuterBox
.Left
, bc
->bc_OuterBox
.Top
+ 1);
1260 Draw(rp
, bc
->bc_OuterBox
.Left
, bc
->bc_OuterBox
.Top
+ bc
->bc_OuterBox
.Height
- 1);
1265 msgport
= CreateMsgPort();
1266 if (!msgport
) subrender
= FALSE
;
1270 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
))
1273 * Setup object position/dimensions and render it.
1275 SetGadgetBounds(md
->md_Object
, &md
->md_Bounds
);
1281 if (sr
= BGUI_AllocPoolMem(sizeof(struct SubRender
)))
1283 proc
= CreateNewProcTags(NP_Entry
, subrender_task
, NP_Name
, "BGUI Render", TAG_DONE
);
1285 if (!proc
) BGUI_FreePoolMem(sr
);
1293 sr
->sr_Message
.mn_ReplyPort
= msgport
;
1294 sr
->sr_Message
.mn_Length
= sizeof(struct SubRender
);
1295 sr
->sr_Object
= md
->md_Object
;
1296 sr
->sr_GInfo
= (struct GadgetInfo
*)bi
;
1299 PutMsg(&proc
->pr_MsgPort
, &sr
->sr_Message
);
1303 AsmDoMethod(md
->md_Object
, GM_RENDER
, bi
, rp
, GREDRAW_REDRAW
);
1309 * Wait for all subtasks to finish.
1311 while (render_count
)
1314 while (sr
= (struct SubRender
*)GetMsg(msgport
))
1316 BGUI_FreePoolMem(sr
);
1320 DeleteMsgPort(msgport
);
1328 * Pass on the hittest message.
1330 METHOD(GroupClassHitTest
, struct gpHitTest
*, gph
)
1332 GD
*gd
= INST_DATA(cl
, obj
);
1338 * See if a member was "hit".
1341 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
))
1346 if ((rc
= ForwardMsg(obj
, md
->md_Object
, (Msg
)gph
)) == GMR_GADGETHIT
)
1349 * Make it the active one.
1351 gd
->gd_Active
= md
->md_Object
;
1357 * Safety precautions.
1359 gd
->gd_Active
= NULL
;
1365 /// GM_GOACTIVE, GM_HANDLEINPUT
1367 * Forward a GM_GOACTIVE or GM_HANDLEINPUT message.
1369 METHOD(GroupClassActiveInput
, struct gpInput
*, gpi
)
1371 GD
*gd
= INST_DATA(cl
, obj
);
1372 ULONG rc
= GMR_NOREUSE
;
1375 * Do we have an active member?
1380 * Tell'm its active.
1382 if (gpi
->MethodID
== GM_GOACTIVE
)
1383 DoSetMethodNG(gd
->gd_Active
, BT_IsActive
, TRUE
, TAG_END
);
1385 rc
= ForwardMsg(obj
, gd
->gd_Active
, (Msg
)gpi
);
1390 DoSuperSetMethodNG(cl
, obj
, GA_ID
, GADGET(gd
->gd_Active
)->GadgetID
, TAG_DONE
);
1398 * Forward the GM_GOINACTIVE message.
1400 METHOD(GroupClassInActive
, Msg
, msg
)
1402 GD
*gd
= INST_DATA(cl
, obj
);
1406 * Inactivate the active member.
1410 rc
= AsmDoMethodA(gd
->gd_Active
, msg
);
1412 * Tell 'm its in-active.
1414 DoSetMethodNG(gd
->gd_Active
, BT_IsActive
, FALSE
, TAG_END
);
1415 gd
->gd_Active
= NULL
;
1423 * Dispose of the group and all
1426 METHOD(GroupClassDispose
, Msg
, msg
)
1428 GD
*gd
= INST_DATA(cl
, obj
);
1433 * Remove and dispose of all members.
1435 while (m
= ListHeadObject((struct List
*)&gd
->gd_Members
))
1437 md
= MEMBER_DATA(m
);
1443 AsmDoMethod(m
, OM_DISPOSE
);
1446 * Dispose of the member.
1448 AsmDoMethod(o
, OM_DISPOSE
);
1451 if (gd
->gd_RD
) BGUI_FreePoolMem(gd
->gd_RD
);
1452 if (gd
->gd_CD
) BGUI_FreePoolMem(gd
->gd_CD
);
1455 * Leave the rest up to the superclass.
1457 return AsmDoSuperMethodA(cl
, obj
, msg
);
1463 * Add a member to the group.
1465 METHOD(GroupClassAddMember
, struct grmAddMember
*, grma
)
1467 GD
*gd
= INST_DATA(cl
, obj
);
1471 * Allocate and initialize node.
1473 if (m
= NewGroupMember(obj
, grma
->grma_Member
, (struct TagItem
*)&grma
->grma_Attr
))
1476 * Add it to the list.
1478 AsmDoMethod(m
, RM_ADDTAIL
, &gd
->gd_Members
);
1480 WW(kprintf("** GroupClassAddMember\n"));
1481 WW(if(BASE_DATA(obj
)->bc_Window
) kprintf("** GroupClassAddMember: sending WM_SETUPGADGET to window\n"));
1483 if(BASE_DATA(obj
)->bc_Window
)
1484 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
, grma
->grma_Member
, NULL
);
1487 * Try to re-layout the group.
1489 WW(kprintf("** GroupClassAddMember: calling relayoutgroup: LGO_Relayout = %d\n",GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grma
->grma_Attr
)));
1491 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grma
->grma_Attr
)
1492 && !RelayoutGroup(obj
))
1494 WW(kprintf("** GroupClassAddMember: relayoutgroup failed. returning FALSE\n"));
1500 WW(kprintf("** GroupClassAddMember: everything done. returning TRUE\n"));
1508 /// GRM_INSERTMEMBER
1510 * Insert a member in the group.
1512 METHOD(GroupClassInsert
, struct grmInsertMember
*, grmi
)
1514 GD
*gd
= INST_DATA(cl
, obj
);
1520 if (!grmi
->grmi_Member
)
1524 * Allocate and initialize node.
1526 if (m
= NewGroupMember(obj
, grmi
->grmi_Member
, (struct TagItem
*)&grmi
->grmi_Attr
))
1528 AsmDoMethod(m
, RM_INSERT
, &gd
->gd_Members
, FindObNode(gd
, grmi
->grmi_Pred
));
1530 if(BASE_DATA(obj
)->bc_Window
)
1531 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
, grmi
->grmi_Member
, NULL
);
1534 * Try to re-layout the group.
1536 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grmi
->grmi_Attr
)
1537 && !RelayoutGroup(obj
))
1550 /// GRM_REPLACEMEMBER
1552 * Replace a member in the group.
1554 METHOD(GroupClassReplace
, struct grmReplaceMember
*, grrm
)
1556 GD
*gd
= INST_DATA(cl
, obj
);
1562 if (!grrm
->grrm_MemberA
|| !grrm
->grrm_MemberB
)
1566 * Allocate and initialize node.
1568 if (m
= NewGroupMember(obj
, grrm
->grrm_MemberB
, (struct TagItem
*)&grrm
->grrm_Attr
))
1571 * Find member to replace.
1573 if (old
= FindObNode(gd
, grrm
->grrm_MemberA
))
1575 AsmDoMethod(m
, RM_INSERT
, &gd
->gd_Members
, old
);
1576 AsmDoMethod(old
, RM_REMOVE
);
1578 if(BASE_DATA(obj
)->bc_Window
)
1579 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
, grrm
->grrm_MemberB
, NULL
);
1582 * Try to re-layout the group.
1584 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grrm
->grrm_Attr
)
1585 && !RelayoutGroup(obj
))
1587 AsmDoMethod(old
, RM_INSERT
, &gd
->gd_Members
);
1595 * Deallocate replaced node.
1602 return (ULONG
)grrm
->grrm_MemberA
;
1611 * Remove an object from the list.
1613 METHOD(GroupClassRemMember
, struct grmRemMember
*, grmr
)
1615 GD
*gd
= INST_DATA(cl
, obj
);
1618 if (m
= FindObNode(gd
, grmr
->grmr_Member
))
1621 * Remove and dealocate it.
1626 * Relayout the group.
1630 return (ULONG
)grmr
->grmr_Member
;
1636 /// GROUPM_OBTAINMEMBERS
1638 METHOD(GroupClassObtainMembers
, struct gmObtainMembers
*, gmom
)
1640 GD
*gd
= INST_DATA(cl
, obj
);
1644 ULONG flags
= gmom
->gmom_Flags
;
1646 if (flags
& GROMF_WAIT
)
1648 if (flags
& GROMF_EXCLUSIVE
)
1650 ObtainSemaphore(&gd
->gd_Lock
);
1654 ObtainSemaphoreShared(&gd
->gd_Lock
);
1659 if (flags
& GROMF_EXCLUSIVE
)
1661 n
= AttemptSemaphore(&gd
->gd_Lock
);
1665 n
= AttemptSemaphoreShared(&gd
->gd_Lock
);
1672 while (md
= NextGroupNode(gd
, &m
, (flags
& GROMF_VISIBLE
) ? MDF_HIDDEN
: 0))
1675 o
= BGUI_AllocPoolMem(sizeof(Object
*) * (n
+ 2));
1679 ReleaseSemaphore(&gd
->gd_Lock
);
1683 *o
++ = obj
; // Marker for safety.
1686 while (md
= NextGroupNode(gd
, &m
, (flags
& GROMF_VISIBLE
) ? MDF_HIDDEN
: 0))
1688 if (flags
& GROMF_OBJECTS
)
1689 *o
++ = md
->md_Object
;
1694 if (gmom
->gmom_Number
) *(gmom
->gmom_Number
) = n
;
1695 return (ULONG
)(o
- n
);
1699 /// GROUPM_RELEASEMEMBERS
1701 METHOD(GroupClassReleaseMembers
, struct gmReleaseMembers
*, gmrm
)
1703 GD
*gd
= INST_DATA(cl
, obj
);
1704 Object
**o
= gmrm
->gmrm_Array
- 1;
1707 if (*o
== obj
) // Check for safety marker.
1709 if (gd
->gd_Lock
.ss_Owner
== FindTask(NULL
))
1711 rc
= gd
->gd_Lock
.ss_NestCount
- 1;
1713 ReleaseSemaphore(&gd
->gd_Lock
);
1715 BGUI_FreePoolMem(o
);
1719 D(bug("*** Attempt to free an invalid group members list\n"));
1721 return (ULONG
)rc
; // rc < 0 = failure, rc = 0 is freed, rc > 0 still locked.
1727 //makeproto ASM ULONG RelayoutGroup(REG(a0) Object *obj)
1728 makeproto ASM
REGFUNC1(ULONG
, RelayoutGroup
,
1729 REGPARAM(A0
, Object
*, obj
))
1731 BC
*bc
= BASE_DATA(obj
);
1732 struct Window
*w
= NULL
;
1733 struct bmRelayout bmr
;
1736 WW(kprintf("** GroupClass_RelayoutGrop\n"));
1740 WW(kprintf("** GroupClass_RelayoutGrop: has bc->bc_Window\n"));
1741 Get_Attr(bc
->bc_Window
, WINDOW_Window
, (ULONG
*)&w
);
1745 bmr
.MethodID
= BASE_RELAYOUT
;
1746 bmr
.bmr_GInfo
= NULL
;
1747 bmr
.bmr_RPort
= w
->RPort
;
1748 WW(kprintf("** GroupClass_RelayoutGrop: has WINDOW_Window --> sending BASE_RELAYOUT to obj\n"));
1750 rc
= BGUI_DoGadgetMethodA(obj
, w
, NULL
, (Msg
)&bmr
);
1758 /// MemberDimensions
1760 * Calculate the minimum size of a group.
1762 METHOD(MemberDimensions
, struct bmDimensions
*, bmd
)
1764 GD
*gd
= INST_DATA(cl
, obj
);
1768 ULONG minw
, minh
, nomw
, nomh
, maxw
, maxh
;
1769 ULONG tmin
, tmax
, tnom
;
1771 BOOL got_members_list
;
1773 if(ObtainMembers(obj
,gd
,&got_members_list
)==NULL
)
1775 if (gd
->gd_NumMembers
)
1777 if (gd
->gd_Style
== GRSTYLE_HORIZONTAL
)
1779 gd
->gd_Rows
= range(gd
->gd_Rows
, 1, gd
->gd_NumMembers
);
1780 gd
->gd_Columns
= (gd
->gd_NumMembers
+ (gd
->gd_Rows
- 1)) / gd
->gd_Rows
;
1783 if (gd
->gd_Style
== GRSTYLE_VERTICAL
)
1785 gd
->gd_Columns
= range(gd
->gd_Columns
, 1, gd
->gd_NumMembers
);
1786 gd
->gd_Rows
= (gd
->gd_NumMembers
+ (gd
->gd_Columns
- 1)) / gd
->gd_Columns
;
1789 if (gd
->gd_RD
) BGUI_FreePoolMem(gd
->gd_RD
);
1790 if (gd
->gd_CD
) BGUI_FreePoolMem(gd
->gd_CD
);
1792 gd
->gd_RD
= BGUI_AllocPoolMem(sizeof(TD
) * gd
->gd_Rows
);
1793 gd
->gd_CD
= BGUI_AllocPoolMem(sizeof(TD
) * gd
->gd_Columns
);
1795 if (!(gd
->gd_RD
&& gd
->gd_CD
)) return 0;
1798 * Scan through the members.
1800 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
1802 td
->td_PreAlign
= 0;
1804 for (r
= 0; r
< gd
->gd_Rows
; r
++)
1806 if (m
= GroupNode(gd
, r
, c
))
1808 md
= MEMBER_DATA(m
);
1811 * Find out how much we must adjust for alignment.
1813 AsmDoMethod(md
->md_Object
, BASE_LEFTEXT
, bmd
->bmd_BInfo
->bi_RPort
, &md
->md_HBLeft
);
1817 if (!(md
->md_Flags
& MDF_NO_NO_ALIGN
))
1818 md
->md_Flags
|= MDF_NO_ALIGN
;
1822 if (md
->md_HBLeft
> td
->td_PreAlign
) td
->td_PreAlign
= md
->md_HBLeft
;
1831 for (r
= 0; r
< gd
->gd_Rows
; r
++)
1833 if (m
= GroupNode(gd
, r
, c
))
1835 md
= MEMBER_DATA(m
);
1837 if (!(md
->md_Flags
& MDF_NO_ALIGN
))
1839 md
->md_HBLeft
= td
->td_PreAlign
- md
->md_HBLeft
;
1846 if (r
== 0) td
->td_Weight
= md
->md_Weight
;
1849 * Adjust the minimum width with the maximum extention.
1851 tmin
= max(tmin
, md
->md_MinWidth
+ md
->md_HBLeft
);
1852 tnom
= max(tnom
, md
->md_NomWidth
+ md
->md_HBLeft
);
1853 tmax
= max(tmax
, md
->md_MaxWidth
);
1859 td
->td_Nom
= range(tnom
, tmin
, tmax
);
1863 * Scan through the members.
1865 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1871 for (c
= 0; c
< gd
->gd_Columns
; c
++)
1873 if (m
= GroupNode(gd
, r
, c
))
1875 md
= MEMBER_DATA(m
);
1877 if (c
== 0) td
->td_Weight
= md
->md_Weight
;
1879 tmin
= max(tmin
, md
->md_MinHeight
);
1880 tnom
= max(tnom
, md
->md_NomHeight
);
1881 tmax
= max(tmax
, md
->md_MaxHeight
);
1887 td
->td_Nom
= range(tnom
, tmin
, tmax
);
1890 minw
= nomw
= HSpace(gd
->gd_SpaceX
) * (gd
->gd_Columns
- 1);
1891 minh
= nomh
= VSpace(gd
->gd_SpaceY
) * (gd
->gd_Rows
- 1);
1894 for (r
= 0, td
= gd
->gd_RD
; r
< gd
->gd_Rows
; r
++, td
++)
1901 for (c
= 0, td
= gd
->gd_CD
; c
< gd
->gd_Columns
; c
++, td
++)
1915 maxw
= maxh
= 0xFFFF;
1918 ReleaseMembers(obj
,gd
,got_members_list
);
1920 minw
= max(minw
, 1);
1921 minh
= max(minh
, 1);
1923 maxw
= range(maxw
, minw
, 0xFFFF);
1924 maxh
= range(maxh
, minh
, 0xFFFF);
1926 nomw
= range(nomw
, minw
, maxw
);
1927 nomh
= range(nomh
, minh
, maxh
);
1929 bmd
->bmd_Extent
->be_Min
.Width
+= minw
;
1930 bmd
->bmd_Extent
->be_Min
.Height
+= minh
;
1931 bmd
->bmd_Extent
->be_Nom
.Width
+= nomw
;
1932 bmd
->bmd_Extent
->be_Nom
.Height
+= nomh
;
1933 bmd
->bmd_Extent
->be_Max
.Width
= maxw
;
1934 bmd
->bmd_Extent
->be_Max
.Height
= maxh
;
1942 * They want our dimensions info.
1944 METHOD(GroupClassDimensions
, struct bmDimensions
*, bmd
)
1946 GD
*gd
= INST_DATA(cl
, obj
);
1947 /* BC *bc = BASE_DATA(obj); */
1950 struct grmDimensions dim
;
1951 UWORD mw
= 0, mh
= 0, minw
, minh
, maxw
, maxh
, nomw
, nomh
;
1954 dim
.MethodID
= GRM_DIMENSIONS
;
1955 dim
.grmd_GInfo
= (struct GadgetInfo
*)bmd
->bmd_BInfo
;
1956 dim
.grmd_RPort
= bmd
->bmd_BInfo
->bi_RPort
;
1957 dim
.grmd_Flags
= bmd
->bmd_Flags
| GDIMF_MAXIMUM
|GDIMF_NOMINAL
;
1958 dim
.grmd_MinSize
.Width
= &minw
;
1959 dim
.grmd_MinSize
.Height
= &minh
;
1960 dim
.grmd_MaxSize
.Width
= &maxw
;
1961 dim
.grmd_MaxSize
.Height
= &maxh
;
1962 dim
.grmd_NomSize
.Width
= &nomw
;
1963 dim
.grmd_NomSize
.Height
= &nomh
;
1966 * Browse through the members.
1969 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
))
1971 if (md
->md_Flags
& MDF_SPACING
)
1973 md
->md_MinWidth
= 0;
1974 md
->md_MinHeight
= 0;
1975 md
->md_NomWidth
= 0;
1976 md
->md_NomHeight
= 0;
1977 md
->md_MaxWidth
= 0xFFFF;
1978 md
->md_MaxHeight
= 0xFFFF;
1985 AsmDoMethodA(md
->md_Object
, (Msg
)&dim
);
1988 * Make sure the fixed sizes are not smaller than allowed.
1990 if (md
->md_FixedWidth
>= 0)
1992 maxw
= minw
= nomw
= range(md
->md_FixedWidth
, minw
, maxw
);
1994 if (md
->md_FixedHeight
>= 0)
1996 maxh
= minh
= nomh
= range(md
->md_FixedHeight
, minh
, maxh
);
1998 if (minw
> mw
) mw
= minw
;
1999 if (minh
> mh
) mh
= minh
;
2001 md
->md_MinWidth
= minw
;
2002 md
->md_MinHeight
= minh
;
2003 md
->md_MaxWidth
= max(minw
, maxw
);
2004 md
->md_MaxHeight
= max(minh
, maxh
);
2005 md
->md_NomWidth
= range(nomw
, minw
, maxw
);
2006 md
->md_NomHeight
= range(nomh
, minh
, maxh
);
2011 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
))
2014 * Set equal width/height.
2016 if (gd
->gd_Flags
& GDF_EQUAL_MINWIDTH
) md
->md_MinWidth
= mw
;
2017 if (gd
->gd_Flags
& GDF_EQUAL_MINHEIGHT
) md
->md_MinHeight
= mh
;
2020 if (rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)bmd
))
2023 * Calculate constraints.
2025 if (!(bmd
->bmd_Flags
& BDF_CUSTOM_GROUP
))
2026 rc
= MemberDimensions(cl
, obj
, bmd
);
2033 METHOD(GroupClassDimensionsX
, struct grmDimensions
*, dim
)
2035 GD
*gd
= INST_DATA(cl
, obj
);
2037 BOOL got_members_list
;
2039 if(ObtainMembers(obj
,gd
,&got_members_list
)==NULL
)
2041 rc
=AsmDoSuperMethodA(cl
, obj
, (Msg
)dim
);
2042 ReleaseMembers(obj
,gd
,got_members_list
);
2050 * Pass on the help message.
2052 METHOD(GroupClassHelp
, struct bmShowHelp
*, bsh
)
2054 GD
*gd
= INST_DATA(cl
, obj
);
2057 ULONG rc
= BMHELP_NOT_ME
;
2060 while ((md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
)) && (rc
== BMHELP_NOT_ME
))
2065 rc
= AsmDoMethodA(md
->md_Object
, (Msg
)bsh
);
2071 /// GRM_ADDSPACEMEMBER
2073 * Add a spacing object.
2075 METHOD(GroupClassAddSpaceMember
, struct grmAddSpaceMember
*, grms
)
2077 GD
*gd
= INST_DATA(cl
, obj
);
2080 if (m
= NewSpaceObject(obj
, grms
->grms_Weight
))
2082 AsmDoMethod(m
, RM_ADDTAIL
, &gd
->gd_Members
);
2091 * Route a BASE_LEFTEXT method.
2093 METHOD(GroupClassLeftExt
, struct bmLeftExt
*, le
)
2095 GD
*gd
= INST_DATA(cl
, obj
);
2096 BC
*bc
= BASE_DATA(obj
);
2100 * Do we have a label or frame? If so we
2101 * take the left-extention of this object.
2105 return AsmDoSuperMethodA(cl
, obj
, (Msg
)le
);
2110 Get_Attr(bc
->bc_Frame
, FRM_Type
, &rc
);
2111 if (rc
!= FRTYPE_NONE
)
2113 return AsmDoSuperMethodA(cl
, obj
, (Msg
)le
);
2118 * Get the biggest in the first column.
2121 *(le
->bmle_Extention
) = gd
->gd_CD
[0].td_PreAlign
;
2124 *(le
->bmle_Extention
)=0;
2133 * Which object is under the mouse?
2135 METHOD(GroupClassWhichObject
, struct grmWhichObject
*, grwo
)
2137 GD
*gd
= INST_DATA(cl
, obj
);
2145 * Pick up the coords.
2147 x
= grwo
->grwo_Coords
.X
;
2148 y
= grwo
->grwo_Coords
.Y
;
2151 * See if the coords are over a member.
2154 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
))
2157 * If this is a group/page we pass on the method.
2159 if (IsMulti(md
->md_Object
))
2161 if (rc
= AsmDoMethodA(md
->md_Object
, (Msg
)grwo
))
2166 * Get hitbox bounds.
2168 ibox
= GADGETBOX(md
->md_Object
);
2173 if (x
>= ibox
->Left
&& x
< (ibox
->Left
+ ibox
->Width
) &&
2174 y
>= ibox
->Top
&& y
< (ibox
->Top
+ ibox
->Height
))
2178 return (ULONG
)md
->md_Object
;
2187 * Which object has the proper key?
2189 METHOD(GroupClassFindKey
, struct bmFindKey
*, bmfk
)
2191 GD
*gd
= INST_DATA(cl
, obj
);
2196 if (rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)bmfk
))
2200 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
| MDF_SPACING
))
2202 if (rc
= AsmDoMethodA(md
->md_Object
, (Msg
)bmfk
))
2211 * Attach keys from labels.
2213 METHOD(GroupClassAll
, Msg
, msg
)
2215 GD
*gd
= INST_DATA(cl
, obj
);
2220 rc
= AsmDoSuperMethodA(cl
, obj
, msg
);
2223 while (md
= NextGroupNode(gd
, &m
, MDF_HIDDEN
))
2225 rc
+= AsmDoMethodA(md
->md_Object
, msg
);
2232 METHOD(GroupClassIsMulti
, Msg
, msg
)
2238 /// Class initialization.
2240 * Class function table.
2242 STATIC DPFUNC ClassFunc
[] = {
2243 BASE_RENDER
, (FUNCPTR
)GroupClassRender
,
2244 BASE_LAYOUT
, (FUNCPTR
)GroupClassLayout
,
2245 BASE_DIMENSIONS
, (FUNCPTR
)GroupClassDimensions
,
2246 GRM_DIMENSIONS
, (FUNCPTR
)GroupClassDimensionsX
,
2248 OM_NEW
, (FUNCPTR
)GroupClassNew
,
2249 OM_SET
, (FUNCPTR
)GroupClassSet
,
2250 OM_GET
, (FUNCPTR
)GroupClassGet
,
2251 OM_DISPOSE
, (FUNCPTR
)GroupClassDispose
,
2252 GM_GOACTIVE
, (FUNCPTR
)GroupClassActiveInput
,
2253 GM_HANDLEINPUT
, (FUNCPTR
)GroupClassActiveInput
,
2254 GM_GOINACTIVE
, (FUNCPTR
)GroupClassInActive
,
2255 GM_HITTEST
, (FUNCPTR
)GroupClassHitTest
,
2257 GROUPM_OBTAINMEMBERS
, (FUNCPTR
)GroupClassObtainMembers
,
2258 GROUPM_RELEASEMEMBERS
, (FUNCPTR
)GroupClassReleaseMembers
,
2259 GROUPM_NEWMEMBER
, (FUNCPTR
)GroupClassNewMember
,
2260 GRM_ADDMEMBER
, (FUNCPTR
)GroupClassAddMember
,
2261 GRM_REMMEMBER
, (FUNCPTR
)GroupClassRemMember
,
2262 GRM_ADDSPACEMEMBER
, (FUNCPTR
)GroupClassAddSpaceMember
,
2263 GRM_INSERTMEMBER
, (FUNCPTR
)GroupClassInsert
,
2264 GRM_REPLACEMEMBER
, (FUNCPTR
)GroupClassReplace
,
2265 GRM_WHICHOBJECT
, (FUNCPTR
)GroupClassWhichObject
,
2266 BASE_MOVEBOUNDS
, (FUNCPTR
)GroupClassAll
,
2267 BASE_FINDKEY
, (FUNCPTR
)GroupClassFindKey
,
2268 BASE_KEYLABEL
, (FUNCPTR
)GroupClassAll
,
2269 BASE_LOCALIZE
, (FUNCPTR
)GroupClassAll
,
2270 BASE_SHOWHELP
, (FUNCPTR
)GroupClassHelp
,
2271 BASE_LEFTEXT
, (FUNCPTR
)GroupClassLeftExt
,
2272 BASE_INHIBIT
, (FUNCPTR
)GroupClassAll
,
2273 BASE_IS_MULTI
, (FUNCPTR
)GroupClassIsMulti
,
2279 * Simple class initialization.
2281 makeproto Class
*InitGroupClass(void)
2283 return BGUI_MakeClass(CLASS_SuperClassBGUI
, BGUI_BASE_GADGET
,
2284 CLASS_ObjectSize
, sizeof(GD
),
2285 CLASS_DFTable
, ClassFunc
,