2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2013, 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 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
198 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
209 * MUIM_Family_AddTail : Add an object as last object to the family.
211 IPTR
Family__MUIM_AddTail(struct IClass
*cl
, Object
*obj
,
212 struct MUIP_Family_AddTail
*msg
)
214 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
218 D(bug("Family_AddTail(%p): obj=%p node=%p\n", obj
, msg
->obj
,
220 DoMethod(msg
->obj
, OM_ADDTAIL
, (IPTR
) & data
->children
);
222 /* if we are in an application tree, propagate pointers */
223 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
225 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
226 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
237 * MUIM_Family_Insert : Add an object after another object to the family.
239 IPTR
Family__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
240 struct MUIP_Family_Insert
*msg
)
242 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
246 Insert(&(data
->children
), (struct Node
*)_OBJECT(msg
->obj
),
247 (struct Node
*)_OBJECT(msg
->pred
));
249 /* if we are in an application tree, propagate pointers */
250 if (muiNotifyData(obj
)->mnd_GlobalInfo
)
252 muiNotifyData(msg
->obj
)->mnd_ParentObject
= obj
;
253 DoMethod(msg
->obj
, MUIM_ConnectParent
, (IPTR
)obj
);
264 * MUIM_Family_Remove : Remove an object from a family.
266 IPTR
Family__MUIM_Remove(struct IClass
*cl
, Object
*obj
,
267 struct MUIP_Family_Remove
*msg
)
269 /* struct MUI_FamilyData *data = INST_DATA(cl, obj);
270 struct Node *node; */
274 /* D(bug("Family_Remove(%p): obj=%p\n", obj, msg->obj)); */
275 DoMethod(msg
->obj
, MUIM_DisconnectParent
);
276 muiNotifyData(msg
->obj
)->mnd_ParentObject
= NULL
;
277 DoMethod(msg
->obj
, OM_REMOVE
);
286 * MUIM_Family_Sort : Sort the children of a family.
288 IPTR
Family__MUIM_Sort(struct IClass
*cl
, Object
*obj
,
289 struct MUIP_Family_Sort
*msg
)
291 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
294 NewList(&(data
->children
));
295 for (i
= 0; msg
->obj
[i
]; i
++)
297 AddTail(&(data
->children
), (struct Node
*)_OBJECT(msg
->obj
[i
]));
304 * MUIM_Family_Transfer : All the children of the family are removed and
305 * added to another family in the same order.
307 IPTR
Family__MUIM_Transfer(struct IClass
*cl
, Object
*obj
,
308 struct MUIP_Family_Transfer
*msg
)
310 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
311 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
314 while ((child
= NextObject(&cstate
)))
316 DoMethod(obj
, MUIM_Family_Remove
, (IPTR
) child
);
317 DoMethod(msg
->family
, MUIM_Family_AddTail
, (IPTR
) child
);
323 /**************************************************************************
324 MUIM_FindUData : tests if the MUIA_UserData of the object
325 contains the given <udata> and returns the object pointer in this case.
326 **************************************************************************/
327 IPTR
Family__MUIM_FindUData(struct IClass
*cl
, Object
*obj
,
328 struct MUIP_FindUData
*msg
)
330 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
331 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
334 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
337 while ((child
= NextObject(&cstate
)))
339 Object
*found
= (Object
*) DoMethodA(child
, (Msg
) msg
);
348 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
349 * contains the given <udata> and gets <attr> to <storage> for itself
352 IPTR
Family__MUIM_GetUData(struct IClass
*cl
, Object
*obj
,
353 struct MUIP_GetUData
*msg
)
355 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
356 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
359 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
361 get(obj
, msg
->attr
, msg
->storage
);
364 while ((child
= NextObject(&cstate
)))
365 if (DoMethodA(child
, (Msg
) msg
))
373 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
374 * contains the given <udata> and sets <attr> to <val> for itself in this case.
376 IPTR
Family__MUIM_SetUData(struct IClass
*cl
, Object
*obj
,
377 struct MUIP_SetUData
*msg
)
379 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
380 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
383 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
384 set(obj
, msg
->attr
, msg
->val
);
386 while ((child
= NextObject(&cstate
)))
387 DoMethodA(child
, (Msg
) msg
);
394 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
395 * contains the given <udata> and sets <attr> to <val> for itself in this case.
397 IPTR
Family__MUIM_SetUDataOnce(struct IClass
*cl
, Object
*obj
,
398 struct MUIP_SetUDataOnce
*msg
)
400 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
401 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
404 if (muiNotifyData(obj
)->mnd_UserData
== msg
->udata
)
406 set(obj
, msg
->attr
, msg
->val
);
409 while ((child
= NextObject(&cstate
)))
410 if (DoMethodA(child
, (Msg
) msg
))
416 IPTR
Family__MUIM_GetChild(struct IClass
*cl
, Object
*obj
,
417 struct MUIP_Family_GetChild
*msg
)
419 struct MUI_FamilyData
*data
= INST_DATA(cl
, obj
);
420 Object
*cstate
= (Object
*) data
->children
.lh_Head
;
421 Object
*child
, *prev
= NULL
;
424 while ((child
= NextObject(&cstate
)))
426 if ((msg
->nr
>= 0) && (msg
->nr
== counter
))
429 if ((msg
->ref
!= NULL
) && (msg
->ref
== child
))
431 if (msg
->nr
== MUIV_Family_GetChild_Next
)
432 return (IPTR
) NextObject(&cstate
);
433 if (msg
->nr
== MUIV_Family_GetChild_Previous
)
437 if (msg
->nr
== MUIV_Family_GetChild_First
)
444 if (msg
->nr
== MUIV_Family_GetChild_Last
)
450 BOOPSI_DISPATCHER(IPTR
, Family_Dispatcher
, cl
, obj
, msg
)
452 switch (msg
->MethodID
)
455 return Family__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
458 return Family__OM_DISPOSE(cl
, obj
, msg
);
461 return Family__OM_GET(cl
, obj
, (struct opGet
*)msg
);
463 case MUIM_Family_AddHead
:
464 return Family__MUIM_AddHead(cl
, obj
, (APTR
) msg
);
467 case MUIM_Family_AddTail
:
468 return Family__MUIM_AddTail(cl
, obj
, (APTR
) msg
);
470 case MUIM_Family_Insert
:
471 return Family__MUIM_Insert(cl
, obj
, (APTR
) msg
);
474 case MUIM_Family_Remove
:
475 return Family__MUIM_Remove(cl
, obj
, (APTR
) msg
);
477 case MUIM_Family_Sort
:
478 return Family__MUIM_Sort(cl
, obj
, (APTR
) msg
);
480 case MUIM_Family_Transfer
:
481 return Family__MUIM_Transfer(cl
, obj
, (APTR
) msg
);
484 return Family__MUIM_FindUData(cl
, obj
, (APTR
) msg
);
487 return Family__MUIM_GetUData(cl
, obj
, (APTR
) msg
);
490 return Family__MUIM_SetUData(cl
, obj
, (APTR
) msg
);
492 case MUIM_SetUDataOnce
:
493 return Family__MUIM_SetUDataOnce(cl
, obj
, (APTR
) msg
);
495 case MUIM_Family_GetChild
:
496 return Family__MUIM_GetChild(cl
, obj
, (APTR
) msg
);
499 return (DoSuperMethodA(cl
, obj
, msg
));
501 BOOPSI_DISPATCHER_END
506 const struct __MUIBuiltinClass _MUI_Family_desc
=
510 sizeof(struct MUI_FamilyData
),
511 (void *) Family_Dispatcher