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.3 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.2 2000/05/15 19:27:02 stegerg
18 * another hundreds of REG() macro replacements in func headers/protos.
20 * Revision 42.1 2000/05/14 23:32:48 stegerg
21 * changed over 200 function headers which all use register
22 * parameters (oh boy ...), because the simple REG() macro
23 * doesn't work with AROS. And there are still hundreds
24 * of headers left to be fixed :(
26 * Many of these functions would also work with stack
27 * params, but since i have fixed every single one
28 * I encountered up to now, I guess will have to do
29 * the same for the rest.
31 * Revision 42.0 2000/05/09 22:09:50 mlemos
32 * Bumped to revision 42.0 before handing BGUI to AROS team
34 * Revision 41.11 2000/05/09 19:54:51 mlemos
35 * Merged with the branch Manuel_Lemos_fixes.
37 * Revision 41.10.2.4 1999/08/30 04:57:39 mlemos
38 * Made the methods that change group members on-fly setup the gadget
39 * attributes using the window WINDOW_SETUPGADGET method.
41 * Revision 41.10.2.3 1999/08/30 00:22:54 mlemos
42 * Made the BASE_INHIBIT method call the superclass to set the base object
44 * Made an added, inserted or replaced page member object be inhibited if it
45 * is not active or the page object is inhibited.
46 * Adjusted the active page number and node pointer when removing a page
49 * Revision 41.10.2.2 1999/08/29 18:58:49 mlemos
50 * Added support to the LGO_Relayout attribute to be able to not relayout a
51 * when calling GRM_ADDMEMBER, GRM_INSERTMEMBER, GRM_REPLACEMEMBER.
53 * Revision 41.10.2.1 1999/08/29 17:08:39 mlemos
54 * Added the implementation of the methods GRM_ADDMEMBER, GRM_REMMEMBER,
55 * GRM_INSERTMEMBER, GRM_REPLACEMEMBER.
57 * Revision 41.10 1998/02/25 21:12:47 mlemos
60 * Revision 1.1 1998/02/25 17:09:20 mlemos
66 /// Class definitions.
68 #include "include/classdefs.h"
71 * Page members are tied together
72 * using these structures.
74 typedef struct PMember
{
75 struct PMember
*pm_Next
; /* next member */
76 struct PMember
*pm_Prev
; /* previous member */
77 Object
*pm_Object
; /* the member */
81 PM
*pl_First
; /* first memeber */
82 PM
*pl_EndMark
; /* end-of-list marker */
83 PM
*pl_Last
; /* last member */
87 * Object instance data.
90 ULONG pd_Flags
; /* see below */
91 PML pd_Members
; /* list of members */
92 PM
*pd_Active
; /* points to the active member */
93 ULONG pd_Num
; /* member number. */
96 #define PDF_ADDFAILURE (1<<0) /* create time failure */
97 #define PDF_INVERTED (1<<1) /* AddHead() */
98 #define PDF_INHIBIT (1<<2) /* Inhibited? */
103 * Get the member 'num'.
105 STATIC ASM PM
*GetMember(REG(a0
) PML
*l
, REG(d0
) ULONG mnum
)
110 for (pm
= l
->pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
, num
++)
121 STATIC ASM VOID
AddMembers( REG(a0
) Class
*cl
, REG(a1
) Object
*obj
, REG(a2
) struct TagItem
*attr
)
123 PD
*pd
= INST_DATA(cl
, obj
);
125 struct TagItem
*tstate
= attr
;
131 while ((tag
= NextTagItem(&tstate
)))
137 * We do not allow NULL-objects.
142 * Allocate PMember structure.
144 if ((pm
= (PM
*)BGUI_AllocPoolMem(sizeof(PM
))))
147 * Initialize structure and add it to the list.
149 pm
->pm_Object
= (Object
*)tag
->ti_Data
;
150 if (pd
->pd_Flags
& PDF_INVERTED
)
151 AddHead((struct List
*)&pd
->pd_Members
, (struct Node
*)pm
);
153 AddTail((struct List
*)&pd
->pd_Members
, (struct Node
*)pm
);
158 pd
->pd_Flags
|= PDF_ADDFAILURE
;
163 pd
->pd_Flags
|= PDF_ADDFAILURE
;
170 * Set members active/deactive.
172 STATIC ASM VOID
DoMembers(REG(a0
) PD
*pd
)
174 PM
*pm
, *active
= pd
->pd_Active
;
175 BOOL inhibit
= pd
->pd_Flags
& PDF_INHIBIT
;
180 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
183 * (De)activate members.
185 AsmDoMethod(pm
->pm_Object
, BASE_INHIBIT
, inhibit
|| (pm
!= active
));
191 * Create a shiny new object.
193 METHOD(PageClassNew
, struct opSet
*, ops
)
196 struct TagItem
*tags
, *tag
;
199 tags
= DefTagList(BGUI_PAGE_GADGET
, ops
->ops_AttrList
);
202 * First we let the superclass
205 if ((rc
= NewSuperObject(cl
, obj
, tags
)))
207 pd
= INST_DATA(cl
, rc
);
209 if ((tag
= FindTagItem(PAGE_NoBufferRP
, tags
)))
211 DoSetMethodNG((Object
*)rc
, BT_Buffer
, !(tag
->ti_Data
), TAG_DONE
);
215 * Initialize the page
218 NewList((struct List
*)&pd
->pd_Members
);
220 GADGET(rc
)->Activation
|= GACT_RELVERIFY
;
222 if (GetTagData(PAGE_Inverted
, FALSE
, tags
))
223 pd
->pd_Flags
|= PDF_INVERTED
;
226 * Add all page members.
228 AddMembers(cl
, (Object
*)rc
, ops
->ops_AttrList
);
230 pd
->pd_Flags
&= ~PDF_INVERTED
;
233 * When successfull return the object.
235 if (!(pd
->pd_Flags
& PDF_ADDFAILURE
))
238 * Get the active member.
240 pd
->pd_Num
= GetTagData(PAGE_Active
, 0, tags
);
241 pd
->pd_Active
= GetMember(&pd
->pd_Members
, pd
->pd_Num
);
247 * Otherwise dispose of the page.
249 AsmCoerceMethod(cl
, (Object
*)rc
, OM_DISPOSE
);
259 /// OM_SET, OM_UPDATE
261 * Set/update page attributes.
263 METHOD(PageClassSetUpdate
, struct opUpdate
*, opu
)
265 PD
*pd
= INST_DATA( cl
, obj
);
266 struct TagItem
*attr
= opu
->opu_AttrList
, *tag
;
267 struct TagItem
*tstate
= attr
;
268 struct GadgetInfo
*gi
= opu
->opu_GInfo
;
274 * First we let the superclass
277 AsmDoSuperMethodA(cl
, obj
, (Msg
)opu
);
279 GADGET(obj
)->Activation
|= GACT_RELVERIFY
;
283 * to interim messages.
285 if ((opu
->MethodID
== OM_UPDATE
) && (opu
->opu_Flags
& OPUF_INTERIM
))
288 while ((tag
= NextTagItem(&tstate
)))
294 case GA_BottomBorder
:
297 case BT_ParentWindow
:
302 * Pass on attribute to the members.
304 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
305 DoSetMethod(pm
->pm_Object
, gi
, tag
->ti_Tag
, data
, TAG_DONE
);
309 if (pd
->pd_Num
!= data
)
312 pd
->pd_Active
= GetMember(&pd
->pd_Members
, data
);
321 * When a visual change is necessary we re-render.
325 DoRenderMethod(obj
, gi
, GREDRAW_REDRAW
);
326 DoNotifyMethod(obj
, gi
, 0, PAGE_Active
, pd
->pd_Num
, TAG_END
);
336 METHOD(PageClassRender
, struct bmRender
*, bmr
)
338 PD
*pd
= INST_DATA(cl
, obj
);
339 BC
*bc
= BASE_DATA(obj
);
340 struct BaseInfo
*bi
= bmr
->bmr_BInfo
;
343 * Render the baseclass.
345 AsmDoSuperMethodA(cl
, obj
, (Msg
)bmr
);
353 * Setup the active member size.
355 DoSetMethodNG(pd
->pd_Active
->pm_Object
, GA_Left
, bc
->bc_InnerBox
.Left
, GA_Top
, bc
->bc_InnerBox
.Top
,
356 GA_Width
, bc
->bc_InnerBox
.Width
, GA_Height
, bc
->bc_InnerBox
.Height
,
357 BT_ParentGroup
, obj
, TAG_DONE
);
361 AsmDoMethod(pd
->pd_Active
->pm_Object
, GM_RENDER
, bi
, bi
->bi_RPort
, GREDRAW_REDRAW
);
369 * They want to know something.
371 METHOD(PageClassGet
, struct opGet
*, opg
)
373 PD
*pd
= INST_DATA(cl
, obj
);
375 IPTR
*store
= opg
->opg_Storage
;
377 switch (opg
->opg_AttrID
)
380 if (pd
->pd_Active
) STORE pd
->pd_Num
;
385 rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)opg
);
394 * Dispose of all objects added to the page-list
395 * and then dispose of the page itself.
397 METHOD(PageClassDispose
, Msg
, msg
)
399 PD
*pd
= INST_DATA(cl
, obj
);
403 * Remove all objects from the list.
405 while ((pm
= (PM
*)RemHead((struct List
*)&pd
->pd_Members
)))
411 AsmDoMethod(pm
->pm_Object
, OM_DISPOSE
);
414 * Deallocate the object
417 BGUI_FreePoolMem(pm
);
421 * Call the super class
422 * to dispose the pageclass object.
424 return AsmDoSuperMethodA(cl
, obj
, msg
);
430 * They want to know something about
433 METHOD(PageClassDimensions
, struct bmDimensions
*, bmd
)
435 PD
*pd
= INST_DATA(cl
, obj
);
436 struct BaseInfo
*bi
= bmd
->bmd_BInfo
;
441 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
444 AsmDoMethod(pm
->pm_Object
, GRM_DIMENSIONS
, bi
, bi
->bi_RPort
, &w
, &h
, 0);
448 return CalcDimensions(cl
, obj
, bmd
, mw
, mh
);
454 * Get the object under the mouse.
456 METHOD(PageClassWhichObject
, struct grmWhichObject
*, grwo
)
458 PD
*pd
= INST_DATA(cl
, obj
);
459 Object
*ob
= pd
->pd_Active
->pm_Object
;
461 * Current page member a group?
467 ob
= (Object
*)AsmDoMethodA(ob
, (Msg
)grwo
);
475 * Forward a message to the active page.
477 METHOD(PageClassForward
, Msg
, msg
)
479 PD
*pd
= INST_DATA(cl
, obj
);
480 ULONG rc
= GMR_NOREUSE
;
483 * Do we have an active member?
488 * Forward the message to the
491 rc
= AsmDoMethodA(pd
->pd_Active
->pm_Object
, msg
);
494 * Take over the active member's GadgetID.
496 GADGET(obj
)->GadgetID
= GADGET(pd
->pd_Active
->pm_Object
)->GadgetID
;
504 * Pass the message to all submembers.
506 METHOD(PageClassAll
, Msg
, msg
)
508 PD
*pd
= INST_DATA(cl
, obj
);
512 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
514 rc
+= AsmDoMethodA(pm
->pm_Object
, msg
);
522 * Inhibit an entire page object.
524 METHOD(PageClassInhibit
, struct bmInhibit
*, bmi
)
526 PD
*pd
= INST_DATA(cl
, obj
);
527 PM
*pm
, *active
= pd
->pd_Active
;
528 BOOL inhibit
= bmi
->bmi_Inhibit
;
530 if(!AsmDoSuperMethodA(cl
, obj
, (Msg
)bmi
))
532 if (inhibit
) pd
->pd_Flags
|= PDF_INHIBIT
;
533 else pd
->pd_Flags
&= ~PDF_INHIBIT
;
535 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
537 AsmDoMethod(pm
->pm_Object
, BASE_INHIBIT
, inhibit
|| (pm
!= active
));
545 METHOD(PageClassIsMulti
, Msg
, msg
)
555 * Add a member to the group.
557 METHOD(PageClassAddMember
, struct grmAddMember
*, grma
)
559 PD
*pd
= INST_DATA(cl
, obj
);
562 if(!(pm
= (PM
*)BGUI_AllocPoolMem(sizeof(PM
))))
564 pm
->pm_Object
=grma
->grma_Member
;
566 AddTail((struct List
*)&pd
->pd_Members
, (struct Node
*)pm
);
569 if(BASE_DATA(obj
)->bc_Window
)
571 struct TagItem tags
[2];
573 tags
[0].ti_Tag
=BT_Inhibit
;
574 tags
[0].ti_Data
=TRUE
;
575 tags
[1].ti_Tag
=TAG_END
;
576 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
,pm
->pm_Object
,&tags
);
580 * Try to re-layout the group.
583 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grma
->grma_Attr
)
584 && !RelayoutGroup(obj
))
587 Remove((struct Node
*)pm
);
589 BGUI_FreePoolMem(pm
);
601 * Remove an object from the list.
603 METHOD(PageClassRemMember
, struct grmRemMember
*, grmr
)
605 PD
*pd
= INST_DATA(cl
, obj
);
608 if(!grmr
->grmr_Member
)
611 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
613 if(pm
->pm_Object
==grmr
->grmr_Member
)
615 if(pm
==pd
->pd_Active
)
616 pd
->pd_Active
=(pm
->pm_Prev
->pm_Prev
? pm
->pm_Prev
: pm
->pm_Next
);
617 Remove((struct Node
*)pm
);
618 BGUI_FreePoolMem(pm
);
619 for(pd
->pd_Num
=0,pm
=pd
->pd_Members
.pl_First
;pm
->pm_Next
&& pm
!=pd
->pd_Active
;pd
->pd_Num
++,pm
=pm
->pm_Next
);
622 return((IPTR
)grmr
->grmr_Member
);
633 * Insert a member in the group.
635 METHOD(PageClassInsert
, struct grmInsertMember
*, grmi
)
637 PD
*pd
= INST_DATA(cl
, obj
);
640 if(!grmi
->grmi_Member
641 || !(new_pm
= (PM
*)BGUI_AllocPoolMem(sizeof(PM
))))
643 new_pm
->pm_Object
=grmi
->grmi_Member
;
645 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
647 if(pm
->pm_Object
==grmi
->grmi_Pred
)
649 Insert((struct List
*)&pd
->pd_Members
,(struct Node
*)new_pm
,(struct Node
*)pm
);
652 if(BASE_DATA(obj
)->bc_Window
)
654 struct TagItem tags
[2];
656 tags
[0].ti_Tag
=BT_Inhibit
;
657 tags
[0].ti_Data
=TRUE
;
658 tags
[1].ti_Tag
=TAG_END
;
659 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
,pm
->pm_Object
,&tags
);
663 * Try to re-layout the group.
665 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grmi
->grmi_Attr
)
666 && !RelayoutGroup(obj
))
669 Remove((struct Node
*)new_pm
);
671 BGUI_FreePoolMem(new_pm
);
680 BGUI_FreePoolMem(new_pm
);
686 /// GRM_REPLACEMEMBER
688 * Replace a member in the group.
690 METHOD(PageClassReplace
, struct grmReplaceMember
*, grrm
)
692 PD
*pd
= INST_DATA(cl
, obj
);
698 if(!grrm
->grrm_MemberA
699 || !grrm
->grrm_MemberB
)
702 for (pm
= pd
->pd_Members
.pl_First
; pm
->pm_Next
; pm
= pm
->pm_Next
)
704 if(pm
->pm_Object
==grrm
->grrm_MemberA
)
706 pm
->pm_Object
=grrm
->grrm_MemberB
;
709 if(BASE_DATA(obj
)->bc_Window
)
711 struct TagItem tags
[2];
713 tags
[0].ti_Tag
=BT_Inhibit
;
714 tags
[0].ti_Data
=((pd
->pd_Flags
& PDF_INHIBIT
)!=0 || (pm
!= pd
->pd_Active
));
715 tags
[1].ti_Tag
=TAG_END
;
716 AsmDoMethod(BASE_DATA(obj
)->bc_Window
, WM_SETUPGADGET
,pm
->pm_Object
,&tags
);
720 * Try to re-layout the group.
722 if(GetTagData(LGO_Relayout
, TRUE
, (struct TagItem
*)&grrm
->grrm_Attr
)
723 && !RelayoutGroup(obj
))
726 pm
->pm_Object
=grrm
->grrm_MemberA
;
732 return((IPTR
)grrm
->grrm_MemberA
);
740 /// Class initialization.
744 STATIC DPFUNC ClassFunc
[] = {
745 { BASE_RENDER
, PageClassRender
},
746 { BASE_DIMENSIONS
, PageClassDimensions
},
747 { OM_NEW
, PageClassNew
},
748 { OM_SET
, PageClassSetUpdate
},
749 { OM_UPDATE
, PageClassSetUpdate
},
750 { OM_DISPOSE
, PageClassDispose
},
751 { OM_GET
, PageClassGet
},
752 { GM_GOINACTIVE
, PageClassForward
},
753 { GM_GOACTIVE
, PageClassForward
},
754 { GM_HANDLEINPUT
, PageClassForward
},
755 { GM_HITTEST
, PageClassForward
},
756 { GRM_WHICHOBJECT
, PageClassWhichObject
},
757 { BASE_INHIBIT
, PageClassInhibit
},
758 { BASE_MOVEBOUNDS
, PageClassForward
},
759 { BASE_LOCALIZE
, PageClassAll
},
760 { BASE_KEYLABEL
, PageClassAll
},
761 { BASE_FINDKEY
, PageClassForward
},
762 { BASE_SHOWHELP
, PageClassForward
},
763 { BASE_IS_MULTI
, PageClassIsMulti
},
764 { GRM_ADDMEMBER
, PageClassAddMember
},
765 { GRM_REMMEMBER
, PageClassRemMember
},
766 { GRM_INSERTMEMBER
, PageClassInsert
},
767 { GRM_REPLACEMEMBER
, PageClassReplace
},
772 * Simple initialization of the page class.
774 makeproto Class
*InitPageClass(void)
776 return BGUI_MakeClass(CLASS_SuperClassBGUI
, BGUI_BASE_GADGET
,
777 CLASS_ObjectSize
, sizeof(PD
),
778 CLASS_DFTable
, ClassFunc
,