Listtree.mcc: implement handling of destruct hook
[AROS.git] / workbench / classes / zune / listtree / listtree.c
blobe80a7c203b307f120b6e647cab5881bd1277d651
1 /*
2 Copyright © 2012-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <proto/muimaster.h>
9 #include <proto/intuition.h>
10 #include <proto/utility.h>
11 #include <proto/graphics.h>
12 #include <clib/alib_protos.h>
13 #include <mui/NListtree_mcc.h>
14 #include <mui/NList_mcc.h>
16 #undef TNF_OPEN
17 #undef TNF_LIST
18 #include "Listtree_mcc.h"
19 #include "listtree_private.h"
21 #include <aros/debug.h>
23 /* Internal version of NListtree that enables controling the dispatcher */
24 #include <aros/symbolsets.h>
25 #define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)
26 #define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)
28 /* Routing of inherited methods calls:
29 * Some methods are often overriden in child classes of Listree, for example DragReport.
30 * On the other hand, those methods get called as interaction on the NListtree object.
31 * To allow using overriden methods, the following call sequence is implemented:
32 * NListtreeInt.A -> Listreee.A
33 * Listtree.A -> NListtreeInt.SuperA
34 * In case user inherited code, the call sequence looks as follows
35 * NListtreeInt.A -> Listreee-inherited.A
36 * Listreee-inherited.A -> Listreee.A
37 * Listtree.A -> NListtreeInt.SuperA
40 #define MUIA_NListtreeInt_Listtree 0xfec81401UL /* .s. Object * */
42 #define MUIM_NListtreeInt_ForwardSuperMethod 0xfec81301UL
44 struct MUIP_NListtreeInt_ForwardSuperMethod
46 STACKED ULONG MethodID;
47 STACKED Msg msg;
50 struct NListtreeInt_DATA
52 Object * listtree;
55 static struct MUI_CustomClass * CL_NListtreeInt;
57 IPTR NListtreeInt__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
59 struct NListtreeInt_DATA *data = INST_DATA(cl, obj);
60 struct TagItem *tstate = msg->ops_AttrList;
61 struct TagItem *tag;
63 while ((tag = NextTagItem(&tstate)) != NULL)
65 switch (tag->ti_Tag)
67 case(MUIA_NListtreeInt_Listtree):
68 data->listtree = (Object *)tag->ti_Data;
69 break;
73 return DoSuperMethodA(cl, obj, (Msg) msg);
76 IPTR NListtreeInt__ForwardListree(struct IClass *cl, Object *obj, Msg msg)
78 struct NListtreeInt_DATA *data = INST_DATA(cl, obj);
80 return DoMethodA(data->listtree, msg);
83 IPTR NListtreeInt__ForwardSuperMethod(struct IClass *cl, Object *obj, struct MUIP_NListtreeInt_ForwardSuperMethod * msg)
85 return DoSuperMethodA(cl, obj, msg->msg);
88 IPTR NListtreeInt__DoDrag(struct IClass *cl, Object *obj, struct MUIP_DoDrag * msg)
90 struct NListtreeInt_DATA *data = INST_DATA(cl, obj);
92 /* Use the listtree as the dragged object */
93 DoMethod(_win(data->listtree), MUIB_Window | 0x00000003,
94 (IPTR)data->listtree, msg->touchx, msg->touchy, msg->flags);
95 return 0;
98 BOOPSI_DISPATCHER(IPTR, NListtreeInt_Dispatcher, cl, obj, msg)
100 switch (msg->MethodID)
102 case(OM_SET): return NListtreeInt__OM_SET(cl, obj, (struct opSet *)msg);
103 case(MUIM_NListtreeInt_ForwardSuperMethod):
104 return NListtreeInt__ForwardSuperMethod(cl, obj, (struct MUIP_NListtreeInt_ForwardSuperMethod *)msg);
105 case(MUIM_DoDrag):
106 return NListtreeInt__DoDrag(cl, obj, (struct MUIP_DoDrag *)msg);
109 return DoSuperMethodA(cl, obj, msg);
111 BOOPSI_DISPATCHER_END
113 static int MCC_NListtreeInt_Startup(struct Library * lib)
115 CL_NListtreeInt = MUI_CreateCustomClass(lib, MUIC_NListtree, NULL, sizeof(struct NListtreeInt_DATA), NListtreeInt_Dispatcher);
116 return CL_NListtreeInt != NULL;
119 static void MCC_NListtreeInt_Shutdown(struct Library * lib)
121 MUI_DeleteCustomClass(CL_NListtreeInt);
124 ADD2INITCLASSES(MCC_NListtreeInt_Startup, -1);
125 ADD2EXPUNGECLASSES(MCC_NListtreeInt_Shutdown, -1);
126 /* Internal version of NListtree that enables controling the dispatcher */
141 /* Relations:
142 * MUIS_Listtree_Treenode -> MUI_NListtree_Treenode via MUIS_Listtree_TreeNodeInt.ref
143 * MUI_NListtree_Treenode -> MUIS_Listtree_Treenode via MUI_NListtree_Treenode.tn_User
145 struct MUIS_Listtree_TreeNodeInt
147 struct MUIS_Listtree_TreeNode base;
148 struct MUI_NListtree_TreeNode *ref;
151 #define SYNC_TREENODE_FLAGS(tn) \
152 if (tn && tn->tn_User) \
153 ((struct MUIS_Listtree_TreeNode *)tn->tn_User)->tn_Flags = tn->tn_Flags;
155 static IPTR NotifySimulate_Function(struct Hook *hook, Object *obj, void ** msg)
157 struct opSet setmsg;
158 struct TagItem setti[] = {{0,0},{TAG_DONE, TAG_DONE}};
160 IPTR attr = (IPTR)msg[0];
161 IPTR val = (IPTR)msg[1];
162 struct IClass * cl = hook->h_Data;
164 setmsg.MethodID = OM_SET;
165 setmsg.ops_AttrList = setti;
166 setmsg.ops_GInfo = NULL;
168 switch(attr)
170 case(MUIA_NListtree_Active):
171 setti[0].ti_Tag = MUIA_Listtree_Active;
172 setti[0].ti_Data = val ? (IPTR)((struct MUI_NListtree_TreeNode *)val)->tn_User : 0;
173 break;
174 case(MUIA_NListtree_DoubleClick):
175 setti[0].ti_Tag = MUIA_Listtree_DoubleClick;
176 setti[0].ti_Data = val;
177 break;
178 case(MUIA_NListtree_Quiet):
179 setti[0].ti_Tag = MUIA_Listtree_Quiet;
180 setti[0].ti_Data = val;
181 break;
182 default:
183 bug("[Listtree] NotifySimulate_Function - unhandled attribute %x\n", attr);
186 /* Super method OM_SET call will go to Notify class and trigger notifications */
187 return DoSuperMethodA(cl, obj, (Msg) &setmsg);
190 static IPTR DisplayHook_Proxy(struct Hook *hook, Object *obj, struct MUIP_NListtree_DisplayMessage *msg)
192 struct Hook * displayhook = (struct Hook *)hook->h_Data;
193 APTR tn = NULL;
195 if (!displayhook)
196 return 0;
198 SYNC_TREENODE_FLAGS(msg->TreeNode);
200 tn = msg->TreeNode ? msg->TreeNode->tn_User : NULL;
202 return CallHookPkt(displayhook, msg->Array, tn);
205 static IPTR DestructHook_Proxy(struct Hook *hook, Object *obj, struct MUIP_NListtree_DestructMessage *msg)
207 struct Listtree_DATA * data = (struct Listtree_DATA *)hook->h_Data;
208 struct MUIS_Listtree_TreeNode * tn = (struct MUIS_Listtree_TreeNode *)msg->UserData;
209 if (!data)
210 return 0;
212 if (data->destrhook && tn)
213 CallHookPkt(data->destrhook, data->pool, tn->tn_User);
215 FreePooled(data->pool, tn, sizeof(struct MUIS_Listtree_TreeNodeInt));
217 return 0;
220 #define NEWHANDLE(attrname) \
221 case(attrname): \
222 bug("[Listtree] OM_NEW:%s - unsupported\n", #attrname); \
223 break;
225 #define CONV(AATTR, BATTR) \
226 case(AATTR): \
227 convtags[i].ti_Tag = BATTR; \
228 convtags[i++].ti_Data = tag->ti_Data; \
229 break;
231 #define COPY(AATTR) \
232 case(AATTR): \
233 supertags[i].ti_Tag = AATTR; \
234 supertags[i++].ti_Data = tag->ti_Data; \
235 break;
237 #define NOTIFY_FORWARD(AATTR) \
238 DoMethod(data->nlisttree, MUIM_Notify, AATTR, MUIV_EveryTime, \
239 obj, 4, MUIM_CallHook, &data->notifysimulatehook, AATTR, MUIV_TriggerValue);
242 /*** Methods ****************************************************************/
243 Object *Listtree__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
245 struct Listtree_DATA *data = NULL;
246 struct TagItem *tag;
247 struct TagItem *tags;
248 Object *nlisttree = NULL;
249 struct TagItem convtags[20];
250 struct TagItem supertags[20];
251 LONG i;
253 /* Convert tags designated for NListtree */
254 for (i = 0, tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
256 switch (tag->ti_Tag)
258 CONV(MUIA_Frame, MUIA_Frame)
259 CONV(MUIA_Listtree_Format, MUIA_NListtree_Format)
260 CONV(MUIA_Listtree_Title, MUIA_NListtree_Title)
261 CONV(MUIA_Listtree_DragDropSort, MUIA_NListtree_DragDropSort)
262 CONV(MUIA_List_Title, MUIA_NList_Title)
263 CONV(MUIA_List_DragSortable, MUIA_NList_DragSortable)
264 CONV(MUIA_List_MinLineHeight, MUIA_NList_MinLineHeight)
267 convtags[i].ti_Tag = TAG_DONE;
269 /* Copy tags designated for super class */
270 for (i = 0, tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
272 switch (tag->ti_Tag)
274 COPY(MUIA_ContextMenu) /* ContextMenuBuild/Choice will be called on child classes of Listtree */
277 supertags[i].ti_Tag = TAG_DONE;
279 /* TODO:
280 * set up a DestructHook which will call proxy MUIS_Listtree_TreeNode destrhook and
281 * free it afterwards
283 obj = (Object *) DoSuperNewTags(cl, obj, 0,
284 Child, nlisttree = (Object *) NewObjectA(CL_NListtreeInt->mcc_Class, NULL, convtags),
285 TAG_MORE, (IPTR)supertags,
286 TAG_DONE);
288 if (!obj) return FALSE;
290 data = INST_DATA(cl, obj);
291 data->nlisttree = nlisttree;
292 data->notifysimulatehook.h_Entry = HookEntry;
293 data->notifysimulatehook.h_SubEntry = (HOOKFUNC)NotifySimulate_Function;
294 data->notifysimulatehook.h_Data = cl;
296 data->pool = CreatePool(MEMF_ANY | MEMF_CLEAR, 16 * 1024, 8 * 1024);
298 /* parse initial taglist */
299 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
301 switch (tag->ti_Tag)
303 case(MUIA_Listtree_ConstructHook):
304 data->constrhook = (struct Hook *)tag->ti_Data;
305 break;
306 case(MUIA_Listtree_DestructHook):
307 data->destrhook = (struct Hook *)tag->ti_Data;
308 break;
309 case(MUIA_Listtree_DisplayHook):
310 data->displayhook = (struct Hook *)tag->ti_Data;
311 break;
312 case(MUIA_List_MinLineHeight):
313 case(MUIA_List_DragSortable):
314 case(MUIA_List_Title):
315 case(MUIA_Listtree_DragDropSort):
316 case(MUIA_Listtree_Format):
317 case(MUIA_Listtree_Title):
318 case(MUIA_Frame):
319 /* Forwarded to NListtree */
320 break;
321 case(MUIA_ContextMenu):
322 /* Forwarded to super class */
323 break;
324 NEWHANDLE(MUIA_Listtree_SortHook)
325 default:
326 bug("[Listtree] OM_NEW: unhandled %x\n", tag->ti_Tag);
330 /* Setup connection */
331 set(data->nlisttree, MUIA_NListtreeInt_Listtree, obj);
333 /* Setup root node */
336 * Leave the tn_User of root node as NULL. It is expected that
337 * parent of first level item is returned as NULL in Listtree
341 /* Setup hook proxies */
342 if (data->displayhook)
344 data->displayhookproxy.h_Entry = HookEntry;
345 data->displayhookproxy.h_SubEntry = (HOOKFUNC)DisplayHook_Proxy;
346 data->displayhookproxy.h_Data = data->displayhook;
347 nnset(data->nlisttree, MUIA_NListtree_DisplayHook, &data->displayhookproxy);
349 /* Destroy hook is mandatory to free proxy structures */
351 data->destructhookproxy.h_Entry = HookEntry;
352 data->destructhookproxy.h_SubEntry = (HOOKFUNC)DestructHook_Proxy;
353 data->destructhookproxy.h_Data = data;
354 nnset(data->nlisttree, MUIA_NListtree_DestructHook, &data->destructhookproxy);
357 /* Setup notification forwarding */
358 NOTIFY_FORWARD(MUIA_NListtree_Active)
359 NOTIFY_FORWARD(MUIA_NListtree_DoubleClick)
360 NOTIFY_FORWARD(MUIA_NListtree_Quiet)
362 return obj;
365 #define SETHANDLE(attrname) \
366 case(attrname): \
367 bug("[Listtree] OM_SET:%s - unsupported\n", #attrname); \
368 break;
370 #define FORWARDSET(AATTR, BATTR) \
371 case(AATTR): \
372 set(data->nlisttree, BATTR, tag->ti_Data); \
373 break;
375 #define IGNORESET(AATTR) case(AATTR): break;
377 IPTR Listtree__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
379 struct Listtree_DATA *data = INST_DATA(cl, obj);
380 struct TagItem *tstate = msg->ops_AttrList;
381 struct TagItem *tag;
383 if (!data->nlisttree)
384 return DoSuperMethodA(cl, obj, (Msg) msg);
386 while ((tag = NextTagItem(&tstate)) != NULL)
388 switch (tag->ti_Tag)
390 FORWARDSET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
391 FORWARDSET(MUIA_List_Active, MUIA_NList_Active)
393 IGNORESET(MUIA_Listview_SelectChange)
395 case(MUIA_Listtree_Active):
396 set(data->nlisttree, MUIA_NListtree_Active,
397 ((struct MUIS_Listtree_TreeNodeInt *)tag->ti_Data)->ref);
398 break;
400 SETHANDLE(MUIA_Listtree_DoubleClick)
401 case MUIB_List | 0x00000010: break;
402 case MUIA_Prop_First: break;
403 case MUIA_Prop_DoSmooth: break;
404 case MUIA_NoNotify: break;
405 case MUIA_Prop_Entries: break;
406 case MUIA_Prop_Visible: break;
407 case MUIA_Prop_DeltaFactor: break;
408 default:
409 bug("[Listtree] OM_SET: passing to parent class %x\n", tag->ti_Tag);
414 return DoSuperMethodA(cl, obj, (Msg) msg);
417 #define GETHANDLE(attrname) \
418 case(attrname): \
419 bug("[Listtree] OM_GET:%s - unsupported\n", #attrname); \
420 break;
423 #define MUIA_List_Prop_Entries /* PRIV */ \
424 (MUIB_MUI | 0x0042a8f5) /* .sg LONG PRIV */
425 #define MUIA_List_Prop_Visible /* PRIV */ \
426 (MUIB_MUI | 0x004273e9) /* .sg LONG PRIV */
427 #define MUIA_List_Prop_First /* PRIV */ \
428 (MUIB_MUI | 0x00429df3) /* .sg LONG PRIV */
430 #define MUIA_List_VertProp_Entries /* PRIV */ \
431 MUIA_List_Prop_Entries /* PRIV */
432 #define MUIA_List_VertProp_Visible /* PRIV */ \
433 MUIA_List_Prop_Visible /* PRIV */
434 #define MUIA_List_VertProp_First /* PRIV */ \
435 MUIA_List_Prop_First /* PRIV */
437 #define FORWARDGET(AATTR, BATTR) \
438 case(AATTR): \
439 *(msg->opg_Storage) = XGET(data->nlisttree, BATTR); \
440 return TRUE;
442 IPTR Listtree__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
444 struct Listtree_DATA *data = INST_DATA(cl, obj);
446 if (!data->nlisttree)
447 return FALSE;
449 switch (msg->opg_AttrID)
451 FORWARDGET(MUIA_Frame, MUIA_Frame)
452 FORWARDGET(MUIA_Listtree_DoubleClick, MUIA_NListtree_DoubleClick)
453 FORWARDGET(MUIA_List_Active, MUIA_NList_Active)
454 FORWARDGET(MUIA_Listtree_Active, MUIA_NListtree_Active)
455 FORWARDGET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
456 FORWARDGET(MUIA_List_Visible, MUIA_NList_Visible)
458 GETHANDLE(MUIA_List_VertProp_Entries)
459 GETHANDLE(MUIA_List_VertProp_Visible)
460 GETHANDLE(MUIA_List_VertProp_First)
461 case MUIA_Disabled: break;
462 case MUIA_Parent: break;
463 case MUIA_Group_ChildList: break;
464 case MUIA_Prop_First: break;
465 case MUIA_Prop_DoSmooth: break;
466 case MUIA_Listview_List: break;
467 case MUIA_Virtgroup_Left: break;
468 case MUIA_Virtgroup_Top: break;
469 case 0x9d510020 /*MUIA_NListview_NList*/: break;
470 default:
471 bug("[Listtree] OM_GET: passing to parent class %x\n", msg->opg_AttrID);
474 return DoSuperMethodA(cl, obj, (Msg) msg);
477 #define METHODSTUB(methodname) \
478 IPTR Listtree__##methodname(struct IClass *cl, Object *obj, Msg msg) \
480 bug("[Listtree] Usupported : %s\n", #methodname); \
481 return (IPTR)FALSE; \
484 METHODSTUB(MUIM_Listtree_SetDropMark)
486 IPTR Listtree__MUIM_Listtree_Insert(struct IClass *cl, Object *obj, struct MUIP_Listtree_Insert *msg)
488 struct Listtree_DATA *data = INST_DATA(cl, obj);
489 struct MUIS_Listtree_TreeNodeInt * _int = AllocPooled(data->pool, sizeof(struct MUIS_Listtree_TreeNodeInt));
490 struct MUIS_Listtree_TreeNode * _return = NULL;
491 struct MUI_NListtree_TreeNode * ln = NULL, * pn = NULL;
493 if (_int == NULL)
494 return (IPTR)NULL;
496 _return = &_int->base;
498 _return->tn_Flags = (UWORD)msg->Flags;
499 if (data->constrhook)
500 _return->tn_User = (APTR)CallHookPkt(data->constrhook, data->pool, msg->User);
501 else
502 _return->tn_User = msg->User;
504 switch((IPTR)msg->ListNode)
506 case(MUIV_Listtree_Insert_ListNode_Root):
507 case(MUIV_Listtree_Insert_ListNode_Active):
508 ln = msg->ListNode;
509 break;
510 default:
511 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
514 switch((IPTR)msg->PrevNode)
516 case(MUIV_Listtree_Insert_PrevNode_Head):
517 case(MUIV_Listtree_Insert_PrevNode_Tail):
518 case(MUIV_Listtree_Insert_PrevNode_Active):
519 case(MUIV_Listtree_Insert_PrevNode_Sorted):
520 pn = msg->PrevNode;
521 break;
522 default:
523 pn = ((struct MUIS_Listtree_TreeNodeInt *)msg->PrevNode)->ref;
526 _int->ref = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
527 MUIM_NListtree_Insert, msg->Name, _return, ln, pn, msg->Flags);
529 _return->tn_Name = _int->ref->tn_Name;
531 return (IPTR)_return;
534 IPTR Listtree__MUIM_Listtree_GetEntry(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetEntry *msg)
536 struct Listtree_DATA *data = INST_DATA(cl, obj);
537 struct MUI_NListtree_TreeNode * tn = NULL, * found = NULL;
539 switch ((IPTR)msg->Node)
541 case(MUIV_Listtree_GetEntry_ListNode_Root):
542 case(MUIV_Listtree_GetEntry_ListNode_Active):
543 tn = msg->Node;
544 break;
545 default:
546 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->Node)->ref;
549 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree,
550 MUIM_NListtree_GetEntry, tn, msg->Position, msg->Flags);
552 if (found)
554 SYNC_TREENODE_FLAGS(found);
555 return (IPTR)found->tn_User;
557 else
558 return (IPTR)NULL;
561 IPTR Listtree__MUIM_Listtree_Remove(struct IClass *cl, Object *obj, struct MUIP_Listtree_Remove *msg)
563 struct Listtree_DATA *data = INST_DATA(cl, obj);
565 /* TODO: handle remaining enumeration values */
566 if ((msg->ListNode == (APTR)MUIV_Listtree_Remove_ListNode_Root) &&
567 ((msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_Active) ||
568 (msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_All)))
570 /* Deallocating of MUIS_Listtree_TreeNode is happening in the DestructHook */
571 return DoMethod(data->nlisttree, MUIM_NListtree_Remove, msg->ListNode, msg->TreeNode, msg->Flags);
574 /* TODO
575 * add handling for cases where ListNode/TreeNode actually point to Treenode structure
577 bug("[Listtree] MUIM_Listtree_Remove unsupported code path Listnode: %x, Treenode: %x, Flags: %d\n", msg->ListNode, msg->TreeNode, msg->Flags);
579 return (IPTR)FALSE;
582 IPTR Listtree__MUIM_List_TestPos(struct IClass *cl, Object *obj, struct MUIP_List_TestPos *msg)
584 struct Listtree_DATA *data = INST_DATA(cl, obj);
586 struct MUI_NList_TestPos_Result res;
587 if (DoMethod(data->nlisttree, MUIM_List_TestPos, msg->x, msg->y, &res))
589 msg->res->entry = res.entry;
590 msg->res->column = res.column;
591 msg->res->flags = res.flags;
592 msg->res->xoffset = res.xoffset;
593 msg->res->yoffset = res.yoffset;
594 return TRUE;
597 return FALSE;
600 IPTR Listtree__MUIM_Listtree_TestPos(struct IClass *cl, Object *obj, struct MUIP_Listtree_TestPos *msg)
602 struct Listtree_DATA *data = INST_DATA(cl, obj);
604 struct MUI_NListtree_TestPos_Result res;
605 struct MUIS_Listtree_TestPos_Result * _ret = (struct MUIS_Listtree_TestPos_Result *)msg->Result;
607 _ret->tpr_TreeNode = NULL;
609 DoMethod(data->nlisttree, MUIM_NListtree_TestPos, msg->X, msg->Y, &res);
611 _ret->tpr_Flags = res.tpr_Type;
612 _ret->tpr_ListEntry = res.tpr_ListEntry;
613 _ret->tpr_ListFlags = res.tpr_ListFlags;
615 if (res.tpr_TreeNode != NULL)
617 SYNC_TREENODE_FLAGS(res.tpr_TreeNode);
618 _ret->tpr_TreeNode = res.tpr_TreeNode->tn_User;
619 return TRUE;
622 return FALSE;
625 IPTR Listtree__MUIM_Listtree_GetNr(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetNr *msg)
627 struct Listtree_DATA *data = INST_DATA(cl, obj);
628 struct MUI_NListtree_TreeNode * tn = NULL;
630 switch((IPTR)msg->TreeNode)
632 case(MUIV_Listtree_GetNr_TreeNode_Active):
633 tn = msg->TreeNode;
634 break;
635 default:
636 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
639 return DoMethod(data->nlisttree, MUIM_NListtree_GetNr, tn, msg->Flags);
642 IPTR Listtree__MUIM_Listtree_Rename(struct IClass *cl, Object *obj, struct MUIP_Listtree_Rename *msg)
644 struct Listtree_DATA *data = INST_DATA(cl, obj);
645 struct MUI_NListtree_TreeNode * tn = NULL, * renamed = NULL;
647 switch((IPTR)msg->TreeNode)
649 case(MUIV_Listtree_Rename_TreeNode_Active):
650 tn = msg->TreeNode;
651 break;
652 default:
653 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
656 renamed = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
657 MUIM_NListtree_Rename, tn, msg->NewName, msg->Flags);
659 if (renamed)
661 ((struct MUIS_Listtree_TreeNode *)renamed->tn_User)->tn_Name = renamed->tn_Name;
662 return (IPTR)renamed->tn_User;
664 else
665 return (IPTR)NULL;
668 IPTR Listtree__MUIM_List_Redraw(struct IClass *cl, Object *obj, struct MUIP_List_Redraw *msg)
670 struct Listtree_DATA *data = INST_DATA(cl, obj);
671 struct MUI_NListtree_TreeNode * entry = msg->entry ?
672 ((struct MUIS_Listtree_TreeNodeInt *)msg->entry)->ref : NULL;
674 switch(msg->pos)
676 case(MUIV_List_Redraw_Entry):
677 return DoMethod(data->nlisttree, MUIM_NList_RedrawEntry, entry);
678 default:
679 return DoMethod(data->nlisttree, MUIM_NList_Redraw, msg->pos);
683 IPTR Listtree__MUIM_Listtree_Open(struct IClass *cl, Object *obj, struct MUIP_Listtree_Open *msg)
685 struct Listtree_DATA *data = INST_DATA(cl, obj);
686 struct MUI_NListtree_TreeNode * tn = NULL, * ln = NULL;
688 switch((IPTR)msg->ListNode)
690 case(MUIV_Listtree_Open_ListNode_Root):
691 case(MUIV_Listtree_Open_ListNode_Parent):
692 case(MUIV_Listtree_Open_ListNode_Active):
693 ln = msg->ListNode;
694 break;
695 default:
696 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
699 switch((IPTR)msg->TreeNode)
701 case(MUIV_Listtree_Open_TreeNode_Head):
702 case(MUIV_Listtree_Open_TreeNode_Tail):
703 case(MUIV_Listtree_Open_TreeNode_Active):
704 case(MUIV_Listtree_Open_TreeNode_All):
705 tn = msg->TreeNode;
706 break;
707 default:
708 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
711 return DoMethod(data->nlisttree, MUIM_NListtree_Open, ln, tn, msg->Flags);
714 IPTR Listtree__MUIM_Listtree_FindName(struct IClass *cl, Object *obj, struct MUIP_Listtree_FindName *msg)
716 struct Listtree_DATA *data = INST_DATA(cl, obj);
717 struct MUI_NListtree_TreeNode * ln = NULL, * found = NULL;
719 switch((IPTR)msg->ListNode)
721 case(MUIV_Listtree_FindName_ListNode_Root):
722 case(MUIV_Listtree_FindName_ListNode_Active):
723 ln = msg->ListNode;
724 break;
725 default:
726 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
729 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree, MUIM_NListtree_FindName,
730 ln, msg->Name, msg->Flags);
732 if (found)
733 return (IPTR)found->tn_User;
734 else
735 return (IPTR)NULL;
738 struct ListImage
740 struct MinNode node;
741 Object *obj;
744 #define MADF_SETUP (1<< 28) /* PRIV - zune-specific */
746 IPTR DoSetupMethod(Object * obj, struct MUI_RenderInfo * info)
748 /* MUI set the correct render info *before* it calls MUIM_Setup so please
749 * only use this function instead of DoMethodA() */
750 muiRenderInfo(obj) = info;
751 return DoMethod(obj, MUIM_Setup, (IPTR) info);
754 IPTR Listtree__MUIM_List_CreateImage(struct IClass *cl, Object *obj, struct MUIP_List_CreateImage *msg)
756 struct Listtree_DATA *data = INST_DATA(cl, obj);
758 if (!(_flags(obj) & MADF_SETUP))
759 return 0;
761 IPTR _ret = DoMethod(data->nlisttree, MUIM_NList_CreateImage, msg->obj, msg->flags);
763 /* There is a use case where an image object created in a Listtree can be passed as O[address]
764 * in the text in the display callback of List. Since Listtree just wraps around NListtree and the
765 * return structures from List_CreateImage and NList_CreateImage are different, this would normally
766 * not work. Luckily, List needs only the msg->obj and it is at the same offset in ListImage and
767 * in structure returned by NList. The case will work as long as this is met.
769 struct ListImage * li = (struct ListImage *)_ret;
770 if (li->obj != msg->obj)
771 bug("[Listtree] CreateImage condition BROKEN, see comment in code!\n");
773 /* Setup the msg->obj as the List is doing */
774 DoMethod(li->obj, MUIM_ConnectParent, (IPTR) obj);
775 DoSetupMethod(li->obj, muiRenderInfo(obj));
777 return _ret;
780 IPTR Listtree__MUIM_List_DeleteImage(struct IClass *cl, Object *obj, struct MUIP_List_DeleteImage *msg)
782 struct Listtree_DATA *data = INST_DATA(cl, obj);
783 struct ListImage * li = (struct ListImage *)msg->listimg;
785 /* DoMethod(li->obj, MUIM_Cleanup); // Called in MUIM_NList_DeleteImage */
786 DoMethod(li->obj, MUIM_DisconnectParent);
787 return DoMethod(data->nlisttree, MUIM_NList_DeleteImage, msg->listimg);
790 IPTR Listtree__MUIM_Listtree_Close(struct IClass *cl, Object *obj, struct MUIP_Listtree_Close *msg)
792 struct Listtree_DATA *data = INST_DATA(cl, obj);
793 struct MUI_NListtree_TreeNode * tn = NULL, * ln = NULL;
795 switch((IPTR)msg->ListNode)
797 case(MUIV_Listtree_Close_ListNode_Root):
798 case(MUIV_Listtree_Close_ListNode_Parent):
799 case(MUIV_Listtree_Close_ListNode_Active):
800 ln = msg->ListNode;
801 break;
802 default:
803 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
806 switch((IPTR)msg->TreeNode)
808 case(MUIV_Listtree_Close_TreeNode_Head):
809 case(MUIV_Listtree_Close_TreeNode_Tail):
810 case(MUIV_Listtree_Close_TreeNode_Active):
811 case(MUIV_Listtree_Close_TreeNode_All):
812 tn = msg->TreeNode;
813 break;
814 default:
815 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
818 return DoMethod(data->nlisttree, MUIM_NListtree_Close, ln, tn, msg->Flags);
821 IPTR Listtree__MUIM_CreateDragImage(struct IClass *cl, Object *obj, struct MUIP_CreateDragImage *msg)
823 struct Listtree_DATA *data = INST_DATA(cl, obj);
824 return DoMethodA(data->nlisttree, (Msg)msg);
827 IPTR Listtree__MUIM_DeleteDragImage(struct IClass *cl, Object *obj, struct MUIP_DeleteDragImage *msg)
829 struct Listtree_DATA *data = INST_DATA(cl, obj);
830 return DoMethodA(data->nlisttree, (Msg)msg);
833 #define FORWARDNLISTTREESUPERMETHOD(methodname) \
834 IPTR Listtree__##methodname(struct IClass *cl, Object *obj, Msg msg) \
836 struct Listtree_DATA *data = INST_DATA(cl, obj); \
837 return DoMethod(data->nlisttree, MUIM_NListtreeInt_ForwardSuperMethod, msg); \