@DataBase "FC_Family"
@Author Olivier Laviale : Lotan <lotan9@aol.com> © 2002
@SmartWrap

@Node Main "Feelin : FC_Family"
@{lindent 2}@{PAR}
@{b}@{u}FC_Family@{ub}@{uu}@{PAR}@{lindent 4}

@{b}FC_Family@{ub} class handles a list of children. This is e.g. the case for
@{"Clients" link FC_Client.guide/Main}, @{"Groups" link FC_Group.guide/Main}, @{"Menus" link FC_Menu.guide/Main}...@{PAR}

These classes are not subclasses of @{b}FC_Family@{ub}. Family objects are simple
objects, but as a subclass of @{"FC_Tool" link FC_Tool.guide/Main}, they know about their @{i}owner@{ui} and
can communicate with it. Take a look at @{"FA_Family" link FA_Family} to see how things work.@{PAR}

@{b}FC_Family@{ub} defines methods and attributes to add and remove children, sort
children, and transfer children to other Family objects.@{PAR}

@{b}FC_Family@{ub} automatically set, and unset, the attribute @{"FA_Parent" link F_Object.guide/FA_Parent} to
the owner of the family e.i the real parent of the child.@{PAR}@{lindent 2}

@{b}Methods@{ub}@{PAR}@{lindent 4}

@{" FM_AddMember       " link FM_Family_AddMember}
@{" FM_RemMember       " link FM_Family_RemMember}@{PAR}

@{" FM_Family_AddHead  " link FM_Family_AddHead}
@{" FM_Family_AddTail  " link FM_Family_AddTail}
@{" FM_Family_Insert   " link FM_Family_Insert}
@{" FM_Family_Remove   " link FM_Family_Remove}
@{" FM_Family_Sort     " link FM_Family_Sort}
@{" FM_Family_Transfer " link FM_Family_Transfer}@{PAR}@{lindent 2}

@{b}Attributes@{ub}@{PAR}@{lindent 4}

@{" FA_Child           " link FA_Child}
@{" FA_Family          " link FA_Family}
@{" FA_Family_Head     " link FA_Family_Head}
@{" FA_Family_List     " link FA_Family_List}
@{" FA_Family_Tail     " link FA_Family_Tail}@{PAR}
@EndNode

@Node FM_Family_AddMember "FC_Family / FM_Family_AddMember"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_AddMember -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_AddMember,struct FeelinObject *child)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Synonimus to @{"FM_Family_AddTail" link FM_Family_AddTail}.@{PAR}
@EndNode
@Node FM_Family_RemMember "FC_Family / FM_Family_RemMember"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_RemMember -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_RemMember,struct FeelinObject *child)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Synonimus to @{"FM_Family_Remove" link FM_Family_Remove}.@{PAR}
@EndNode

@Node FM_Family_AddHead "FC_Family / FM_Family_AddHead"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_AddHead -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_AddHead,struct FeelinObject *child)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Add an object as first object to the family. Classes using @{b}FC_Family @{ub}
usually define which types of objects are possible within their family.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}child@{ub} - the object to be added.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FM_Family_AddTail  " link FM_Family_AddTail}
@{" FM_Family_Insert   " link FM_Family_Insert}
@{" FM_Family_Remove   " link FM_Family_Remove}@{PAR}

@{" FA_Child           " link FA_Child}@{PAR}
@EndNode
@Node FM_Family_AddTail "FC_Family / FM_Family_AddTail"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_AddTail -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_AddTail,struct FeelinObject *child)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Add an object as last object to the family. Classes using @{b}FC_Family @{ub}
usually define which types of objects are possible within their family.@{PAR}

This method has @{fg highlight}FM_AddMember@{fg text} as synonimus.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}obj@{ub} - the object to be added.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FM_Family_AddHead  " link FM_Family_AddHead}
@{" FM_Family_Insert   " link FM_Family_Insert}
@{" FM_Family_Remove   " link FM_Family_Remove}@{PAR}

