Listtree.mcc: implement proxying of DisplayHook
[AROS.git] / workbench / classes / zune / listtree / listtree.c
blob0bbc3ee0bea45dd71286ec087c9362085c20d1f7
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 /* Relations:
24 * MUIS_Listtree_Treenode -> MUI_NListtree_Treenode via MUIS_Listtree_TreeNodeInt.ref
25 * MUI_NListtree_Treenode -> MUIS_Listtree_Treenode via MUI_NListtree_Treenode.tn_User
27 struct MUIS_Listtree_TreeNodeInt
29 struct MUIS_Listtree_TreeNode base;
30 struct MUI_NListtree_TreeNode *ref;
33 static IPTR NotifySimulate_Function(struct Hook *hook, Object *obj, void ** msg)
35 struct opSet setmsg;
36 struct TagItem setti[] = {{0,0},{TAG_DONE, TAG_DONE}};
38 IPTR attr = (IPTR)msg[0];
39 IPTR val = (IPTR)msg[1];
40 struct IClass * cl = hook->h_Data;
42 setmsg.MethodID = OM_SET;
43 setmsg.ops_AttrList = setti;
44 setmsg.ops_GInfo = NULL;
46 switch(attr)
48 case(MUIA_NListtree_Active):
49 setti[0].ti_Tag = MUIA_Listtree_Active;
50 setti[0].ti_Data = val ? (IPTR)((struct MUI_NListtree_TreeNode *)val)->tn_User : 0;
51 break;
52 default:
53 bug("[Listtree] NotifySimulate_Function - unhandled attribute %x\n", attr);
56 /* Super method OM_SET call will go to Notify class and trigger notifications */
57 return DoSuperMethodA(cl, obj, (Msg) &setmsg);
60 static IPTR DisplayHook_Proxy(struct Hook *hook, Object *obj, struct MUIP_NListtree_DisplayMessage *msg)
62 struct _temp { STACKED APTR array; STACKED APTR treenode; } t;
63 struct Hook * displayhook = (struct Hook *)hook->h_Data;
65 if (!displayhook)
66 return FALSE;
68 t.array = msg->Array;
69 t.treenode = msg->TreeNode ? msg->TreeNode->tn_User : NULL;
71 return CallHookPkt(displayhook, t.array, t.treenode);
74 #define NEWHANDLE(attrname) \
75 case(attrname): \
76 bug("[Listtree] OM_NEW:%s - unsupported\n", #attrname); \
77 break;
79 #define CONV(AATTR, BATTR) \
80 case(AATTR): \
81 convtags[i].ti_Tag = BATTR; \
82 convtags[i++].ti_Data = tag->ti_Data; \
83 break;
85 #define CONVFIN \
86 convtags[i].ti_Tag = TAG_DONE; \
87 convtags[i].ti_Data = TAG_DONE;
89 /*** Methods ****************************************************************/
90 Object *Listtree__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
92 struct Listtree_DATA *data = NULL;
93 struct TagItem *tag;
94 struct TagItem *tags;
95 Object *nlisttree = NULL;
96 struct TagItem convtags[20];
97 LONG i = 0;
99 /* Convert tags designated for NListtree */
100 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
102 switch (tag->ti_Tag)
104 CONV(MUIA_Frame, MUIA_Frame)
105 CONV(MUIA_Listtree_Format, MUIA_NListtree_Format)
106 CONV(MUIA_Listtree_Title, MUIA_NListtree_Title)
107 CONV(MUIA_Listtree_DragDropSort, MUIA_NListtree_DragDropSort)
108 CONV(MUIA_List_Title, MUIA_NList_Title)
109 CONV(MUIA_List_DragSortable, MUIA_NList_DragSortable)
110 // CONV(MUIA_ContextMenu, MUIA_ContextMenu) // FIXME causes a crash when right clicking
111 CONV(MUIA_List_MinLineHeight, MUIA_NList_MinLineHeight)
114 CONVFIN
116 /* TODO:
117 * set up a DestructHook which will call proxy MUIS_Listtree_TreeNode destrhook and
118 * free it afterwards
120 obj = (Object *) DoSuperNewTags(cl, obj, 0,
121 Child, nlisttree = (Object *) NListtreeObject,
122 TAG_MORE, (IPTR)convtags,
123 End,
126 if (!obj) return FALSE;
128 data = INST_DATA(cl, obj);
129 data->nlisttree = nlisttree;
130 data->notifysimulatehook.h_Entry = HookEntry;
131 data->notifysimulatehook.h_SubEntry = (HOOKFUNC)NotifySimulate_Function;
132 data->notifysimulatehook.h_Data = cl;
134 data->pool = CreatePool(MEMF_ANY | MEMF_CLEAR, 16 * 1024, 8 * 1024);
136 /* parse initial taglist */
137 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
139 switch (tag->ti_Tag)
141 case(MUIA_Listtree_ConstructHook):
142 data->constrhook = (struct Hook *)tag->ti_Data;
143 break;
144 case(MUIA_Listtree_DestructHook):
145 data->destrhook = (struct Hook *)tag->ti_Data;
146 break;
147 case(MUIA_Listtree_DisplayHook):
148 data->displayhook = (struct Hook *)tag->ti_Data;
149 break;
150 case(MUIA_List_MinLineHeight):
151 case(MUIA_ContextMenu):
152 case(MUIA_List_DragSortable):
153 case(MUIA_List_Title):
154 case(MUIA_Listtree_DragDropSort):
155 case(MUIA_Listtree_Format):
156 case(MUIA_Listtree_Title):
157 case(MUIA_Frame):
158 /* Forwarded to NListtree */
159 break;
160 NEWHANDLE(MUIA_Listtree_SortHook)
161 default:
162 bug("[Listtree] OM_NEW: unhandled %x\n", tag->ti_Tag);
166 /* Setup hook proxies */
167 if (data->displayhook)
169 data->displayhookproxy.h_Entry = HookEntry;
170 data->displayhookproxy.h_SubEntry = (HOOKFUNC)DisplayHook_Proxy;
171 data->displayhookproxy.h_Data = data->displayhook;
172 nnset(data->nlisttree, MUIA_NListtree_DisplayHook, &data->displayhookproxy);
175 /* Setup notification forwarding */
176 DoMethod(data->nlisttree, MUIM_Notify, MUIA_NListtree_Active, MUIV_EveryTime,
177 obj, 4, MUIM_CallHook, &data->notifysimulatehook, MUIA_NListtree_Active, MUIV_TriggerValue);
179 return obj;
182 #define SETHANDLE(attrname) \
183 case(attrname): \
184 bug("[Listtree] OM_SET:%s - unsupported\n", #attrname); \
185 break;
187 #define FORWARDSET(AATTR, BATTR) \
188 case(AATTR): \
189 set(data->nlisttree, BATTR, tag->ti_Data); \
190 break;
192 #define IGNORESET(AATTR) case(AATTR): break;
194 IPTR Listtree__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
196 struct Listtree_DATA *data = INST_DATA(cl, obj);
197 struct TagItem *tstate = msg->ops_AttrList;
198 struct TagItem *tag;
200 if (!data->nlisttree)
201 return DoSuperMethodA(cl, obj, (Msg) msg);
203 while ((tag = NextTagItem(&tstate)) != NULL)
205 switch (tag->ti_Tag)
207 FORWARDSET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
208 FORWARDSET(MUIA_List_Active, MUIA_NList_Active)
210 IGNORESET(MUIA_Listview_SelectChange)
212 case(MUIA_Listtree_Active):
213 set(data->nlisttree, MUIA_NListtree_Active,
214 ((struct MUIS_Listtree_TreeNodeInt *)tag->ti_Data)->ref);
215 break;
217 SETHANDLE(MUIA_Listtree_DoubleClick)
218 case MUIB_List | 0x00000010: break;
219 case MUIA_Prop_First: break;
220 case MUIA_Prop_DoSmooth: break;
221 case MUIA_NoNotify: break;
222 case MUIA_Prop_Entries: break;
223 case MUIA_Prop_Visible: break;
224 case MUIA_Prop_DeltaFactor: break;
225 default:
226 bug("[Listtree] OM_SET: passing to parent class %x\n", tag->ti_Tag);
231 return DoSuperMethodA(cl, obj, (Msg) msg);
234 #define GETHANDLE(attrname) \
235 case(attrname): \
236 bug("[Listtree] OM_GET:%s - unsupported\n", #attrname); \
237 break;
240 #define MUIA_List_Prop_Entries /* PRIV */ \
241 (MUIB_MUI | 0x0042a8f5) /* .sg LONG PRIV */
242 #define MUIA_List_Prop_Visible /* PRIV */ \
243 (MUIB_MUI | 0x004273e9) /* .sg LONG PRIV */
244 #define MUIA_List_Prop_First /* PRIV */ \
245 (MUIB_MUI | 0x00429df3) /* .sg LONG PRIV */
247 #define MUIA_List_VertProp_Entries /* PRIV */ \
248 MUIA_List_Prop_Entries /* PRIV */
249 #define MUIA_List_VertProp_Visible /* PRIV */ \
250 MUIA_List_Prop_Visible /* PRIV */
251 #define MUIA_List_VertProp_First /* PRIV */ \
252 MUIA_List_Prop_First /* PRIV */
254 #define FORWARDGET(AATTR, BATTR) \
255 case(AATTR): \
256 *(msg->opg_Storage) = XGET(data->nlisttree, BATTR); \
257 return TRUE;
259 IPTR Listtree__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
261 struct Listtree_DATA *data = INST_DATA(cl, obj);
263 if (!data->nlisttree)
264 return FALSE;
266 switch (msg->opg_AttrID)
268 FORWARDGET(MUIA_Frame, MUIA_Frame)
269 FORWARDGET(MUIA_Listtree_DoubleClick, MUIA_NListtree_DoubleClick)
270 FORWARDGET(MUIA_List_Active, MUIA_NList_Active)
271 FORWARDGET(MUIA_Listtree_Active, MUIA_NListtree_Active)
272 FORWARDGET(MUIA_Listtree_Quiet, MUIA_NListtree_Quiet)
273 FORWARDGET(MUIA_List_Visible, MUIA_NList_Visible)
275 GETHANDLE(MUIA_List_VertProp_Entries)
276 GETHANDLE(MUIA_List_VertProp_Visible)
277 GETHANDLE(MUIA_List_VertProp_First)
278 case MUIA_Disabled: break;
279 case MUIA_Parent: break;
280 case MUIA_Group_ChildList: break;
281 case MUIA_Prop_First: break;
282 case MUIA_Prop_DoSmooth: break;
283 case MUIA_Listview_List: break;
284 case MUIA_Virtgroup_Left: break;
285 case MUIA_Virtgroup_Top: break;
286 case 0x9d510020 /*MUIA_NListview_NList*/: break;
287 default:
288 bug("[Listtree] OM_GET: passing to parent class %x\n", msg->opg_AttrID);
291 return DoSuperMethodA(cl, obj, (Msg) msg);
294 #define METHODSTUB(methodname) \
295 IPTR Listtree__##methodname(struct IClass *cl, Object *obj, Msg msg) \
297 bug("[Listtree] Usupported : %s\n", #methodname); \
298 return (IPTR)FALSE; \
301 METHODSTUB(MUIM_Listtree_Close)
302 METHODSTUB(MUIM_Listtree_SetDropMark)
304 IPTR Listtree__MUIM_Listtree_Insert(struct IClass *cl, Object *obj, struct MUIP_Listtree_Insert *msg)
306 struct Listtree_DATA *data = INST_DATA(cl, obj);
307 struct MUIS_Listtree_TreeNodeInt * _int = AllocPooled(data->pool, sizeof(struct MUIS_Listtree_TreeNodeInt));
308 struct MUIS_Listtree_TreeNode * _return = NULL;
309 struct MUI_NListtree_TreeNode * ln = NULL, * pn = NULL;
311 if (_int == NULL)
312 return (IPTR)NULL;
314 _return = &_int->base;
316 _return->tn_Flags = (UWORD)msg->Flags;
317 if (data->constrhook)
318 _return->tn_User = (APTR)CallHookPkt(data->constrhook, data->pool, msg->User);
319 else
320 _return->tn_User = msg->User;
322 switch((IPTR)msg->ListNode)
324 case(MUIV_Listtree_Insert_ListNode_Root):
325 case(MUIV_Listtree_Insert_ListNode_Active):
326 ln = msg->ListNode;
327 break;
328 default:
329 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
332 switch((IPTR)msg->PrevNode)
334 case(MUIV_Listtree_Insert_PrevNode_Head):
335 case(MUIV_Listtree_Insert_PrevNode_Tail):
336 case(MUIV_Listtree_Insert_PrevNode_Active):
337 case(MUIV_Listtree_Insert_PrevNode_Sorted):
338 pn = msg->PrevNode;
339 break;
340 default:
341 pn = ((struct MUIS_Listtree_TreeNodeInt *)msg->PrevNode)->ref;
344 _int->ref = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
345 MUIM_NListtree_Insert, msg->Name, _return, ln, pn, msg->Flags);
347 _return->tn_Name = _int->ref->tn_Name;
349 return (IPTR)_return;
352 IPTR Listtree__MUIM_Listtree_GetEntry(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetEntry *msg)
354 struct Listtree_DATA *data = INST_DATA(cl, obj);
355 struct MUI_NListtree_TreeNode * tn = NULL, * found = NULL;
357 switch ((IPTR)msg->Node)
359 case(MUIV_Listtree_GetEntry_ListNode_Root):
360 case(MUIV_Listtree_GetEntry_ListNode_Active):
361 tn = msg->Node;
362 break;
363 default:
364 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->Node)->ref;
367 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree,
368 MUIM_NListtree_GetEntry, tn, msg->Position, msg->Flags);
370 if (found)
371 return (IPTR)found->tn_User;
372 else
373 return (IPTR)NULL;
376 IPTR Listtree__MUIM_Listtree_Remove(struct IClass *cl, Object *obj, struct MUIP_Listtree_Remove *msg)
378 struct Listtree_DATA *data = INST_DATA(cl, obj);
380 /* TODO: handle remaining enumeration values */
381 if ((msg->ListNode == (APTR)MUIV_Listtree_Remove_ListNode_Root) &&
382 ((msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_Active) ||
383 (msg->TreeNode == (APTR)MUIV_Listtree_Remove_TreeNode_All)))
385 /* Deallocating of MUIS_Listtree_TreeNode is happening in the DestructHook */
386 return DoMethod(data->nlisttree, MUIM_NListtree_Remove, msg->ListNode, msg->TreeNode, msg->Flags);
389 /* TODO
390 * add handling for cases where ListNode/TreeNode actually point to Treenode structure
392 bug("[Listtree] MUIM_Listtree_Remove unsupported code path Listnode: %x, Treenode: %x, Flags: %d\n", msg->ListNode, msg->TreeNode, msg->Flags);
394 return (IPTR)FALSE;
397 IPTR Listtree__MUIM_List_TestPos(struct IClass *cl, Object *obj, struct MUIP_List_TestPos *msg)
399 struct Listtree_DATA *data = INST_DATA(cl, obj);
401 struct MUI_NList_TestPos_Result res;
402 if (DoMethod(data->nlisttree, MUIM_List_TestPos, msg->x, msg->y, &res))
404 msg->res->entry = res.entry;
405 msg->res->column = res.column;
406 msg->res->flags = res.flags;
407 msg->res->xoffset = res.xoffset;
408 msg->res->yoffset = res.yoffset;
409 return TRUE;
412 return FALSE;
415 IPTR Listtree__MUIM_Listtree_TestPos(struct IClass *cl, Object *obj, struct MUIP_Listtree_TestPos *msg)
417 struct Listtree_DATA *data = INST_DATA(cl, obj);
419 struct MUI_NListtree_TestPos_Result res;
420 struct MUIS_Listtree_TestPos_Result * _ret = (struct MUIS_Listtree_TestPos_Result *)msg->Result;
422 _ret->tpr_TreeNode = NULL;
424 DoMethod(data->nlisttree, MUIM_NListtree_TestPos, msg->X, msg->Y, &res);
426 _ret->tpr_Flags = res.tpr_Type;
427 _ret->tpr_ListEntry = res.tpr_ListEntry;
428 _ret->tpr_ListFlags = res.tpr_ListFlags;
430 if (res.tpr_TreeNode != NULL)
432 _ret->tpr_TreeNode = res.tpr_TreeNode->tn_User;
433 return TRUE;
436 return FALSE;
439 IPTR Listtree__MUIM_Listtree_GetNr(struct IClass *cl, Object *obj, struct MUIP_Listtree_GetNr *msg)
441 struct Listtree_DATA *data = INST_DATA(cl, obj);
442 struct MUI_NListtree_TreeNode * tn = NULL;
444 switch((IPTR)msg->TreeNode)
446 case(MUIV_Listtree_GetNr_TreeNode_Active):
447 tn = msg->TreeNode;
448 break;
449 default:
450 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
453 return DoMethod(data->nlisttree, MUIM_NListtree_GetNr, tn, msg->Flags);
456 IPTR Listtree__MUIM_Listtree_Rename(struct IClass *cl, Object *obj, struct MUIP_Listtree_Rename *msg)
458 struct Listtree_DATA *data = INST_DATA(cl, obj);
459 struct MUI_NListtree_TreeNode * tn = NULL, * renamed = NULL;
461 switch((IPTR)msg->TreeNode)
463 case(MUIV_Listtree_Rename_TreeNode_Active):
464 tn = msg->TreeNode;
465 break;
466 default:
467 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
470 renamed = (struct MUI_NListtree_TreeNode *)DoMethod(data->nlisttree,
471 MUIM_NListtree_Rename, tn, msg->NewName, msg->Flags);
473 if (renamed)
475 ((struct MUIS_Listtree_TreeNode *)renamed->tn_User)->tn_Name = renamed->tn_Name;
476 return (IPTR)renamed->tn_User;
478 else
479 return (IPTR)NULL;
482 IPTR Listtree__MUIM_List_Redraw(struct IClass *cl, Object *obj, struct MUIP_List_Redraw *msg)
484 struct Listtree_DATA *data = INST_DATA(cl, obj);
485 struct MUI_NListtree_TreeNode * entry = msg->entry ?
486 ((struct MUIS_Listtree_TreeNodeInt *)msg->entry)->ref : NULL;
488 switch(msg->pos)
490 case(MUIV_List_Redraw_Entry):
491 return DoMethod(data->nlisttree, MUIM_NList_RedrawEntry, entry);
492 default:
493 return DoMethod(data->nlisttree, MUIM_NList_Redraw, msg->pos);
497 IPTR Listtree__MUIM_Listtree_Open(struct IClass *cl, Object *obj, struct MUIP_Listtree_Open *msg)
499 struct Listtree_DATA *data = INST_DATA(cl, obj);
500 struct MUI_NListtree_TreeNode * tn = NULL, * ln = NULL;
502 switch((IPTR)msg->ListNode)
504 case(MUIV_Listtree_Open_ListNode_Root):
505 case(MUIV_Listtree_Open_ListNode_Parent):
506 case(MUIV_Listtree_Open_ListNode_Active):
507 ln = msg->ListNode;
508 break;
509 default:
510 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
513 switch((IPTR)msg->TreeNode)
515 case(MUIV_Listtree_Open_TreeNode_Head):
516 case(MUIV_Listtree_Open_TreeNode_Tail):
517 case(MUIV_Listtree_Open_TreeNode_Active):
518 case(MUIV_Listtree_Open_TreeNode_All):
519 tn = msg->TreeNode;
520 break;
521 default:
522 tn = ((struct MUIS_Listtree_TreeNodeInt *)msg->TreeNode)->ref;
525 return DoMethod(data->nlisttree, MUIM_NListtree_Open, ln, tn, msg->Flags);
528 IPTR Listtree__MUIM_Listtree_FindName(struct IClass *cl, Object *obj, struct MUIP_Listtree_FindName *msg)
530 struct Listtree_DATA *data = INST_DATA(cl, obj);
531 struct MUI_NListtree_TreeNode * ln = NULL, * found = NULL;
533 switch((IPTR)msg->ListNode)
535 case(MUIV_Listtree_FindName_ListNode_Root):
536 case(MUIV_Listtree_FindName_ListNode_Active):
537 ln = msg->ListNode;
538 break;
539 default:
540 ln = ((struct MUIS_Listtree_TreeNodeInt *)msg->ListNode)->ref;
543 found = (struct MUI_NListtree_TreeNode *) DoMethod(data->nlisttree, MUIM_NListtree_FindName,
544 ln, msg->Name, msg->Flags);
546 if (found)
547 return (IPTR)found->tn_User;
548 else
549 return (IPTR)NULL;