forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / bgui / gadgets / TreeView / TVLVHandlers.c
blob2d26b39f1258a9a12cc7eb3f46a40139163055df
1 /*
2 * @(#) $Header$
4 * BGUI Tree List View class
6 * (C) Copyright 1999 Manuel Lemos.
7 * (C) Copyright 1996-1999 Nick Christie.
8 * All Rights Reserved.
10 * $Log$
11 * Revision 42.2 2004/06/16 20:16:49 verhaegs
12 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
14 * Revision 42.1 2000/05/15 19:29:08 stegerg
15 * replacements for REG macro
17 * Revision 42.0 2000/05/09 22:21:48 mlemos
18 * Bumped to revision 42.0 before handing BGUI to AROS team
20 * Revision 41.11 2000/05/09 20:35:34 mlemos
21 * Bumped to revision 41.11
23 * Revision 1.2 2000/05/09 20:00:32 mlemos
24 * Merged with the branch Manuel_Lemos_fixes.
26 * Revision 1.1.2.3 1999/05/31 01:14:43 mlemos
27 * Fixed bug of trying to access the last clicked entry when was not set.
29 * Revision 1.1.2.2 1999/05/24 23:58:36 mlemos
30 * Fixed bug of attempting to notifying a change in NULL tree node pointer.
32 * Revision 1.1.2.1 1999/02/21 04:07:47 mlemos
33 * Nick Christie sources.
39 /************************************************************************
40 ****************** TREEVIEW CLASS: LISTVIEW HANDLERS ******************
41 ************************************************************************/
44 /************************************************************************
45 ****************************** INCLUDES *******************************
46 ************************************************************************/
48 #include "TreeViewPrivate.h"
49 #include "TVUtil.h"
51 /************************************************************************
52 ************************** LOCAL DEFINITIONS **************************
53 ************************************************************************/
56 /************************************************************************
57 ************************* EXTERNAL REFERENCES *************************
58 ************************************************************************/
61 * Functions from TVUtil are listed in TVUtil.h
64 /************************************************************************
65 ***************************** PROTOTYPES ******************************
66 ************************************************************************/
68 /************************************************************************
69 ***************************** LOCAL DATA ******************************
70 ************************************************************************/
73 * Default DrawInfo pens
76 LOCAL UWORD DefDriPens[ 12 ] = { 0, 1, 1, 2, 1, 3, 1, 0, 2, 1, 2, 1 };
79 * Pattern used for ghosting disabled entries
82 //LOCAL UWORD GhostPattern[] = { 0x2222, 0x8888 };
84 /************************************************************************
85 ************************* TV_LVRSRCHANDLER() **************************
86 *************************************************************************
87 * Resource handler for embedded listview. We add TreeNodes to this
88 * listview and we don't want them copied or anything, so this handler
89 * just tells the listview to add the TreeNode ptr itself. When removing
90 * entries, there is similarly nothing special to do.
92 *************************************************************************/
94 //ASM SAVEDS ULONG TV_LVRsrcHandler(REG(a0) struct Hook *hook,
95 // REG(a2) Object *obj, REG(a1) struct lvResource *lvr)
96 ASM SAVEDS REGFUNC3(ULONG, TV_LVRsrcHandler,
97 REGPARAM(A0, struct Hook *, hook),
98 REGPARAM(A2, Object *, obj),
99 REGPARAM(A1, struct lvResource *, lvr))
101 if (lvr->lvr_Command == LVRC_MAKE)
102 return((IPTR) lvr->lvr_Entry);
103 else
104 return(0);
106 REGFUNC_END
108 /************************************************************************
109 ************************* TV_LVDISPHANDLER() **************************
110 *************************************************************************
111 * Display handler for embedded listview. The members of the list are
112 * TreeNodes, so the display must take into account their depth in the
113 * hierarchy (represented by indentation), and whether their children
114 * are expanded out (render a boxed plus sign or minus sign to the
115 * left). The last item to render is the treenode's label, this will
116 * need to be passed to the user's custom display hook (if any).
118 * STUB! Doesn't use custom display hook yet.
120 *************************************************************************/
122 //ASM SAVEDS ULONG TV_LVDispHandler(REG(a0) struct Hook *hook,
123 // REG(a2) Object *obj, REG(a1) struct lvRender *lvr)
124 ASM SAVEDS REGFUNC3(ULONG, TV_LVDispHandler,
125 REGPARAM(A0, struct Hook *, hook),
126 REGPARAM(A2, Object *, obj),
127 REGPARAM(A1, struct lvRender *, lvr))
129 TVData *tv;
130 struct RastPort *rp;
131 struct Rectangle *rect;
132 TNPTR tn;
133 struct Image *img;
134 WORD imgwid,imghgt;
135 struct IBox box;
136 struct TextExtent te;
137 STRPTR text;
138 ULONG len;
139 ULONG imgstate;
140 ULONG depth;
141 UWORD fpen,bpen;
142 UWORD *dripens;
143 // BOOL disabled;
145 tv = (TVData *) hook->h_Data;
146 tn = (TNPTR) lvr->lvr_Entry;
147 rp = lvr->lvr_RPort;
148 text = tn->tn_Entry;
149 rect = &lvr->lvr_Bounds;
150 // disabled = FALSE;
151 depth = TV_TreeNodeDepth(tn) - 1;
153 /* debug
154 KPrintF("Render 1: Node:%08lx Name:%s L:%ld T:%ld R:%ld B:%ld\n",
155 tn, tn->tn_Entry, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY);
159 * Determine pens to use
162 dripens = lvr->lvr_DrawInfo ? lvr->lvr_DrawInfo->dri_Pens : DefDriPens;
164 switch(lvr->lvr_State)
166 case LVRS_SELECTED:
167 fpen = TEXTPEN;
168 bpen = FILLPEN;
169 imgstate = IDS_SELECTED;
170 break;
172 case LVRS_NORMAL_DISABLED:
173 fpen = TEXTPEN;
174 bpen = BACKGROUNDPEN;
175 imgstate = IDS_DISABLED;
176 // disabled = TRUE;
177 break;
179 case LVRS_SELECTED_DISABLED:
180 fpen = TEXTPEN;
181 bpen = FILLPEN;
182 imgstate = IDS_DISABLED;
183 // disabled = TRUE;
184 break;
186 /* case LVRS_NORMAL: */
187 default:
188 fpen = TEXTPEN;
189 bpen = BACKGROUNDPEN;
190 imgstate = IDS_NORMAL;
191 break;
193 } /* endswitch lvr_State */
195 fpen = dripens[fpen];
196 bpen = dripens[bpen];
199 * Prefill the area with the background pen
202 SetAPen(rp,bpen);
203 SetDrMd(rp,JAM1);
204 RectFill(rp,rect->MinX,rect->MinY,rect->MaxX,rect->MaxY);
207 * Leave appropriate indentation based on node's depth in tree,
208 * unless TVA_LeftAlignImage has been set.
211 box.Left = rect->MinX + 2;
212 if (!tv->tv_LeftAlignImage)
213 box.Left += depth * tv->tv_Indentation;
214 box.Top = rect->MinY;
215 box.Width = rect->MaxX - box.Left + 1;
216 box.Height = rect->MaxY - rect->MinY + 1;
219 * Render the node image for this item, if there's space.
220 * If TVA_NoLeafImage is set, don't draw an image for
221 * leaf nodes.
224 if (tv->tv_NoLeafImage && !HasChildren(tn))
226 img = NULL;
227 imgwid = ((IMGPTR) tv->tv_ExpandedImage)->Width;
228 imghgt = ((IMGPTR) tv->tv_ExpandedImage)->Height;
230 else
232 img = (IMGPTR) (IsExpanded(tn) ?
233 tv->tv_ExpandedImage : tv->tv_ContractedImage);
234 imgwid = img->Width;
235 imghgt = img->Height;
238 if (imgwid <= box.Width)
240 if (img && (imghgt <= box.Height))
242 UWORD y;
244 y = box.Top + (box.Height - imghgt) / 2;
245 DrawImageState(rp,img,box.Left,y,imgstate,lvr->lvr_DrawInfo);
248 if ( tv->tv_GoingActive && img &&
249 (tv->tv_LastClickX >= box.Left) &&
250 (tv->tv_LastClickX <= box.Left + imgwid - 1) &&
251 (tv->tv_LastClickY >= box.Top) &&
252 (tv->tv_LastClickY <= box.Top + box.Height - 1)
255 tv->tv_ImageClicked = tn;
257 /* debug
258 KPrintF("Render 2: ImageClicked: Node:%08lx Name:%s\n",
259 tn, tn->tn_Entry);
264 * If TVA_LeftAlignImage was set, put indentation in now,
265 * after the image
268 if (tv->tv_LeftAlignImage)
270 box.Left += depth * tv->tv_Indentation;
271 box.Width = rect->MaxX - box.Left + 1;
275 * Determine if we need to draw connecting lines,
276 * and in what style, from tv_LineStyle. If the
277 * image is left-aligned, we don't draw lines.
280 if ((tv->tv_LineStyle != TVLS_NONE) && !tv->tv_LeftAlignImage)
282 TNPTR pn,pn2;
283 UWORD x,y;
285 SetAPen(rp,dripens[TEXTPEN]);
286 SetDrMd(rp,JAM1);
288 switch(tv->tv_LineStyle)
290 case TVLS_DOTS:
291 SetDrPt(rp,0xaaaa);
292 break;
294 case TVLS_DASH:
295 SetDrPt(rp,0xcccc);
296 break;
298 case TVLS_SOLID:
299 default:
300 SetDrPt(rp,0xffff);
301 break;
305 * If entry has children, draw small vertical below image
308 if (IsExpanded(tn) && HasChildren(tn))
310 x = box.Left + (imgwid / 2) - 1;
311 y = box.Top + imghgt + (box.Height - imghgt) / 2;
312 Move(rp,x,y);
313 Draw(rp,x,box.Top + box.Height - 1);
317 * If depth > 0, draw horizontal to left of image.
318 * If img is NULL then this was an image-less leaf
319 * node and we should start just to the left of the
320 * label, not the left of the (nonexistent) image.
323 if (depth > 0)
325 y = box.Top + (box.Height / 2);
326 x = box.Left - 1;
327 Move(rp,x + (img ? 0 : imgwid),y);
328 x -= tv->tv_Indentation - (imgwid / 2);
329 Draw(rp,x,y);
332 * If entry has next sibling, draw full height vertical
333 * at lefthand point of horizontal line, otherwise just
334 * draw half-height vertical.
337 Move(rp,x,box.Top);
338 Draw(rp,x,NextSiblingOf(tn) ? box.Top + box.Height - 1 : y);
341 * For each further parent with a next sibling,
342 * draw a full height vertical line.
345 pn = ParentOf(tn);
347 while((pn2 = ParentOf(pn)))
349 x -= tv->tv_Indentation;
351 if (NextSiblingOf(pn))
353 Move(rp,x,box.Top);
354 Draw(rp,x,box.Top + box.Height - 1);
357 pn = pn2;
362 * Reset rastport to solid line pattern
365 SetDrPt(rp,0xffff);
368 box.Left += imgwid + rp->TxWidth;
369 box.Width -= imgwid + rp->TxWidth;
371 SetAPen(rp,fpen);
372 SetDrMd(rp,JAM1);
373 Move(rp,box.Left,box.Top + rp->Font->tf_Baseline);
374 len = TextFit(rp,text,strlen(text),&te,NULL,1,box.Width,32767);
375 Text(rp,text,len);
378 return(0);
380 REGFUNC_END
382 /************************************************************************
383 ************************* TV_LVCOMPHANDLER() **************************
384 *************************************************************************
385 * Compare handler for embedded listview. Sorts entries by parents
386 * before sorting by individual entry.
388 *************************************************************************/
390 //ASM SAVEDS ULONG TV_LVCompHandler(REG(a0) struct Hook *hook,
391 // REG(a2) Object *obj, REG(a1) struct lvCompare *lvc)
392 ASM SAVEDS REGFUNC3(ULONG, TV_LVCompHandler,
393 REGPARAM(A0, struct Hook *, hook),
394 REGPARAM(A2, Object *, obj),
395 REGPARAM(A1, struct lvCompare *, lvc))
397 struct tvCompare tvc;
398 TVData *tv;
399 TNPTR tna,tnb;
400 ULONG da,db;
402 tv = (TVData *) hook->h_Data;
403 tna = (TNPTR) lvc->lvc_EntryA;
404 tnb = (TNPTR) lvc->lvc_EntryB;
405 da = TV_TreeNodeDepth(tna);
406 db = TV_TreeNodeDepth(tnb);
408 while(db < da)
409 { tna = ParentOf(tna); da--; }
411 while(da < db)
412 { tnb = ParentOf(tnb); db--; }
414 tvc.tvc_EntryA = tna->tn_Entry;
415 tvc.tvc_EntryB = tnb->tn_Entry;
417 return(CallHookPkt(tv->tv_CompareHook,tv->tv_TreeView,&tvc));
419 REGFUNC_END
421 /************************************************************************
422 ************************ TV_LVNOTIFYHANDLER() *************************
423 *************************************************************************
424 * Notification hook added to embedded listview: called when the currently
425 * selected item in the listview changes. If the user clicked on the
426 * tree image for an entry, and the released the LMB while the mouse
427 * pointer was over that entry, we expand or contract it. Same applies
428 * if the user has just double-clicked on an entry.
430 * This relies on the fact that our TV_GoActive method has determined
431 * the initial position of the mousepointer, and our TV_LVDispHandler
432 * hook has set tv_ImageClicked to point at the clicked entry, if the
433 * user clicked on the tree image, rather than the entry itself.
435 *************************************************************************/
437 //ASM SAVEDS ULONG TV_LVNotifyHandler(REG(a0) struct Hook *hook,
438 // REG(a2) Object *obj, REG(a1) struct opUpdate *opu)
439 ASM SAVEDS REGFUNC3(ULONG, TV_LVNotifyHandler,
440 REGPARAM(A0, struct Hook *, hook),
441 REGPARAM(A2, Object *, obj),
442 REGPARAM(A1, struct opUpdate *, opu))
444 struct TagItem *tag;
445 TVData *tv;
446 TNPTR tn,pn;
447 ULONG time[2];
448 ULONG rc;
450 tv = (TVData *) hook->h_Data;
451 rc = 0;
454 * Find the LISTV_Entry tag in the notification taglist, and verify
455 * that this notification is a final one, not an interim update.
458 if ((tag = FindTagItem(LISTV_Entry,opu->opu_AttrList)))
460 tn = (TNPTR) tag->ti_Data;
462 if (!(opu->opu_Flags & OPUF_INTERIM))
465 * User activated gadget with LMB down on a tree image,
466 * and released the LMB with the pointer over that entry?
469 if (tv->tv_ImageClicked && (tn == tv->tv_ImageClicked))
472 * Yes: expand/contract this entry
475 tv->tv_LastClickTime[0] = tv->tv_LastClickTime[1] = 0;
476 rc = 1;
478 /* debug
479 KPrintF("LVNotifyHandler: Image click expand node: %s\n",
480 tv->tv_ImageClicked->tn_Entry);
483 else
486 * User double-clicked on entry? And it's not an
487 * image-less leaf node?
490 CurrentTime(&time[0],&time[1]);
492 if (tn
493 && (tn == tv->tv_LastClicked)
494 && (!tv->tv_NoLeafImage || HasChildren(tn))
495 && (DoubleClick(tv->tv_LastClickTime[0],tv->tv_LastClickTime[1],
496 time[0],time[1])))
499 * Yes: expand/contract this entry
502 tv->tv_LastClickTime[0] = tv->tv_LastClickTime[1] = 0;
503 rc = 1;
505 /* debug
506 KPrintF("LVNotifyHandler: Double click expand node: %s\n",
507 tn->tn_Entry);
510 else
512 tv->tv_LastClickTime[0] = time[0];
513 tv->tv_LastClickTime[1] = time[1];
517 if (tv->tv_LastClicked)
518 tv->tv_LastClicked->tn_Flags &= ~TNF_SELECTED;
520 if (rc) /* expand/contract entry */
522 rc = BGUI_DoGadgetMethod(tv->tv_TreeView,
523 opu->opu_GInfo ? opu->opu_GInfo->gi_Window : NULL,
524 NULL, TVM_EXPAND, NULL, tv->tv_LastClicked,
525 TVW_ENTRY, TVF_TOGGLE|TVF_USER_ACTION|TVF_INTERNAL);
529 if((tv->tv_LastClicked = tn))
531 tn->tn_Flags |= TNF_SELECTED;
532 pn = ParentOf(tn);
534 TV_NotifyAttrChange(tv->tv_TreeView,opu->opu_GInfo,opu->opu_Flags,
535 TVA_Entry, tn->tn_Entry,
536 TVA_Parent, pn ? pn->tn_Entry : NULL,
537 TVA_Moved, FALSE,
538 TAG_DONE);
542 return(rc);
544 REGFUNC_END