@{" FA_Child           " link FA_Child}@{PAR}
@EndNode
@Node FM_Family_Insert "FC_Family / FM_Family_Insert"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_Insert -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_Insert,struct FeelinObject *child,struct FeelinObject *pred)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Add an object after another object to the family. Classes using @{b}FC_Family @{ub}
usually define which types of objects are possible within their family.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}child@{ub} - the object to be added.@{PAR}
@{b}pred@{ub} - the new object is inserted @{u}after@{uu} this object. @{b}pred@{ub} must of course be
a member of the family.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FM_Family_AddHead  " link FM_Family_AddHead}
@{" FM_Family_AddTail  " link FM_Family_AddTail}
@{" FM_Family_Remove   " link FM_Family_Remove}@{PAR}

@{" FA_Child           " link FA_Child}@{PAR}
@EndNode
@Node FM_Family_Remove "FC_Family / FM_Family_Remove"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_Remove -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_Remove,struct FeelinObject *child)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Remove an object from a family.@{PAR}

This method has @{fg highlight}FM_RemMember@{fg text} as synonimus.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}child@{ub} - the object to be removed.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FM_Family_AddHead  " link FM_Family_AddHead}
@{" FM_Family_AddTail  " link FM_Family_AddTail}
@{" FM_Family_Insert   " link FM_Family_Insert}@{PAR}

@{" FA_Child           " link FA_Child}@{PAR}
@EndNode
@Node FM_Family_Sort "FC_Family / FM_Family_Sort"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_Sort -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_Sort,struct FeelinObject *child1, ..., struct FeelinObject *childn,ULONG NULL)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Sort the children of a family.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

Array that contains @{u}all@{uu} the children of the family in the desired order. The
array @{u}must@{uu} be terminated with a NULL entry.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Child " link FA_Child}@{PAR}
@EndNode
@Node FM_Family_Transfer "FC_Family / FM_Family_Transfer"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FM_Family_Transfer -- (00.00)@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{PAR}@{lindent 4}

F_Do(obj,FM_Family_Transfer,APTR family)@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

All the children of the family are removed and added to another family in
the same order.@{PAR}@{lindent 2}

@{fg shine}@{b}INPUTS@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}family@{ub} - the destination family.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Child           " link FA_Child}@{PAR}
@EndNode

@Node FA_Child "FC_Family / FA_Child"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FA_Child -- (00.00) [I..], struct FeelinObject *@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

You supply a pointer to a previously created Feelin object here. This object
will be added to the family at family creation time. Of course you can
specify any number of child objects, limited only by available memory.@{PAR}

Normally, the value for a @{fg shine}FA_Child@{fg text} tag is a direct call to another
@{"F_NewObjA()" link Feelin.guide/F_NewObjA}, children are generated @{i}on the fly@{ui}.@{PAR}

When a family is disposed, all of its children will also get deleted. If you
supply a NULL pointer as child, the family object will fail and previously
dispose all valid children found in the taglist.@{PAR}

This behaviour makes it possible to generate a complete family within one
single (but long) @{"F_NewObjA()" link Feelin.guide/F_NewObjA} call. Error checking is not necessary since
every error, even if it occurs in a very deep nesting level, will cause the
complete call to fail without leaving back any previously created object.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FM_Family_AddHead  " link FM_Family_AddHead}
@{" FM_Family_AddTail  " link FM_Family_AddTail}
@{" FM_Family_Insert   " link FM_Family_Insert}
@{" FM_Family_Remove   " link FM_Family_Remove}@{PAR}

@{" FA_Family          " link FA_Family}@{PAR}
@EndNode
@Node FA_Family "FC_Family / FA_Family"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FA_Family -- (00.00) [..G], APTR@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

This attribute is designed to communicate with the owner of the Family
object. Classes with Family capabilities are not subclasses of the @{b}FC_Family@{ub},
they use a Family object as a @{"Tool" link F_Tool.guide/Main}.@{PAR}

