childs -> children.
[AROS.git] / workbench / libs / muimaster / classes / family.c
blobdb2be6150a435b38e4186b7563099aee2b80887d
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2012, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
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 */
18 #include "debug.h"
19 #include "muimaster_intern.h"
20 #include "mui.h"
22 extern struct Library *MUIMasterBase;
24 struct MUI_FamilyData
26 struct List children;
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;
57 /* static void */
58 /* debuglist(struct List *list) */
59 /* { */
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); */
64 /* } */
66 /* static void */
67 /* printlist (struct List *list) */
68 /* { */
69 /* struct Node *node; */
71 /* debuglist(list); */
73 /* for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) */
74 /* { */
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); */
77 /* } */
78 /* g_print("\n"); */
79 /* } */
82 * OM_NEW
84 IPTR Family__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
86 struct MUI_FamilyData *data;
87 struct TagItem *tags;
88 struct TagItem *tag;
89 BOOL bad_children = FALSE;
91 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
92 if (!obj)
93 return FALSE;
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 */
112 bad_children = TRUE;
117 if (bad_children)
119 CoerceMethod(cl, obj, OM_DISPOSE);
120 return 0;
123 return (IPTR) obj;
128 * 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;
134 Object *child;
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);
147 * OM_GET
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;
158 return TRUE;
160 case MUIA_Version:
161 *store = __version;
162 return TRUE;
164 case MUIA_Revision:
165 *store = __revision;
166 return TRUE;
168 case MUIA_Family_ChildCount:
170 Object *cstate = (Object *) data->children.lh_Head;
171 *store = 0;
172 while (NextObject(&cstate))
173 (*store)++;
174 return TRUE;
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);
190 if (msg->obj)
192 AddHead(&(data->children), (struct Node *)_OBJECT(msg->obj));
193 return TRUE;
195 else
196 return FALSE;
201 * MUIM_Family_AddTail : Add an object as last object to the family.
203 IPTR Family__MUIM_AddTail(struct IClass *cl, Object *obj,
204 struct MUIP_Family_AddTail *msg)
206 struct MUI_FamilyData *data = INST_DATA(cl, obj);
208 if (msg->obj)
210 D(bug("Family_AddTail(%p): obj=%p node=%p\n", obj, msg->obj,
211 _OBJECT(msg->obj)));
212 DoMethod(msg->obj, OM_ADDTAIL, (IPTR) & data->children);
213 return TRUE;
215 else
216 return FALSE;
221 * MUIM_Family_Insert : Add an object after another object to the family.
223 IPTR Family__MUIM_Insert(struct IClass *cl, Object *obj,
224 struct MUIP_Family_Insert *msg)
226 struct MUI_FamilyData *data = INST_DATA(cl, obj);
228 if (msg->obj)
230 Insert(&(data->children), (struct Node *)_OBJECT(msg->obj),
231 (struct Node *)_OBJECT(msg->pred));
232 return TRUE;
234 else
235 return FALSE;
240 * MUIM_Family_Remove : Remove an object from a family.
242 IPTR Family__MUIM_Remove(struct IClass *cl, Object *obj,
243 struct MUIP_Family_Remove *msg)
245 /* struct MUI_FamilyData *data = INST_DATA(cl, obj);
246 struct Node *node; */
248 if (msg->obj)
250 /* D(bug("Family_Remove(%p): obj=%p\n", obj, msg->obj)); */
251 DoMethod(msg->obj, OM_REMOVE);
252 return TRUE;
254 else
255 return FALSE;
260 * MUIM_Family_Sort : Sort the children of a family.
262 IPTR Family__MUIM_Sort(struct IClass *cl, Object *obj,
263 struct MUIP_Family_Sort *msg)
265 struct MUI_FamilyData *data = INST_DATA(cl, obj);
266 int i;
268 NewList(&(data->children));
269 for (i = 0; msg->obj[i]; i++)
271 AddTail(&(data->children), (struct Node *)_OBJECT(msg->obj[i]));
273 return TRUE;
278 * MUIM_Family_Transfer : All the children of the family are removed and
279 * added to another family in the same order.
281 IPTR Family__MUIM_Transfer(struct IClass *cl, Object *obj,
282 struct MUIP_Family_Transfer *msg)
284 struct MUI_FamilyData *data = INST_DATA(cl, obj);
285 Object *cstate = (Object *) data->children.lh_Head;
286 Object *child;
288 while ((child = NextObject(&cstate)))
290 DoMethod(obj, MUIM_Family_Remove, (IPTR) child);
291 DoMethod(msg->family, MUIM_Family_AddTail, (IPTR) child);
293 return TRUE;
297 /**************************************************************************
298 MUIM_FindUData : tests if the MUIA_UserData of the object
299 contains the given <udata> and returns the object pointer in this case.
300 **************************************************************************/
301 IPTR Family__MUIM_FindUData(struct IClass *cl, Object *obj,
302 struct MUIP_FindUData *msg)
304 struct MUI_FamilyData *data = INST_DATA(cl, obj);
305 Object *cstate = (Object *) data->children.lh_Head;
306 Object *child;
308 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
309 return (IPTR) obj;
311 while ((child = NextObject(&cstate)))
313 Object *found = (Object *) DoMethodA(child, (Msg) msg);
314 if (found)
315 return (IPTR) found;
317 return 0;
322 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
323 * contains the given <udata> and gets <attr> to <storage> for itself
324 * in this case.
326 IPTR Family__MUIM_GetUData(struct IClass *cl, Object *obj,
327 struct MUIP_GetUData *msg)
329 struct MUI_FamilyData *data = INST_DATA(cl, obj);
330 Object *cstate = (Object *) data->children.lh_Head;
331 Object *child;
333 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
335 get(obj, msg->attr, msg->storage);
336 return TRUE;
338 while ((child = NextObject(&cstate)))
339 if (DoMethodA(child, (Msg) msg))
340 return TRUE;
342 return FALSE;
347 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
348 * contains the given <udata> and sets <attr> to <val> for itself in this case.
350 IPTR Family__MUIM_SetUData(struct IClass *cl, Object *obj,
351 struct MUIP_SetUData *msg)
353 struct MUI_FamilyData *data = INST_DATA(cl, obj);
354 Object *cstate = (Object *) data->children.lh_Head;
355 Object *child;
357 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
358 set(obj, msg->attr, msg->val);
360 while ((child = NextObject(&cstate)))
361 DoMethodA(child, (Msg) msg);
363 return TRUE;
368 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
369 * contains the given <udata> and sets <attr> to <val> for itself in this case.
371 IPTR Family__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
372 struct MUIP_SetUDataOnce *msg)
374 struct MUI_FamilyData *data = INST_DATA(cl, obj);
375 Object *cstate = (Object *) data->children.lh_Head;
376 Object *child;
378 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
380 set(obj, msg->attr, msg->val);
381 return TRUE;
383 while ((child = NextObject(&cstate)))
384 if (DoMethodA(child, (Msg) msg))
385 return TRUE;
387 return FALSE;
390 IPTR Family__MUIM_GetChild(struct IClass *cl, Object *obj,
391 struct MUIP_Family_GetChild *msg)
393 struct MUI_FamilyData *data = INST_DATA(cl, obj);
394 Object *cstate = (Object *) data->children.lh_Head;
395 Object *child, *prev = NULL;
396 LONG counter = 0;
398 while ((child = NextObject(&cstate)))
400 if ((msg->nr >= 0) && (msg->nr == counter))
401 return (IPTR) child;
403 if ((msg->ref != NULL) && (msg->ref == child))
405 if (msg->nr == MUIV_Family_GetChild_Next)
406 return (IPTR) NextObject(&cstate);
407 if (msg->nr == MUIV_Family_GetChild_Previous)
408 return (IPTR) prev;
411 if (msg->nr == MUIV_Family_GetChild_First)
412 return (IPTR) child;
414 prev = child;
415 counter++;
418 if (msg->nr == MUIV_Family_GetChild_Last)
419 return (IPTR) prev;
421 return (IPTR) NULL;
424 BOOPSI_DISPATCHER(IPTR, Family_Dispatcher, cl, obj, msg)
426 switch (msg->MethodID)
428 case OM_NEW:
429 return Family__OM_NEW(cl, obj, (struct opSet *)msg);
431 case OM_DISPOSE:
432 return Family__OM_DISPOSE(cl, obj, msg);
434 case OM_GET:
435 return Family__OM_GET(cl, obj, (struct opGet *)msg);
437 case MUIM_Family_AddHead:
438 return Family__MUIM_AddHead(cl, obj, (APTR) msg);
440 case OM_ADDMEMBER:
441 case MUIM_Family_AddTail:
442 return Family__MUIM_AddTail(cl, obj, (APTR) msg);
444 case MUIM_Family_Insert:
445 return Family__MUIM_Insert(cl, obj, (APTR) msg);
447 case OM_REMMEMBER:
448 case MUIM_Family_Remove:
449 return Family__MUIM_Remove(cl, obj, (APTR) msg);
451 case MUIM_Family_Sort:
452 return Family__MUIM_Sort(cl, obj, (APTR) msg);
454 case MUIM_Family_Transfer:
455 return Family__MUIM_Transfer(cl, obj, (APTR) msg);
457 case MUIM_FindUData:
458 return Family__MUIM_FindUData(cl, obj, (APTR) msg);
460 case MUIM_GetUData:
461 return Family__MUIM_GetUData(cl, obj, (APTR) msg);
463 case MUIM_SetUData:
464 return Family__MUIM_SetUData(cl, obj, (APTR) msg);
466 case MUIM_SetUDataOnce:
467 return Family__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
469 case MUIM_Family_GetChild:
470 return Family__MUIM_GetChild(cl, obj, (APTR) msg);
473 return (DoSuperMethodA(cl, obj, msg));
475 BOOPSI_DISPATCHER_END
478 * Class descriptor.
480 const struct __MUIBuiltinClass _MUI_Family_desc =
482 MUIC_Family,
483 MUIC_Notify,
484 sizeof(struct MUI_FamilyData),
485 (void *) Family_Dispatcher