Listtree.mcc: check if list image was passed to the call
[AROS.git] / workbench / classes / zune / listtree / listtree.c
blobe3b3a955d8d0322f8ea6241db769fa126d03d6a2
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 IPTR Listtree__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
367 struct Listtree_DATA *data = INST_DATA(cl, obj);
369 DeletePool(data->pool);
371 return DoSuperMethodA(cl, obj, msg);
374 #define SETHANDLE(attrname) \
375 case(attrname): \
376 bug("[Listtree] OM_SET:%s - unsupported\n", #attrname); \
377 break;
379 #define FORWARDSET(AATTR, BATTR) \
380 case(AATTR): \
381 set(data->nlisttree, BATTR, tag->ti_Data); \
382 break;
384 #define IGNORESET(AATTR) case(AATTR): break;
386 IPTR Listtree__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
388 struct Listtree_DATA *data = INST_DATA(cl, obj);
389 struct TagItem *tstate = msg->ops_AttrList;
390 struct TagItem *tag;
392 if (!data->nlisttree)
393 return DoSuperMethodA(cl, obj, (Msg) msg);
395 while ((tag = NextTagItem(&tstate)) != NULL)
397 switch (tag->ti_Tag)
399 FORWARDSET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
400 FORWARDSET(MUIA_List_Active, MUIA_NList_Active)
402 IGNORESET(MUIA_Listview_SelectChange)
404 case(MUIA_Listtree_Active):
405 set(data->nlisttree, MUIA_NListtree_Active,
406 ((struct MUIS_Listtree_TreeNodeInt *)tag->ti_Data)->ref);
407 break;
409 SETHANDLE(MUIA_Listtree_DoubleClick)
410 case MUIB_List | 0x00000010: break;
411 case MUIA_Prop_First: break;
412 case MUIA_Prop_DoSmooth: break;
413 case MUIA_NoNotify: break;
414 case MUIA_Prop_Entries: break;
415 case MUIA_Prop_Visible: break;
416 case MUIA_Prop_DeltaFactor: break;
417 default:
418 bug("[Listtree] OM_SET: passing to parent class %x\n", tag->ti_Tag);
423 return DoSuperMethodA(cl, obj, (Msg) msg);
426 #define GETHANDLE(attrname) \
427 case(attrname): \
428 bug("[Listtree] OM_GET:%s - unsupported\n", #attrname); \
429 break;
432 #define MUIA_List_Prop_Entries /* PRIV */ \
433 (MUIB_MUI | 0x0042a8f5) /* .sg LONG PRIV */
434 #define MUIA_List_Prop_Visible /* PRIV */ \
435 (MUIB_MUI | 0x004273e9) /* .sg LONG PRIV */
436 #define MUIA_List_Prop_First /* PRIV */ \
437 (MUIB_MUI | 0x00429df3) /* .sg LONG PRIV */
439 #define MUIA_List_VertProp_Entries /* PRIV */ \
440 MUIA_List_Prop_Entries /* PRIV */
441 #define MUIA_List_VertProp_Visible /* PRIV */ \
442 MUIA_List_Prop_Visible /* PRIV */
443 #define MUIA_List_VertProp_First /* PRIV */ \
444 MUIA_List_Prop_First /* PRIV */
446 #define FORWARDGET(AATTR, BATTR) \
447 case(AATTR): \
448 *(msg->opg_Storage) = XGET(data->nlisttree, BATTR); \
449 return TRUE;
451 IPTR Listtree__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
453 struct Listtree_DATA *data = INST_DATA(cl, obj);
455 if (!data->nlisttree)
456 return FALSE;
458 switch (msg->opg_AttrID)
460 FORWARDGET(MUIA_Frame, MUIA_Frame)
461 FORWARDGET(MUIA_Listtree_DoubleClick, MUIA_NListtree_DoubleClick)
462 FORWARDGET(MUIA_List_Active, MUIA_NList_Active)
463 FORWARDGET(MUIA_Listtree_Active, MUIA_NListtree_Active)
464 FORWARDGET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
465 FORWARDGET(MUIA_List_Visible, MUIA_NList_Visible)
467 GETHANDLE(MUIA_List_VertProp_Entries)
468 GETHANDLE(MUIA_List_VertProp_Visible)
469 GETHANDLE(MUIA_List_VertProp_First)
470 case MUIA_Disabled: break;
471 case MUIA_Parent: break;
472 case MUIA_Group_ChildList: break;
473 case MUIA_Prop_First: break;
474 case MUIA_Prop_DoSmooth: break;
475 case MUIA_Listview_List: break;
476 case MUIA_Virtgroup_Left: break;
477 case MUIA_Virtgroup_Top: break;
478 case 0x9d510020 /*MUIA_NListview_NList*/: break;
479 default:
480 bug("[Listtree] OM_GET: passing to parent class %x\n", msg->opg_AttrID);
483 return DoSuperMethodA(cl, obj, (Msg) msg);
486 #define METHODSTUB(methodname) \
487 IPTR Listtree__##methodname(struct IClass *cl, Object *obj, Msg msg) \
489 bug("[Listtree] Usupported : %s\n", #methodname); \
490 return (IPTR)FALSE; \
493 METHODSTUB(MUIM_Listtree_SetDropMark)
495 IPTR Listtree__MUIM_Listtree_Insert(struct IClass *cl, Object *obj, struct MUIP_Listtree_Insert *msg)
497 struct Listtree_DATA *data = INST_DATA(cl, obj);
498 struct MUIS_Listtree_TreeNodeInt * _int = AllocPooled(data->pool, sizeof(struct MUIS_Listtree_TreeNodeInt));
499 struct MUIS_Listtree_TreeNode * _return = NULL;
500 struct MUI_NListtree_TreeNode * ln = NULL, * pn = NULL;
502 if (_int == NULL)
503 return (IPTR)NULL;
505 _return = &_int->base;
507 _return->tn_Flags = (UWORD)msg->Flags;
508 if (data->constrhook)
509 _return->tn_User = (APTR)CallHookPkt(data->constrhook, data->pool, msg->User);
510 else
511 _return->tn_User = msg->User;
513 switch((IPTR)msg->ListNode)
515 case(MUIV_Listtree_Insert_ListNode_Root):
516 case(MUIV_Listtree_Insert_ListNode_Active):
517 ln = msg->ListNode;
518 break;
519 default:
520 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
523 switch((IPTR)msg->PrevNode)
525 case(MUIV_Listtree_Insert_PrevNode_Head):
526 case(MUIV_Listtree_Insert_PrevNode_Tail):
527 case(MUIV_Listtree_Insert_PrevNode_Active):
528 case(MUIV_Listtree_Insert_PrevNode_Sorted):
529 pn = msg->PrevNode;
530 break;
531 default:
532 pn = ((struct MUIS_Listtree_TreeNodeInt *)msg->PrevNode)->ref;
535 _int->ref = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
536 MUIM_NListtree_Insert, msg->Name, _return, ln, pn, msg->Flags);
538 _return->tn_Name = _int->ref->tn_Name;
540 return (IPTR)_return;
543 IPTR Listtree__MUIM_Listtree_GetEntry(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetEntry *msg)
545 struct Listtree_DATA *data = INST_DATA(cl, obj);
546 struct MUI_NListtree_TreeNode * tn = NULL, * found = NULL;
548 switch ((IPTR)msg->Node)
550 case(MUIV_Listtree_GetEntry_ListNode_Root):
551 case(MUIV_Listtree_GetEntry_ListNode_Active):
552 tn = msg->Node;
553 break;
554 default:
555 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->Node)->ref;
558 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree,
559 MUIM_NListtree_GetEntry, tn, msg->Position, msg->Flags);
561 if (found)
563 SYNC_TREENODE_FLAGS(found);
564 return (IPTR)found->tn_User;
566 else
567 return (IPTR)NULL;
570 IPTR Listtree__MUIM_Listtree_Remove(struct IClass *cl, Object *obj, struct MUIP_Listtree_Remove *msg)
572 struct Listtree_DATA *data = INST_DATA(cl, obj);
574 /* TODO: handle remaining enumeration values */
575 if ((msg->ListNode == (APTR)MUIV_Listtree_Remove_ListNode_Root) &&
576 ((msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_Active) ||
577 (msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_All)))
579 /* Deallocating of MUIS_Listtree_TreeNode is happening in the DestructHook */
580 return DoMethod(data->nlisttree, MUIM_NListtree_Remove, msg->ListNode, msg->TreeNode, msg->Flags);
583 /* TODO
584 * add handling for cases where ListNode/TreeNode actually point to Treenode structure
586 bug("[Listtree] MUIM_Listtree_Remove unsupported code path Listnode: %x, Treenode: %x, Flags: %d\n", msg->ListNode, msg->TreeNode, msg->Flags);
588 return (IPTR)FALSE;
591 IPTR Listtree__MUIM_List_TestPos(struct IClass *cl, Object *obj, struct MUIP_List_TestPos *msg)
593 struct Listtree_DATA *data = INST_DATA(cl, obj);
595 struct MUI_NList_TestPos_Result res;
596 if (DoMethod(data->nlisttree, MUIM_List_TestPos, msg->x, msg->y, &res))
598 msg->res->entry = res.entry;
599 msg->res->column = res.column;
600 msg->res->flags = res.flags;
601 msg->res->xoffset = res.xoffset;
602 msg->res->yoffset = res.yoffset;
603 return TRUE;
606 return FALSE;
609 IPTR Listtree__MUIM_Listtree_TestPos(struct IClass *cl, Object *obj, struct MUIP_Listtree_TestPos *msg)
611 struct Listtree_DATA *data = INST_DATA(cl, obj);
613 struct MUI_NListtree_TestPos_Result res;
614 struct MUIS_Listtree_TestPos_Result * _ret = (struct MUIS_Listtree_TestPos_Result *)msg->Result;
616 _ret->tpr_TreeNode = NULL;
618 DoMethod(data->nlisttree, MUIM_NListtree_TestPos, msg->X, msg->Y, &res);
620 _ret->tpr_Flags = res.tpr_Type;
621 _ret->tpr_ListEntry = res.tpr_ListEntry;
622 _ret->tpr_ListFlags = res.tpr_ListFlags;
624 if (res.tpr_TreeNode != NULL)
626 SYNC_TREENODE_FLAGS(res.tpr_TreeNode);
627 _ret->tpr_TreeNode = res.tpr_TreeNode->tn_User;
628 return TRUE;
631 return FALSE;
634 IPTR Listtree__MUIM_Listtree_GetNr(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetNr *msg)
636 struct Listtree_DATA *data = INST_DATA(cl, obj);
637 struct MUI_NListtree_TreeNode * tn = NULL;
639 switch((IPTR)msg->TreeNode)
641 case(MUIV_Listtree_GetNr_TreeNode_Active):
642 tn = msg->TreeNode;
643 break;
644 default:
645 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
648 return DoMethod(data->nlisttree, MUIM_NListtree_GetNr, tn, msg->Flags);
651 IPTR Listtree__MUIM_Listtree_Rename(struct IClass *cl, Object *obj, struct MUIP_Listtree_Rename *msg)
653 struct Listtree_DATA *data = INST_DATA(cl, obj);
654 struct MUI_NListtree_TreeNode * tn = NULL, * renamed = NULL;
656 switch((IPTR)msg->TreeNode)
658 case(MUIV_Listtree_Rename_TreeNode_Active):
659 tn = msg->TreeNode;
660 break;
661 default:
662 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
665 renamed = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
666 MUIM_NListtree_Rename, tn, msg->NewName, msg->Flags);
668 if (renamed)
670 ((struct MUIS_Listtree_TreeNode *)renamed->tn_User)->tn_Name = renamed->tn_Name;
671 return (IPTR)renamed->tn_User;
673 else
674 return (IPTR)NULL;
677 IPTR Listtree__MUIM_List_Redraw(struct IClass *cl, Object *obj, struct MUIP_List_Redraw *msg)
679 struct Listtree_DATA *data = INST_DATA(cl, obj);
680 struct MUI_NListtree_TreeNode * entry = msg->entry ?
681 ((struct MUIS_Listtree_TreeNodeInt *)msg->entry)->ref : NULL;
683 switch(msg->pos)
685 case(MUIV_List_Redraw_Entry):
686 return DoMethod(data->nlisttree, MUIM_NList_RedrawEntry, entry);
687 default:
688 return DoMethod(data->nlisttree, MUIM_NList_Redraw, msg->pos);
692 IPTR Listtree__MUIM_Listtree_Open(struct IClass *cl, Object *obj, struct MUIP_Listtree_Open *msg)
694 struct Listtree_DATA *data = INST_DATA(cl, obj);
695 struct MUI_NListtree_TreeNode * tn = NULL, * ln = NULL;
697 switch((IPTR)msg->ListNode)
699 case(MUIV_Listtree_Open_ListNode_Root):
700 case(MUIV_Listtree_Open_ListNode_Parent):
701 case(MUIV_Listtree_Open_ListNode_Active):
702 ln = msg->ListNode;
703 break;
704 default:
705 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
708 switch((IPTR)msg->TreeNode)
710 case(MUIV_Listtree_Open_TreeNode_Head):
711 case(MUIV_Listtree_Open_TreeNode_Tail):
712 case(MUIV_Listtree_Open_TreeNode_Active):
713 case(MUIV_Listtree_Open_TreeNode_All):
714 tn = msg->TreeNode;
715 break;
716 default:
717 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
720 return DoMethod(data->nlisttree, MUIM_NListtree_Open, ln, tn, msg->Flags);
723 IPTR Listtree__MUIM_Listtree_FindName(struct IClass *cl, Object *obj, struct MUIP_Listtree_FindName *msg)
725 struct Listtree_DATA *data = INST_DATA(cl, obj);
726 struct MUI_NListtree_TreeNode * ln = NULL, * found = NULL;
728 switch((IPTR)msg->ListNode)
730 case(MUIV_Listtree_FindName_ListNode_Root):
731 case(MUIV_Listtree_FindName_ListNode_Active):
732 ln = msg->ListNode;
733 break;
734 default:
735 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
738 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree, MUIM_NListtree_FindName,
739 ln, msg->Name, msg->Flags);
741 if (found)
742 return (IPTR)found->tn_User;
743 else
744 return (IPTR)NULL;
747 struct ListImage
749 struct MinNode node;
750 Object *obj;
753 #define MADF_SETUP (1<< 28) /* PRIV - zune-specific */
755 IPTR DoSetupMethod(Object * obj, struct MUI_RenderInfo * info)
757 /* MUI set the correct render info *before* it calls MUIM_Setup so please
758 * only use this function instead of DoMethodA() */
759 muiRenderInfo(obj) = info;
760 return DoMethod(obj, MUIM_Setup, (IPTR) info);
763 IPTR Listtree__MUIM_List_CreateImage(struct IClass *cl, Object *obj, struct MUIP_List_CreateImage *msg)
765 struct Listtree_DATA *data = INST_DATA(cl, obj);
767 if (!(_flags(obj) & MADF_SETUP))
768 return 0;
770 IPTR _ret = DoMethod(data->nlisttree, MUIM_NList_CreateImage, msg->obj, msg->flags);
772 /* There is a use case where an image object created in a Listtree can be passed as O[address]
773 * in the text in the display callback of List. Since Listtree just wraps around NListtree and the
774 * return structures from List_CreateImage and NList_CreateImage are different, this would normally
775 * not work. Luckily, List needs only the msg->obj and it is at the same offset in ListImage and
776 * in structure returned by NList. The case will work as long as this is met.
778 struct ListImage * li = (struct ListImage *)_ret;
779 if (li->obj != msg->obj)
780 bug("[Listtree] CreateImage condition BROKEN, see comment in code!\n");
782 /* Setup the msg->obj as the List is doing */
783 DoMethod(li->obj, MUIM_ConnectParent, (IPTR) obj);
784 DoSetupMethod(li->obj, muiRenderInfo(obj));
786 return _ret;
789 IPTR Listtree__MUIM_List_DeleteImage(struct IClass *cl, Object *obj, struct MUIP_List_DeleteImage *msg)
791 struct Listtree_DATA *data = INST_DATA(cl, obj);
792 struct ListImage * li = (struct ListImage *)msg->listimg;
794 if (!li)
795 return 0;
797 /* DoMethod(li->obj, MUIM_Cleanup); // Called in MUIM_NList_DeleteImage */
798 DoMethod(li->obj, MUIM_DisconnectParent);
799 return DoMethod(data->nlisttree, MUIM_NList_DeleteImage, msg->listimg);
802 IPTR Listtree__MUIM_Listtree_Close(struct IClass *cl, Object *obj, struct MUIP_Listtree_Close *msg)
804 struct Listtree_DATA *data = INST_DATA(cl, obj);
805 struct MUI_NListtree_TreeNode * tn = NULL, * ln = NULL;
807 switch((IPTR)msg->ListNode)
809 case(MUIV_Listtree_Close_ListNode_Root):
810 case(MUIV_Listtree_Close_ListNode_Parent):
811 case(MUIV_Listtree_Close_ListNode_Active):
812 ln = msg->ListNode;
813 break;
814 default:
815 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
818 switch((IPTR)msg->TreeNode)
820 case(MUIV_Listtree_Close_TreeNode_Head):
821 case(MUIV_Listtree_Close_TreeNode_Tail):
822 case(MUIV_Listtree_Close_TreeNode_Active):
823 case(MUIV_Listtree_Close_TreeNode_All):
824 tn = msg->TreeNode;
825 break;
826 default:
827 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
830 return DoMethod(data->nlisttree, MUIM_NListtree_Close, ln, tn, msg->Flags);
833 IPTR Listtree__MUIM_CreateDragImage(struct IClass *cl, Object *obj, struct MUIP_CreateDragImage *msg)
835 struct Listtree_DATA *data = INST_DATA(cl, obj);
836 return DoMethodA(data->nlisttree, (Msg)msg);
839 IPTR Listtree__MUIM_DeleteDragImage(struct IClass *cl, Object *obj, struct MUIP_DeleteDragImage *msg)
841 struct Listtree_DATA *data = INST_DATA(cl, obj);
842 return DoMethodA(data->nlisttree, (Msg)msg);
845 #define FORWARDNLISTTREESUPERMETHOD(methodname) \
846 IPTR Listtree__##methodname(struct IClass *cl, Object *obj, Msg msg) \
848 struct Listtree_DATA *data = INST_DATA(cl, obj); \
849 return DoMethod(data->nlisttree, MUIM_NListtreeInt_ForwardSuperMethod, msg); \