The attribute @{fg shine}FA_Family@{fg text} may be used by classes to return a pointer to their
Family object.@{PAR}@{lindent 2}

@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{PAR}@{lindent 4}

@{fg highlight}FM_New@{fg text}:@{lindent 8}@{PAR}
if (@{fg highlight}F_NewObj@{fg text}(@{fg shine}FC_Family@{fg text},@{PAR}
             @{fg shine}FA_Tool_Owner@{fg text}, obj,    /* Pointer to the object holding the Family Object */@{PAR}
             TAG_MORE,      tags,   /* TagItems that comes with the FM_New method */@{PAR}
             TAG_DONE))@{PAR}
{@{PAR}

/* If some children have failed i.e @{"FA_Child" link FA_Child} is found NULL in the taglist,
all children in the taglist will be disposed by the @{b}FC_Family@{ub}, and the
Family object will fail to create. Do not save Family object pointer here !!
This will be done automatically if everything was ok using the @{fg shine}FA_Family @{fg text}
attribute, just check for NULL */@{PAR}

   return obj;@{PAR}
}@{PAR}@{lindent 4}

@{fg highlight}FM_Dispose@{fg text}:@{lindent 8}@{PAR}
Self->Family = (APTR)@{fg highlight}F_DisposeObj@{fg text}(Self->Family);@{PAR}

/* When Family object is disposed all children are disposed too. Remember
that @{"F_DisposeObj()" link Feelin.guide/F_DisposeObj} always return NULL and handles NULL pointers */@{PAR}@{lindent 4}

@{fg highlight}FM_Set@{fg text}:@{lindent 8}@{PAR}
while (item = NextTagItem(&Tags))@{PAR}
{@{PAR}
    switch (item->ti_Tag)@{PAR}
    {@{PAR}
        case @{fg shine}FA_Family@{fg text}: LOD->Family = item->ti_Data; break; /* Only save Family object pointer here */@{PAR}
        ...@{PAR}
    }@{PAR}
}@{PAR}@{lindent 4}

@{fg highlight}FM_Get@{fg text}:@{lindent 8}@{PAR}
while (item = NextTagItem(&tags))
{@{PAR}
    save = item->ti_Data;@{PAR}

    switch (item->ti_Tag)@{PAR}
    {@{PAR}
        case @{fg shine}FA_Family@{fg text}: *save = LOD->Family; break; /* This is recommended */@{PAR}
        ...@{PAR}
    }@{PAR}
}@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Child " link FA_Child}@{PAR}
@EndNode
@Node FA_Family_List "FC_Family / FA_Family_List"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FA_Family_List -- (00.00) [..G], struct FeelinList *@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Returns a pointer to a struct FeelinList which contains the children of a
family object. You must parse this list with @{"F_NextObject()" link Feelin.guide/F_NextObject}.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Child " link FA_Child}@{PAR}
@EndNode
@Node FA_Family_Head "FC_Family / FA_Family_Head"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FA_Family_Head -- (00.00) [..G], struct FeelinObject *@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Returns a pointer to the first object of the family.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Family_List " link FA_Family_List}
@{" FA_Family_Tail " link FA_Family_Tail}@{PAR}
@EndNode
@Node FA_Family_Tail "FC_Family / FA_Family_Tail"
@{lindent 2}@{PAR}
@{fg shine}@{b}NAME@{ub}@{fg text}@{PAR}@{lindent 4}

@{b}FA_Family_Tail -- (00.00) [..G], struct FeelinObject *@{ub}@{PAR}@{lindent 2}

@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{PAR}@{lindent 4}

Returns a pointer to the last object of the family.@{PAR}@{lindent 2}

@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{PAR}@{lindent 4}

@{" FA_Family_Head " link FA_Family_Head}
@{" FA_Family_List " link FA_Family_List}@{PAR}
@EndNode
