2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2015, 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/muimaster.h>
17 /* #define MYDEBUG 1 */
19 #include "muimaster_intern.h"
22 extern struct Library
*MUIMasterBase
;
30 * Family class is the base class for objects that are able
31 * to handle a list of children. This is e.g. the case for
32 * MUIs Menustrip, Menu and Menuitem objects.
33 * Group class and application class should also be a
34 * subclass of Family class, but due to BOOPSI system
35 * limitations, this is currently impossible.
39 Family.mui/MUIA_Family_Child [I..] done (note : == MUIA_Group_Child)
40 Family.mui/MUIA_Family_List [..G] done
42 Family.mui/MUIM_Family_AddHead done
43 Family.mui/MUIM_Family_AddTail done
44 Family.mui/MUIM_Family_Insert done
45 Family.mui/MUIM_Family_Remove done
46 Family.mui/MUIM_Family_Sort done
47 Family.mui/MUIM_Family_Transfer done
48 Notify.mui/MUIM_FindUData done
49 Notify.mui/MUIM_GetUData done
50 Notify.mui/MUIM_SetUData done
51 Notify.mui/MUIM_SetUDataOnce done
54 static const int __version
= 1;
55 static const int __revision
= 1;
58 /* debuglist(struct List *list) */
60 /* g_print("list %p:\nlh_Head@%p = %p\nlh_Tail@%p = %p\nlh_TailPred@%p = %p\n", */
61 /* list, &list->lh_Head, list->lh_Head, */
62 /* &list->lh_Tail, list->lh_Tail, */
63 /* &list->lh_TailPred, list->lh_TailPred); */
67 /* printlist (struct List *list) */
69 /* struct Node *node; */
71 /* debuglist(list); */
73 /* for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) */
75 /* g_print("%s (ln_Succ@%p = %p | ln_Pred@%p = %p)\n", "node->ln_Name", */
76 /* &node->ln_Succ, node->ln_Succ, &node->ln_Pred, node->ln_Pred); */
84 IPTR
Family__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
86 struct MUI_FamilyData
*data
;
89 BOOL bad_children
= FALSE
;
91 obj
= (Object
*) DoSuperMethodA(cl
, obj
, (Msg
) msg
);
95 * Initial local instance data
97 data
= INST_DATA(cl
, obj
);
98 NewList(&(data
->children
));
101 * parse initial taglist
103 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
105 if (tag
->ti_Tag
== MUIA_Family_Child
106 || tag
->ti_Tag
== MUIA_Group_Child
)
108 if (tag
->ti_Data
) /* add child */
109 DoMethod(obj
, MUIM_Family_AddTail
, tag
->ti_Data
);
110 else /* fail and dispose children */
119 CoerceMethod(cl
, obj
, OM_DISPOSE
);
130 IPTR
Family__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
132 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
133 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
136 while ((child
= NextObject(&cstate
)))
138 /* g_print("Family_Dispose: dispose child %p\n", child); */
139 MUI_DisposeObject(child
);
142 return DoSuperMethodA(cl
, obj
, msg
);
149 IPTR
Family__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
151 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
152 IPTR
*store
= msg
->opg_Storage
;
154 switch (msg
->opg_AttrID
)
156 case MUIA_Family_List
:
157 *store
= (IPTR
) & data
->children
;
168 case MUIA_Family_ChildCount
:
170 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
172 while (NextObject(&cstate
))
178 return (DoSuperMethodA(cl
, obj
, (Msg
) msg
));
183 * MUIM_Family_AddHead : Add an object as first object to the family.
185 IPTR
Family__MUIM_AddHead(struct IClass
*cl
, Object
*obj
,
186 struct MUIP_Family_AddHead
*msg
)
188 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
192 AddHead(&(data
->children
), (struct Node
*)_OBJECT(msg
->obj
));
194 /* if we are in an application tree, propagate pointers */
195 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
197 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
200 /* Some apps (Odyssey) expect _parent() will work before group tree
201 * is added to application tree */
202 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
212 * MUIM_Family_AddTail : Add an object as last object to the family.
214 IPTR
Family__MUIM_AddTail(struct IClass
*cl
, Object
*obj
,
215 struct MUIP_Family_AddTail
*msg
)
217 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
221 D(bug("Family_AddTail(%p): obj=%p node=%p\n", obj
, msg
->obj
,
223 DoMethod(msg
->obj
, OM_ADDTAIL
, (IPTR
) & data
->children
);
225 /* if we are in an application tree, propagate pointers */
226 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
228 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
231 /* Some apps (Odyssey) expect _parent() will work before group tree
232 * is added to application tree */
233 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
243 * MUIM_Family_Insert : Add an object after another object to the family.
245 IPTR
Family__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
246 struct MUIP_Family_Insert
*msg
)
248 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
252 Insert(&(data
->children
), (struct Node
*)_OBJECT(msg
->obj
),
253 (struct Node
*)_OBJECT(msg
->pred
));
255 /* if we are in an application tree, propagate pointers */
256 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
258 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
261 /* Some apps (Odyssey) expect _parent() will work before group tree
262 * is added to application tree */
263 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
273 * MUIM_Family_Remove : Remove an object from a family.
275 IPTR
Family__MUIM_Remove(struct IClass
*cl
, Object
*obj
,
276 struct MUIP_Family_Remove
*msg
)
278 /* struct MUI_FamilyData *data = INST_DATA(cl, obj);
279 struct Node *node; */
283 /* D(bug("Family_Remove(%p): obj=%p\n", obj, msg->obj)); */
284 DoMethod(msg
->obj
, MUIM_DisconnectParent
);
285 muiNotifyData(msg
->obj
)->mnd_ParentObject
= NULL
;
286 DoMethod(msg
->obj
, OM_REMOVE
);
295 * MUIM_Family_Sort : Sort the children of a family.
297 IPTR
Family__MUIM_Sort(struct IClass
*cl
, Object
*obj
,
298 struct MUIP_Family_Sort
*msg
)
300 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
303 NewList(&(data
->children
));
304 for (i
= 0; msg
->obj
[i
]; i
++)
306 AddTail(&(data
->children
), (struct Node
*)_OBJECT(msg
->obj
[i
]));
313 * MUIM_Family_Transfer : All the children of the family are removed and
314 * added to another family in the same order.
316 IPTR
Family__MUIM_Transfer(struct IClass
*cl
, Object
*obj
,
317 struct MUIP_Family_Transfer
*msg
)
319 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
320 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
323 while ((child
= NextObject(&cstate
)))
325 DoMethod(obj
, MUIM_Family_Remove
, (IPTR
) child
);
326 DoMethod(msg
->family
, MUIM_Family_AddTail
, (IPTR
) child
);
332 /**************************************************************************
333 MUIM_FindUData : tests if the MUIA_UserData of the object
334 contains the given <udata> and returns the object pointer in this case.
335 **************************************************************************/
336 IPTR
Family__MUIM_FindUData(struct IClass
*cl
, Object
*obj
,
337 struct MUIP_FindUData
*msg
)
339 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
340 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
343 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
346 while ((child
= NextObject(&cstate
)))
348 Object
*found
= (Object
*) DoMethodA(child
, (Msg
) msg
);
357 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
358 * contains the given <udata> and gets <attr> to <storage> for itself
361 IPTR
Family__MUIM_GetUData(struct IClass
*cl
, Object
*obj
,
362 struct MUIP_GetUData
*msg
)
364 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
365 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
368 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
370 get(obj
, msg
->attr
, msg
->storage
);
373 while ((child
= NextObject(&cstate
)))
374 if (DoMethodA(child
, (Msg
) msg
))
382 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
383 * contains the given <udata> and sets <attr> to <val> for itself in this case.
385 IPTR
Family__MUIM_SetUData(struct IClass
*cl
, Object
*obj
,
386 struct MUIP_SetUData
*msg
)
388 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
389 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
392 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
393 set(obj
, msg
->attr
, msg
->val
);
395 while ((child
= NextObject(&cstate
)))
396 DoMethodA(child
, (Msg
) msg
);
403 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
404 * contains the given <udata> and sets <attr> to <val> for itself in this case.
406 IPTR
Family__MUIM_SetUDataOnce(struct IClass
*cl
, Object
*obj
,
407 struct MUIP_SetUDataOnce
*msg
)
409 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
410 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
413 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
415 set(obj
, msg
->attr
, msg
->val
);
418 while ((child
= NextObject(&cstate
)))
419 if (DoMethodA(child
, (Msg
) msg
))
425 IPTR
Family__MUIM_GetChild(struct IClass
*cl
, Object
*obj
,
426 struct MUIP_Family_GetChild
*msg
)
428 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
429 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
430 Object
*child
, *prev
= NULL
;
433 while ((child
= NextObject(&cstate
)))
435 if ((msg
->nr
>= 0) && (msg
->nr
== counter
))
438 if ((msg
->ref
!= NULL
) && (msg
->ref
== child
))
440 if (msg
->nr
== MUIV_Family_GetChild_Next
)
441 return (IPTR
) NextObject(&cstate
);
442 if (msg
->nr
== MUIV_Family_GetChild_Previous
)
446 if (msg
->nr
== MUIV_Family_GetChild_First
)
453 if (msg
->nr
== MUIV_Family_GetChild_Last
)
459 BOOPSI_DISPATCHER(IPTR
, Family_Dispatcher
, cl
, obj
, msg
)
461 switch (msg
->MethodID
)
464 return Family__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
467 return Family__OM_DISPOSE(cl
, obj
, msg
);
470 return Family__OM_GET(cl
, obj
, (struct opGet
*)msg
);
472 case MUIM_Family_AddHead
:
473 return Family__MUIM_AddHead(cl
, obj
, (APTR
) msg
);
476 case MUIM_Family_AddTail
:
477 return Family__MUIM_AddTail(cl
, obj
, (APTR
) msg
);
479 case MUIM_Family_Insert
:
480 return Family__MUIM_Insert(cl
, obj
, (APTR
) msg
);
483 case MUIM_Family_Remove
:
484 return Family__MUIM_Remove(cl
, obj
, (APTR
) msg
);
486 case MUIM_Family_Sort
:
487 return Family__MUIM_Sort(cl
, obj
, (APTR
) msg
);
489 case MUIM_Family_Transfer
:
490 return Family__MUIM_Transfer(cl
, obj
, (APTR
) msg
);
493 return Family__MUIM_FindUData(cl
, obj
, (APTR
) msg
);
496 return Family__MUIM_GetUData(cl
, obj
, (APTR
) msg
);
499 return Family__MUIM_SetUData(cl
, obj
, (APTR
) msg
);
501 case MUIM_SetUDataOnce
:
502 return Family__MUIM_SetUDataOnce(cl
, obj
, (APTR
) msg
);
504 case MUIM_Family_GetChild
:
505 return Family__MUIM_GetChild(cl
, obj
, (APTR
) msg
);
508 return (DoSuperMethodA(cl
, obj
, msg
));
510 BOOPSI_DISPATCHER_END
515 const struct __MUIBuiltinClass _MUI_Family_desc
=
519 sizeof(struct MUI_FamilyData
),
520 (void *) Family_Dispatcher