1 /***************************************************************************
3 NListtree.mcc - New Listtree MUI Custom Class
4 Copyright (C) 1999-2001 by Carsten Scholling
5 Copyright (C) 2001-2014 NList Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 NList classes Support Site: http://www.sf.net/projects/nlist-classes
21 ***************************************************************************/
23 /****** NListtree.mcc/--background-- *****************************************
25 * There are two possible entry-types in a NListtree class list:
26 * Leaves and nodes. Leaves are simple entries which have no special
27 * features except they are holding some data. Nodes are almost
28 * the same type, holding data too, but having a list attached
29 * where you can simply add other entries which can be again leaves
32 * Every node is structured as follows:
34 * struct MUI_NListtree_TreeNode {
36 * struct MinNode tsn_Node;
42 * It contains a name field tn_Name, flags tn_Flags and a pointer to
45 * The tn_Flags field can hold the following flags:
47 * TNF_LIST The node contains a list where other nodes
50 * TNF_OPEN The list node is open, sub nodes are displayed.
52 * TNF_FROZEN The node doesn't react on doubleclick or
53 * open/close by the user.
55 * TNF_NOSIGN The indicator of list nodes isn't shown.
57 * TNF_SELECTED The entry is currently selected.
59 * These flags, except TNF_SELECTED, can be used in
60 * MUIM_NListtree_Insert at creation time. They will be passed to
61 * the newly created entry. Also you can do a quick check about the
62 * state and kind of each entry. But - NEVER EVER - modify any flag
63 * yourself or NListtree will crash. Be warned!
65 * *********************************************************************
66 * THE ABOVE STRUCT IS READ-ONLY!! NEVER CHANGE ANY ENTRY OF THIS
67 * STRUCTURE DIRECTLY NOR THINK ABOUT THE CONTENTS OF ANY PRIVATE
68 * FIELD OR YOU WILL DIE IN HELL!
69 * *********************************************************************
72 * You can create very complex tree structures. NListtree only uses
73 * one list which holds all information needed and has no extra
74 * display list like other list tree classes ;-)
76 * The tree nodes can be inserted and removed, sorted, moved, exchanged,
77 * renamed or multi selected. To sort you can also drag&drop them.
78 * Modifications can be made in relation to the whole tree, to only one
79 * level, to a sub-tree or to only one tree node.
81 * The user can control the listtree by the MUI keys, this means a node
82 * is opened with "Right" and closed with "Left". Check your MUI prefs
83 * for the specified keys.
85 * You can define which of the columns will react on double-clicking.
86 * The node toggles its status from open or closed and vice versa.
89 * Drag&Drop capabilities:
91 * If you set MUIA_NList_DragSortable to TRUE, the list tree will
92 * become active for Drag&Drop. This means you can drag and drop
93 * entries on the same list tree again. While dragging an indicator
94 * shows where to drop.
96 * Drag a Drop on Result
98 * leaf leaf Exchange leaves.
99 * node leaf Nothing happens.
100 * entry closed node Move entry, the compare hook is used.
101 * entry open node Move entry to defined position.
103 * You can not drop an entry on itself, nor can you drop an opened node on
104 * any of its members.
106 * To exchange data with other objects, you have to create your own
107 * subclass of NListtree class and react on the drag methods.
110 * Author: Carsten Scholling (c)1999-2000 email: cs@aphaso.de
112 ******************************************************************************
123 #include <graphics/gfxmacros.h>
126 #include <libraries/gadtools.h>
127 #include <clib/alib_protos.h>
128 #include <clib/macros.h>
129 #include <proto/muimaster.h>
130 #include <proto/intuition.h>
131 #include <proto/graphics.h>
132 #include <proto/utility.h>
133 #include <proto/exec.h>
137 #include "NListtree.h"
139 #include "muiextra.h"
141 #define DATA_BUF_SIZE 4096
143 /*********************************************************************************************/
145 // stack definition (where is this used!?)
146 LONG __stack
= 16384;
149 ** Small helpful macros...
151 #define DIFF(a,b) (MAX((a),(b))-MIN((a),(b)))
152 #define CLN(x) ((struct MUI_NListtree_ListNode *)(x))
153 #define CTN(x) ((struct MUI_NListtree_TreeNode *)(x))
156 ** Type definition for compare function.
159 void qsort2(struct MUI_NListtree_TreeNode
**table
, ULONG entries
, struct NListtree_Data
*data
);
164 ULONG
MultiTestFunc( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG seltype
, LONG selflags
);
166 struct TreeImage_Data
172 #if !defined(__MORPHOS__)
174 static __attribute__ ((noinline
)) Object
* VARARGS68K
DoSuperNew(struct IClass
*cl
, Object
*obj
, Tag tag1
, ...)
176 AROS_SLOWSTACKTAGS_PRE_AS(tag1
, Object
*)
177 retval
= (Object
*)DoSuperMethod(cl
, obj
, OM_NEW
, AROS_SLOWSTACKTAGS_ARG(tag1
), NULL
);
178 AROS_SLOWSTACKTAGS_POST
181 static Object
* VARARGS68K
DoSuperNew(struct IClass
*cl
, Object
*obj
, ...)
189 rc
= (Object
*)DoSuperMethod(cl
, obj
, OM_NEW
, VA_ARG(args
, ULONG
), NULL
);
196 #endif // !__MORPHOS__
198 /*****************************************************************************\
199 *******************************************************************************
201 ** Graphic and drawing functions.
203 *******************************************************************************
204 \*****************************************************************************/
207 ** Set A/B-Pen and DrawMode depending on OS version.
209 INLINE VOID
MySetABPenDrMd( struct RastPort
*rp
, LONG apen
, LONG bpen
, UBYTE drmd
)
211 if ( LIBVER( GfxBase
) >= 39 )
212 SetABPenDrMd( rp
, apen
, bpen
, drmd
);
223 ** Draw a simple line from l/t to r/b. All lines are pure horiz. or vert.!
225 INLINE VOID
DrawLine( struct RastPort
*rp
, WORD l
, WORD t
, WORD r
, WORD b
)
233 ** Draw windows line l/t to r/b. All
234 ** lines are pure horiz. or vert.!
236 INLINE VOID
DrawLineDotted( struct RastPort
*rp
, WORD l
, WORD t
, WORD r
, WORD b
)
242 WritePixel( rp
, l
, t
);
250 WritePixel( rp
, l
, t
);
259 ** Draw a vertical bar.
261 INLINE VOID
DrawTreeVertBar( struct TreeImage_Data
*data
, struct MyImage
*im
, WORD l
, WORD t
, UNUSED WORD r
, WORD b
)
263 struct RastPort
*rp
= (struct RastPort
*)_rp( data
->obj
);
264 UWORD m
= l
+ ( im
->nltdata
->MaxImageWidth
- 1 ) / 2;
268 switch(im
->nltdata
->LineType
)
270 case MUICFGV_NListtree_LineType_Disabled
:
274 case MUICFGV_NListtree_LineType_Normal
:
276 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
277 DrawLine( rp
, m
, t
, m
, b
);
281 case MUICFGV_NListtree_LineType_Dotted
:
283 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
284 DrawLineDotted( rp
, m
, t
, m
, b
);
288 case MUICFGV_NListtree_LineType_Shadow
:
290 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
291 DrawLine( rp
, m
+1, t
, m
+1, b
);
292 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
293 DrawLine( rp
, m
, t
, m
, b
);
297 case MUICFGV_NListtree_LineType_Glow
:
299 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
300 DrawLine( rp
, m
+ 2, t
, m
+ 2, b
);
302 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
303 DrawLine( rp
, m
, t
, m
, b
);
305 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Glow
] ) );
306 DrawLine( rp
, m
- 1, t
, m
- 1, b
);
307 DrawLine( rp
, m
+1, t
, m
+1, b
);
317 ** Draw a vertical T bar.
319 INLINE VOID
DrawTreeVertBarT( struct TreeImage_Data
*data
, struct MyImage
*im
, WORD l
, WORD t
, WORD r
, WORD b
)
321 struct RastPort
*rp
= (struct RastPort
*)_rp( data
->obj
);
322 UWORD m
= l
+ ( im
->nltdata
->MaxImageWidth
- 1 ) / 2;
323 UWORD h
= t
+ ( b
- t
) / 2;
327 switch(im
->nltdata
->LineType
)
329 case MUICFGV_NListtree_LineType_Disabled
:
333 case MUICFGV_NListtree_LineType_Normal
:
335 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
336 DrawLine( rp
, m
, t
, m
, b
);
337 DrawLine( rp
, m
, h
, r
, h
);
341 case MUICFGV_NListtree_LineType_Dotted
:
343 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
344 DrawLineDotted( rp
, m
, t
, m
, b
);
345 DrawLineDotted( rp
, m
, h
, m
+ (im
->nltdata
->MaxImageWidth
-1)/2 + im
->nltdata
->IndentWidth
, h
);
349 case MUICFGV_NListtree_LineType_Shadow
:
351 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
352 DrawLine( rp
, m
+1, t
, m
+1, b
);
353 DrawLine( rp
, m
+1, h
+ 1, r
, h
+ 1 );
355 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
356 DrawLine( rp
, m
, t
, m
, b
);
357 DrawLine( rp
, m
, h
, r
, h
);
361 case MUICFGV_NListtree_LineType_Glow
:
363 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
364 DrawLine( rp
, m
+ 2, t
, m
+ 2, b
);
365 DrawLine( rp
, m
+ 3, h
+ 2, r
, h
+ 2 );
367 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Glow
] ) );
368 DrawLine( rp
, m
- 1, t
, m
- 1, b
);
369 DrawLine( rp
, m
+1, t
, m
+1, b
);
371 DrawLine( rp
, m
+1, h
- 1, r
, h
- 1 );
372 DrawLine( rp
, m
+1, h
+ 1, r
, h
+ 1 );
374 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
375 DrawLine( rp
, m
, t
, m
, b
);
376 DrawLine( rp
, m
, h
, r
, h
);
387 ** Draw a vertical end bar.
389 INLINE VOID
DrawTreeVertBarEnd( struct TreeImage_Data
*data
, struct MyImage
*im
, WORD l
, WORD t
, WORD r
, WORD b
)
391 struct RastPort
*rp
= (struct RastPort
*)_rp( data
->obj
);
392 UWORD m
= l
+ ( im
->nltdata
->MaxImageWidth
- 1 ) / 2;
393 UWORD h
= t
+ ( b
- t
) / 2;
397 switch(im
->nltdata
->LineType
)
399 case MUICFGV_NListtree_LineType_Disabled
:
403 case MUICFGV_NListtree_LineType_Normal
:
405 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
406 DrawLine( rp
, m
, t
, m
, h
);
407 DrawLine( rp
, m
, h
, r
, h
);
411 case MUICFGV_NListtree_LineType_Dotted
:
413 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
414 DrawLineDotted( rp
, m
, t
, m
, h
);
415 DrawLineDotted( rp
, m
, h
, m
+ (im
->nltdata
->MaxImageWidth
-1)/2 + im
->nltdata
->IndentWidth
, h
);
419 case MUICFGV_NListtree_LineType_Shadow
:
421 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
422 DrawLine( rp
, m
+1, t
, m
+1, h
);
423 DrawLine( rp
, m
+1, h
+ 1, r
, h
+ 1 );
425 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
426 DrawLine( rp
, m
, t
, m
, h
);
427 DrawLine( rp
, m
, h
, r
, h
);
431 case MUICFGV_NListtree_LineType_Glow
:
433 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
434 DrawLine( rp
, m
+ 2, t
, m
+ 2, h
- 2 );
435 DrawLine( rp
, m
, h
+ 2, r
, h
+ 2 );
437 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Glow
] ) );
438 DrawLine( rp
, m
- 1, t
, m
- 1, h
);
439 DrawLine( rp
, m
+1, h
- 1, r
, h
- 1 );
441 DrawLine( rp
, m
+1, t
, m
+1, h
);
442 DrawLine( rp
, m
- 1, h
+ 1, r
, h
+ 1 );
444 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
445 DrawLine( rp
, m
, t
, m
, h
);
446 DrawLine( rp
, m
, h
, r
, h
);
456 ** Draw a horizontal bar.
458 INLINE VOID
DrawTreeHorBar( struct TreeImage_Data
*data
, struct MyImage
*im
, WORD l
, WORD t
, WORD r
, WORD b
)
460 struct RastPort
*rp
= (struct RastPort
*)_rp( data
->obj
);
461 UWORD h
= t
+ ( b
- t
) / 2;
465 switch(im
->nltdata
->LineType
)
467 case MUICFGV_NListtree_LineType_Disabled
:
471 case MUICFGV_NListtree_LineType_Normal
:
473 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
474 DrawLine( rp
, l
-1, h
, r
+1, h
);
478 case MUICFGV_NListtree_LineType_Dotted
:
480 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
481 DrawLineDotted( rp
, l
-1, h
, r
+1, h
);
485 case MUICFGV_NListtree_LineType_Shadow
:
487 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
488 DrawLine( rp
, l
-1, h
+ 1, r
+1, h
+ 1 );
490 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
491 DrawLine( rp
, l
-1, h
, r
+1, h
);
495 case MUICFGV_NListtree_LineType_Glow
:
497 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Shadow
] ) );
498 DrawLine( rp
, l
-1, h
+ 2, r
, h
+ 2 );
500 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Glow
] ) );
501 DrawLine( rp
, l
-1, h
- 1, r
, h
- 1 );
502 DrawLine( rp
, l
-1, h
+ 1, r
, h
+ 1 );
504 SetAPen( rp
, MUIPEN( im
->nltdata
->Pen
[PEN_Line
] ) );
505 DrawLine( rp
, l
-1, h
, r
, h
);
515 /*****************************************************************************\
516 *******************************************************************************
518 ** Tree image class functions.
520 *******************************************************************************
521 \*****************************************************************************/
524 ** Draw function for special tree image class.
526 IPTR
TreeImage_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
528 struct TreeImage_Data
*data
= INST_DATA( cl
, obj
);
530 DoSuperMethodA( cl
, obj
, (Msg
)msg
);
532 if(isFlagSet(msg
->flags
, MADF_DRAWOBJECT
) || isFlagSet(msg
->flags
, MADF_DRAWUPDATE
))
537 D(DBF_DRAW
, "DRAW SPEC: %ld - %ld/%ld/%ld/%ld", data
->spec
, _defwidth(obj
), _defheight(obj
), _minwidth(obj
), _minheight(obj
));
538 D(DBF_DRAW
, "%ld/%ld/%ld/%ld", _left(obj
), _top(obj
), _right(obj
), _bottom(obj
));
540 im
= (struct MyImage
*)xget( obj
, MUIA_UserData
);
547 SetDrMd( _rp( obj
), JAM1
);
552 DrawTreeVertBar( data
, im
, l
, t
, r
, b
);
556 DrawTreeVertBarT( data
, im
, l
, t
, r
, b
);
560 DrawTreeVertBarEnd( data
, im
, l
, t
, r
, b
);
564 DrawTreeHorBar( data
, im
, l
, t
, r
, b
);
579 ** Special tree image class creation.
581 IPTR
TreeImage_New(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
583 struct TreeImage_Data
*data
;
585 if ( !( obj
= (Object
*)DoSuperMethodA( cl
, obj
, (Msg
)msg
) ) )
590 data
= INST_DATA( cl
, obj
);
601 ** Attribute setting function for special tree image class.
603 ULONG
TreeImage_Set(struct IClass
*cl
, Object
*obj
, Msg msg
)
605 struct TreeImage_Data
*data
= INST_DATA( cl
, obj
);
606 struct TagItem
*tags
, *tag
;
608 for(tags
= ((struct opSet
*)msg
)->ops_AttrList
; (tag
= (struct TagItem
*)NextTagItem((APTR
)&tags
));)
610 switch( tag
->ti_Tag
)
613 data
->spec
= tag
->ti_Data
;
618 D(DBF_IMAGES
, "SET SPEC: %ld", data
->spec
);
625 ** Dispatcher for the special tree image class.
628 DISPATCHER(TreeImage_Dispatcher
)
630 switch( msg
->MethodID
)
632 case OM_NEW
: return( TreeImage_New( cl
, obj
, (APTR
)msg
) );
633 case OM_SET
: return( TreeImage_Set( cl
, obj
, (APTR
)msg
) );
634 case MUIM_Draw
: return( TreeImage_Draw( cl
, obj
, (APTR
)msg
) );
637 return( DoSuperMethodA( cl
, obj
, msg
) );
641 ** Dispatcher for the special tree image class no. 2.
642 ** Get the maximum width of images.
644 DISPATCHER(NodeImage_Dispatcher
)
646 if ( msg
->MethodID
== MUIM_Show
)
651 im
= (struct MyImage
*)xget( obj
, MUIA_UserData
);
653 w
= _defwidth( obj
);
654 h
= _defheight( obj
);
656 if ( im
->nltdata
->MaxImageWidth
< w
)
657 im
->nltdata
->MaxImageWidth
= w
;
659 if ( im
->nltdata
->MaxImageHeight
< h
)
661 im
->nltdata
->MaxImageHeight
= h
;
663 if ( xget( obj
, MUIA_NList_LineHeight
) < h
)
664 nnset( im
->nltdata
->Obj
, MUIA_NList_MinLineHeight
, h
);
667 D(DBF_IMAGES
, "=====> DefWidth: %ld, DefHeight: %ld, MaxWidth: %ld", w
, h
, im
->nltdata
->MaxImageWidth
);
670 return( DoSuperMethodA( cl
, obj
, (Msg
)msg
) );
673 /*****************************************************************************\
674 *******************************************************************************
676 ** Helpful handling functions.
678 *******************************************************************************
679 \*****************************************************************************/
681 /* MorphOS, OS4 and AROS support Alloc/FreeVecPooled internally */
682 #if defined(__amigaos3__)
689 ** Allocate pooled memory.
691 INLINE APTR
AllocVecPooled( APTR mempool
, ULONG size
)
695 if((mem
= (ULONG
*)AllocPooled(mempool
, size
+ 4)))
699 D(DBF_MEMORY
, "0x%08lx = AllocPooled( mempool, %ld ) ==> total: %ld", mem
, size
+ 4, totalmem
);
710 ** Free previously allocated pool memory.
712 INLINE VOID
FreeVecPooled( APTR mempool
, APTR mem
)
714 ULONG
*m
= (ULONG
*)mem
;
718 D(DBF_MEMORY
, " FreePooled( mempool, 0x%08lx, %ld ) ==> total: %ld", &m
[-1], m
[-1] + 4, totalmem
);
721 FreePooled( mempool
, &m
[-1], m
[-1] + 4 );
724 #endif /* !__MORPHOS__ && !__amigaos4__ */
726 #if !defined(__amigaos4__) && !defined(__AROS__)
727 struct Node
*GetSucc(struct Node
*node
)
729 struct Node
*result
= NULL
;
731 if(node
!= NULL
&& node
->ln_Succ
!= NULL
&& node
->ln_Succ
->ln_Succ
!= NULL
)
732 result
= node
->ln_Succ
;
737 struct Node
*GetPred(struct Node
*node
)
739 struct Node
*result
= NULL
;
741 if(node
!= NULL
&& node
->ln_Pred
!= NULL
&& node
->ln_Pred
->ln_Pred
!= NULL
)
742 result
= node
->ln_Pred
;
747 struct Node
*GetHead(struct List
*list
)
749 struct Node
*result
= NULL
;
751 if(list
!= NULL
&& IsListEmpty(list
) == FALSE
)
752 result
= list
->lh_Head
;
757 struct Node
*GetTail(struct List
*list
)
759 struct Node
*result
= NULL
;
761 if(list
!= NULL
&& IsListEmpty(list
) == FALSE
)
762 result
= list
->lh_TailPred
;
766 #endif // !__amigaos4__ && !__AROS__
768 /*****************************************************************************\
769 *******************************************************************************
771 ** Helpful object related functions.
773 *******************************************************************************
774 \*****************************************************************************/
777 INLINE ULONG
MyCallHookA(struct Hook
*hook
, struct NListtree_Data
*data
, struct NListtree_HookMessage
*msg
)
779 return(CallHookPkt(hook
, data
->Obj
, msg
));
784 #define MyCallHook(hook, data, ...) \
785 ({ IPTR __args[] = { AROS_PP_VARIADIC_CAST2IPTR(__VA_ARGS__) }; \
786 CallHookPkt(hook, data->Obj, __args); })
788 static IPTR STDARGS VARARGS68K
MyCallHook(struct Hook
*hook
, struct NListtree_Data
*data
, ...)
794 ret
= CallHookPkt(hook
, data
->Obj
, VA_ARG(va
, APTR
));
804 VOID
RelPen( struct MUI_RenderInfo
*mri
, LONG
*pen
)
809 ** Only valid between Setup/Cleanup!
813 MUI_ReleasePen( mri
, *pen
);
822 ** Relase pen if obtained and obtain a new pen.
824 VOID
ObtPen( struct MUI_RenderInfo
*mri
, LONG
*pen
, struct MUI_PenSpec
*ps
)
827 ** Only valid between Setup/Cleanup!
832 *pen
= MUI_ObtainPen( mri
, ps
, 0 );
838 ** Fully clear and dispose an image for NList use.
840 VOID
DisposeImage( struct NListtree_Data
*data
, ULONG nr
)
842 if ( data
->Image
[nr
].ListImage
)
844 DoMethod( data
->Obj
, MUIM_NList_DeleteImage
, data
->Image
[nr
].ListImage
);
845 data
->Image
[nr
].ListImage
= NULL
;
847 if ( data
->Image
[nr
].Image
)
849 MUI_DisposeObject( data
->Image
[nr
].Image
);
850 data
->Image
[nr
].Image
= NULL
;
857 ** Fully set up an image for NList use.
859 VOID
SetupImage( struct NListtree_Data
*data
, struct MUI_ImageSpec
*is
, ULONG nr
)
867 data
->Image
[nr
].nltdata
= data
;
868 data
->MaxImageWidth
= 0;
869 data
->MaxImageHeight
= 0;
871 if ( nr
== IMAGE_Folder
)
873 rim
= MUI_NewObject( MUIC_Image
, MUIA_Image_Spec
, is
, MUIA_UserData
, &data
->Image
[nr
], TAG_DONE
);
877 rim
= NewObject( data
->CL_NodeImage
->mcc_Class
, NULL
, MUIA_Image_Spec
, is
,
878 MUIA_Frame
, MUIV_Frame_None
,
884 MUIA_UserData
, &data
->Image
[nr
], TAG_DONE
);
889 data
->Image
[nr
].Image
= rim
;
890 data
->Image
[nr
].ListImage
= (Object
*)DoMethod( data
->Obj
, MUIM_NList_CreateImage
, rim
, 0 );
902 ** Activate Active/DoubleClick notification.
904 INLINE VOID
ActivateNotify( struct NListtree_Data
*data
)
906 D(DBF_NOTIFY
, "Activenotify: %lx",data
);
907 if(isFlagClear(data
->Flags
, NLTF_ACTIVENOTIFY
))
909 DoMethod(data
->Obj
, MUIM_Notify
, MUIA_NList_Active
, MUIV_EveryTime
,
910 data
->Obj
, 2, MUIM_NListtree_GetListActive
, 0);
912 DoMethod(data
->Obj
, MUIM_Notify
, MUIA_NList_DoubleClick
, MUIV_EveryTime
,
913 data
->Obj
, 2, MUIM_NListtree_GetDoubleClick
, MUIV_TriggerValue
);
915 SET_FLAG(data
->Flags
, NLTF_ACTIVENOTIFY
);
921 ** Deactivate Active/DoubleClick notification.
923 INLINE VOID
DeactivateNotify( struct NListtree_Data
*data
)
925 D(DBF_NOTIFY
, "Deactivenotify: %lx",data
);
926 if(isFlagSet(data
->Flags
, NLTF_ACTIVENOTIFY
))
928 DoMethod(data
->Obj
, MUIM_KillNotifyObj
, MUIA_NList_DoubleClick
, data
->Obj
);
929 DoMethod(data
->Obj
, MUIM_KillNotifyObj
, MUIA_NList_Active
, data
->Obj
);
931 if(isFlagClear(data
->Flags
, NLTF_SAFE_NOTIFIES
))
933 // removing MUI notifies must be considered unsafe
934 // The solution is to trigger an artifical notification to let
935 // the object's superclass Notify.mui finally remove the killed
936 // notifies from above before
937 // NOTE: MUIA_NList_ListCompatibility is considered obsolete and
938 // currently obeyed during OM_NEW only. Hence it is safe to use
939 // this attribute for the trigger.
940 set(data
->Obj
, MUIA_NList_ListCompatibility
, 0);
943 CLEAR_FLAG(data
->Flags
, NLTF_ACTIVENOTIFY
);
950 #define MakeNotify( data, attr, val ) if ( !( data->Flags & NLTF_QUIET ) ) SetAttrs( data->Obj, MUIA_Group_Forward, FALSE, MUIA_NListtree_OnlyTrigger, TRUE, attr, val, TAG_DONE )
951 #define MakeSet( data, attr, val ) if ( !( data->Flags & NLTF_QUIET ) ) set( data->Obj, attr, val )
955 INLINE VOID
MakeNotify( struct NListtree_Data
*data
, ULONG tag
, APTR val
)
957 if(isFlagClear(data
->Flags
, NLTF_QUIET
))
959 SetAttrs( data
->Obj
, MUIA_Group_Forward
, FALSE
, MUIA_NListtree_OnlyTrigger
, TRUE
, tag
, val
, TAG_DONE
);
963 INLINE VOID
MakeSet( struct NListtree_Data
*data
, ULONG tag
, APTR val
)
965 if(isFlagClear(data
->Flags
, NLTF_QUIET
))
967 set( data
->Obj
, tag
, val
);
971 SET_FLAG(data
->Flags
, NLTF_SETACTIVE
);
976 /*****************************************************************************\
977 *******************************************************************************
979 ** List and table handling functions.
981 *******************************************************************************
982 \*****************************************************************************/
987 struct MUI_NListtree_TreeNode
**NLCreateTable( struct NListtree_Data
*data
, struct Table
*table
, LONG numentrieswanted
)
989 struct MUI_NListtree_TreeNode
**newtable
;
993 ** Don't allocate less than one entry.
995 if ( numentrieswanted
< 1 )
996 numentrieswanted
= 1;
999 ** Round to next multiple of 64.
1001 oldtablesize
= table
->tb_Size
;
1002 table
->tb_Size
= ( numentrieswanted
+ 63 ) & ~63;
1005 ** Allocate the table.
1007 if((newtable
= (struct MUI_NListtree_TreeNode
**)AllocVecPooled(data
->TreePool
, sizeof(struct MUI_NListtree_TreeNode
*) * table
->tb_Size
)))
1010 ** If there is an old table given, copy it to the new table.
1012 if ( table
->tb_Table
)
1014 CopyMem( table
->tb_Table
, newtable
, sizeof( struct MUI_NListtree_TreeNode
* ) * oldtablesize
);
1015 FreeVecPooled( data
->TreePool
, table
->tb_Table
);
1021 ** Clear all the unused entries.
1023 memset( &newtable
[oldtablesize
], 0, ( table
->tb_Size
- oldtablesize
) * sizeof( struct MUI_NListtree_TreeNode
* ) );
1024 table
->tb_Table
= newtable
;
1032 ** Add an entry to a table.
1034 BOOL
NLAddToTable( struct NListtree_Data
*data
, struct Table
*table
, struct MUI_NListtree_TreeNode
*newentry
)
1037 ** If the table is filled `to the brim', expand it.
1039 if ( ( table
->tb_Entries
+ 1 ) > table
->tb_Size
)
1042 ** Allocate another list table.
1044 if ( !NLCreateTable( data
, table
, table
->tb_Entries
+ 1 ) )
1049 ** Add it to the end of the table.
1051 table
->tb_Table
[table
->tb_Entries
++] = newentry
;
1058 ** Find an entry in a table.
1060 LONG
NLFindInTable( struct Table
*table
, struct MUI_NListtree_TreeNode
*entry
)
1064 for( i
= 0; i
< table
->tb_Entries
; i
++ )
1066 if ( table
->tb_Table
[i
] == entry
)
1078 ** Remove an entry from a table.
1080 VOID
NLRemoveFromTable( struct NListtree_Data
*data
, struct Table
*table
, struct MUI_NListtree_TreeNode
*entry
)
1084 if ( ( i
= NLFindInTable( table
, entry
) ) != -1 )
1086 if ( --table
->tb_Entries
== 0 )
1088 FreeVecPooled( data
->TreePool
, table
->tb_Table
);
1089 table
->tb_Table
= NULL
;
1091 table
->tb_Current
= -2;
1098 ** Remove the entry from the table.
1100 for( j
= i
; j
<= table
->tb_Entries
; j
++ )
1101 table
->tb_Table
[j
] = table
->tb_Table
[j
+ 1];
1104 ** Clear the last entry and shrink the table.
1106 table
->tb_Table
[table
->tb_Entries
] = NULL
;
1108 if ( table
->tb_Current
>= i
)
1109 table
->tb_Current
--;
1116 /*****************************************************************************\
1117 *******************************************************************************
1119 ** Tree-List handling functions.
1121 *******************************************************************************
1122 \*****************************************************************************/
1125 ** Do a refresh, but only if not frozen. If so, set refresh flag.
1127 INLINE VOID
DoRefresh( struct NListtree_Data
*data
)
1129 if(isFlagSet(data
->Flags
, NLTF_QUIET
))
1131 SET_FLAG(data
->Flags
, NLTF_REFRESH
);
1135 DoMethod( data
->Obj
, MUIM_NList_Redraw
, MUIV_NList_Redraw_All
);
1141 ** Do only one quiet.
1143 INLINE ULONG
DoQuiet( struct NListtree_Data
*data
, BOOL quiet
)
1147 SET_FLAG(data
->Flags
, NLTF_QUIET
);
1149 if ( ++data
->QuietCounter
== 1 )
1150 nnset( data
->Obj
, MUIA_NList_Quiet
, TRUE
);
1154 if ( --data
->QuietCounter
== 0 )
1156 nnset( data
->Obj
, MUIA_NList_Quiet
, FALSE
);
1157 CLEAR_FLAG(data
->Flags
, NLTF_QUIET
);
1159 if(isFlagSet(data
->Flags
, NLTF_SETACTIVE
))
1161 set( data
->Obj
, MUIA_NListtree_Active
, data
->ActiveNode
);
1162 CLEAR_FLAG(data
->Flags
, NLTF_SETACTIVE
);
1167 return( data
->QuietCounter
);
1172 ** Get the parent node to a given.
1174 INLINE
struct MUI_NListtree_TreeNode
*GetParent( struct MUI_NListtree_TreeNode
*tn
)
1176 return( tn
? tn
->tn_Parent
: NULL
);
1181 ** Get the parent node to a given, but NOT the root list.
1183 struct MUI_NListtree_TreeNode
*GetParentNotRoot( struct MUI_NListtree_TreeNode
*tn
)
1185 if((tn
= GetParent(tn
)))
1187 if ( GetParent( tn
) )
1198 ** Check, if a given node is a child of another.
1200 struct MUI_NListtree_TreeNode
*IsXChildOfY( struct MUI_NListtree_TreeNode
*x
, struct MUI_NListtree_TreeNode
*y
)
1209 while((y
= GetParentNotRoot(y
)));
1216 ** Check, if a given node is a child of a list member.
1218 struct MUI_NListtree_TreeNode
*IsXChildOfListMemberNotSelf( struct MUI_NListtree_TreeNode
*entry
, struct Table
*table
)
1222 for( i
= 0; i
< table
->tb_Entries
; i
++ )
1224 if ( entry
!= table
->tb_Table
[i
] )
1226 if ( IsXChildOfY( table
->tb_Table
[i
], entry
) )
1228 return( table
->tb_Table
[i
] );
1237 struct MUI_NListtree_TreeNode
*IsXChildOfListMember( struct MUI_NListtree_TreeNode
*entry
, struct Table
*table
)
1241 for( i
= 0; i
< table
->tb_Entries
; i
++ )
1243 if ( IsXChildOfY( table
->tb_Table
[i
], entry
) )
1245 return( table
->tb_Table
[i
] );
1254 /*****************************************************************************\
1255 *******************************************************************************
1257 ** Helpful tree handling functions.
1259 *******************************************************************************
1260 \*****************************************************************************/
1262 INLINE VOID
RemoveNListEntry( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, ULONG pos
)
1264 D(DBF_LISTTREE
, "Removed entry '%s' from pos %ld.", tn
->tn_Name
, tn
->tn_NListEntry
? tn
->tn_NListEntry
->entpos
: 999999);
1266 DoMethod( data
->Obj
, MUIM_NList_Remove
, pos
);
1267 tn
->tn_NListEntry
= NULL
;
1271 INLINE VOID
InsertNListEntry( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, ULONG pos
)
1273 struct MUI_NList_GetEntryInfo ei
;
1275 DoMethod( data
->Obj
, MUIM_NList_InsertSingle
, tn
, pos
);
1277 if(isFlagSet(data
->Flags
, NLTF_NLIST_DIRECT_ENTRY_SUPPORT
))
1279 ei
.pos
= -3; ei
.line
= -2;
1280 DoMethod( data
->Obj
, MUIM_NList_GetEntryInfo
, &ei
);
1281 tn
->tn_NListEntry
= (struct NListEntry
*)ei
.entry
;
1283 D(DBF_LISTTREE
, "Inserted entry '%s' at pos %ld.", tn
->tn_Name
, tn
->tn_NListEntry
->entpos
);
1287 INLINE VOID
ReplaceNListEntry( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, ULONG pos
)
1289 struct MUI_NList_GetEntryInfo ei
;
1291 DoMethod(data
->Obj
, MUIM_NList_ReplaceSingle
, tn
, pos
, NOWRAP
, ALIGN_LEFT
);
1293 if(isFlagSet(data
->Flags
, NLTF_NLIST_DIRECT_ENTRY_SUPPORT
))
1295 ei
.pos
= -3; ei
.line
= -2;
1296 DoMethod( data
->Obj
, MUIM_NList_GetEntryInfo
, &ei
);
1297 tn
->tn_NListEntry
= (struct NListEntry
*)ei
.entry
;
1299 D(DBF_LISTTREE
, "Replaced entry '%s' at pos %ld.", tn
->tn_Name
, tn
->tn_NListEntry
->entpos
);
1305 ** Iterate through all entries recursive and get specified entry by pos.
1307 struct MUI_NListtree_TreeNode
*GetEntryByTotalPos( struct MUI_NListtree_ListNode
*ln
, LONG pos
, LONG
*cpos
, ULONG flags
)
1309 struct MUI_NListtree_TreeNode
*tn
= CTN( (APTR
)&ln
->ln_List
);
1311 if(isFlagSet(ln
->ln_Flags
, TNF_LIST
))
1313 if(isFlagClear(flags
, MUIV_NListtree_GetEntry_Flag_Visible
) || isFlagSet(ln
->ln_Flags
, TNF_OPEN
))
1315 while((tn
= CTN(GetSucc((struct Node
*)tn
))))
1317 struct MUI_NListtree_TreeNode
*rettn
;
1322 if(isFlagClear(flags
, MUIV_NListtree_GetEntry_Flag_Visible
) || isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1325 if(isFlagClear(flags
, MUIV_NListtree_GetEntry_Flag_SameLevel
))
1327 if((rettn
= GetEntryByTotalPos(CLN(tn
), pos
, cpos
, flags
)))
1339 ** Iterate through all entries recursive and get the pos of the specified entry.
1341 BOOL
GetEntryPos( struct MUI_NListtree_ListNode
*ln
, struct MUI_NListtree_TreeNode
*stn
, LONG
*pos
)
1343 struct MUI_NListtree_TreeNode
*tn
= CTN( (APTR
)&ln
->ln_List
);
1345 while((tn
= CTN(GetSucc((struct Node
*)tn
))))
1352 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
1354 if ( GetEntryPos( CLN( tn
), stn
, pos
) )
1363 /*************************************************************************
1364 Return the visual position (i.e. the position within the plain list)
1365 of the given TreeNode
1366 **************************************************************************/
1367 static LONG
GetVisualPos(struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1373 if(tn
!= CTN((APTR
)&data
->RootList
) && tn
!= NULL
)
1375 if(isFlagSet(data
->Flags
, NLTF_NLIST_DIRECT_ENTRY_SUPPORT
))
1377 // respect visible nodes only
1378 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
) && tn
->tn_NListEntry
!= NULL
)
1379 pos
= (int)tn
->tn_NListEntry
->entpos
;
1382 // respect visible nodes only
1383 if(pos
== -1 && isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1385 // result will be MUIV_NList_GetPos_End (-1) if not found.
1386 pos
= MUIV_NList_GetPos_Start
;
1387 DoMethod(data
->Obj
, MUIM_NList_GetPos
, tn
, &pos
);
1395 /*************************************************************************
1396 Count the number of visual entries in a tree node (excluding the
1397 node itself). A invisible has also 0 entries. Returns also 0 if the
1399 **************************************************************************/
1400 static LONG
GetVisualEntries( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1407 if(tn
== CTN((APTR
)&data
->RootList
))
1408 entries
= xget(data
->Obj
, MUIA_NList_Entries
);
1409 else if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagSet(tn
->tn_Flags
, TNF_OPEN
) && isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1411 struct MUI_NListtree_TreeNode
*tn2
;
1413 tn2
= CTN(GetSucc((struct Node
*)tn
));
1414 if(tn2
!= NULL
&& isFlagSet(tn2
->tn_IFlags
, TNIF_VISIBLE
))
1416 return GetVisualPos(data
,tn2
) - GetVisualPos(data
,tn
) - 1;
1420 /* Number of entries is number of the entries directly in this
1421 ** list and the number of the entries within the open nodes
1424 struct Table
*tb
= &CLN( tn
)->ln_Table
;
1427 entries
= tb
->tb_Entries
;
1429 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
1431 entries
+= GetVisualEntries(data
, tb
->tb_Table
[i
]);
1441 ** Count the number of visual entries in a tree node until a maximum of max.
1443 static BOOL
GetVisualEntriesMax( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG pos
, LONG
*ent
, LONG max
)
1445 BOOL success
= FALSE
;
1449 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1451 struct Table
*tb
= &CLN( tn
)->ln_Table
;
1454 *ent
+= tb
->tb_Entries
;
1456 for( i
= 0; ( i
< tb
->tb_Entries
) && ( *ent
<= max
); i
++ )
1458 if(GetVisualEntriesMax(data
, tb
->tb_Table
[i
], pos
, ent
, max
))
1471 /*************************************************************************
1472 Determine the visual position a node would have, if inserted after
1474 **************************************************************************/
1475 static LONG
GetVisualInsertPos( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, struct MUI_NListtree_TreeNode
*prevtn
)
1481 if ((SIPTR
)prevtn
== INSERT_POS_HEAD
)
1482 ent
= GetVisualPos(data
, CTN(ln
)) + 1;
1483 else if ( (SIPTR
)prevtn
== INSERT_POS_TAIL
)
1484 ent
= GetVisualPos(data
, CTN(ln
)) + GetVisualEntries(data
, CTN(ln
)) + 1;
1486 ent
= GetVisualPos(data
, CTN(prevtn
)) + GetVisualEntries(data
,CTN(prevtn
)) + 1;
1492 struct MUI_NListtree_TreeNode
*TreeNodeSelectAdd( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1494 NLAddToTable( data
, &data
->SelectedTable
, tn
);
1496 D(DBF_LISTTREE
, "Node 0x%08lx - %s selected (%ld nodes selected), Current: %ld", tn
, tn
->tn_Name
, data
->SelectedTable
.tb_Entries
, data
->SelectedTable
.tb_Current
);
1502 static void TreeNodeSelectRemove( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1504 NLRemoveFromTable( data
, &data
->SelectedTable
, tn
);
1506 D(DBF_LISTTREE
, "Node 0x%08lx - %s DEselected (%ld nodes selected), Current: %ld", tn
, tn
->tn_Name
, data
->SelectedTable
.tb_Entries
, data
->SelectedTable
.tb_Current
);
1511 ** Change the selection state of one entry depending on supplied info.
1513 LONG
TreeNodeSelectOne( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG seltype
, LONG selflags
, LONG
*state
)
1515 BOOL doselect
= TRUE
;
1516 LONG st
, wassel
= tn
->tn_Flags
;
1518 if ( seltype
== MUIV_NListtree_Select_Toggle
)
1520 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1521 st
= MUIV_NListtree_Select_Off
;
1523 st
= MUIV_NListtree_Select_On
;
1528 if(isFlagClear(selflags
, MUIV_NListtree_Select_Flag_Force
))
1530 doselect
= MultiTestFunc( data
, tn
, st
, selflags
);
1535 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1537 if( st
== MUIV_NListtree_Select_On
&& isFlagClear(wassel
, TNF_SELECTED
))
1538 DoMethod( data
->Obj
, MUIM_NList_Select
, GetVisualPos( data
, tn
), MUIV_NList_Select_On
, NULL
);
1540 else if(st
== MUIV_NListtree_Select_Off
&& isFlagSet(wassel
, TNF_SELECTED
))
1541 DoMethod( data
->Obj
, MUIM_NList_Select
, GetVisualPos( data
, tn
), MUIV_NList_Select_Off
, NULL
);
1547 case MUIV_NListtree_Select_On
:
1548 SET_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
1551 case MUIV_NListtree_Select_Off
:
1552 CLEAR_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
1566 ** Iterate through all entries recursive and let change flags (selected).
1568 VOID
TreeNodeSelectAll( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, LONG seltype
, LONG selflags
, LONG
*state
)
1571 struct Table
*tb
= &ln
->ln_Table
;
1573 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
1575 TreeNodeSelectOne( data
, tb
->tb_Table
[i
], seltype
, selflags
, state
);
1577 if(isFlagSet(tb
->tb_Table
[i
]->tn_Flags
, TNF_LIST
))
1579 TreeNodeSelectAll( data
, CLN( tb
->tb_Table
[i
] ), seltype
, selflags
, state
);
1587 ** Iterate through all entries recursive and let change flags (selected) of visible entries.
1589 VOID
TreeNodeSelectVisible( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, LONG seltype
, LONG selflags
, LONG
*state
)
1592 struct Table
*tb
= &ln
->ln_Table
;
1594 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
1596 if(isFlagSet(tb
->tb_Table
[i
]->tn_IFlags
, TNIF_VISIBLE
))
1598 TreeNodeSelectOne( data
, tb
->tb_Table
[i
], seltype
, selflags
, state
);
1600 if(isFlagSet(tb
->tb_Table
[i
]->tn_Flags
, TNF_LIST
))
1602 TreeNodeSelectAll( data
, CLN( tb
->tb_Table
[i
] ), seltype
, selflags
, state
);
1611 ** Change the selection state depending on supplied info.
1613 LONG
TreeNodeSelect( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG seltype
, LONG selflags
, LONG
*state
)
1615 if(isFlagSet(data
->Flags
, NLTF_AUTOSELECT_CHILDS
))
1617 TreeNodeSelectAll( data
, CLN( tn
), seltype
, selflags
, state
);
1621 TreeNodeSelectOne( data
, tn
, seltype
, selflags
, state
);
1624 return( state
? *state
: 0 );
1630 struct MUI_NListtree_TreeNode
*GetInsertNodeSorted( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*li
, struct MUI_NListtree_TreeNode
*tn
)
1632 struct MUI_NListtree_TreeNode
*in
, *in2
= NULL
;
1635 ** <0 -> move to next
1636 ** >=0 -> insert here
1639 if((in
= CTN(GetHead((struct List
*)&li
->ln_List
))))
1641 while((LONG
)DoMethod(data
->Obj
, MUIM_NListtree_Compare
, in
, tn
, 0) < 0)
1645 if ( !( in
= CTN(GetSucc( (struct Node
*)in
) ) ) )
1654 in2
= CTN( INSERT_POS_HEAD
);
1662 VOID
RemoveTreeVisible( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG pos
)
1664 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) && ( tn
= CTN( GetHead( (struct List
*)&(CLN( tn
))->ln_List
) ) ) )
1668 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1670 D(DBF_LISTTREE
, "Visible removing node \"%s\" at pos %ld ( %s | %s )", tn
->tn_Name
, pos
, isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) ? "SEL" : "", isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1672 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1674 D(DBF_LISTTREE
, "Unselecting node \"%s\" at pos %ld ( %s )", tn
->tn_Name
, pos
, isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1676 DoMethod( data
->Obj
, MUIM_NList_Select
, pos
, MUIV_NList_Select_Off
, NULL
);
1678 if(isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
))
1679 SET_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
1682 CLEAR_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
1683 RemoveNListEntry( data
, tn
, pos
);
1686 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1688 RemoveTreeVisible( data
, tn
, pos
);
1691 while((tn
= CTN(GetSucc((struct Node
*)tn
))));
1696 VOID
ReplaceTreeVisibleSort(struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG
*pos
)
1699 ** Determine that the node holds a list
1700 ** and the node is not open.
1702 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1704 if((tn
= CTN(GetHead((struct List
*)&(CLN(tn
))->ln_List
))))
1708 ReplaceNListEntry(data
, tn
, *pos
);
1710 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1712 DoMethod(data
->Obj
, MUIM_NList_Select
, *pos
, MUIV_NList_Select_On
, NULL
);
1715 if(*pos
>= 0) *pos
+= 1;
1717 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1719 ReplaceTreeVisibleSort(data
, tn
, pos
);
1722 while((tn
= CTN(GetSucc((struct Node
*)tn
))));
1728 VOID
RemoveTreeNodeVisible( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG
*xpos
)
1732 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1734 pos
= GetVisualPos( data
, tn
);
1736 D(DBF_LISTTREE
, "Visible removing node \"%s\" at pos %ld ( %s | %s )", tn
->tn_Name
, pos
, isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) ? "SEL" : "", isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1738 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1740 D(DBF_LISTTREE
, "Unselecting node \"%s\" at pos %ld ( %s )", tn
->tn_Name
, pos
, isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1742 DoMethod( data
->Obj
, MUIM_NList_Select
, pos
, MUIV_NList_Select_Off
, NULL
);
1744 if(isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
))
1745 SET_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
1748 CLEAR_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
1749 RemoveNListEntry( data
, tn
, pos
);
1754 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1756 RemoveTreeVisible( data
, tn
, pos
);
1759 if ( pos
> 0 ) DoMethod( data
->Obj
, MUIM_NList_Redraw
, pos
- 1 );
1764 VOID
InsertTreeVisible( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG
*pos
)
1767 ** Determine that the node holds a list
1768 ** and the node is not open.
1770 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
1772 if((tn
= CTN(GetHead((struct List
*)&(CLN(tn
))->ln_List
))))
1776 if(isFlagClear(tn
->tn_IFlags
, TNIF_VISIBLE
))
1778 D(DBF_LISTTREE
, "Visible inserting node \"%s\" at pos %ld ( %s | %s )", tn
->tn_Name
, pos
, isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) ? "SEL" : "", isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1780 SET_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
1781 InsertNListEntry( data
, tn
, *pos
);
1783 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1785 D(DBF_LISTTREE
, " Selecting node \"%s\" at pos %ld ( %s )", tn
->tn_Name
, pos
, isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1787 DoMethod( data
->Obj
, MUIM_NList_Select
, *pos
, MUIV_NList_Select_On
, NULL
);
1791 if ( *pos
>= 0 ) *pos
+= 1;
1793 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1795 InsertTreeVisible( data
, tn
, pos
);
1798 while((tn
= CTN(GetSucc((struct Node
*)tn
))));
1804 LONG
InsertTreeNodeVisible( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, struct MUI_NListtree_ListNode
*ln
, struct MUI_NListtree_TreeNode
*prevtn
)
1806 LONG pos
= 0, temppos
;
1808 if (isFlagSet(ln
->ln_Flags
, TNF_OPEN
) && ((pos
= GetVisualInsertPos( data
, ln
, prevtn
)) != -1))
1810 SET_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
1812 D(DBF_LISTTREE
, "Visible inserting node 0x%lx into list 0x%lx after 0x%lx at pos %ld", tn
, ln
, prevtn
, pos
);
1814 InsertNListEntry( data
, tn
, pos
);
1816 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
1818 D(DBF_LISTTREE
, " Selecting node \"%s\" at pos %ld ( %s )", tn
->tn_Name
, pos
, isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
) ? "LSHIFT" : "");
1820 DoMethod( data
->Obj
, MUIM_NList_Select
, pos
, MUIV_NList_Select_On
, NULL
);
1825 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1827 InsertTreeVisible( data
, tn
, &temppos
);
1831 DoMethod( data
->Obj
, MUIM_NList_Redraw
, pos
- 1 );
1835 CLEAR_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
1843 VOID
ShowTree(struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1845 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
1847 LONG first
= xget(data
->Obj
, MUIA_NList_First
);
1848 LONG visible
= xget(data
->Obj
, MUIA_NList_Visible
);
1853 LONG treeentries
= 0;
1856 pos
= GetVisualPos(data
, tn
);
1857 GetVisualEntriesMax(data
, tn
, pos
, &treeentries
, visible
);
1860 b
= visible
- a
- 1;
1863 jmp
= pos
+ MIN(max
, treeentries
);
1865 D(DBF_LISTTREE
, "first: %ld, visible: %ld, pos: %ld, treeentries: %ld, a: %ld, b: %ld, max: %ld, jmp: %ld",
1866 first
, visible
, pos
, treeentries
, a
, b
, max
, jmp
);
1868 DoMethod(data
->Obj
, MUIM_NList_Jump
, jmp
);
1877 VOID
ExpandTree( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1880 ** Determine that the node holds a list
1882 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
1886 struct Table
*tb
= &CLN( tn
)->ln_Table
;
1888 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
1890 if(isFlagSet(tb
->tb_Table
[i
]->tn_Flags
, TNF_LIST
) && isFlagClear(tb
->tb_Table
[i
]->tn_Flags
, TNF_OPEN
))
1892 if ( data
->OpenHook
)
1894 MyCallHook( data
->OpenHook
, data
, MUIA_NListtree_OpenHook
, tb
->tb_Table
[i
] );
1897 D(DBF_LISTTREE
, "Expanding node \"%s\"", tb
->tb_Table
[i
]->tn_Name
);
1899 SET_FLAG(tb
->tb_Table
[i
]->tn_Flags
, TNF_OPEN
);
1902 CLEAR_FLAG(tb
->tb_Table
[i
]->tn_IFlags
, TNIF_VISIBLE
);
1904 ExpandTree( data
, tb
->tb_Table
[i
] );
1910 VOID
OpenTreeNode( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1912 LONG entries
, pos
, spos
=0;
1914 if(isFlagClear(tn
->tn_Flags
, TNF_OPEN
))
1916 SET_FLAG(tn
->tn_Flags
, TNF_OPEN
);
1918 if ( data
->OpenHook
)
1920 MyCallHook( data
->OpenHook
, data
, MUIA_NListtree_OpenHook
, tn
);
1923 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
1925 spos
= pos
= GetVisualPos( data
, tn
);
1926 entries
= xget( data
->Obj
, MUIA_NList_Entries
);
1930 if ( pos
== entries
)
1932 pos
= MUIV_NList_Insert_Bottom
;
1935 DeactivateNotify( data
);
1938 if ( tb->tb_Entries > ( data->NumEntries / 4 ) )
1940 i = MUIV_NList_Insert_Bottom;
1942 DoMethod( data->Obj, MUIM_NList_Clear, 0 );
1944 CLEAR_FLAG(tn->tn_IFlags, TNIF_VISIBLE);
1945 InsertTreeVisible( data, CTN( &data->RootList ), &i );
1950 InsertTreeVisible( data
, tn
, &pos
);
1953 ActivateNotify( data
);
1955 /* sba: the active note could be changed, but the notify calling was disabled */
1956 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
1959 DoMethod( data
->Obj
, MUIM_NList_Redraw
, spos
);
1964 VOID
OpenTreeNodeExpand( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
1968 pos
= GetVisualPos( data
, tn
);
1969 entries
= xget( data
->Obj
, MUIA_NList_Entries
);
1973 if ( pos
== entries
)
1975 pos
= MUIV_NList_Insert_Bottom
;
1978 if(isFlagClear(tn
->tn_Flags
, TNF_OPEN
))
1980 if ( data
->OpenHook
)
1982 MyCallHook( data
->OpenHook
, data
, MUIA_NListtree_OpenHook
, tn
);
1985 D(DBF_LISTTREE
, "Expanding node \"%s\"", tn
->tn_Name
);
1987 SET_FLAG(tn
->tn_Flags
, TNF_OPEN
);
1989 ExpandTree( data
, tn
);
1990 InsertTreeVisible( data
, tn
, &pos
);
1998 VOID
OpenTreeNodeListExpand( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
)
2001 struct Table
*tb
= &ln
->ln_Table
;
2003 if ( ln
== &data
->RootList
)
2005 i
= MUIV_NList_Insert_Bottom
;
2007 DoMethod( data
->Obj
, MUIM_NList_Clear
, 0 );
2009 ExpandTree( data
, CTN( ln
) );
2010 InsertTreeVisible( data
, CTN( ln
), &i
);
2013 else if ( tb->tb_Entries > (LONG)( data->NumEntries / 4 ) )
2015 i = MUIV_NList_Insert_Bottom;
2017 DoMethod( data->Obj, MUIM_NList_Clear, 0 );
2019 ExpandTree( data, CTN( ln ) );
2020 InsertTreeVisible( data, CTN( &data->RootList ), &i );
2025 DoMethod(data
->Obj
, MUIM_NList_Redraw
, GetVisualPos(data
, tb
->tb_Table
[0]));
2027 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
2029 OpenTreeNodeExpand( data
, tb
->tb_Table
[i
] );
2039 VOID
CollapseTree( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, BOOL clearvisible
)
2042 ** Determine that the node holds a list
2044 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
2048 struct Table
*tb
= &CLN( tn
)->ln_Table
;
2050 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
2052 if(isFlagSet(tb
->tb_Table
[i
]->tn_Flags
, TNF_OPEN
))
2054 if ( data
->CloseHook
)
2056 MyCallHook( data
->CloseHook
, data
, MUIA_NListtree_CloseHook
, tb
->tb_Table
[i
] );
2059 D(DBF_LISTTREE
, "Collapsing node \"%s\"", tb
->tb_Table
[i
]->tn_Name
);
2061 CLEAR_FLAG(tb
->tb_Table
[i
]->tn_Flags
, TNF_OPEN
);
2065 CLEAR_FLAG(tb
->tb_Table
[i
]->tn_IFlags
, TNIF_VISIBLE
);
2067 CollapseTree( data
, tb
->tb_Table
[i
], clearvisible
);
2075 VOID
CloseTreeNode( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
2079 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
2081 pos
= GetVisualPos( data
, tn
) + 1;
2083 if ( data
->CloseHook
)
2085 MyCallHook( data
->CloseHook
, data
, MUIA_NListtree_CloseHook
, tn
);
2088 CLEAR_FLAG(tn
->tn_Flags
, TNF_OPEN
);
2090 DeactivateNotify( data
);
2093 if ( tb->tb_Entries > ( data->NumEntries / 4 ) )
2095 i = MUIV_NList_Insert_Bottom;
2097 DoMethod( data->Obj, MUIM_NList_Clear, 0 );
2099 CLEAR_FLAG(tn->tn_IFlags, TNIF_VISIBLE);
2100 InsertTreeVisible( data, CTN( &data->RootList ), &i );
2105 RemoveTreeVisible( data
, tn
, pos
);
2108 ActivateNotify( data
);
2110 /* sba: the active note could be changed, but the notify calling was disabled */
2111 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
2113 DoMethod( data
->Obj
, MUIM_NList_Redraw
, pos
- 1 );
2118 VOID
CloseTreeNodeCollapse( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
2122 pos
= GetVisualPos( data
, tn
) + 1;
2124 if(isFlagSet(tn
->tn_Flags
, TNF_OPEN
))
2126 if ( data
->CloseHook
)
2128 MyCallHook( data
->CloseHook
, data
, MUIA_NListtree_CloseHook
, tn
);
2131 D(DBF_LISTTREE
, "Collapsing node \"%s\"", tn
->tn_Name
);
2133 CLEAR_FLAG(tn
->tn_Flags
, TNF_OPEN
);
2136 RemoveTreeVisible( data
, tn
, pos
);
2137 CollapseTree( data
, tn
, FALSE
);
2139 DoMethod( data
->Obj
, MUIM_NList_Redraw
, pos
- 1 );
2146 VOID
CloseTreeNodeListCollapse( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
)
2149 struct Table
*tb
= &ln
->ln_Table
;
2151 if ( ln
== &data
->RootList
)
2153 i
= MUIV_NList_Insert_Bottom
;
2155 DoMethod( data
->Obj
, MUIM_NList_Clear
, 0 );
2157 CollapseTree( data
, CTN( ln
), TRUE
);
2158 InsertTreeVisible( data
, CTN( ln
), &i
);
2161 else if(tb->tb_Entries > (LONG)(data->NumEntries / 4))
2163 i = MUIV_NList_Insert_Bottom;
2165 DoMethod( data->Obj, MUIM_NList_Clear, 0 );
2167 CollapseTree( data, CTN( ln ), TRUE );
2168 InsertTreeVisible( data, CTN( &data->RootList ), &i );
2173 for( i
= 0; i
< tb
->tb_Entries
; i
++ )
2175 CloseTreeNodeCollapse( data
, tb
->tb_Table
[i
] );
2182 VOID
ActivateTreeNode(struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
)
2184 struct MUI_NListtree_TreeNode
*tn2
= tn
;
2188 if(data
->ActiveNode
!= NULL
)
2190 switch(data
->AutoVisible
)
2192 case MUIV_NListtree_AutoVisible_Off
:
2198 case MUIV_NListtree_AutoVisible_Normal
:
2200 if(isFlagSet(tn2
->tn_IFlags
, TNIF_VISIBLE
))
2202 jmppos
= GetVisualPos(data
, tn2
);
2203 DoMethod(data
->Obj
, MUIM_NList_Jump
, jmppos
);
2208 case MUIV_NListtree_AutoVisible_FirstOpen
:
2210 while(isFlagClear(tn2
->tn_IFlags
, TNIF_VISIBLE
))
2211 tn2
= tn2
->tn_Parent
;
2213 jmppos
= GetVisualPos(data
, tn2
);
2214 DoMethod(data
->Obj
, MUIM_NList_Jump
, jmppos
);
2218 case MUIV_NListtree_AutoVisible_Expand
:
2220 while((tn2
= tn2
->tn_Parent
) != NULL
)
2221 OpenTreeNode(data
, tn2
);
2223 jmppos
= GetVisualPos(data
, tn2
);
2224 DoMethod(data
->Obj
, MUIM_NList_Jump
, jmppos
);
2231 newact
= GetVisualPos(data
, tn
);
2233 newact
= MUIV_NList_Active_Off
;
2235 /* sba: set the new entry only if it really changes, otherwise we lose some
2236 MUIA_NList_Active notifications */
2238 D(DBF_LISTTREE
, "ActivateTreeNode: %ld %ld",newact
,xget(data
->Obj
,MUIA_NList_Active
));
2239 if(newact
!= (LONG
)xget(data
->Obj
,MUIA_NList_Active
))
2240 set(data
->Obj
, MUIA_NList_Active
, newact
);
2244 VOID
RemoveNode1( struct NListtree_Data
*data
, UNUSED
struct MUI_NListtree_ListNode
*li
, struct MUI_NListtree_TreeNode
*tn
, LONG pos
)
2249 ** If deleted entry is active, then activate the next/previous node.
2251 if ( data
->TempActiveNode
== tn
)
2254 ** Make sure that deleting the last entry in a
2255 ** list node causes the NEW last entry to be active!
2257 if ( !( data
->TempActiveNode
= CTN( GetSucc( (struct Node
*)&tn
->tn_Node
) ) ) )
2258 if ( !( data
->TempActiveNode
= CTN( GetPred( (struct Node
*)&tn
->tn_Node
) ) ) )
2259 data
->TempActiveNode
= GetParentNotRoot( tn
);
2261 D(DBF_LISTTREE
, "Would set active node to: %s - 0x%08lx", data
->TempActiveNode
? data
->TempActiveNode
->tn_Name
: (STRPTR
)"NULL", data
->TempActiveNode
);
2264 D(DBF_LISTTREE
, "Removing node: %s - 0x%08lx, pos: %ld", tn
->tn_Name
, tn
, pos
);
2267 ** Prevent calculating positions with practical
2270 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
2272 CLEAR_FLAG(tn
->tn_IFlags
, TNIF_VISIBLE
);
2274 RemoveNListEntry( data
, tn
, pos
);
2278 ** Remove the node from the selected list.
2280 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
))
2281 TreeNodeSelectRemove( data
, tn
);
2286 VOID
RemoveNode2( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*li
, struct MUI_NListtree_TreeNode
*tn
)
2290 Remove( (struct Node
*)&tn
->tn_Node
);
2291 NLRemoveFromTable( data
, &li
->ln_Table
, tn
);
2294 ** Call internal/user supplied destruct function.
2296 DoMethod(data
->Obj
, MUIM_NListtree_Destruct
, tn
->tn_Name
, tn
->tn_User
, data
->TreePool
, 0);
2299 ** Free all allocated memory.
2301 if(isFlagSet(tn
->tn_IFlags
, TNIF_ALLOCATED
))
2304 FreeVecPooled( data
->TreePool
, tn
->tn_Name
);
2307 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
2309 if ( ( (struct MUI_NListtree_ListNode
*)tn
)->ln_Table
.tb_Table
)
2310 FreeVecPooled( data
->TreePool
, ( (struct MUI_NListtree_ListNode
*)tn
)->ln_Table
.tb_Table
);
2312 ( (struct MUI_NListtree_ListNode
*)tn
)->ln_Table
.tb_Table
= NULL
;
2315 FreeVecPooled( data
->TreePool
, tn
);
2318 ** Subtract one from the global number of entries.
2327 VOID
RemoveChildNodes( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG pos
)
2329 struct MUI_NListtree_ListNode
*ln
= CLN( tn
);
2333 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
2335 while((tn
= CTN(GetHead((struct List
*)&ln
->ln_List
))))
2337 D(DBF_LISTTREE
, "Removing node \"%s\", pos %ld", tn
->tn_Name
, pos
);
2339 RemoveChildNodes( data
, tn
, pos
+ 1 );
2340 RemoveNode1( data
, CLN( GetParent( tn
) ), tn
, pos
);
2341 RemoveNode2( data
, CLN( GetParent( tn
) ), tn
);
2350 VOID
RemoveNodes( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*li
, struct MUI_NListtree_TreeNode
*tn
, LONG pos
)
2354 RemoveChildNodes( data
, tn
, pos
+ 1 );
2355 RemoveNode1( data
, li
, tn
, pos
);
2356 RemoveNode2( data
, li
, tn
);
2359 DoMethod(data
->Obj
, MUIM_NList_Redraw
, pos
- 1);
2366 VOID
QuickRemoveNodes( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*li
)
2368 struct MUI_NListtree_ListNode
*ln
= li
;
2370 if(isFlagSet(li
->ln_Flags
, TNF_LIST
))
2372 while((li
= CLN(RemHead((struct List
*)&ln
->ln_List
))))
2374 if(isFlagSet(li
->ln_Flags
, TNF_LIST
))
2375 QuickRemoveNodes( data
, li
);
2377 if(isFlagSet(li
->ln_Flags
, TNF_SELECTED
))
2379 TreeNodeSelectRemove( data
, CTN( li
) );
2383 ** Call internal/user supplied destruct function.
2385 DoMethod(data
->Obj
, MUIM_NListtree_Destruct
, li
->ln_Name
, li
->ln_User
, data
->TreePool
, 0);
2391 struct MUI_NListtree_TreeNode
*FindTreeNodeByName( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, STRPTR name
, UWORD flags
)
2393 struct MUI_NListtree_TreeNode
*tn2
, *tn
;
2395 if(isFlagSet(flags
, MUIV_NListtree_FindName_Flag_StartNode
))
2398 tn
= CTN( GetHead( (struct List
*)&ln
->ln_List
) );
2405 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
) || isFlagClear(flags
, MUIV_NListtree_FindName_Flag_Visible
))
2407 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) || isFlagClear(flags
, MUIV_NListtree_FindName_Flag_Selected
))
2409 if ( !( (LONG
)MyCallHook( data
->FindNameHook
, data
, MUIA_NListtree_FindNameHook
, name
, tn
->tn_Name
, tn
->tn_User
, flags
) ) )
2416 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagClear(flags
, MUIV_NListtree_FindName_Flag_SameLevel
))
2418 if((tn2
= FindTreeNodeByName(data
, CLN(tn
), name
, (flags
& ~MUIV_NListtree_FindName_Flag_StartNode
))))
2424 while((tn
= CTN(GetSucc((struct Node
*)&tn
->tn_Node
))));
2432 struct MUI_NListtree_TreeNode
*FindTreeNodeByNameRev( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, STRPTR name
, UWORD flags
)
2434 struct MUI_NListtree_TreeNode
*tn
;
2438 if(isFlagSet(flags
, MUIV_NListtree_FindName_Flag_StartNode
))
2441 tn
= CTN( GetTail( (struct List
*)&ln
->ln_List
) );
2447 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
) || isFlagClear(flags
, MUIV_NListtree_FindName_Flag_Visible
))
2449 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) || isFlagClear(flags
, MUIV_NListtree_FindName_Flag_Selected
))
2451 if ( !( (LONG
)MyCallHook( data
->FindNameHook
, data
, MUIA_NListtree_FindNameHook
, name
, tn
->tn_Name
, tn
->tn_User
, flags
) ) )
2458 while((tn
= CTN(GetPred((struct Node
*)&tn
->tn_Node
))));
2460 if(isFlagClear(flags
, MUIV_NListtree_FindName_Flag_SameLevel
))
2462 ln
= CLN( GetParent( CTN( ln
) ) );
2463 SET_FLAG(flags
, MUIV_NListtree_FindName_Flag_StartNode
);
2476 struct MUI_NListtree_TreeNode
*FindTreeNodeByUserData( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, STRPTR userdata
, UWORD flags
)
2478 struct MUI_NListtree_TreeNode
*tn2
, *tn
;
2480 if(isFlagSet(flags
, MUIV_NListtree_FindUserData_Flag_StartNode
))
2483 tn
= CTN( GetHead( (struct List
*)&ln
->ln_List
) );
2490 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
) || isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_Visible
))
2492 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) || isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_Selected
))
2494 if ( !( (LONG
)MyCallHook( data
->FindUserDataHook
, data
, MUIA_NListtree_FindUserDataHook
, userdata
, tn
->tn_User
, tn
->tn_Name
, flags
) ) )
2501 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_SameLevel
))
2503 if((tn2
= FindTreeNodeByUserData(data
, CLN(tn
), userdata
, (flags
& ~MUIV_NListtree_FindUserData_Flag_StartNode
))))
2509 while((tn
= CTN(GetSucc((struct Node
*)&tn
->tn_Node
))));
2517 struct MUI_NListtree_TreeNode
*FindTreeNodeByUserDataRev( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, STRPTR userdata
, UWORD flags
)
2519 struct MUI_NListtree_TreeNode
*tn
;
2523 if(isFlagSet(flags
, MUIV_NListtree_FindUserData_Flag_StartNode
))
2526 tn
= CTN( GetTail( (struct List
*)&ln
->ln_List
) );
2532 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
) || isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_Visible
))
2534 if(isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) || isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_Selected
))
2536 if ( !( (LONG
)MyCallHook( data
->FindUserDataHook
, data
, MUIA_NListtree_FindUserDataHook
, userdata
, tn
->tn_User
, tn
->tn_Name
, flags
) ) )
2543 while((tn
= CTN(GetPred((struct Node
*)&tn
->tn_Node
))));
2545 if(isFlagClear(flags
, MUIV_NListtree_FindUserData_Flag_SameLevel
))
2547 ln
= CLN( GetParent( CTN( ln
) ) );
2548 SET_FLAG(flags
, MUIV_NListtree_FindUserData_Flag_StartNode
);
2561 VOID
InsertTreeNode( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*ln
, struct MUI_NListtree_TreeNode
*tn1
, struct MUI_NListtree_TreeNode
*tn2
)
2564 ** Give the entry a parent.
2566 tn1
->tn_Parent
= CTN( ln
);
2569 ** Insert entry into list.
2571 if ( (IPTR
)tn2
== (IPTR
)INSERT_POS_HEAD
)
2573 AddHead( (struct List
*)&ln
->ln_List
, (struct Node
*)&tn1
->tn_Node
);
2575 else if ( (IPTR
)tn2
== (IPTR
)INSERT_POS_TAIL
)
2577 AddTail( (struct List
*)&ln
->ln_List
, (struct Node
*)&tn1
->tn_Node
);
2581 Insert( (struct List
*)&ln
->ln_List
, (struct Node
*)&tn1
->tn_Node
, (struct Node
*)&tn2
->tn_Node
);
2584 InsertTreeNodeVisible( data
, tn1
, ln
, tn2
);
2585 NLAddToTable( data
, &ln
->ln_Table
, tn1
);
2590 struct MUI_NListtree_TreeNode
*DuplicateNode( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*nodetodup
)
2592 struct MUI_NListtree_ListNode
*new;
2595 if((new = CLN(AllocVecPooled(data
->TreePool
, isFlagSet(nodetodup
->tn_Flags
, TNF_LIST
) ? sizeof(struct MUI_NListtree_ListNode
) : sizeof(struct MUI_NListtree_TreeNode
)))) != NULL
)
2597 if(isFlagSet(nodetodup
->tn_Flags
, TNF_LIST
))
2598 NewList((struct List
*)&new->ln_List
);
2601 ** Should we duplicate the supplied node name?
2603 if(isFlagSet(data
->Flags
, NLTF_DUPNODENAMES
))
2605 int len
= strlen(nodetodup
->tn_Name
) + 1;
2607 if((new->ln_Name
= (STRPTR
)AllocVecPooled(data
->TreePool
, len
)) != NULL
)
2609 strlcpy(new->ln_Name
, nodetodup
->tn_Name
, len
);
2610 SET_FLAG(new->ln_IFlags
, TNIF_ALLOCATED
);
2614 new->ln_Name
= nodetodup
->tn_Name
;
2617 ** Create new user dats
2619 if(new->ln_Name
!= NULL
)
2621 user
= (APTR
)DoMethod(data
->Obj
, MUIM_NListtree_Construct
, nodetodup
->tn_Name
, nodetodup
->tn_User
, data
->TreePool
, MUIV_NListtree_ConstructHook_Flag_AutoCreate
);
2626 ** Free all previously allocated memory if
2627 ** something failed before.
2629 if(isFlagSet(new->ln_IFlags
, TNIF_ALLOCATED
))
2630 FreeVecPooled(data
->TreePool
, new->ln_Name
);
2632 DoMethod(data
->Obj
, MUIM_NListtree_Destruct
, nodetodup
->tn_Name
, nodetodup
->tn_User
, data
->TreePool
, 0);
2634 FreeVecPooled(data
->TreePool
, new);
2639 new->ln_User
= user
;
2640 new->ln_Flags
= ( nodetodup
->tn_Flags
& ~TNF_SELECTED
);
2643 ** Add one to the global number of entries
2650 FreeVecPooled(data
->TreePool
, new);
2660 struct MUI_NListtree_TreeNode
*CreateParentStructure( struct NListtree_Data
*data
, ULONG method
, struct MUI_NListtree_ListNode
**destlist
, struct MUI_NListtree_TreeNode
**destentry
, struct MUI_NListtree_TreeNode
*nodetodup
, UWORD cnt
)
2662 struct MUI_NListtree_ListNode
*prevnode
, *newlist
;
2664 if((prevnode
= CLN(GetParentNotRoot(nodetodup
))))
2665 *destlist
= CLN( CreateParentStructure( data
, method
, destlist
, destentry
, CTN(prevnode
), cnt
+ 1 ) );
2667 D(DBF_LISTTREE
, "Adding node 0x%08lx - %s to node 0x%08lx - %s", nodetodup
, nodetodup
->tn_Name
, *destlist
, (*destlist
)->ln_Name
);
2670 ** Allocate memory for the new entry and
2671 ** initialize list structure for use.
2673 if ( ( method
== MUIM_NListtree_Copy
) || cnt
)
2675 newlist
= CLN( DuplicateNode( data
, nodetodup
) );
2679 newlist
= CLN(nodetodup
);
2685 ** Add the new created entry to the specified list.
2690 ** Insert entry into list.
2692 InsertTreeNode( data
, *destlist
, CTN(newlist
), *destentry
);
2693 *destentry
= CTN( INSERT_POS_TAIL
);
2694 if(isFlagSet(nodetodup
->tn_IFlags
, TNIF_VISIBLE
))
2695 SET_FLAG(newlist
->ln_IFlags
, TNIF_VISIBLE
);
2697 CLEAR_FLAG(newlist
->ln_IFlags
, TNIF_VISIBLE
);
2701 return( CTN( newlist
) );
2706 struct MUI_NListtree_TreeNode
*CreateChildStructure( struct NListtree_Data
*data
, struct MUI_NListtree_ListNode
*listnode
, struct MUI_NListtree_ListNode
*nodetodup
, struct MUI_NListtree_ListNode
*orignode
, ULONG cnt
)
2708 struct MUI_NListtree_ListNode
*new;
2711 new = CLN(DuplicateNode( data
, CTN(nodetodup
)));
2718 ** Insert entry into list.
2720 InsertTreeNode( data
, listnode
, CTN(new), CTN( INSERT_POS_TAIL
) );
2722 if(isFlagSet(orignode
->ln_Flags
, TNF_LIST
))
2724 if ( !IsListEmpty( &orignode
->ln_List
) )
2726 struct MUI_NListtree_ListNode
*ln
= CLN( &orignode
->ln_List
);
2729 for ( i
= 0; i
< orignode
->ln_Table
.tb_Entries
; i
++ )
2731 ln
= CLN( GetSucc( (struct Node
*)ln
) );
2733 CreateChildStructure( data
, new, ln
, ln
, cnt
+ 1 );
2744 /*****************************************************************************\
2745 *******************************************************************************
2747 ** Graphical and render functions.
2749 *******************************************************************************
2750 \*****************************************************************************/
2752 static void InsertTreeImages( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, struct MUI_NListtree_TreeNode
*otn
, UWORD cnt
)
2754 struct MUI_NListtree_TreeNode
*gp
;
2758 LONG x1
= -1, x2
= 0;
2760 // we do a recursive call in case we find a
2761 // parent node for the current one.
2762 if((gp
= GetParent(tn
)))
2763 InsertTreeImages( data
, gp
, otn
, cnt
+ 1 );
2765 x2
= data
->MaxImageWidth
;
2767 if ( GetSucc( (struct Node
*)&tn
->tn_Node
) )
2771 if(isFlagClear(tn
->tn_Flags
, TNF_LIST
))
2785 if(isFlagClear(tn
->tn_Flags
, TNF_LIST
))
2796 if ( ( x1
!= -1 ) && x2
)
2798 char tmpbuf
[DATA_BUF_SIZE
];
2800 if ( x1
== SPEC_Space
)
2801 otn
->tn_Space
+= x2
+ data
->IndentWidth
;
2803 if ( otn
->tn_Space
> 0 )
2805 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx;%x;%d,%d]", (unsigned long)data
->Image
[IMAGE_Tree
].ListImage
, (unsigned int)MUIA_TI_Spec
, (int)SPEC_Space
, (int)otn
->tn_Space
);
2806 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2808 otn
->tn_ImagePos
+= otn
->tn_Space
;
2812 if ( x1
!= SPEC_Space
)
2814 x2
+= data
->IndentWidth
;
2817 ** Should we draw the root tree? No? Just use space.
2819 if(isFlagSet(data
->Flags
, NLTF_NO_ROOT_TREE
) && gp
->tn_Parent
== NULL
)
2821 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx;%x;%d,%d]", (unsigned long)data
->Image
[IMAGE_Tree
].ListImage
, (unsigned int)MUIA_TI_Spec
, (int)SPEC_Space
, (int)x2
);
2822 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2824 otn
->tn_ImagePos
+= x2
;
2828 // ensures proper text alignment with subnodes in
2829 // case the user selected an additional indentwidth
2830 if(data
->IndentWidth
> 0)
2833 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx;%x;%d,%d]", (unsigned long)data
->Image
[IMAGE_Tree
].ListImage
, (unsigned int)MUIA_TI_Spec
, (int)x1
, (int)x2
);
2834 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2836 otn
->tn_ImagePos
+= x2
;
2843 static void InsertImage( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*otn
)
2845 struct MUI_NListtree_ListNode
*ln
= CLN( otn
);
2846 char tmpbuf
[DATA_BUF_SIZE
];
2849 InsertTreeImages( data
, otn
, otn
, 0 );
2851 if((isFlagSet(otn
->tn_Flags
, TNF_LIST
) && isFlagClear(otn
->tn_Flags
, TNF_NOSIGN
)) && ( !IsListEmpty( &ln
->ln_List
) || isFlagClear(data
->Flags
, NLTF_EMPTYNODES
)))
2853 if(isFlagSet(otn
->tn_Flags
, TNF_OPEN
))
2862 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx]", (unsigned long)data
->Image
[x1
].ListImage
);
2863 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2867 // add some indent width
2868 if(data
->IndentWidth
> 0)
2870 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx;%x;%d,%d]", (unsigned long)data
->Image
[IMAGE_Tree
].ListImage
, (unsigned int)MUIA_TI_Spec
, (int)x1
, (unsigned int)data
->IndentWidth
);
2871 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2874 if(data
->UseFolderImage
== TRUE
)
2876 snprintf(tmpbuf
, DATA_BUF_SIZE
, "\033O[%lx]\033O[%lx;%x;%d,%d]", (unsigned long)data
->Image
[IMAGE_Folder
].ListImage
, (unsigned long)data
->Image
[IMAGE_Tree
].ListImage
, (unsigned int)MUIA_TI_Spec
, (unsigned int)SPEC_Space
, 3);
2877 strncat(data
->buf
, tmpbuf
, DATA_BUF_SIZE
);
2883 static void DrawImages( struct MUI_NListtree_TreeNode
*otn
, struct MUI_NListtree_TreeNode
*tn
, struct NListtree_Data
*data
, UWORD cnt
)
2887 struct MUI_NListtree_TreeNode
*gp
;
2889 if((gp
= GetParent(tn
)))
2890 DrawImages( otn
, gp
, data
, cnt
+ 1 );
2893 InsertImage( data
, otn
);
2899 /*****************************************************************************\
2900 *******************************************************************************
2902 ** General internal class related functions.
2904 *******************************************************************************
2905 \*****************************************************************************/
2907 ULONG
MultiTestFunc( struct NListtree_Data
*data
, struct MUI_NListtree_TreeNode
*tn
, LONG seltype
, LONG selflags
)
2909 LONG currtype
= isFlagSet(tn
->tn_Flags
, TNF_SELECTED
) ? MUIV_NListtree_Select_On
: MUIV_NListtree_Select_Off
;
2910 BOOL doselect
= TRUE
;
2912 if(isFlagSet(data
->Flags
, NLTF_DRAGDROP
))
2915 if(isFlagSet(data
->Flags
, NLTF_NLIST_NO_SCM_SUPPORT
))
2918 if ( currtype
!= seltype
)
2920 if ( data
->MultiTestHook
)
2922 doselect
= (BOOL
)MyCallHook( data
->MultiTestHook
, data
, MUIA_NListtree_MultiTestHook
, tn
, seltype
, selflags
, currtype
);
2927 doselect
= DoMethod( data
->Obj
, MUIM_NListtree_MultiTest
, tn
, seltype
, selflags
, currtype
);
2934 D(DBF_ALWAYS, "MULTITEST: 0x%08lx - %s", tn, tn->tn_Name);
2940 HOOKPROTONH(NList_MultiTestFunc
, ULONG
, Object
*obj
, struct MUI_NListtree_TreeNode
*tn
)
2942 struct NListtree_Data
*data
;
2945 data
= (struct NListtree_Data
*)xget( obj
, MUIA_UserData
);
2947 if(isFlagSet(data
->Flags
, NLTF_SELECT_METHOD
))
2950 if ( data
->MultiSelect
!= MUIV_NListtree_MultiSelect_None
)
2952 if ( ( data
->MultiSelect
== MUIV_NListtree_MultiSelect_Default
) ||
2953 ( data
->MultiSelect
== MUIV_NListtree_MultiSelect_Always
) ||
2954 ( ( data
->MultiSelect
== MUIV_NListtree_MultiSelect_Shifted
) && isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
)))
2956 ret
= MultiTestFunc( data
, tn
, MUIV_NListtree_Select_On
, 0 );
2962 MakeStaticHook(NList_MultiTestHook
, NList_MultiTestFunc
);
2964 HOOKPROTONHNO(_ConstructFunc
, APTR
, struct MUIP_NListtree_ConstructMessage
*msg
)
2969 ** Allocate memory for the user field and
2970 ** copy the supplied string to the new
2971 ** allocated piece of memory.
2973 if ( msg
->UserData
)
2975 int len
= strlen((STRPTR
)msg
->UserData
) + 1;
2977 if((retdata
= AllocVecPooled(msg
->MemPool
, len
)))
2979 strlcpy( (STRPTR
)retdata
, (STRPTR
)msg
->UserData
, len
);
2981 D(DBF_LISTTREE
, "Internal CostructHook ==> Data: '%s'", (STRPTR
)msg
->UserData
);
2989 MakeStaticHook(_ConstructHook
, _ConstructFunc
);
2991 HOOKPROTONHNO(_DestructFunc
, ULONG
, struct MUIP_NListtree_DestructMessage
*msg
)
2993 D(DBF_LISTTREE
, "Internal DestructHook ==> Data: '%s'", (STRPTR
)msg
->UserData
);
2996 ** Free the string memory.
2998 if ( msg
->UserData
)
3000 FreeVecPooled( msg
->MemPool
, msg
->UserData
);
3005 MakeStaticHook(_DestructHook
, _DestructFunc
);
3009 ** The internal compare hook functions.
3012 HOOKPROTONHNONP(_CompareFunc_Head
, LONG
) //struct MUIP_NListtree_CompareMessage *msg)
3016 MakeStaticHook(_CompareHook_Head
, _CompareFunc_Head
);
3018 HOOKPROTONHNONP(_CompareFunc_Tail
, LONG
) //struct MUIP_NListtree_CompareMessage *msg)
3022 MakeStaticHook(_CompareHook_Tail
, _CompareFunc_Tail
);
3024 HOOKPROTONHNO(_CompareFunc_LeavesTop
, LONG
, struct MUIP_NListtree_CompareMessage
*msg
)
3026 if(isFlagSet(msg
->TreeNode1
->tn_Flags
, TNF_LIST
) && isFlagSet(msg
->TreeNode2
->tn_Flags
, TNF_LIST
))
3028 return( Stricmp( msg
->TreeNode1
->tn_Name
, msg
->TreeNode2
->tn_Name
) );
3030 else if(isFlagSet(msg
->TreeNode1
->tn_Flags
, TNF_LIST
))
3034 else if(isFlagSet(msg
->TreeNode2
->tn_Flags
, TNF_LIST
))
3040 return( Stricmp( msg
->TreeNode1
->tn_Name
, msg
->TreeNode2
->tn_Name
) );
3043 MakeStaticHook(_CompareHook_LeavesTop
, _CompareFunc_LeavesTop
);
3045 HOOKPROTONHNO(_CompareFunc_LeavesBottom
, LONG
, struct MUIP_NListtree_CompareMessage
*msg
)
3047 if(isFlagSet(msg
->TreeNode1
->tn_Flags
, TNF_LIST
) && isFlagSet(msg
->TreeNode2
->tn_Flags
, TNF_LIST
))
3049 return( Stricmp( msg
->TreeNode1
->tn_Name
, msg
->TreeNode2
->tn_Name
) );
3051 else if(isFlagSet(msg
->TreeNode1
->tn_Flags
, TNF_LIST
))
3055 else if(isFlagSet(msg
->TreeNode2
->tn_Flags
, TNF_LIST
))
3061 return( Stricmp( msg
->TreeNode1
->tn_Name
, msg
->TreeNode2
->tn_Name
) );
3064 MakeStaticHook(_CompareHook_LeavesBottom
, _CompareFunc_LeavesBottom
);
3066 HOOKPROTONHNO(_CompareFunc_LeavesMixed
, LONG
, struct MUIP_NListtree_CompareMessage
*msg
)
3068 return( Stricmp( msg
->TreeNode1
->tn_Name
, msg
->TreeNode2
->tn_Name
) );
3070 MakeStaticHook(_CompareHook_LeavesMixed
, _CompareFunc_LeavesMixed
);
3072 static void SortList( struct MUI_NListtree_ListNode
*ln
, struct NListtree_Data
*data
)
3074 if ( ln
->ln_Table
.tb_Entries
> 1 )
3076 struct MUI_NListtree_TreeNode
**localtable
;
3079 // let's start the quicksort algorithm to sort our entries.
3080 qsort2(ln
->ln_Table
.tb_Table
, ln
->ln_Table
.tb_Entries
, data
);
3082 localtable
= ln
->ln_Table
.tb_Table
;
3084 NewList( (struct List
*)&ln
->ln_List
);
3086 for( i
= 0; i
< ln
->ln_Table
.tb_Entries
; i
++ )
3088 AddTail( (struct List
*)&ln
->ln_List
, (struct Node
*)localtable
[i
] );
3093 struct MUI_NListtree_ListNode
*ListNode_Sort( struct MUI_NListtree_ListNode
*ln
, struct NListtree_Data
*data
, ULONG flags
)
3095 if(isFlagSet(flags
, MUIV_NListtree_Sort_Flag_RecursiveAll
) || isFlagSet(flags
, MUIV_NListtree_Sort_Flag_RecursiveOpen
))
3097 struct MUI_NListtree_ListNode
*ln2
= CLN( &ln
->ln_List
);
3099 while((ln2
= CLN(GetSucc((struct Node
*)ln2
))))
3101 if(isFlagSet(ln2
->ln_Flags
, TNF_LIST
))
3103 if(isFlagSet(ln2
->ln_Flags
, TNF_OPEN
) || isFlagSet(flags
, MUIV_NListtree_Sort_Flag_RecursiveAll
))
3105 ListNode_Sort( ln2
, data
, flags
);
3111 if(isFlagSet(ln
->ln_Flags
, TNF_LIST
))
3112 SortList( ln
, data
);
3117 HOOKPROTONHNO(_FindNameFunc_CaseSensitive
, LONG
, struct MUIP_NListtree_FindNameMessage
*msg
)
3119 return( strcmp( msg
->Name
, msg
->NodeName
) );
3121 MakeStaticHook(_FindNameHook_CaseSensitive
, _FindNameFunc_CaseSensitive
);
3123 HOOKPROTONHNO(_FindNameFunc_CaseInsensitive
, LONG
, struct MUIP_NListtree_FindNameMessage
*msg
)
3125 return( Stricmp( msg
->Name
, msg
->NodeName
) );
3127 MakeStaticHook(_FindNameHook_CaseInsensitive
, _FindNameFunc_CaseInsensitive
);
3129 HOOKPROTONHNO(_FindNameFunc_Part
, LONG
, struct MUIP_NListtree_FindNameMessage
*msg
)
3131 return( strncmp( msg
->Name
, msg
->NodeName
, strlen( msg
->Name
) ) );
3133 MakeStaticHook(_FindNameHook_Part
, _FindNameFunc_Part
);
3135 HOOKPROTONHNO(_FindNameFunc_PartCaseInsensitive
, LONG
, struct MUIP_NListtree_FindNameMessage
*msg
)
3137 return( Strnicmp( msg
->Name
, msg
->NodeName
, strlen( msg
->Name
) ) );
3139 MakeStaticHook(_FindNameHook_PartCaseInsensitive
, _FindNameFunc_PartCaseInsensitive
);
3141 HOOKPROTONHNO(_FindNameFunc_PointerCompare
, LONG
, struct MUIP_NListtree_FindNameMessage
*msg
)
3143 return( (LONG
)( (SIPTR
)msg
->Name
- (SIPTR
)msg
->NodeName
) );
3145 MakeStaticHook(_FindNameHook_PointerCompare
, _FindNameFunc_PointerCompare
);
3147 HOOKPROTONHNO(_FindUserDataFunc_CaseSensitive
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
3149 return( strcmp( (STRPTR
)msg
->User
, (STRPTR
)msg
->UserData
) );
3151 MakeStaticHook(_FindUserDataHook_CaseSensitive
, _FindUserDataFunc_CaseSensitive
);
3153 HOOKPROTONHNO(_FindUserDataFunc_CaseInsensitive
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
3155 return( Stricmp( (STRPTR
)msg
->User
, (STRPTR
)msg
->UserData
) );
3157 MakeStaticHook(_FindUserDataHook_CaseInsensitive
, _FindUserDataFunc_CaseInsensitive
);
3159 HOOKPROTONHNO(_FindUserDataFunc_Part
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
3161 return( strncmp( (STRPTR
)msg
->User
, (STRPTR
)msg
->UserData
, strlen( (STRPTR
)msg
->User
) ) );
3163 MakeStaticHook(_FindUserDataHook_Part
, _FindUserDataFunc_Part
);
3165 HOOKPROTONHNO(_FindUserDataFunc_PartCaseInsensitive
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
3167 return( Strnicmp( (STRPTR
)msg
->User
, (STRPTR
)msg
->UserData
, strlen( (STRPTR
)msg
->User
) ) );
3169 MakeStaticHook(_FindUserDataHook_PartCaseInsensitive
, _FindUserDataFunc_PartCaseInsensitive
);
3171 HOOKPROTONHNO(_FindUserDataFunc_PointerCompare
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
3173 return( (LONG
)( (SIPTR
)msg
->User
- (SIPTR
)msg
->UserData
) );
3175 MakeStaticHook(_FindUserDataHook_PointerCompare
, _FindUserDataFunc_PointerCompare
);
3178 /*****************************************************************************\
3179 *******************************************************************************
3181 ** General internal class related help functions.
3183 *******************************************************************************
3184 \*****************************************************************************/
3186 /****** NListtree.mcc/MUIA_NListtree_Active **********************************
3190 * MUIA_NListtree_Active -- [.SG], struct MUI_NListtree_TreeNode *
3195 * MUIV_NListtree_Active_Off
3196 * MUIV_NListtree_Active_Parent
3197 * MUIV_NListtree_Active_First
3198 * MUIV_NListtree_Active_FirstVisible
3199 * MUIV_NListtree_Active_LastVisible
3204 * Setting this attribute will move the cursor to the defined tree node
3205 * if it is visible. If the node is in an opened tree the listview is
3206 * scrolling into the visible area. Setting MUIV_NListtree_Active_Off will
3207 * vanish the cursor.
3209 * MUIV_NListtree_Active_First/FirstVisible/LastVisible are special values
3210 * for activating the lists first or the top/bottom visible entry.
3212 * See MUIA_NListtree_AutoVisible for special activation features.
3214 * If this attribute is read it returns the active tree node. The result
3215 * is MUIV_NListtree_Active_Off if there is no active entry.
3220 * You can create a notification on MUIA_NListtree_Active. The
3221 * TriggerValue is the active tree node.
3226 * MUIA_NListtree_AutoVisible, MUIA_NList_First, MUIA_NList_Visible,
3227 * MUIA_NListtree_ActiveList
3229 ******************************************************************************
3233 /****** NListtree.mcc/MUIA_NListtree_ActiveList ******************************
3237 * MUIA_NListtree_ActiveList -- [..G], struct MUI_NListtree_TreeNode *
3242 * MUIV_NListtree_ActiveList_Off
3247 * If this attribute is read it returns the active list node. The
3248 * active list node is always the parent of the active entry.
3249 * The result is MUIV_NListtree_ActiveList_Off if there is no
3250 * active list (when there is no active entry).
3255 * You can create notifications on MUIA_NListtree_ActiveList. The
3256 * TriggerValue is the active list node.
3261 * MUIA_NListtree_Active
3263 ******************************************************************************
3267 /****** NListtree.mcc/MUIA_NListtree_AutoVisible *****************************
3271 * MUIA_NListtree_AutoVisible -- [ISG], struct MUI_NListtree_TreeNode *
3276 * MUIV_NListtree_AutoVisible_Off
3277 * MUIV_NListtree_AutoVisible_Normal
3278 * MUIV_NListtree_AutoVisible_FirstOpen
3279 * MUIV_NListtree_AutoVisible_Expand
3284 * Set this to make your list automatically jump to the active
3287 * MUIV_NListtree_AutoVisible_Off:
3288 * The display does NOT scroll the active entry into the
3291 * MUIV_NListtree_AutoVisible_Normal:
3292 * This will scroll the active entry into the visible area
3293 * if it is visible (entry is a member of an open node).
3294 * This is the default.
3296 * MUIV_NListtree_AutoVisible_FirstOpen:
3297 * Nodes are not opened, but the first open parent node of
3298 * the active entry is scrolled into the visible area if the
3299 * active entry is not visible.
3301 * MUIV_NListtree_AutoVisible_Expand:
3302 * All parent nodes are opened until the first open node is
3303 * reached and the active entry will be scrolled into the
3312 * MUIA_NListtree_Active, MUIA_NList_AutoVisible
3314 ******************************************************************************
3318 /****** NListtree.mcc/MUIA_NListtree_CloseHook *******************************
3322 * MUIA_NListtree_CloseHook -- [IS.], struct Hook *
3330 * The close hook is called after a list node is closed, then you can
3333 * The close hook will be called with the hook in A0, the object in A2
3334 * and a MUIP_NListtree_CloseMessage struct in A1 (see nlisttree_mcc.h).
3336 * To remove the hook set this to NULL.
3344 * MUIA_NListtree_Open, MUIA_NListtree_CloseHook
3347 ******************************************************************************
3351 /****** NListtree.mcc/MUIA_NListtree_CompareHook *****************************
3355 * MUIA_NListtree_CompareHook -- [IS.], struct Hook *
3360 * MUIV_NListtree_CompareHook_Head
3361 * MUIV_NListtree_CompareHook_Tail
3362 * MUIV_NListtree_CompareHook_LeavesTop
3363 * MUIV_NListtree_CompareHook_LeavesMixed
3364 * MUIV_NListtree_CompareHook_LeavesBottom
3369 * Set this attribute to your own hook if you want to sort the entries in
3370 * the list tree by your own way.
3372 * When you sort your list or parts of your list via MUIM_NListtree_Sort,
3373 * using the insert method with MUIV_NListtree_Insert_Sort or dropping an
3374 * entry on a closed node, this compare hook is called.
3376 * There are some builtin compare hooks available, called:
3378 * MUIV_NListtree_CompareHook_Head
3379 * Any entry is inserted at head of the list.
3381 * MUIV_NListtree_CompareHook_Tail
3382 * Any entry is inserted at tail of the list.
3384 * MUIV_NListtree_CompareHook_LeavesTop
3385 * Leaves are inserted at top of the list, nodes at bottom. They are
3386 * alphabetically sorted.
3388 * MUIV_NListtree_CompareHook_LeavesMixed
3389 * The entries are only alphabetically sorted.
3391 * MUIV_NListtree_CompareHook_LeavesBottom
3392 * Leaves are inserted at bottom of the list, nodes at top. They are
3393 * alphabetically sorted. This is default.
3395 * The hook will be called with the hook in A0, the object in A2 and
3396 * a MUIP_NListtree_CompareMessage struct in A1 (see nlisttree_mcc.h). You
3397 * should return something like:
3399 * <0 (TreeNode1 < TreeNode2)
3400 * 0 (TreeNode1 == TreeNode2)
3401 * >0 (TreeNode1 > TreeNode2)
3409 * MUIA_NListtree_Insert, MUIM_DragDrop,
3410 * MUIA_NList_CompareHook
3413 ******************************************************************************
3417 /****** NListtree.mcc/MUIA_NListtree_ConstructHook ***************************
3421 * MUIA_NListtree_ConstructHook -- [IS.], struct Hook *
3426 * MUIV_NListtree_ConstructHook_String
3428 * MUIV_NListtree_ConstructHook_Flag_AutoCreate
3429 * If using the KeepStructure feature in MUIM_NListtree_Move or
3430 * MUIM_NListtree_Copy, this flag will be set when calling your
3431 * construct hook. Then you can react if your hook is not simply
3432 * allocating memory.
3437 * The construct hook is called whenever you add an entry to your
3438 * listtree. The pointer isn't inserted directly, the construct hook is
3439 * called and its result code is added.
3441 * When an entry shall be removed the corresponding destruct hook is
3444 * The construct hook will be called with the hook in A0, the object in
3445 * A2 and a MUIP_NListtree_ConstructMessage struct in A1 (see
3447 * The message holds a standard kick 3.x memory pool pointer. If you want,
3448 * you can use the exec or amiga.lib functions for allocating memory
3449 * within this pool, but this is only an option.
3451 * If the construct hook returns NULL, nothing will be added to the list.
3453 * There is a builtin construct hook available called
3454 * MUIV_NListtree_ConstructHook_String. This expects that the field
3455 * 'tn_User' in the treenode is a string pointer (STRPTR), which's
3457 * Of course you have to use MUIV_NListtree_DestructHook_String in
3460 * To remove the hook set this to NULL.
3462 * NEVER pass a NULL pointer when you have specified the internal string
3463 * construct/destruct hooks or NListtree will die!
3471 * MUIA_NList_ConstructHook, MUIA_NListtree_DestructHook,
3472 * MUIA_NListtree_DisplayHook
3475 ******************************************************************************
3479 /****** NListtree.mcc/MUIA_NListtree_DestructHook ****************************
3483 * MUIA_NListtree_DestructHook -- [IS.], struct Hook *
3488 * MUIV_NListtree_DestructHook_String
3493 * Set up a destruct hook for your listtree. The destruct hook is called
3494 * whenevere you remove an entry from the listtree. Here you can free memory
3495 * which was allocated by the construct hook before.
3497 * The destruct hook will be called with the hook in A0, the object
3498 * in A2 and a MUIP_NListtree_DestructMessage struct in A1 (see
3500 * The message holds a standard kick 3.x memory pool pointer. You must
3501 * use this pool when you have used it inside the construct hook to
3502 * allocate pooled memory.
3504 * There is a builtin destruct hook available called
3505 * MUIV_NListtree_DestructHook_String. This expects that the 'User' data
3506 * in the treenode is a string and you have used
3507 * MUIV_NListtree_ConstructHook_String in the construct hook!
3509 * To remove the hook set this to NULL.
3517 * MUIA_NList_ConstructHook, MUIA_NListtree_ConstructHook,
3518 * MUIA_NListtree_DisplayHook
3521 ******************************************************************************
3525 /****** NListtree.mcc/MUIA_NListtree_DisplayHook *****************************
3529 * MUIA_NListtree_DisplayHook -- [IS.],
3537 * You have to supply a display hook to specify what should be shown in
3538 * the listview, otherwise only the name of the nodes is displayed.
3540 * The display hook will be called with the hook in A0, the object in
3541 * A2 and a MUIP_NListtree_DisplayMessage struct in A1 (see nlisttree_mcc.h).
3543 * The structure holds a pointer to a string array containing as many
3544 * entries as your listtree may have columns. You have to fill this
3545 * array with the strings you want to display. Check out that the array
3546 * pointer of the tree column is set to NULL, if the normal name of the
3547 * node should appear.
3548 * You can set a preparse string in Preparse for the corresponding col
3549 * element. Using it you'll be able to avoid copying the string in a
3550 * buffer to add something in the beginning of the col string.
3552 * The display hook also gets the position of the current entry as
3553 * additional parameter. It is stored in the longword preceding the col
3554 * array (don't forget it's a LONG).
3556 * You can set the array pointer of the tree column to a string, which is
3557 * diplayed instead of the node name. You can use this to mark nodes.
3559 * See MUIA_NList_Format for details about column handling.
3561 * To remove the hook and use the internal default display hook set this
3570 * MUIA_NList_Format, MUIA_Text_Contents
3573 ******************************************************************************
3577 /****** NListtree.mcc/MUIA_NListtree_CopyToClipHook **************************
3581 * MUIA_NListtree_CopyToClipHook -- [IS.],
3586 * MUIV_NListtree_CopyToClipHook_Default
3591 * This thing works near like MUIA_NListtree_DisplayHook, but is
3592 * called when the NListtree object want to make a clipboard copy.
3594 * You can return only one string pointer. If you return NULL,
3595 * nothing will be copied. If you return -1, the entry will be
3596 * handled as a normal string and the name field is used.
3598 * The builtin hook skips all ESC sequences and adds a tab char
3607 * MUIM_NListtree_CopyToClip
3610 ******************************************************************************
3614 /****** NListtree.mcc/MUIA_NListtree_DoubleClick *****************************
3618 * MUIA_NListtree_DoubleClick -- [ISG], ULONG
3623 * MUIV_NListtree_DoubleClick_Off
3624 * MUIV_NListtree_DoubleClick_All
3625 * MUIV_NListtree_DoubleClick_Tree
3626 * MUIV_NListtree_DoubleClick_NoTrigger
3631 * A doubleclick opens a node if it was closed, it is closed if the node
3632 * was open. You have to set the column which should do this.
3634 * Normally only the column number is set here, but there are special
3637 * MUIV_NListtree_DoubleClick_Off:
3638 * A doubleclick is not handled.
3640 * MUIV_NListtree_DoubleClick_All:
3641 * All columns react on doubleclick.
3643 * MUIV_NListtree_DoubleClick_Tree
3644 * Only a doubleclick on the defined tree column is recognized.
3646 * MUIV_NListtree_DoubleClick_NoTrigger:
3647 * A doubleclick is not handled and not triggered!
3652 * The TriggerValue of the notification is the tree node you have double-
3653 * clicked, you can GetAttr() MUIA_NListtree_DoubleClick for the column
3654 * number. The struct 'MUI_NListtree_TreeNode *'Â is used for trigger.
3656 * The notification is done on leaves and on node columns, which are not
3657 * set in MUIA_NListtree_DoubleClick.
3662 ******************************************************************************
3666 /****** NListtree.mcc/MUIA_NListtree_DragDropSort ****************************
3670 * MUIA_NListtree_DragDropSort -- [IS.], BOOL
3678 * Setting this attribute to FALSE will disable the ability to sort the
3679 * list tree by drag & drop. Defaults to TRUE.
3689 ******************************************************************************
3693 /****** NListtree.mcc/MUIA_NListtree_DupNodeName *****************************
3697 * MUIA_NListtree_DupNodeName -- [IS.], BOOL
3705 * If this attribute is set to FALSE the names of the node will not be
3706 * duplicated, only the string pointers are used. Be careful the strings
3707 * have to be valid everytime.
3717 ******************************************************************************
3721 /****** NListtree.mcc/MUIA_NListtree_EmptyNodes ******************************
3725 * MUIA_NListtree_EmptyNodes -- [IS.], BOOL
3733 * Setting this attribute to TRUE will display all empty nodes as leaves,
3734 * this means no list indicator is shown. Nevertheless the entry is
3735 * handled like a node.
3745 ******************************************************************************
3749 /****** NListtree.mcc/MUIA_NListtree_FindNameHook ****************************
3753 * MUIA_NListtree_FindNameHook -- [IS.],
3758 * MUIV_NListtree_FindNameHook_CaseSensitive
3759 * Search for the complete string, case sensitive.
3761 * MUIV_NListtree_FindNameHook_CaseInsensitive
3762 * Search for the complete string, case insensitive.
3764 * MUIV_NListtree_FindNameHook_Part
3765 * Search for the first part of the string, case sensitive.
3767 * MUIV_NListtree_FindNameHook_PartCaseInsensitive
3768 * Search for the first part of the string, case insensitive.
3770 * MUIV_NListtree_FindNameHook_PointerCompare
3771 * Do only a pointer comparision. Note, that this is in fact
3772 * a pointer subtraction to fit into the rules. It returns
3773 * the difference of the two fields if no match.
3777 * You can install a FindName hook to specify your own search
3780 * The find name hook will be called with the hook in A0, the object in
3781 * A2 and a MUIP_NListtree_FindNameMessage struct in A1
3782 * (see nlisttree_mcc.h). It should return (ret != 0) for entries which
3783 * are not matching the pattern and a value of 0 if a match.
3785 * The find name message structure holds a pointer to a string
3786 * containing the name to search for and pointers to the name- and user-
3787 * field of the node which is currently processed.
3789 * The MUIV_NListtree_FindNameHook_CaseSensitive will be used as default.
3796 * MUIM_NListtree_FindName, MUIM_NListtree_FindUserData,
3797 * MUIA_NListtree_FindUserDataHook
3799 ******************************************************************************
3803 /****** NListtree.mcc/MUIA_NListtree_FindUserDataHook ************************
3807 * MUIA_NListtree_FindUserDataHook -- [IS.],
3812 * MUIV_NListtree_FindUserDataHook_CaseSensitive
3813 * Search for the complete string, case sensitive.
3815 * MUIV_NListtree_FindUserDataHook_CaseInsensitive
3816 * Search for the complete string, case insensitive.
3818 * MUIV_NListtree_FindUserDataHook_Part
3819 * Search for the first part of the string, case sensitive.
3821 * MUIV_NListtree_FindUserDataHook_PartCaseInsensitive
3822 * Search for the first part of the string, case insensitive.
3824 * MUIV_NListtree_FindUserDataHook_PointerCompare
3825 * Do only a pointer comparision. Note, that this is in fact
3826 * a pointer subtraction to fit into the rules. It returns
3827 * the difference of the two user fields if no match.
3832 * You can install a FindUserData hook to specify your own search
3835 * The find user data hook will be called with the hook in A0, the object
3836 * in A2 and a MUIP_NListtree_FindUserDataMessage struct in A1
3837 * (see nlisttree_mcc.h). It should return (ret != 0) for entries which
3838 * are not matching the pattern and a value of 0 if a match.
3840 * The find user data message structure holds a pointer to a string
3841 * containing the data to search for and pointers to the user- and name-
3842 * field of the node which is currently processed.
3844 * MUIV_NListtree_FindUserDataHook_CaseSensitive will be used as
3852 * MUIM_NListtree_FindName, MUIM_NListtree_FindUserData,
3853 * MUIA_NListtree_FindNameHook
3855 ******************************************************************************
3859 /****** NListtree.mcc/MUIA_NListtree_Format **********************************
3863 * MUIA_NListtree_Format -- [IS.], STRPTR
3871 * Same as MUIA_NList_Format, but one column is reserved for the tree
3872 * indicators and the names of the nodes.
3874 * For further detailed information see MUIA_NList_Format!
3882 * MUIA_NList_Format, MUIA_NListtree_DisplayHook,
3883 * MUIA_Text_Contents
3886 ******************************************************************************
3890 /****** NListtree.mcc/MUIA_NListtree_MultiSelect *****************************
3894 * MUIA_NListtree_MultiSelect -- [I..],
3899 * MUIV_NListtree_MultiSelect_None
3900 * MUIV_NListtree_MultiSelect_Default
3901 * MUIV_NListtree_MultiSelect_Shifted
3902 * MUIV_NListtree_MultiSelect_Always
3907 * Four possibilities exist for a listviews multi select
3910 * MUIV_NListtree_MultiSelect_None:
3911 * The list tree cannot multiselect at all.
3913 * MUIV_NListtree_MultiSelect_Default:
3914 * The multi select type (with or without shift)
3915 * depends on the users preferences setting.
3917 * MUIV_NListtree_MultiSelect_Shifted:
3918 * Overrides the users prefs, multi selecting only
3919 * together with shift key.
3921 * MUIV_NListtree_MultiSelect_Always:
3922 * Overrides the users prefs, multi selecting
3923 * without shift key.
3932 * MUIA_NListtree_MultiTestHook, MUIM_NListtree_MultiSelect
3935 ******************************************************************************
3939 /****** NListtree.mcc/MUIA_NListtree_MultiTestHook ***************************
3943 * MUIA_NListtree_MultiTestHook -- [IS.], struct Hook *
3951 * If you plan to have a multi selecting list tree but not
3952 * all of your entries are actually multi selectable, you
3953 * can supply a MUIA_NListtree_MultiTestHook.
3955 * The multi test hook will be called with the hook in A0, the object
3956 * in A2 and a MUIP_NListtree_MultiTestMessage struct in A1 (see
3957 * nlisttree_mcc.h) and should return TRUE if the entry is multi
3958 * selectable, FALSE otherwise.
3960 * To remove the hook set this to NULL.
3968 * MUIA_NListtree_ConstructHook, MUIA_NListtree_DestructHook
3971 ******************************************************************************
3975 /****** NListtree.mcc/MUIA_NListtree_OpenHook ********************************
3979 * MUIA_NListtree_OpenHook -- [IS.], struct Hook *
3987 * The open hook is called whenever a list node will be opened, so you
3988 * can change the list before the node is open.
3990 * The open hook will be called with the hook in A0, the object in A2
3991 * and a MUIP_NListtree_OpenMessage struct in A1 (see nlisttree_mcc.h).
3993 * To remove the hook set this to NULL.
4001 * MUIA_NListtree_Open, MUIA_NListtree_CloseHook
4004 ******************************************************************************
4008 /****** NListtree.mcc/MUIA_NListtree_Quiet ***********************************
4012 * MUIA_NListtree_Quiet -- [.S.], QUIET
4020 * If you add/remove lots of entries to/from a listtree, this will cause
4021 * lots of screen action and slow down the operation. Setting
4022 * MUIA_NListtree_Quiet to TRUE will temporarily prevent the listtree from
4023 * being refreshed, this refresh will take place only once when you set
4024 * it back to FALSE again.
4026 * MUIA_NListtree_Quiet holds a nesting count to avoid trouble with
4027 * multiple setting/unsetting this attribute. You are encoraged to
4028 * always use TRUE/FALSE pairs here or you will went in trouble.
4030 * DO NOT USE MUIA_NList_Quiet here!
4038 * MUIM_NListtree_Insert, MUIM_NListtree_Remove
4041 ******************************************************************************
4045 /****** NListtree.mcc/MUIA_NListtree_Title ***********************************
4049 * MUIA_NListtree_Title -- [IS.], BOOL
4057 * Specify a title for the current listtree.
4059 * For detailed information see MUIA_NList_Title!
4067 * The title should not be a string as for single column listviews. This
4068 * attribute can only be set to TRUE or FALSE.
4075 ******************************************************************************
4079 /****** NListtree.mcc/MUIA_NListtree_TreeColumn ******************************
4083 * MUIA_NListtree_TreeColumn -- [ISG], ULONG
4090 * Specify the column of the list tree, the node indicator and the name
4091 * of the node are displayed in.
4099 * MUIA_NListtree_DisplayHook, MUIA_NListtree_Format
4102 ******************************************************************************
4106 /****** NListtree.mcc/MUIA_NListtree_ShowTree ********************************
4110 * MUIA_NListtree_ShowTree -- [ISG], ULONG
4117 * Specify FALSE here if you want the whole tree to be disappear.
4126 ******************************************************************************
4130 /****** NListtree.mcc/MUIA_NListtree_DropType ********************************
4134 * MUIA_NListtree_DropType -- [..G], ULONG
4139 * MUIV_NListtree_DropType_None
4140 * MUIV_NListtree_DropType_Above
4141 * MUIV_NListtree_DropType_Below
4142 * MUIV_NListtree_DropType_Onto
4147 * After a successful drop operation, this value holds the position
4148 * relative to the value of MUIA_NListtree_DropTarget/DropTargetPos.
4156 * MUIA_NListtree_DropTarget, MUIA_NListtree_DropTargetPos
4159 ******************************************************************************
4163 /****** NListtree.mcc/MUIA_NListtree_DropTarget ******************************
4167 * MUIA_NListtree_DropTarget -- [..G], ULONG
4174 * After a successful drop operation, this value holds the entry where
4175 * the entry was dropped. The relative position (above etc.) can be
4176 * obtained by reading the attribute MUIA_NListtree_DropType.
4184 * MUIA_NListtree_DropTargetPos, MUIA_NListtree_DropType
4187 ******************************************************************************
4191 /****** NListtree.mcc/MUIA_NListtree_DropTargetPos ***************************
4195 * MUIA_NListtree_DropTargetPos -- [..G], ULONG
4202 * After a successful drop operation, this value holds the integer
4203 * position of the entry where the dragged entry was dropped. The
4204 * entry itself can be obtained by reading MUIA_NListtree_DropTarget,
4205 * the relative position (above etc.) can be obtained by reading the
4206 * attribute MUIA_NListtree_DropType.
4214 * MUIA_NListtree_DropTarget, MUIA_NListtree_DropType
4217 ******************************************************************************
4221 static VOID
SetAttributes( struct NListtree_Data
*data
, struct opSet
*msg
, BOOL initial
)
4223 struct MUI_NListtree_ListNode
*actlist
;
4224 struct MUI_NListtree_TreeNode
*actnode
;
4225 struct TagItem
*tags
, *tag
;
4226 struct Hook
*orgHook
= NULL
;
4227 BOOL intfunc
, onlytrigger
= FALSE
;
4229 for(tags
= msg
->ops_AttrList
; (tag
= NextTagItem((APTR
)&tags
)); )
4233 switch( tag
->ti_Tag
)
4236 ** Configuration part.
4238 case MUIA_NListtree_IsMCP
:
4239 SET_FLAG(data
->Flags
, NLTF_ISMCP
);
4242 case MUICFG_NListtree_ImageSpecClosed
:
4244 DisposeImage( data
, IMAGE_Closed
);
4245 SetupImage( data
, (struct MUI_ImageSpec
*)tag
->ti_Data
, IMAGE_Closed
);
4248 D(DBF_GETSET
, "SET MUICFG_NListtree_ImageSpecClosed: '%s'", (STRPTR
)tag
->ti_Data
);
4252 case MUICFG_NListtree_ImageSpecOpen
:
4254 DisposeImage( data
, IMAGE_Open
);
4255 SetupImage( data
, (struct MUI_ImageSpec
*)tag
->ti_Data
, IMAGE_Open
);
4258 D(DBF_GETSET
, "SET MUICFG_NListtree_ImageSpecOpen: '%s'", (STRPTR
)tag
->ti_Data
);
4262 case MUICFG_NListtree_ImageSpecFolder
:
4264 DisposeImage( data
, IMAGE_Folder
);
4265 SetupImage( data
, (struct MUI_ImageSpec
*)tag
->ti_Data
, IMAGE_Folder
);
4268 D(DBF_GETSET
, "SET MUICFG_NListtree_ImageSpecFolder: '%s'", (STRPTR
)tag
->ti_Data
);
4272 case MUICFG_NListtree_PenSpecLines
:
4276 ObtPen( data
->MRI
, &data
->Pen
[PEN_Line
], (struct MUI_PenSpec
*)tag
->ti_Data
);
4279 D(DBF_GETSET
, "SET MUICFG_NListtree_PenSpecLines: %s", (STRPTR
)tag
->ti_Data
);
4284 case MUICFG_NListtree_PenSpecShadow
:
4288 ObtPen( data
->MRI
, &data
->Pen
[PEN_Shadow
], (struct MUI_PenSpec
*)tag
->ti_Data
);
4291 D(DBF_GETSET
, "SET MUICFG_NListtree_PenSpecShadow: %s", (STRPTR
)tag
->ti_Data
);
4296 case MUICFG_NListtree_PenSpecGlow
:
4300 ObtPen( data
->MRI
, &data
->Pen
[PEN_Glow
], (struct MUI_PenSpec
*)tag
->ti_Data
);
4303 D(DBF_GETSET
, "SET MUICFG_NListtree_PenSpecGlow: %s", (STRPTR
)tag
->ti_Data
);
4308 case MUICFG_NListtree_IndentWidth
:
4310 data
->IndentWidth
= (BYTE
)tag
->ti_Data
;
4313 D(DBF_GETSET
, "SET MUICFG_NListtree_IndentWidth: %ld", tag
->ti_Data
);
4317 case MUICFG_NListtree_LineType
:
4319 data
->LineType
= (ULONG
)tag
->ti_Data
;
4322 D(DBF_GETSET
, "SET MUICFG_NListtree_LineType: %ld", tag
->ti_Data
);
4326 case MUICFG_NListtree_UseFolderImage
:
4328 data
->UseFolderImage
= (BOOL
)tag
->ti_Data
;
4331 D(DBF_GETSET
, "SET MUICFG_NListtree_UseFolderImage: %ld", tag
->ti_Data
);
4335 case MUICFG_NListtree_OpenAutoScroll
:
4337 if ( (BOOL
)tag
->ti_Data
)
4338 SET_FLAG(data
->Flags
, NLTF_OPENAUTOSCROLL
);
4340 CLEAR_FLAG(data
->Flags
, NLTF_OPENAUTOSCROLL
);
4342 D(DBF_GETSET
, "SET MUICFG_NListtree_OpenAutoScroll: %ld", tag
->ti_Data
);
4349 case MUIA_NListtree_OnlyTrigger
:
4352 D(DBF_GETSET
, "SET MUIA_NListtree_OnlyTrigger");
4356 case MUIA_NList_Active
:
4358 D(DBF_GETSET
, "SET MUIA_NList_Active %ld%s",tag
->ti_Data
,isFlagSet(data
->Flags
, NLTF_ACTIVENOTIFY
)?" notify activation set":"no notify set");
4362 case MUIA_NListtree_Active
:
4364 D(DBF_GETSET
, "SET MUIA_NListtree_Active");
4365 if((tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_Off
) ||
4366 (tag
->ti_Data
== (IPTR
)&data
->RootList
) ||
4367 ((tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_Parent
) &&
4368 (data
->ActiveNode
== (APTR
)MUIV_NListtree_Active_Off
))
4371 actnode
= MUIV_NListtree_Active_Off
;
4372 actlist
= &data
->RootList
;
4376 struct MUI_NListtree_TreeNode
*tn
;
4379 ** Parent of the active node.
4381 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_Parent
)
4383 tag
->ti_Data
= (IPTR
)GetParent( data
->ActiveNode
);
4387 ** First list entry (visible or not).
4389 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_First
)
4390 tag
->ti_Data
= (IPTR
)GetHead( (struct List
*)&data
->RootList
.ln_List
);
4393 ** First visible entry.
4395 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_FirstVisible
)
4399 firstvisible
= xget( data
->Obj
, MUIA_NList_First
);
4400 DoMethod( data
->Obj
, MUIM_NList_GetEntry
, firstvisible
, &tn
);
4402 tag
->ti_Data
= (IPTR
)tn
;
4406 ** Last visible entry.
4408 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_Active_LastVisible
)
4412 lastvisible
= xget( data
->Obj
, MUIA_NList_First
) + xget( data
->Obj
, MUIA_NList_Visible
) - 1;
4413 DoMethod( data
->Obj
, MUIM_NList_GetEntry
, lastvisible
, &tn
);
4415 tag
->ti_Data
= (IPTR
)tn
;
4418 if ( tag
->ti_Data
!= (IPTR
)&data
->RootList
)
4420 actnode
= CTN( tag
->ti_Data
);
4421 actlist
= CLN( GetParent( (CTN( tag
->ti_Data
) ) ) );
4430 ** With actnode and actlist we avoid ActiveNode ping-pong...
4432 if(!initial
&& (actnode
!= data
->ActiveNode
|| isFlagSet(data
->Flags
, NLTF_SETACTIVE
)))
4434 data
->ActiveNode
= actnode
;
4435 data
->ActiveNodeNum
= xget( data
->Obj
, MUIA_NList_Active
);
4441 ** For notification only.
4443 if (data
->ActiveList
!= actlist
)
4445 data
->ActiveList
= actlist
;
4446 MakeNotify( data
, MUIA_NListtree_ActiveList
, actlist
);
4453 ActivateTreeNode( data
, actnode
);
4454 DoMethod( data
->Obj
, MUIM_NListtree_Active
, data
->ActiveNodeNum
, data
->ActiveNode
);
4456 D(DBF_GETSET
, "SET MUIA_NListtree_Active: %s - 0x%08lx - list: 0x%08lx rootlist: 0x%lx", actnode
? actnode
->tn_Name
: (STRPTR
)"NULL", actnode
, data
->ActiveList
, &data
->RootList
);
4460 D(DBF_GETSET
, "SET MUIA_NListtree_Active: TRIGGER: %s - 0x%08lx", actnode
? actnode
->tn_Name
: (STRPTR
)"NULL", actnode
);
4466 ** Dummy for notification.
4468 case MUIA_NListtree_ActiveList
:
4469 D(DBF_GETSET
, "SET MUIA_NListtree_ActiveList (dummy)");
4472 case MUIA_NListtree_AutoVisible
:
4474 data
->AutoVisible
= (IPTR
)tag
->ti_Data
;
4476 D(DBF_GETSET
, "SET MUIA_NListtree_AutoVisible: %ld", tag
->ti_Data
);
4480 case MUIA_NListtree_CloseHook
:
4482 data
->CloseHook
= (struct Hook
*)tag
->ti_Data
;
4484 D(DBF_GETSET
, "SET MUIA_NListtree_CloseHook: 0x%08lx", tag
->ti_Data
);
4488 case MUIA_NListtree_CompareHook
:
4490 switch( tag
->ti_Data
)
4492 case MUIV_NListtree_CompareHook_Head
:
4494 orgHook
= &_CompareHook_Head
;
4495 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: MUIV_NListtree_CompareHook_Head");
4499 case MUIV_NListtree_CompareHook_Tail
:
4501 orgHook
= &_CompareHook_Tail
;
4502 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: MUIV_NListtree_CompareHook_Tail");
4506 case MUIV_NListtree_CompareHook_LeavesTop
:
4508 orgHook
= &_CompareHook_LeavesTop
;
4509 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: MUIV_NListtree_CompareHook_LeavesTop");
4513 case MUIV_NListtree_CompareHook_LeavesMixed
:
4515 orgHook
= &_CompareHook_LeavesMixed
;
4516 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: MUIV_NListtree_CompareHook_LeavesMixed");
4520 case MUIV_NListtree_CompareHook_LeavesBottom
:
4522 orgHook
= &_CompareHook_LeavesBottom
;
4523 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: MUIV_NListtree_CompareHook_LeavesBottom");
4531 data
->CompareHook
= (struct Hook
*)tag
->ti_Data
;
4533 D(DBF_GETSET
, "SET MUIA_NListtree_CompareHook: 0x%08lx", tag
->ti_Data
);
4540 /* The flags is quiet sensless because nobody asks for it expect in OM_NEW (which should be rewritten anywhy) */
4541 SET_FLAG(data
->Flags
, NLTF_INT_COMPAREHOOK
);
4542 InitHook(&data
->IntCompareHook
, *orgHook
, data
);
4543 data
->CompareHook
= &data
->IntCompareHook
;
4546 CLEAR_FLAG(data
->Flags
, NLTF_INT_COMPAREHOOK
);
4550 case MUIA_NListtree_ConstructHook
:
4553 ** If old hook is internal, remove complete
4554 ** hook with all memory allocated.
4556 if ( data
->ConstructHook
)
4558 if ( data
->ConstructHook
->h_Entry
== (HOOKFUNC
)_ConstructFunc
)
4560 FreeVecPooled( data
->MemoryPool
, data
->ConstructHook
);
4561 data
->ConstructHook
= NULL
;
4565 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_ConstructHook_String
)
4567 D(DBF_GETSET
, "SET MUIA_NListtree_ConstructHook: MUIV_NListtree_ConstructHook_String");
4569 if((data
->ConstructHook
= AllocVecPooled(data
->MemoryPool
, sizeof(struct Hook
))))
4571 SET_FLAG(data
->Flags
, NLTF_INT_CONSTRDESTRHOOK
);
4573 InitHook(data
->ConstructHook
, _ConstructHook
, data
);
4575 else data
->Error
= TRUE
;
4579 data
->ConstructHook
= (struct Hook
*)tag
->ti_Data
;
4581 D(DBF_GETSET
, "SET MUIA_NListtree_ConstructHook: 0x%08lx", tag
->ti_Data
);
4586 case MUIA_NListtree_DestructHook
:
4589 ** If old hook is internal, remove complete
4590 ** hook with all memory allocated.
4592 if ( data
->DestructHook
)
4594 if ( data
->DestructHook
->h_Entry
== (HOOKFUNC
)_DestructFunc
)
4596 FreeVecPooled( data
->MemoryPool
, data
->DestructHook
);
4597 data
->DestructHook
= NULL
;
4601 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_DestructHook_String
)
4603 D(DBF_GETSET
, "SET MUIA_NListtree_DestructHook: MUIV_NListtree_DestructHook_String");
4605 if((data
->DestructHook
= AllocVecPooled(data
->MemoryPool
, sizeof(struct Hook
))))
4607 SET_FLAG(data
->Flags
, NLTF_INT_CONSTRDESTRHOOK
);
4609 InitHook(data
->DestructHook
, _DestructHook
, data
);
4611 else data
->Error
= TRUE
;
4615 data
->DestructHook
= (struct Hook
*)tag
->ti_Data
;
4617 D(DBF_GETSET
, "SET MUIA_NListtree_DestructHook: 0x%08lx", tag
->ti_Data
);
4622 case MUIA_NListtree_DisplayHook
:
4624 if(tag
->ti_Data
!= (ULONG
)MUIV_NListtree_DisplayHook_Default
)
4626 data
->DisplayHook
= (struct Hook
*)tag
->ti_Data
;
4629 data
->DisplayHook
= NULL
;
4631 D(DBF_GETSET
, "SET MUIA_NListtree_DisplayHook: 0x%08lx", tag
->ti_Data
);
4635 case MUIA_NListtree_CopyToClipHook
:
4637 if ( tag
->ti_Data
== MUIV_NListtree_CopyToClipHook_Default
)
4639 D(DBF_GETSET
, "SET MUIA_NListtree_CopyToClipHook: MUIV_NListtree_CopyToClipHook_Default");
4641 data
->CopyToClipHook
= NULL
;
4645 data
->CopyToClipHook
= (struct Hook
*)tag
->ti_Data
;
4647 D(DBF_GETSET
, "SET MUIA_NListtree_CopyToClipHook: 0x%08lx", tag
->ti_Data
);
4652 case MUIA_NListtree_DoubleClick
:
4656 data
->DoubleClick
= (BYTE
)tag
->ti_Data
;
4657 D(DBF_GETSET
, "SET MUIA_NListtree_DoubleClick: 0x%08lx", tag
->ti_Data
);
4662 case MUIA_NListtree_DragDropSort
:
4664 if ( (BOOL
)tag
->ti_Data
)
4665 SET_FLAG(data
->Flags
, NLTF_DRAGDROPSORT
);
4667 CLEAR_FLAG(data
->Flags
, NLTF_DRAGDROPSORT
);
4669 D(DBF_GETSET
, "SET MUIA_NListtree_DragDropSort: %ld", tag
->ti_Data
);
4673 case MUIA_NListtree_DupNodeName
:
4675 if ( (BOOL
)tag
->ti_Data
)
4676 SET_FLAG(data
->Flags
, NLTF_DUPNODENAMES
);
4678 CLEAR_FLAG(data
->Flags
, NLTF_DUPNODENAMES
);
4680 D(DBF_GETSET
, "SET MUIA_NListtree_DupNodeName: %ld", tag
->ti_Data
);
4684 case MUIA_NListtree_EmptyNodes
:
4686 if ( (BOOL
)tag
->ti_Data
)
4687 SET_FLAG(data
->Flags
, NLTF_EMPTYNODES
);
4689 CLEAR_FLAG(data
->Flags
, NLTF_EMPTYNODES
);
4694 D(DBF_GETSET
, "SET MUIA_NListtree_EmptyNodes: %ld", tag
->ti_Data
);
4698 case MUIA_NListtree_FindNameHook
:
4701 ** If old hook is internal, remove complete
4702 ** hook with all memory allocated.
4704 if ( data
->FindNameHook
)
4706 FreeVecPooled( data
->MemoryPool
, data
->FindNameHook
);
4707 data
->FindNameHook
= NULL
;
4710 data
->FindNameHook
= AllocVecPooled( data
->MemoryPool
, sizeof( struct Hook
) );
4712 switch( tag
->ti_Data
)
4714 case MUIV_NListtree_FindNameHook_CaseSensitive
:
4716 orgHook
= &_FindNameHook_CaseSensitive
;
4717 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: MUIV_NListtree_FindNameHook_CaseSensitive");
4721 case MUIV_NListtree_FindNameHook_CaseInsensitive
:
4723 orgHook
= &_FindNameHook_CaseInsensitive
;
4724 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: MUIV_NListtree_FindNameHook_CaseInsensitive");
4728 case MUIV_NListtree_FindNameHook_Part
:
4730 orgHook
= &_FindNameHook_Part
;
4731 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: MUIV_NListtree_FindNameHook_Part");
4735 case MUIV_NListtree_FindNameHook_PartCaseInsensitive
:
4737 orgHook
= &_FindNameHook_PartCaseInsensitive
;
4738 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: MUIV_NListtree_FindNameHook_PartCaseInsensitive");
4742 case MUIV_NListtree_FindNameHook_PointerCompare
:
4744 orgHook
= &_FindNameHook_PointerCompare
;
4745 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: MUIV_NListtree_FindNameHook_PointerCompare");
4753 CopyMem( (APTR
)tag
->ti_Data
, data
->FindNameHook
, sizeof( struct Hook
) );
4755 D(DBF_GETSET
, "SET MUIA_NListtree_FindNameHook: 0x%08lx", tag
->ti_Data
);
4762 InitHook(data
->FindNameHook
, *orgHook
, data
);
4767 case MUIA_NListtree_FindUserDataHook
:
4770 ** If old hook is internal, remove complete
4771 ** hook with all memory allocated.
4773 if ( data
->FindUserDataHook
)
4775 FreeVecPooled( data
->MemoryPool
, data
->FindUserDataHook
);
4776 data
->FindUserDataHook
= NULL
;
4779 data
->FindUserDataHook
= AllocVecPooled( data
->MemoryPool
, sizeof( struct Hook
) );
4781 switch( tag
->ti_Data
)
4783 case MUIV_NListtree_FindUserDataHook_CaseSensitive
:
4785 orgHook
= &_FindUserDataHook_CaseSensitive
;
4786 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: MUIV_NListtree_FindUserDataHook_CaseSensitive");
4790 case MUIV_NListtree_FindUserDataHook_CaseInsensitive
:
4792 orgHook
= &_FindUserDataHook_CaseInsensitive
;
4793 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: MUIV_NListtree_FindUserDataHook_CaseInsensitive");
4797 case MUIV_NListtree_FindUserDataHook_Part
:
4799 orgHook
= &_FindUserDataHook_Part
;
4800 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: MUIV_NListtree_FindUserDataHook_Part");
4804 case MUIV_NListtree_FindUserDataHook_PartCaseInsensitive
:
4806 orgHook
= &_FindUserDataHook_PartCaseInsensitive
;
4807 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: MUIV_NListtree_FindUserDataHook_PartCaseInsensitive");
4811 case MUIV_NListtree_FindUserDataHook_PointerCompare
:
4813 orgHook
= &_FindUserDataHook_PointerCompare
;
4814 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: MUIV_NListtree_FindUserDataHook_PointerCompare");
4822 CopyMem( (APTR
)tag
->ti_Data
, data
->FindUserDataHook
, sizeof( struct Hook
) );
4824 D(DBF_GETSET
, "SET MUIA_NListtree_FindUserDataHook: 0x%08lx", tag
->ti_Data
);
4831 InitHook(data
->FindUserDataHook
, *orgHook
, data
);
4836 case MUIA_NListtree_Format
:
4841 ** If old data there, remove it.
4845 FreeVecPooled( data
->MemoryPool
, data
->Format
);
4846 data
->Format
= NULL
;
4850 ** Save raw list format.
4852 len
= strlen((STRPTR
)tag
->ti_Data
) + 1;
4854 if((data
->Format
= AllocVecPooled( data
->MemoryPool
, len
)))
4856 strlcpy( data
->Format
, (STRPTR
)tag
->ti_Data
, len
);
4859 nnset( data
->Obj
, MUIA_NList_Format
, data
->Format
);
4861 D(DBF_GETSET
, "SET MUIA_NListtree_Format: %s", (STRPTR
)tag
->ti_Data
);
4866 case MUIA_NListtree_MultiSelect
:
4868 data
->MultiSelect
= (UBYTE
)( tag
->ti_Data
& 0x00ff );
4871 if ( tag->ti_Data & MUIV_NListtree_MultiSelect_Flag_AutoSelectChilds )
4872 SET_FLAG(data->Flags, NLTF_AUTOSELECT_CHILDS);
4875 D(DBF_GETSET
, "SET MUIA_NListtree_MultiSelect: 0x%08lx", tag
->ti_Data
);
4879 case MUIA_NListtree_MultiTestHook
:
4881 data
->MultiTestHook
= (struct Hook
*)tag
->ti_Data
;
4883 D(DBF_GETSET
, "SET MUIA_NListtree_MultiTestHook: 0x%08lx", tag
->ti_Data
);
4887 case MUIA_NListtree_OpenHook
:
4889 data
->OpenHook
= (struct Hook
*)tag
->ti_Data
;
4891 D(DBF_GETSET
, "SET MUIA_NListtree_OpenHook: 0x%08lx", tag
->ti_Data
);
4895 case MUIA_NListtree_Quiet
:
4897 if ( !DoQuiet( data
, (BOOL
)tag
->ti_Data
) )
4899 if(isFlagSet(data
->Flags
, NLTF_REFRESH
))
4901 if(isFlagSet(data
->Flags
, NLTF_ISMCP
))
4904 CLEAR_FLAG(data
->Flags
, NLTF_REFRESH
);
4908 D(DBF_GETSET
, "SET MUIA_NListtree_Quiet: %ld - Counter = %ld", tag
->ti_Data
, data
->QuietCounter
);
4912 case MUICFG_NListtree_RememberStatus
:
4914 if ( (BOOL
)tag
->ti_Data
)
4915 SET_FLAG(data
->Flags
, NLTF_REMEMBER_STATUS
);
4917 CLEAR_FLAG(data
->Flags
, NLTF_REMEMBER_STATUS
);
4919 D(DBF_GETSET
, "SET MUICFG_NListtree_RememberStatus: %ld", tag
->ti_Data
);
4923 case MUIA_NListtree_Title
:
4926 SET_FLAG(data
->Flags
, NLTF_TITLE
);
4928 CLEAR_FLAG(data
->Flags
, NLTF_TITLE
);
4931 nnset( data
->Obj
, MUIA_NList_Title
, tag
->ti_Data
);
4933 D(DBF_GETSET
, "SET MUIA_NListtree_Title: %ld", tag
->ti_Data
);
4937 case MUIA_NListtree_TreeColumn
:
4939 data
->TreeColumn
= (UWORD
)( tag
->ti_Data
& 0x00ff );
4944 D(DBF_GETSET
, "SET MUIA_NListtree_TreeColumn: 0x%08lx", tag
->ti_Data
);
4948 case MUIA_NListtree_ShowTree
:
4950 if(tag
->ti_Data
== (ULONG
)MUIV_NListtree_ShowTree_Toggle
)
4952 if(isFlagSet(data
->Flags
, NLTF_NO_TREE
))
4953 CLEAR_FLAG(data
->Flags
, NLTF_NO_TREE
);
4955 SET_FLAG(data
->Flags
, NLTF_NO_TREE
);
4957 else if ( !tag
->ti_Data
)
4958 SET_FLAG(data
->Flags
, NLTF_NO_TREE
);
4960 CLEAR_FLAG(data
->Flags
, NLTF_NO_TREE
);
4965 D(DBF_GETSET
, "SET MUIA_NListtree_ShowTree: 0x%08lx", tag
->ti_Data
);
4969 case MUIA_NListtree_NoRootTree
:
4972 ** data->MRI is set in _Setup(). This makes sure, this tag is only
4973 ** used in the initial configuration.
4975 if ( tag
->ti_Data
&& !data
->MRI
)
4977 SET_FLAG(data
->Flags
, NLTF_NO_ROOT_TREE
);
4983 D(DBF_GETSET
, "SET attribute 0x%08lx to 0x%08lx", tag
->ti_Tag
, tag
->ti_Data
);
4990 static BOOL
GetAttributes( struct NListtree_Data
*data
, Msg msg
)
4992 IPTR
*store
= ( (struct opGet
*)msg
)->opg_Storage
;
4996 switch( ( (struct opGet
*)msg
)->opg_AttrID
)
4999 *store
= LIB_VERSION
;
5003 *store
= LIB_REVISION
;
5006 case MUIA_NListtree_Active
:
5008 *store
= (IPTR
)data
->ActiveNode
;
5009 D(DBF_GETSET
, "GET MUIA_NListtree_Active: 0x%08lx", *store
);
5012 case MUIA_NListtree_ActiveList
:
5014 if ( data
->ActiveList
== &data
->RootList
)
5015 *store
= (IPTR
)MUIV_NListtree_ActiveList_Off
;
5017 *store
= (IPTR
)data
->ActiveList
;
5018 D(DBF_GETSET
, "GET MUIA_NListtree_ActiveList: 0x%08lx",*store
);
5021 case MUIA_NListtree_DoubleClick
:
5023 *store
= (IPTR
)data
->LDClickColumn
;
5024 D(DBF_GETSET
, "GET MUIA_NListtree_DoubleClick: 0x%08lx", *store
);
5027 case MUIA_NListtree_TreeColumn
:
5029 *store
= (IPTR
)data
->TreeColumn
;
5030 D(DBF_GETSET
, "GET MUIA_NListtree_TreeColumn: 0x%08lx", *store
);
5033 case MUIA_NListtree_ShowTree
:
5035 *store
= (IPTR
)isFlagClear(data
->Flags
, NLTF_NO_TREE
);
5036 D(DBF_GETSET
, "GET MUIA_NListtree_ShowTree: 0x%08lx", *store
);
5039 case MUIA_NListtree_AutoVisible
:
5041 *store
= (IPTR
)data
->AutoVisible
;
5042 D(DBF_GETSET
, "GET MUIA_NListtree_AutoVisible: 0x%08lx", *store
);
5045 case MUIA_NListtree_DropType
:
5047 *store
= (IPTR
)data
->DropType
;
5050 case MUIA_NListtree_DropTarget
:
5052 *store
= (IPTR
)data
->DropTarget
;
5055 case MUIA_NListtree_DropTargetPos
:
5057 *store
= (IPTR
)data
->DropTargetPos
;
5060 case MUIA_NListtree_SelectChange
:
5062 D(DBF_GETSET
, "GET MUIA_NListtree_SelectChange");
5066 ** We ignore these tags ;-)
5068 case MUIA_NList_CompareHook
:
5069 case MUIA_NList_ConstructHook
:
5070 case MUIA_NList_DestructHook
:
5071 case MUIA_NList_DisplayHook
:
5072 case MUIA_NList_DragSortable
:
5073 case MUIA_NList_DropMark
:
5074 case MUIA_NList_Format
:
5075 case MUIA_NList_MinLineHeight
:
5076 case MUIA_NList_MultiTestHook
:
5077 case MUIA_NList_Pool
:
5078 case MUIA_NList_PoolPuddleSize
:
5079 case MUIA_NList_PoolThreshSize
:
5080 case MUIA_NList_ShowDropMarks
:
5081 case MUIA_NList_SourceArray
:
5082 case MUIA_NList_Title
:
5087 D(DBF_GETSET
, "GET 0x%08lx", ( (struct opGet
*)msg
)->opg_AttrID
);
5096 /*****************************************************************************\
5097 *******************************************************************************
5099 ** Standard class related functions.
5101 *******************************************************************************
5102 \*****************************************************************************/
5104 IPTR
_New(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
5106 struct NListtree_Data ld
;
5108 memset(&ld
, 0, sizeof(struct NListtree_Data
));
5111 ** Create new memory pool.
5113 #if defined(__amigaos4__)
5114 ld
.MemoryPool
= AllocSysObjectTags(ASOT_MEMPOOL
, ASOPOOL_MFlags
, MEMF_SHARED
|MEMF_CLEAR
,
5115 ASOPOOL_Puddle
, 16384,
5116 ASOPOOL_Threshold
, 8192,
5117 ASOPOOL_Name
, "NListtree.mcc pool",
5118 ASOPOOL_LockMem
, FALSE
,
5121 ld
.MemoryPool
= CreatePool(MEMF_CLEAR
, 16384, 8192);
5123 if(ld
.MemoryPool
!= NULL
)
5125 #if defined(__amigaos4__)
5126 ld
.TreePool
= AllocSysObjectTags(ASOT_MEMPOOL
, ASOPOOL_MFlags
, MEMF_SHARED
|MEMF_CLEAR
,
5127 ASOPOOL_Puddle
, 16384,
5128 ASOPOOL_Threshold
, 4096,
5129 ASOPOOL_Name
, "NListtree.mcc tree pool",
5130 ASOPOOL_LockMem
, FALSE
,
5133 ld
.TreePool
= CreatePool(MEMF_CLEAR
, 16384, 4096);
5135 if(ld
.TreePool
!= NULL
)
5138 ld
.ActiveNode
= CTN( MUIV_NListtree_Active_Off
);
5139 ld
.DoubleClick
= MUIV_NListtree_DoubleClick_All
;
5143 ** Default values!!!
5145 SET_FLAG(ld
.Flags
, NLTF_DUPNODENAMES
);
5146 SET_FLAG(ld
.Flags
, NLTF_OPENAUTOSCROLL
);
5147 SET_FLAG(ld
.Flags
, NLTF_DRAGDROPSORT
);
5148 ld
.AutoVisible
= MUIV_NListtree_AutoVisible_Normal
;
5150 /* data will be set below because we don't have the correct address yet...somebody really should rewrite this */
5151 InitHook(&ld
.IntCompareHook
, _CompareHook_LeavesBottom
, NULL
);
5153 SET_FLAG(ld
.Flags
, NLTF_INT_COMPAREHOOK
);
5155 SetAttributes( &ld
, msg
, TRUE
);
5158 ** If all hooks successfully installed, set up
5159 ** the class for use.
5162 ** Finally create the superclass.
5164 obj
= (Object
*)DoSuperNew( cl
, obj
,
5165 //$$$ MUIA_Listview_Input
5166 MUIA_NList_Input
, TRUE
,
5167 //$$$ MUIA_Listview_MultiSelect
5168 MUIA_NList_MultiSelect
, ld
.MultiSelect
,
5169 ( ld
.MultiSelect
!= 0 ) ? MUIA_NList_MultiTestHook
: TAG_IGNORE
, &NList_MultiTestHook
,
5170 //$$$ MUIA_Listview_DragType
5171 MUIA_NList_DragType
, isFlagSet(ld
.Flags
, NLTF_DRAGDROPSORT
) ? MUIV_NList_DragType_Default
: MUIV_NList_DragType_None
,
5172 MUIA_NList_DragSortable
, isFlagSet(ld
.Flags
, NLTF_DRAGDROPSORT
) ? TRUE
: FALSE
,
5173 MUIA_NList_ShowDropMarks
, isFlagSet(ld
.Flags
, NLTF_DRAGDROPSORT
) ? TRUE
: FALSE
,
5175 MUIA_NList_EntryValueDependent
, TRUE
,
5176 isFlagSet(ld
.Flags
, NLTF_TITLE
) ? MUIA_NList_Title
: TAG_IGNORE
, TRUE
,
5177 ld
.Format
? MUIA_NList_Format
: TAG_IGNORE
, ld
.Format
,
5178 //$$$ Not implemented
5179 MUIA_ContextMenu
, MUIV_NList_ContextMenu_Always
,
5180 TAG_MORE
, msg
->ops_AttrList
);
5184 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5185 struct Task
*mytask
;
5186 const char *taskname
;
5189 CopyMem( &ld
, data
, sizeof( struct NListtree_Data
) );
5191 data
->IntCompareHook
.h_Data
= data
; /* now we have the correct address of data */
5193 if(isFlagSet(data
->Flags
, NLTF_INT_COMPAREHOOK
))
5194 data
->CompareHook
= &data
->IntCompareHook
; /* and now we also have the correct address of the hook */
5196 DoSuperMethod(cl
, obj
, OM_GET
, MUIA_Version
, &ver
);
5197 DoSuperMethod(cl
, obj
, OM_GET
, MUIA_Revision
, &rev
);
5199 D(DBF_ALWAYS
, "NList version: %ld.%ld", ver
, rev
);
5201 mytask
= FindTask( NULL
);
5203 if ( mytask
->tc_Node
.ln_Name
)
5204 taskname
= mytask
->tc_Node
.ln_Name
;
5206 taskname
= "MUI Application";
5208 if ( ( ver
< 20 ) || ( ( ver
== 20 ) && ( rev
< 130 ) ) )
5210 struct EasyStruct es
;
5212 memset(&es
,0,sizeof(es
));
5213 es
.es_StructSize
= sizeof(struct EasyStruct
);
5214 es
.es_Title
= (STRPTR
)"Update information...";
5215 es
.es_TextFormat
= (STRPTR
)"NListtree.mcc has detected that your version of\n"
5216 "NList.mcc which is used by task `%s'\n"
5217 "is outdated (V%ld.%ld). Please update at least to\n"
5218 "version 20.130, which is available at\n\n"
5219 "http://www.sf.net/projects/nlist-classes\n\n"
5220 "NListtree will terminate now to avoid problems...\n";
5221 es
.es_GadgetFormat
= (STRPTR
)"Terminate";
5223 EasyRequest( NULL
, &es
, NULL
, (IPTR
)taskname
, ver
, rev
);
5225 //CoerceMethod( cl, obj, OM_DISPOSE );
5229 SET_FLAG(data
->Flags
, NLTF_NLIST_DIRECT_ENTRY_SUPPORT
);
5232 ** Save instance data in private NList data field.
5234 set( obj
, MUIA_UserData
, data
);
5237 ** Instance data is now valid. Here we set
5238 ** up the default hooks.
5240 if(!data
->FindNameHook
)
5242 data
->FindNameHook
= AllocVecPooled( data
->MemoryPool
, sizeof( struct Hook
) );
5244 InitHook(data
->FindNameHook
, _FindNameHook_CaseInsensitive
, data
);
5247 if ( !data
->FindUserDataHook
)
5249 data
->FindUserDataHook
= AllocVecPooled( data
->MemoryPool
, sizeof( struct Hook
) );
5251 InitHook(data
->FindUserDataHook
, _FindUserDataHook_CaseInsensitive
, data
);
5254 data
->buf
= AllocVecPooled( data
->MemoryPool
, DATA_BUF_SIZE
);
5258 ** Here we initialize the root list and setting
5259 ** some important values to it.
5261 NewList( (struct List
*)&data
->RootList
.ln_List
);
5263 data
->RootList
.ln_Parent
= NULL
;
5264 SET_FLAG(data
->RootList
.ln_Flags
, TNF_LIST
);
5265 SET_FLAG(data
->RootList
.ln_Flags
, TNF_OPEN
);
5266 SET_FLAG(data
->RootList
.ln_IFlags
, TNIF_VISIBLE
);
5267 SET_FLAG(data
->RootList
.ln_IFlags
, TNIF_ROOT
);
5269 // Initialize Selected-Table.
5270 data
->SelectedTable
.tb_Current
= -2;
5272 // check if removing MUI notifies is safe
5273 #if defined(__amigaos3__) || defined(__amigaos4__)
5274 if(LIB_VERSION_IS_AT_LEAST(MUIMasterBase
, 20, 5824))
5276 // MUI4 for AmigaOS is safe for V20.5824+
5277 SET_FLAG(data
->Flags
, NLTF_SAFE_NOTIFIES
);
5279 else if(LIB_VERSION_IS_AT_LEAST(MUIMasterBase
, 20, 2346) && LIBREV(MUIMasterBase
) < 5000)
5281 // MUI3.9 for AmigaOS is safe for V20.2346+
5282 SET_FLAG(data
->Flags
, NLTF_SAFE_NOTIFIES
);
5286 // MUI 3.8 and older version of MUI 3.9 or MUI4 are definitely unsafe
5287 CLEAR_FLAG(data
->Flags
, NLTF_SAFE_NOTIFIES
);
5290 // MorphOS and AROS must be considered unsafe unless someone from the
5291 // MorphOS/AROS team confirms that removing notifies in nested OM_SET
5293 CLEAR_FLAG(data
->Flags
, NLTF_SAFE_NOTIFIES
);
5296 // Setup spacial image class and tree image.
5297 if((data
->CL_TreeImage
= MUI_CreateCustomClass(NULL
, (STRPTR
)MUIC_Area
, NULL
, sizeof(struct TreeImage_Data
), ENTRY(TreeImage_Dispatcher
))))
5299 if((data
->CL_NodeImage
= MUI_CreateCustomClass(NULL
, (STRPTR
)MUIC_Image
, NULL
, sizeof(struct TreeImage_Data
), ENTRY(NodeImage_Dispatcher
))))
5301 ActivateNotify( data
);
5303 return( (IPTR
)obj
);
5310 CoerceMethod( cl
, obj
, OM_DISPOSE
);
5316 IPTR
_Dispose(struct IClass
*cl
, Object
*obj
, Msg msg
)
5318 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5320 struct MUI_CustomClass
*im1
, *im2
;
5321 APTR mempool
, treepool
;
5326 ** Clear complete list without setting a new active entry.
5328 DoMethod( obj
, MUIM_NListtree_Clear
, NULL
, 0 );
5330 im1
= data
->CL_TreeImage
;
5331 im2
= data
->CL_NodeImage
;
5332 mempool
= data
->MemoryPool
;
5333 treepool
= data
->TreePool
;
5335 ret
= DoSuperMethodA(cl
, obj
, msg
);
5337 if(treepool
!= NULL
)
5339 #if defined(__amigaos4__)
5340 FreeSysObject(ASOT_MEMPOOL
, treepool
);
5342 DeletePool(treepool
);
5348 #if defined(__amigaos4__)
5349 FreeSysObject(ASOT_MEMPOOL
, mempool
);
5351 DeletePool(mempool
);
5356 ** Delete special image classes.
5359 MUI_DeleteCustomClass( im1
);
5362 MUI_DeleteCustomClass( im2
);
5370 IPTR
_Set(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
5372 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5374 SetAttributes(data
, msg
, FALSE
);
5376 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
5380 IPTR
_Get(struct IClass
*cl
, Object
*obj
, Msg msg
)
5382 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5384 if(GetAttributes(data
, msg
) == TRUE
)
5387 return DoSuperMethodA(cl
, obj
, msg
);
5391 IPTR
_Setup(struct IClass
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
5393 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5394 Object
*pdobj
, *idobj
;
5400 if(!(DoSuperMethodA(cl
, obj
, (Msg
)msg
)))
5406 D(DBF_SETUP
, "Before: cl_SubclassCount = %ld, cl_ObjectCount = %ld", cl
->cl_SubclassCount
, cl
->cl_ObjectCount
);
5409 ** Obtain pens (render info is valid after Setup()!
5411 data
->MRI
= msg
->RenderInfo
;
5415 ** These values are used for drawing the lines.
5417 data
->Image
[IMAGE_Tree
].nltdata
= data
;
5418 data
->Image
[IMAGE_Tree
].Image
= NewObject( data
->CL_TreeImage
->mcc_Class
, NULL
, MUIA_FillArea
, FALSE
,
5419 MUIA_Frame
, MUIV_Frame_None
,
5420 MUIA_UserData
, &data
->Image
[IMAGE_Tree
],
5421 MUIA_InnerBottom
, 0,
5427 data
->Image
[IMAGE_Tree
].ListImage
= (Object
*)DoMethod( obj
, MUIM_NList_CreateImage
, data
->Image
[IMAGE_Tree
].Image
, 0L );
5429 data
->compositingActive
= 0;
5430 #if defined(__amigaos4__)
5431 // check whether compositing is enabled on our screen
5432 GetScreenAttrs(_screen(obj
), SA_Compositing
, &data
->compositingActive
, TAG_DONE
);
5436 ** Get and set image config.
5438 if(isFlagClear(data
->Flags
, NLTF_ISMCP
))
5441 ** Set up temporary objects.
5443 pdobj
= MUI_NewObject( MUIC_Pendisplay
, TAG_DONE
);
5444 idobj
= MUI_NewObject( MUIC_Imagedisplay
, TAG_DONE
);
5447 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_ImageSpecClosed
, &d
) )
5449 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Closed
);
5451 D(DBF_SETUP
, "C-Closed node image: '%s'", (STRPTR
)d
);
5455 set( idobj
, MUIA_Imagedisplay_Spec
, MUICFGV_NListtree_ImageSpecClosed_Default
);
5456 d
= xget( idobj
, MUIA_Imagedisplay_Spec
);
5458 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Closed
);
5460 D(DBF_SETUP
, "Closed node image: '%s'", (STRPTR
)d
);
5464 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_ImageSpecOpen
, &d
) )
5466 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Open
);
5468 D(DBF_SETUP
, "C-Open node image: '%s'", (STRPTR
)d
);
5472 set( idobj
, MUIA_Imagedisplay_Spec
, MUICFGV_NListtree_ImageSpecOpen_Default
);
5473 d
= xget( idobj
, MUIA_Imagedisplay_Spec
);
5475 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Open
);
5477 D(DBF_SETUP
, "Open node image: '%s'", (STRPTR
)d
);
5481 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_ImageSpecFolder
, &d
) )
5483 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Folder
);
5485 D(DBF_SETUP
, "C-Folder image: '%s'", (STRPTR
)d
);
5489 set( idobj
, MUIA_Imagedisplay_Spec
, MUICFGV_NListtree_ImageSpecFolder_Default
);
5490 d
= xget( idobj
, MUIA_Imagedisplay_Spec
);
5492 SetupImage( data
, (struct MUI_ImageSpec
*)d
, IMAGE_Folder
);
5494 D(DBF_SETUP
, "Folder image: '%s'", (STRPTR
)d
);
5498 ** Get and set line, shadow and draw pens
5500 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_PenSpecLines
, &d
) )
5501 ObtPen( data
->MRI
, &data
->Pen
[PEN_Line
], (struct MUI_PenSpec
*)d
);
5504 DoMethod( pdobj
, MUIM_Pendisplay_SetMUIPen
, MUICFGV_NListtree_PenSpecLines_Default
);
5505 ObtPen( data
->MRI
, &data
->Pen
[PEN_Line
], (struct MUI_PenSpec
*)xget( pdobj
, MUIA_Pendisplay_Spec
) );
5509 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_PenSpecShadow
, &d
) )
5510 ObtPen( data
->MRI
, &data
->Pen
[PEN_Shadow
], (struct MUI_PenSpec
*)d
);
5513 DoMethod( pdobj
, MUIM_Pendisplay_SetMUIPen
, MUICFGV_NListtree_PenSpecShadow_Default
);
5514 ObtPen( data
->MRI
, &data
->Pen
[PEN_Shadow
], (struct MUI_PenSpec
*)xget( pdobj
, MUIA_Pendisplay_Spec
) );
5518 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_PenSpecGlow
, &d
) )
5519 ObtPen( data
->MRI
, &data
->Pen
[PEN_Glow
], (struct MUI_PenSpec
*)d
);
5522 DoMethod( pdobj
, MUIM_Pendisplay_SetMUIPen
, MUICFGV_NListtree_PenSpecGlow_Default
);
5523 ObtPen( data
->MRI
, &data
->Pen
[PEN_Glow
], (struct MUI_PenSpec
*)xget( pdobj
, MUIA_Pendisplay_Spec
) );
5530 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_LineType
, &d
) )
5531 data
->LineType
= atoi( (STRPTR
)d
);
5533 data
->LineType
= MUICFGV_NListtree_LineType_Default
;
5536 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_IndentWidth
, &d
) )
5537 data
->IndentWidth
= atoi( (STRPTR
)d
);
5539 data
->IndentWidth
= MUICFGV_NListtree_IndentWidth_Default
;
5541 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_RememberStatus
, &d
) )
5542 x
= atoi( (STRPTR
)d
);
5544 x
= MUICFGV_NListtree_RememberStatus_Default
;
5547 SET_FLAG(data
->Flags
, NLTF_REMEMBER_STATUS
);
5549 CLEAR_FLAG(data
->Flags
, NLTF_REMEMBER_STATUS
);
5552 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_OpenAutoScroll
, &d
) )
5553 x
= atoi( (STRPTR
)d
);
5555 x
= MUICFGV_NListtree_OpenAutoScroll_Default
;
5558 SET_FLAG(data
->Flags
, NLTF_OPENAUTOSCROLL
);
5560 CLEAR_FLAG(data
->Flags
, NLTF_OPENAUTOSCROLL
);
5562 if ( DoMethod( obj
, MUIM_GetConfigItem
, MUICFG_NListtree_UseFolderImage
, &d
) )
5563 data
->UseFolderImage
= atoi( (STRPTR
)d
);
5565 data
->UseFolderImage
= MUICFGV_NListtree_UseFolderImage_Default
;
5569 ** Dispose temporary created objects.
5572 MUI_DisposeObject( pdobj
);
5575 MUI_DisposeObject( idobj
);
5579 D(DBF_SETUP
, "After: cl_SubclassCount = %ld, cl_ObjectCount = %ld", cl
->cl_SubclassCount
, cl
->cl_ObjectCount
);
5588 IPTR
_Cleanup(struct IClass
*cl
, Object
*obj
, Msg msg
)
5590 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5593 D(DBF_SETUP
, "Before: cl_SubclassCount = %ld, cl_ObjectCount = %ld", cl
->cl_SubclassCount
, cl
->cl_ObjectCount
);
5598 for( i
= 0; i
< 4; i
++ )
5599 DisposeImage( data
, i
);
5601 RelPen( data
->MRI
, &data
->Pen
[PEN_Line
] );
5602 RelPen( data
->MRI
, &data
->Pen
[PEN_Shadow
] );
5603 RelPen( data
->MRI
, &data
->Pen
[PEN_Glow
] );
5607 D(DBF_SETUP
, "After: cl_SubclassCount = %ld, cl_ObjectCount = %ld", cl
->cl_SubclassCount
, cl
->cl_ObjectCount
);
5609 return( DoSuperMethodA( cl
, obj
, msg
) );
5613 IPTR
_Show(struct IClass
*cl
, Object
*obj
, Msg msg
)
5615 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5617 if (!DoSuperMethodA( cl
, obj
, (Msg
)msg
))
5620 data
->EHNode
.ehn_Priority
= 2;
5621 data
->EHNode
.ehn_Flags
= 0;
5622 data
->EHNode
.ehn_Object
= obj
;
5623 data
->EHNode
.ehn_Class
= cl
;
5624 data
->EHNode
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
5625 DoMethod( _win( obj
), MUIM_Window_AddEventHandler
, &data
->EHNode
);
5631 IPTR
_Hide(struct IClass
*cl
, Object
*obj
, Msg msg
)
5633 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5635 DoMethod( _win( obj
), MUIM_Window_RemEventHandler
, &data
->EHNode
);
5637 return DoSuperMethodA(cl
, obj
, msg
);
5641 IPTR
_AskMinMax(struct IClass
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
5643 DoSuperMethodA( cl
, obj
, (Msg
)msg
);
5645 msg
->MinMaxInfo
->MinWidth
+= 20;
5646 msg
->MinMaxInfo
->DefWidth
+= 50;
5647 msg
->MinMaxInfo
->MaxWidth
+= MUI_MAXMAX
;
5649 msg
->MinMaxInfo
->MinHeight
+= 20;
5650 msg
->MinMaxInfo
->DefHeight
+= 50;
5651 msg
->MinMaxInfo
->MaxHeight
+= MUI_MAXMAX
;
5658 IPTR
_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
5660 return( DoSuperMethodA( cl
, obj
, (Msg
)msg
) );
5664 IPTR
_HandleEvent(struct IClass
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
5666 #define _between( a, x, b ) ( ( x ) >= ( a ) && ( x ) <= ( b ) )
5667 #define _isinobject( x, y ) ( _between( _mleft( obj ), ( x ), _mright( obj ) ) && _between( _mtop( obj ), ( y ), _mbottom( obj ) ) )
5668 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
5673 struct MUI_NListtree_TreeNode
*tn
;
5675 switch ( msg
->muikey
)
5679 BOOL changed
= FALSE
;
5681 if ( data
->ActiveNode
)
5683 if(isFlagSet(data
->ActiveNode
->tn_Flags
, TNF_LIST
) && isFlagSet(data
->ActiveNode
->tn_Flags
, TNF_OPEN
))
5685 DoMethod( obj
, MUIM_NListtree_Close
, MUIV_NListtree_Close_ListNode_Active
, MUIV_NListtree_Close_TreeNode_Active
, 0 );
5688 else if ( (IPTR
)GetParent( data
->ActiveNode
) != (IPTR
)&data
->RootList
)
5690 set( obj
, MUIA_NListtree_Active
, GetParent( data
->ActiveNode
) );
5696 set( obj
, MUIA_NListtree_Active
, MUIV_NListtree_Active_LastVisible
);
5701 ret
= MUI_EventHandlerRC_Eat
;
5707 BOOL changed
= FALSE
;
5709 if ( data
->ActiveNode
)
5711 if(isFlagSet(data
->ActiveNode
->tn_Flags
, TNF_LIST
))
5713 if(isFlagClear(data
->ActiveNode
->tn_Flags
, TNF_OPEN
))
5715 DoMethod( obj
, MUIM_NListtree_Open
, MUIV_NListtree_Open_ListNode_Active
, MUIV_NListtree_Open_TreeNode_Active
, 0 );
5718 else if((tn
= CTN(DoMethod(obj
, MUIM_NListtree_GetEntry
, data
->ActiveNode
, MUIV_NListtree_GetEntry_Position_Head
, 0))))
5720 if(xget(obj
, MUIA_NListtree_Active
) != (IPTR
)tn
)
5722 set( obj
, MUIA_NListtree_Active
, tn
);
5730 set( obj
, MUIA_NListtree_Active
, MUIV_NListtree_Active_FirstVisible
);
5735 ret
= MUI_EventHandlerRC_Eat
;
5756 ** We make this here, because the first act
5757 ** in the list tree may be selection.
5759 if(isFlagSet(msg
->imsg
->Qualifier
, IEQUALIFIER_LSHIFT
))
5761 SET_FLAG(data
->Flags
, NLTF_QUALIFIER_LSHIFT
);
5765 CLEAR_FLAG(data
->Flags
, NLTF_QUALIFIER_LSHIFT
);
5768 if(isFlagSet(msg
->imsg
->Qualifier
, IEQUALIFIER_CONTROL
))
5770 SET_FLAG(data
->Flags
, NLTF_QUALIFIER_CONTROL
);
5774 CLEAR_FLAG(data
->Flags
, NLTF_QUALIFIER_CONTROL
);
5777 mx
= msg
->imsg
->MouseX
;
5778 my
= msg
->imsg
->MouseY
;
5780 switch ( msg
->imsg
->Class
)
5782 case IDCMP_MOUSEBUTTONS
:
5784 D(DBF_INPUT
, "mousebutton");
5785 if ( _isinobject( mx
, my
) )
5787 struct MUI_NListtree_TreeNode
*tn
;
5788 struct MUI_NList_TestPos_Result tpres
;
5790 D(DBF_INPUT
, "inobject");
5792 switch( msg
->imsg
->Code
)
5797 ** Get pointer to the selected node.
5798 ** Set active node and list in global
5801 DoMethod( obj
, MUIM_NList_TestPos
, mx
, my
, &tpres
);
5803 if ( tpres
.entry
!= -1 )
5806 ** When user changed the column positions,
5807 ** we use this to avoid trouble.
5809 //$$$ Remove is List used
5810 tpres
.column
= DoMethod( obj
, MUIM_NList_ColumnToCol
, tpres
.column
);
5812 DoMethod( obj
, MUIM_NList_GetEntry
, tpres
.entry
, &tn
);
5815 ** Only react if node is not frozen.
5817 if(isFlagClear(tn
->tn_Flags
, TNF_FROZEN
))
5819 STATIC UWORD lastclickentry
= 0;
5822 ** If node is a list entry, open or close the node
5823 ** by simple click on the image depending on the
5826 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
) &&
5827 tpres
.column
== data
->TreeColumn
&&
5828 tpres
.xoffset
>= tn
->tn_ImagePos
&&
5829 tpres
.xoffset
<= tn
->tn_ImagePos
+ data
->MaxImageWidth
)
5832 ** Do not start dragging if user clicked on arrow-image.
5834 //SET_FLAG(data->Flags, NLTF_OVER_ARROW);
5835 //D(bug( "SETTING OVER_ARROW FLAG\n" ) );
5837 data
->OpenCloseEntry
= tn
;
5840 ** NList should do nothing in case of arrow-click
5841 ** with LSHIFT qualifier..
5843 if(isFlagSet(data
->Flags
, NLTF_QUALIFIER_LSHIFT
))
5844 ret
= MUI_EventHandlerRC_Eat
;
5848 ** We get the click time out of the intuimessage
5849 ** If double click, reset time values, if not, set values to current time.
5851 if(DoubleClick(data
->LDClickTimeSecs
, data
->LDClickTimeMicros
, msg
->imsg
->Seconds
, msg
->imsg
->Micros
) &&
5852 (tpres
.entry
== lastclickentry
))
5855 ** Do not start dragging if user double clicked on an entry.
5857 //SET_FLAG(data->Flags, NLTF_OVER_ARROW);
5858 //D(bug( "SETTING OVER_ARROW FLAG\n" ) );
5861 ** Double clicked!! Check what we have to do...
5863 if ( ( data
->DoubleClick
!= MUIV_NListtree_DoubleClick_Off
) && ( data
->DoubleClick
!= MUIV_NListtree_DoubleClick_NoTrigger
) )
5865 //D(bug( "DoubleClick: %ld, TreeColumn: %ld, tpres.column: %ld\n", data->DoubleClick, data->TreeColumn, tpres.column ) );
5867 if ( ( ( data
->DoubleClick
== MUIV_NListtree_DoubleClick_Tree
) && ( tpres
.column
== data
->TreeColumn
) ) ||
5868 ( data
->DoubleClick
== MUIV_NListtree_DoubleClick_All
) )
5870 data
->OpenCloseEntry
= tn
;
5872 data
->LDClickEntry
= tpres
.entry
;
5873 data
->LDClickColumn
= tpres
.column
;
5875 //D(bug( "Double click detected on node 0x%08lx\n", tn ) );
5880 data
->LDClickEntry
= -1;
5881 data
->LDClickColumn
= -1;
5884 data
->LDClickTimeSecs
= 0;
5885 data
->LDClickTimeMicros
= 0;
5889 data
->LDClickTimeSecs
= msg
->imsg
->Seconds
;
5890 data
->LDClickTimeMicros
= msg
->imsg
->Micros
;
5893 lastclickentry
= tpres
.entry
;
5902 ** Get pointer to the selected node.
5903 ** Set active node and list in global
5906 DoMethod( obj
, MUIM_NList_TestPos
, mx
, my
, &tpres
);
5908 if ( tpres
.entry
!= -1 )
5911 ** When user changed the column positions,
5912 ** we use this to avoid trouble.
5915 tpres
.column
= DoMethod( obj
, MUIM_NList_ColumnToCol
, tpres
.column
);
5917 DoMethod( obj
, MUIM_NList_GetEntry
, tpres
.entry
, &tn
);
5919 D(DBF_INPUT
, "Clicked on xoffset = %ld, col: %ld, impos = %ld, arrowwidth = %ld", tpres
.xoffset
, tpres
.column
, tn
->tn_ImagePos
, data
->MaxImageWidth
);
5921 if ( data
->OpenCloseEntry
)
5923 if(isFlagSet(data
->OpenCloseEntry
->tn_Flags
, TNF_OPEN
))
5924 DoMethod( obj
, MUIM_NListtree_Close
, GetParent( data
->OpenCloseEntry
), data
->OpenCloseEntry
, 0 );
5926 DoMethod( obj
, MUIM_NListtree_Open
, GetParent( data
->OpenCloseEntry
), data
->OpenCloseEntry
, 0 );
5928 data
->OpenCloseEntry
= NULL
;
5933 ** Delete over arrow flag when releasing mouse button.
5935 //CLEAR_FLAG(data->Flags, NLTF_OVER_ARROW);
5936 //D(bug( "RESETTING OVER_ARROW FLAG\n" ) );
5943 struct MUI_NList_TestPos_Result tpres;
5946 DoMethod( obj, MUIM_NList_TestPos, mx, my, &tpres );
5948 if ( tpres.entry != -1 )
5950 struct MUI_NListtree_TreeNode *tn;
5952 DoMethod( obj, MUIM_NList_GetEntry, tpres.entry, &tn );
5954 CurrentTime( &tv.Seconds, &tv.Microseconds );
5956 if ( DoubleClick( data->MDClickTime.Seconds, data->MDClickTime.Microseconds, tv.Seconds, tv.Microseconds ) &&
5957 ( tpres.entry == data->MDClickEntry ) )
5959 data->MDClickTime.Seconds = 0;
5960 data->MDClickTime.Microseconds = 0;
5961 data->MDClickEntry = -1;
5962 data->MDClickColumn = -1;
5966 data->MDClickTime.Seconds = tv.Seconds;
5967 data->MDClickTime.Microseconds = tv.Microseconds;
5968 data->MDClickEntry = tpres.entry;
5969 data->MDClickColumn = tpres.column;
5983 case IDCMP_MOUSEMOVE
:
5985 if ( _isinobject( mx
, my
) )
5993 #if defined(__amigaos3__)
5994 // with MUI 3.8 the superclass does not get this method, hence we must forward it ourself.
5995 if(ret
!= MUI_EventHandlerRC_Eat
&& MUIMasterBase
!= NULL
&& MUIMasterBase
->lib_Version
<= 19)
5996 ret
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
6005 IPTR
_DragNDrop_DragQuery(struct IClass
*cl
, Object
*obj
, Msg msg
)
6007 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6008 struct MUIP_DragQuery
*d
= (struct MUIP_DragQuery
*)msg
;
6015 //if(isFlagSet(data->Flags, NLTF_DRAGDROPSORT) && isFlagClear(data->Flags, NLTF_OVER_ARROW))
6016 if(isFlagSet(data
->Flags
, NLTF_DRAGDROPSORT
))
6018 RETURN(MUIV_DragQuery_Accept
);
6019 return MUIV_DragQuery_Accept
;
6023 RETURN(MUIV_DragQuery_Refuse
);
6024 return MUIV_DragQuery_Refuse
;
6028 result
= DoSuperMethodA(cl
, obj
, msg
);
6035 IPTR
_DragNDrop_DragBegin(struct IClass
*cl
, Object
*obj
, Msg msg
)
6037 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6043 ** If active entry is the only selected one, use it
6047 if ( !data->SelectedTable.tb_Entries )
6049 data->TempSelected = TreeNodeSelectAdd( data, data->ActiveNode );
6053 SET_FLAG(data
->Flags
, NLTF_DRAGDROP
);
6054 data
->OldDropTarget
= NULL
;
6056 result
= DoSuperMethodA(cl
, obj
, msg
);
6064 #define _between(a, x, b) ((x) >= (a) && (x) <= (b))
6067 #define _isinobject(x, y) (_between(_mleft(obj), (x), _mright(obj)) && _between(_mtop(obj), (y), _mbottom(obj)))
6069 IPTR
_DragNDrop_DragReport(struct IClass
*cl
, Object
*obj
, Msg msg
)
6071 struct MUIP_DragReport
*d
= (struct MUIP_DragReport
*)msg
;
6076 if(_isinobject(d
->x
, d
->y
))
6077 result
= DoSuperMethodA(cl
, obj
, msg
);
6079 result
= MUIV_DragReport_Abort
;
6086 IPTR
_DragNDrop_DropType(struct IClass
*cl
, Object
*obj
, struct MUIP_NList_DropType
*msg
)
6088 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6092 DoMethod(obj
, MUIM_NList_GetEntry
, *msg
->pos
, &data
->DropTarget
);
6094 data
->DropTargetPos
= *msg
->pos
;
6096 if(IsXChildOfListMember(data
->DropTarget
, &data
->SelectedTable
) == NULL
)
6098 if(msg
->mousey
<= msg
->miny
+ 2)
6100 *msg
->type
= MUIV_NListtree_DropType_Above
;
6102 else if(msg
->mousey
>= msg
->maxy
- 2)
6104 *msg
->type
= MUIV_NListtree_DropType_Below
;
6109 *msg
->type
= MUIV_NListtree_DropType_Onto
;
6114 *msg
->type
= MUIV_NListtree_DropType_None
;
6117 if(*msg
->type
== MUIV_NListtree_DropType_Onto
&& isFlagSet(data
->DropTarget
->tn_Flags
, TNF_LIST
))
6118 data
->DropType
= MUIV_NListtree_DropType_Sorted
;
6120 data
->DropType
= *msg
->type
;
6122 DoMethod(obj
, MUIM_NListtree_DropType
, &data
->DropTargetPos
, &data
->DropType
, msg
->minx
, msg
->maxx
, msg
->miny
, msg
->maxy
, msg
->mousex
, msg
->mousey
);
6124 if(*msg
->type
== MUIV_NListtree_DropType_Below
&& data
->DropType
!= MUIV_NListtree_DropType_Below
)
6127 if(data
->DropType
== MUIV_NListtree_DropType_Sorted
)
6128 *msg
->type
= MUIV_NListtree_DropType_Onto
;
6130 *msg
->type
= data
->DropType
;
6132 D(DBF_DRAGDROP
, "OPos: %ld, OType: %ld, Pos: %ld, Type: %ld", *msg
->pos
, *msg
->type
, data
->DropTargetPos
, data
->DropType
);
6134 if(isFlagSet(data
->DropTarget
->tn_Flags
, TNF_LIST
) && isFlagClear(data
->DropTarget
->tn_Flags
, TNF_OPEN
) && *msg
->type
== MUIV_NListtree_DropType_Onto
)
6136 // Make sure the screen is currently not locked because of the current DnD action.
6137 // Opening the node now might lead to a deadlock, because the redraw might require
6138 // another lock. However, OS4's MUI is able to perform lockless DnD actions on true
6140 if(data
->compositingActive
!= 0 && _screen(obj
)->LayerInfo
.Lock
.ss_Owner
== NULL
)
6142 // the current possible drop target is a closed list node
6143 if(data
->OldDropTarget
!= data
->DropTarget
)
6145 D(DBF_DRAGDROP
, "drop target changed, old='%s', new='%s'", data
->OldDropTarget
!= NULL
? data
->OldDropTarget
->tn_Name
: (STRPTR
)"NULL", data
->DropTarget
? data
->DropTarget
->tn_Name
: (STRPTR
)"NULL");
6146 // the possible drop target node has changed
6147 // remember the current time
6148 CurrentTime(&data
->OpenDropListSecs
, &data
->OpenDropListMicros
);
6152 // no target change and we can drop something on the node
6153 // now check if the desired delay has passed
6158 // get the current system time
6159 CurrentTime(&secs
, µs
);
6160 // calculate the difference to the last time
6161 diffSecs
= secs
- data
->OpenDropListSecs
;
6162 if(micros
< data
->OpenDropListMicros
)
6167 // open the node if the user held the mouse for at least one second
6168 // over the closed node
6171 D(DBF_DRAGDROP
, "drop target same since one second '%s'", data
->DropTarget
? data
->DropTarget
->tn_Name
: (STRPTR
)"NULL");
6172 // the time has passed, now open the list node
6173 DoMethod(obj
, MUIM_NListtree_Open
, GetParent(data
->DropTarget
), data
->DropTarget
, 0);
6174 // reset the start time
6175 data
->OpenDropListSecs
= secs
;
6176 data
->OpenDropListMicros
= micros
;
6182 data
->OldDropTarget
= data
->DropTarget
;
6189 IPTR
_DragNDrop_NDropDraw(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_DropDraw
*msg
)
6191 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6192 struct RastPort
*rp
= _rp( obj
);
6194 UWORD
*pens
= _pens( obj
);
6197 D(DBF_DRAGDROP, "OPos: %ld, OType: %ld, Pos: %ld, Type: %ld", msg->pos, msg->type,
6198 data->DropTargetPos, data->DropType);
6201 apen
= GetAPen( rp
);
6202 bpen
= GetBPen( rp
);
6204 MySetABPenDrMd( rp
, pens
[MPEN_SHINE
], pens
[MPEN_SHADOW
], JAM1
);
6205 SetDrPt( rp
, 0xF0F0 );
6207 switch ( data
->DropType
)
6209 case MUIV_NListtree_DropType_Above
:
6211 Move( rp
, msg
->MinX
, msg
->MinY
);
6212 Draw( rp
, msg
->MaxX
, msg
->MinY
);
6214 MySetABPenDrMd( rp
, MUIPEN( data
->Pen
[PEN_Shadow
] ), MUIPEN( data
->Pen
[PEN_Shadow
] ), JAM1
);
6215 SetDrPt( rp
, 0x0F0F );
6217 Move( rp
, msg
->MinX
, msg
->MinY
);
6218 Draw( rp
, msg
->MaxX
, msg
->MinY
);
6222 case MUIV_NListtree_DropType_Below
:
6223 Move( rp
, msg
->MinX
, msg
->MaxY
);
6224 Draw( rp
, msg
->MaxX
, msg
->MaxY
);
6226 Move( rp
, msg
->MinX
, msg
->MaxY
);
6227 Draw( rp
, msg
->MaxX
, msg
->MaxY
);
6229 MySetABPenDrMd( rp
, MUIPEN( data
->Pen
[PEN_Shadow
] ), MUIPEN( data
->Pen
[PEN_Shadow
] ), JAM1
);
6230 SetDrPt( rp
, 0x0F0F );
6232 Move( rp
, msg
->MinX
, msg
->MaxY
);
6233 Draw( rp
, msg
->MaxX
, msg
->MaxY
);
6235 Move( rp
, msg
->MinX
, msg
->MaxY
);
6236 Draw( rp
, msg
->MaxX
, msg
->MaxY
);
6239 case MUIV_NListtree_DropType_Onto
:
6240 case MUIV_NListtree_DropType_Sorted
:
6241 Move( rp
, msg
->MinX
, msg
->MinY
+ 1 );
6242 Draw( rp
, msg
->MaxX
, msg
->MinY
+ 1 );
6244 Move( rp
, msg
->MinX
, msg
->MaxY
- 1 );
6245 Draw( rp
, msg
->MaxX
, msg
->MaxY
- 1 );
6247 MySetABPenDrMd( rp
, MUIPEN( data
->Pen
[PEN_Shadow
] ), MUIPEN( data
->Pen
[PEN_Shadow
] ), JAM1
);
6248 SetDrPt( rp
, 0x0F0F );
6250 Move( rp
, msg
->MinX
, msg
->MinY
+ 1 );
6251 Draw( rp
, msg
->MaxX
, msg
->MinY
+ 1 );
6253 Move( rp
, msg
->MinX
, msg
->MaxY
- 1 );
6254 Draw( rp
, msg
->MaxX
, msg
->MaxY
- 1 );
6258 SetDrPt( rp
, (UWORD
)~0 );
6259 MySetABPenDrMd( rp
, apen
, bpen
, JAM1
);
6266 IPTR
_DragNDrop_DropDraw(struct IClass
*cl
, Object
*obj
, struct MUIP_NList_DropDraw
*msg
)
6268 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6269 struct MUI_NListtree_TreeNode
*drawtarget
;
6271 D(DBF_DRAGDROP
, "DropType: %ld, DropPos: %ld", msg
->type
, msg
->pos
);
6273 DoMethod( obj
, MUIM_NList_GetEntry
, msg
->pos
, &drawtarget
);
6275 DoMethod( obj
, MUIM_NListtree_DropDraw
, data
->DropTargetPos
, data
->DropType
, msg
->minx
+ drawtarget
->tn_ImagePos
, msg
->maxx
, msg
->miny
, msg
->maxy
);
6281 IPTR
_DragNDrop_DragFinish(struct IClass
*cl
, Object
*obj
, Msg msg
)
6283 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6288 CLEAR_FLAG(data
->Flags
, NLTF_DRAGDROP
);
6290 result
= DoSuperMethodA(cl
, obj
, msg
);
6297 IPTR
_DragNDrop_DragDrop(struct IClass
*cl
, Object
*obj
, UNUSED Msg msg
)
6299 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6300 struct MUI_NListtree_TreeNode
*tn
, *tn2
, *dtn
, *nexttn
= NULL
;
6301 struct MUI_NListtree_ListNode
*ln
= NULL
;
6303 dtn
= data
->DropTarget
;
6305 D(DBF_DRAGDROP
, "MUIM_DragDrop");
6307 if ( data
->SelectedTable
.tb_Entries
> 0 )
6309 struct MUI_NListtree_TreeNode
*rettn
;
6311 DoQuiet( data
, TRUE
);
6312 DeactivateNotify( data
);
6313 data
->IgnoreSelectionChange
= 1;
6315 tn
= (struct MUI_NListtree_TreeNode
*)MUIV_NListtree_NextSelected_Start
;
6319 DoMethod( obj
, MUIM_NListtree_NextSelected
, &tn
);
6321 if ( (IPTR
)tn
== (IPTR
)MUIV_NListtree_NextSelected_End
)
6324 if((rettn
= IsXChildOfListMemberNotSelf(tn
, &data
->SelectedTable
)))
6326 D(DBF_DRAGDROP
, "Entry 0x%08lx - %s already inserted through node 0x%08lx - %s", tn
, tn
->tn_Name
, rettn
, rettn
->tn_Name
);
6330 switch( data
->DropType
)
6332 case MUIV_NListtree_DropType_Above
:
6333 D(DBF_DRAGDROP
, "Inserting entry 0x%08lx - %s above L: %s, N: %s", tn
, tn
->tn_Name
, dtn
->tn_Parent
->tn_Name
, dtn
->tn_Name
);
6335 ln
= CLN( GetParent( dtn
) );
6337 if ( !( tn2
= CTN( GetPred( (struct Node
*)&dtn
->tn_Node
) ) ) )
6338 tn2
= CTN( MUIV_NListtree_Move_NewTreeNode_Head
);
6340 DoMethod( obj
, MUIM_NListtree_Move
, GetParent( tn
), tn
, ln
, tn2
, 0 );
6345 case MUIV_NListtree_DropType_Below
:
6346 D(DBF_DRAGDROP
, "Inserting entry 0x%08lx below L: 0x%lx, N: 0x%lx", tn
, dtn
->tn_Parent
, dtn
);
6350 if(isFlagSet(dtn
->tn_Flags
, TNF_LIST
) && isFlagSet(dtn
->tn_Flags
, TNF_OPEN
))
6353 tn2
= MUIV_NListtree_Move_NewTreeNode_Head
;
6357 ln
= CLN( GetParent( dtn
) );
6366 DoMethod( obj
, MUIM_NListtree_Move
, GetParent( tn
), tn
, ln
, tn2
, 0 );
6371 case MUIV_NListtree_DropType_Onto
:
6372 case MUIV_NListtree_DropType_Sorted
:
6373 D(DBF_DRAGDROP
, "Inserting entry 0x%08lx onto L: 0x%lx, N: 0x%lx", tn
, dtn
->tn_Parent
, dtn
);
6375 if(isFlagSet(dtn
->tn_Flags
, TNF_LIST
))
6378 ln
= CLN( GetParent( dtn
) );
6381 if ( data
->SelectedTable
.tb_Entries
== 1 )
6383 if(isFlagClear(dtn
->tn_Flags
, TNF_LIST
) && isFlagClear(tn
->tn_Flags
, TNF_LIST
))
6387 DoMethod( obj
, MUIM_NListtree_Exchange
, GetParent( tn
), tn
,
6392 if(isFlagSet(dtn
->tn_Flags
, TNF_LIST
))
6394 tn2
= CTN(MUIV_NListtree_Move_NewTreeNode_Sorted
);
6396 DoMethod( obj
, MUIM_NListtree_Move
, GetParent( tn
), tn
, ln
, tn2
, 0 );
6406 data
->IgnoreSelectionChange
= 0;
6407 ActivateNotify( data
);
6409 /* sba: the active node could be changed, but the notify calling was disabled */
6410 // data->ForceActiveNotify = 1;
6411 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
6413 DoQuiet( data
, FALSE
);
6417 ** If active entry moved, deselect him.
6420 if ( data->TempSelected )
6422 TreeNodeSelectRemove( data, data->TempSelected );
6423 data->TempSelected = NULL;
6427 CLEAR_FLAG(data
->Flags
, NLTF_DRAGDROP
);
6433 IPTR
_NList_Display(struct IClass
*cl
, Object
*obj
, struct MUIP_NList_Display
*msg
)
6435 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6436 struct MUI_NListtree_TreeNode
*tn
= CTN(msg
->entry
);
6439 if ( !strcmp( "comp", tn->tn_Name ) )
6443 // invoke the display method, this may be overridden by subclassed instances
6444 DoMethod(obj
, MUIM_NListtree_Display
, tn
, msg
->entry_pos
, msg
->strings
, msg
->preparses
);
6448 D(DBF_DRAW
, "render flags=%lx %s %s",tn
->tn_Flags
,isFlagSet(tn
->tn_Flags
, TNF_LIST
)?" list":"",msg
->strings
[1]);
6450 if(msg
->strings
[data
->TreeColumn
] == NULL
)
6452 msg
->strings
[data
->TreeColumn
] = tn
->tn_Name
;
6456 ** Reset image position. Will be updated inside DrawPos().
6458 tn
->tn_ImagePos
= 0;
6460 // NUL terminate the string
6461 data
->buf
[0] = '\0';
6462 if(isFlagClear(data
->Flags
, NLTF_NO_TREE
))
6463 DrawImages(tn
, tn
, data
, 0);
6465 if(msg
->preparses
[data
->TreeColumn
] != NULL
)
6466 strlcat(data
->buf
, msg
->preparses
[data
->TreeColumn
], DATA_BUF_SIZE
);
6468 strlcat(data
->buf
, msg
->strings
[data
->TreeColumn
], DATA_BUF_SIZE
);
6470 D(DBF_DRAW
, "%s - %s", isFlagSet(data
->Flags
, NLTF_QUIET
) ? "QUIET" : "RUN", data
->buf
);
6472 msg
->strings
[data
->TreeColumn
] = data
->buf
;
6479 IPTR
_NListtree_Construct(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Construct
*msg
)
6481 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6484 // we just fallback to the construct hook, if any is set
6485 if(data
->ConstructHook
!= NULL
)
6486 result
= (IPTR
)MyCallHook(data
->ConstructHook
, data
, MUIA_NListtree_ConstructHook
, msg
->Name
, msg
->UserData
, msg
->MemPool
, msg
->Flags
);
6488 result
= (IPTR
)msg
->UserData
;
6494 IPTR
_NListtree_Destruct(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Destruct
*msg
)
6496 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6498 if(data
->DestructHook
!= NULL
)
6499 MyCallHook(data
->DestructHook
, data
, MUIA_NListtree_DestructHook
, msg
->Name
, msg
->UserData
, msg
->MemPool
, msg
->Flags
);
6505 IPTR
_NListtree_Display(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Display
*msg
)
6507 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6509 // we just fallback to the display hook, if any is set
6510 if(data
->DisplayHook
!= NULL
)
6511 MyCallHook(data
->DisplayHook
, data
, MUIA_NListtree_DisplayHook
, msg
->TreeNode
, msg
->EntryPos
, msg
->Array
, msg
->Preparse
);
6513 msg
->Array
[data
->TreeColumn
] = NULL
;
6519 IPTR
_NListtree_Compare(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Compare
*msg
)
6521 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6524 // fall back to the compare hook if one is given, otherwise we assume node1 < node2
6525 if(data
->CompareHook
!= NULL
)
6526 cmp
= (LONG
)MyCallHook(data
->CompareHook
, data
, MUIA_NListtree_CompareHook
, msg
->TreeNode1
, msg
->TreeNode2
, 0);
6535 IPTR
_ContextMenuBuild(struct IClass
*cl
, Object
*obj
, struct MUIP_NList_ContextMenuBuild
*msg
)
6537 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6539 STATIC
struct NewMenu ContextMenu
[] =
6542 ** Type Label Key Flg MX UserData
6543 ** ======== =============================== === === === ==============
6545 { NM_TITLE
, (STRPTR
)"NListtree", 0, 0, 0, NULL
, },
6547 { NM_ITEM
, (STRPTR
)"Copy to clipboard", 0, 0, 0, NULL
, },
6549 { NM_SUB
, (STRPTR
)"Unit 0", 0, 0, 0, (APTR
)0, },
6550 { NM_SUB
, (STRPTR
)"Unit 1", 0, 0, 0, (APTR
)1, },
6551 { NM_SUB
, (STRPTR
)"Unit 2", 0, 0, 0, (APTR
)2, },
6552 { NM_SUB
, (STRPTR
)"Unit 3", 0, 0, 0, (APTR
)3, },
6554 { NM_END
, NULL
, 0, 0, 0, NULL
, }
6557 data
->MenuChoice
.pos
= msg
->pos
;
6558 data
->MenuChoice
.col
= msg
->column
;
6559 data
->MenuChoice
.ontop
= msg
->ontop
;
6562 return( (IPTR
)MUI_MakeObject( MUIO_MenustripNM
, ContextMenu
, 0 ) );
6564 return( DoSuperMethodA( cl
, obj
, (Msg
)msg
) );
6569 IPTR
_ContextMenuChoice(struct IClass
*cl
, Object
*obj
, struct MUIP_ContextMenuChoice
*msg
)
6571 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6572 struct MUI_NListtree_TreeNode
*tn
;
6574 if ( !data
->MenuChoice
.ontop
)
6576 DoMethod( obj
, MUIM_NList_GetEntry
, data
->MenuChoice
.pos
, &tn
);
6577 DoMethod( obj
, MUIM_NListtree_CopyToClip
, tn
, data
->MenuChoice
.pos
, muiUserData( msg
->item
) );
6583 return( DoSuperMethodA( cl
, obj
, (Msg
)msg
) );
6588 /*****************************************************************************\
6589 *******************************************************************************
6593 *******************************************************************************
6594 \*****************************************************************************/
6596 /****** NListtree.mcc/MUIM_NListtree_Open ***********************************
6600 * MUIM_NListtree_Open -- Open the specified tree node. (V1)
6605 * DoMethod(obj, MUIM_NListtree_Open,
6606 * struct MUI_NListtree_TreeNode *listnode,
6607 * struct MUI_NListtree_TreeNode *treenode,
6613 * Opens a node in the listtree. To open a child, which isn't displayed,
6614 * use 'MUIV_NListtree_Open_ListNode_Parent' to open all its parents, too.
6616 * Only nodes can be opened.
6621 * listnode - Specify the node which list is used to open the node.
6623 * MUIV_NListtree_Open_ListNode_Root
6624 * The root list is used.
6626 * MUIV_NListtree_Open_ListNode_Parent
6627 * Indicates, that all the parents of the node specified in
6628 * 'treenode' should be opened too.
6630 * MUIV_NListtree_Open_ListNode_Active
6631 * The list of the active node is used.
6633 * treenode - The node to open.
6635 * MUIV_NListtree_Open_TreeNode_Head
6636 * Opens the head node of the list.
6638 * MUIV_NListtree_Open_TreeNode_Tail
6639 * Opens the tail node of the list.
6641 * MUIV_NListtree_Open_TreeNode_Active
6642 * The active node will be opened.
6644 * MUIV_NListtree_Open_TreeNode_All:
6645 * All the nodes of the list are opened.
6651 * // Open the active list.
6652 * DoMethod(obj, MUIM_NListtree_Open,
6653 * MUIV_NListtree_Open_ListNode_Active,
6654 * MUIV_NListtree_Open_TreeNode_Active, 0);
6662 * MUIM_NListtree_Close
6665 ******************************************************************************
6668 IPTR
_NListtree_Open(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Open
*msg
)
6670 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6671 struct MUI_NListtree_TreeNode
*tn
, *tn2
;
6672 struct MUI_NListtree_ListNode
*ln
;
6673 BOOL openall
= FALSE
;
6675 //D(bug( "Node: 0x%08lx - 0x%08lx", msg->ListNode, msg->TreeNode ) );
6680 switch( (IPTR
)msg
->ListNode
)
6682 case MUIV_NListtree_Open_ListNode_Root
:
6683 ln
= &data
->RootList
;
6686 case MUIV_NListtree_Open_ListNode_Parent
:
6687 ln
= &data
->RootList
;
6690 case MUIV_NListtree_Open_ListNode_Active
:
6691 ln
= data
->ActiveList
;
6695 ln
= CLN( msg
->ListNode
);
6702 switch( (IPTR
)msg
->TreeNode
)
6704 case MUIV_NListtree_Open_TreeNode_Head
:
6705 tn
= CTN( GetHead( (struct List
*)&ln
->ln_List
) );
6708 case MUIV_NListtree_Open_TreeNode_Tail
:
6709 tn
= CTN( GetTail( (struct List
*)&ln
->ln_List
) );
6712 case MUIV_NListtree_Open_TreeNode_Active
:
6713 tn
= data
->ActiveNode
;
6716 case MUIV_NListtree_Open_TreeNode_All
:
6717 tn
= CTN( ln
); // *** Dummy for check below.
6728 ** Determine if the node holds a list
6729 ** and the node is not open.
6733 if(isFlagClear(tn
->tn_Flags
, TNF_LIST
))
6734 tn
= GetParentNotRoot( tn
);
6738 if((isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagClear(tn
->tn_Flags
, TNF_OPEN
)) || openall
)
6740 DeactivateNotify( data
);
6741 DoQuiet( data
, TRUE
);
6743 //D(bug( "Node: 0x%08lx - %s%s", tn, tn->tn_Name, openall ? " (expand)" : "" ) );
6746 OpenTreeNodeListExpand( data
, ln
);
6748 OpenTreeNode( data
, tn
);
6750 if ((IPTR
)msg
->ListNode
== (IPTR
)MUIV_NListtree_Open_ListNode_Parent
)
6754 while((tn2
= GetParentNotRoot(tn2
)))
6756 //D(bug( "Opening node: 0x%08lx - %s", tn2, tn2->tn_Name ) );
6758 OpenTreeNode( data
, tn2
);
6762 if(isFlagSet(data
->Flags
, NLTF_OPENAUTOSCROLL
) && !openall
)
6763 ShowTree( data
, tn
);
6765 DoQuiet( data
, FALSE
);
6766 ActivateNotify( data
);
6768 /* sba: the active note could be changed, but the notify calling was disabled */
6769 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
6779 /****** NListtree.mcc/MUIM_NListtree_Close ***********************************
6783 * MUIM_NListtree_Close -- Close the specified list node. (V1)
6788 * DoMethod(obj, MUIM_NListtree_Close,
6789 * struct MUI_NListtree_TreeNode *listnode,
6790 * struct MUI_NListtree_TreeNode *treenode,
6796 * Close a node or nodes of a listtree. It is checked if the tree node
6797 * is a node, not a leaf!
6799 * When the active entry was a child of the closed node, the closed node
6800 * will become active.
6805 * listnode - Specify the node which list is used to find the entry. The
6806 * search is started at the head of this list.
6808 * MUIV_NListtree_Close_ListNode_Root
6809 * The root list is used.
6811 * MUIV_NListtree_Close_ListNode_Parent
6812 * The list which is the parent of the active list is used.
6814 * MUIV_NListtree_Close_ListNode_Active
6815 * The list of the active node is used.
6818 * treenode - The node which should be closed. If there are children
6819 * of the node, they are also closed.
6821 * MUIV_NListtree_Close_TreeNode_Head
6822 * The head of the list defined in 'listnode' is closed.
6824 * MUIV_NListtree_Close_TreeNode_Tail:
6825 * Closes the tail of the list defined in 'listnode'.
6827 * MUIV_NListtree_Close_TreeNode_Active:
6828 * Closes the active node.
6830 * MUIV_NListtree_Close_TreeNode_All:
6831 * Closes all nodes of the list which is specified in
6839 * // Close the active list.
6840 * DoMethod(obj, MUIM_NListtree_Close,
6841 * MUIV_NListtree_Close_ListNode_Active,
6842 * MUIV_NListtree_Close_TreeNode_Active, 0);
6850 * MUIM_NListtree_Open
6853 ******************************************************************************
6856 IPTR
_NListtree_Close(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Close
*msg
)
6858 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
6859 struct MUI_NListtree_TreeNode
*tn
;
6860 struct MUI_NListtree_ListNode
*ln
;
6861 BOOL closeall
= FALSE
;
6866 switch( (IPTR
)msg
->ListNode
)
6868 case MUIV_NListtree_Close_ListNode_Root
:
6869 ln
= &data
->RootList
;
6872 case MUIV_NListtree_Close_ListNode_Parent
:
6873 ln
= CLN( data
->ActiveList
->ln_Parent
);
6876 case MUIV_NListtree_Close_ListNode_Active
:
6877 ln
= data
->ActiveList
;
6881 ln
= CLN( msg
->ListNode
);
6888 switch( (IPTR
)msg
->TreeNode
)
6890 case MUIV_NListtree_Close_TreeNode_Head
:
6891 tn
= CTN( GetHead( (struct List
*)&ln
->ln_List
) );
6894 case MUIV_NListtree_Close_TreeNode_Tail
:
6895 tn
= CTN( GetTail( (struct List
*)&ln
->ln_List
) );
6898 case MUIV_NListtree_Close_TreeNode_Active
:
6899 tn
= data
->ActiveNode
;
6902 case MUIV_NListtree_Close_TreeNode_All
:
6903 tn
= CTN( ln
); // *** Dummy for check below.
6914 ** Determine if the node holds a list
6915 ** and the node is not open.
6919 if((isFlagSet(tn
->tn_Flags
, TNF_LIST
) && isFlagSet(tn
->tn_Flags
, TNF_OPEN
)) || closeall
)
6921 struct MUI_NListtree_TreeNode
*temp
= data
->ActiveNode
;
6923 DeactivateNotify( data
);
6924 DoQuiet( data
, TRUE
);
6926 //D(bug( "Node: 0x%08lx - %s%s", tn, tn->tn_Name, closeall ? " (collapse)" : "" ) );
6932 CloseTreeNodeListCollapse( data
, ln
);
6936 if(isFlagSet(data
->Flags
, NLTF_REMEMBER_STATUS
))
6937 CloseTreeNode( data
, tn
);
6939 CloseTreeNodeCollapse( data
, tn
);
6942 DoQuiet( data
, FALSE
);
6943 ActivateNotify( data
);
6947 if(isFlagSet(temp
->tn_IFlags
, TNIF_VISIBLE
))
6948 set( obj
, MUIA_NListtree_Active
, temp
);
6950 set( obj
, MUIA_NListtree_Active
, tn
);
6960 /****** NListtree.mcc/MUIM_NListtree_Insert **********************************
6964 * MUIM_NListtree_Insert -- Insert an entry at the specified position. (V1)
6969 * struct MUI_NListtree_TreeNode *treenode =
6970 * DoMethod(obj, MUIM_NListtree_Insert,
6971 * STRPTR name, APTR userdata,
6972 * struct MUI_NListtree_TreeNode *listnode,
6973 * struct MUI_NListtree_TreeNode *prevtreenode,
6979 * Insert an entry at the position, which is defined in 'listnode'
6980 * and 'prevtreenode'. Name contains the name of the entry as string
6981 * which is buffered. The user entry can be used as you like.
6986 * name/userdata - What the names say ;-)
6989 * listnode - Specify the node which list is used to insert
6992 * MUIV_NListtree_Insert_ListNode_Root
6993 * Use the root list.
6995 * MUIV_NListtree_Insert_ListNode_Active
6996 * Use the list of the active node.
6998 * MUIV_NListtree_Insert_ListNode_ActiveFallback
6999 * Use the list of the active node. If no list is active,
7000 * an automatic fallback to the root list is done.
7002 * MUIV_NListtree_Insert_ListNode_LastInserted
7003 * Insert entry in the list the last entry was inserted.
7006 * prevtreenode - The node which is the predecessor of the node
7009 * MUIV_NListtree_Insert_PrevNode_Head
7010 * The entry will be inserted at the head of the list.
7012 * MUIV_NListtree_Insert_PrevNode_Tail
7013 * The entry will be inserted at the tail of the list.
7015 * MUIV_NListtree_Insert_PrevNode_Active
7016 * The entry will be inserted after the active node of
7017 * the list. If no entry is active, the entry will be
7018 * inserted at the tail.
7020 * MUIV_NListtree_Insert_PrevNode_Sorted:
7021 * The entry will be inserted using the defined sort hook.
7025 * MUIV_NListtree_Insert_Flag_Active
7026 * The inserted entry will be set to active. This means the
7027 * cursor is moved to the newly inserted entry. If the entry
7028 * was inserted into a closed node, it will be opened.
7030 * MUIV_NListtree_Insert_Flag_NextNode
7031 * 'prevtreenode' is the successor, not the predecessor.
7036 * A pointer to the newly inserted entry.
7041 * // Insert an entry after the active one and make it active.
7042 * DoMethod(obj, MUIM_NListtree_Insert, "Hello", NULL,
7043 * MUIV_NListtree_Insert_ListNode_Active,
7044 * MUIV_NListtree_Insert_PrevNode_Active,
7045 * MUIV_NListtree_Insert_Flag_Active);
7052 * Not implemented yet:
7053 * MUIV_NListtree_Insert_Flag_NextNode
7058 * MUIA_NListtree_ConstructHook, MUIA_NListtree_CompareHook
7061 ******************************************************************************
7064 IPTR
_NListtree_Insert(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Insert
*msg
)
7066 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
7067 struct MUI_NListtree_TreeNode
*tn
= NULL
;
7068 struct MUI_NListtree_ListNode
*ln
;
7070 static const char *np
= "*** NULL POINTER ***";
7072 D(DBF_LISTTREE
, "MUIM_NListtree_Insert: name=%s flags=0x%lx listnode:0x%lx prevnode:0x%lx %ld",msg
->Name
,msg
->Flags
,msg
->ListNode
,msg
->PrevNode
,data
->NumEntries
);
7075 ** Construct new user data
7077 user
= (APTR
)DoMethod(obj
, MUIM_NListtree_Construct
, msg
->Name
, msg
->User
, data
->TreePool
, 0);
7080 ** Allocate memory for the new entry and, if
7081 ** list, initialize list structure for use.
7083 if(isFlagSet(msg
->Flags
, TNF_LIST
))
7085 if((ln
= CLN(AllocVecPooled(data
->TreePool
, sizeof(struct MUI_NListtree_ListNode
)))))
7089 NewList( (struct List
*)&ln
->ln_List
);
7093 tn
= CTN( AllocVecPooled( data
->TreePool
, sizeof( struct MUI_NListtree_TreeNode
) ) );
7097 ** If allocated memory successfully, set up all fields,
7098 ** get special list and node pointers if needed and add
7103 struct MUI_NListtree_ListNode
*li
;
7106 msg
->Name
= (char *)np
;
7109 ** Should we duplicate the supplied node name?
7111 if(isFlagSet(data
->Flags
, NLTF_DUPNODENAMES
))
7113 int len
= strlen( msg
->Name
) + 1;
7114 tn
->tn_Name
= (STRPTR
)AllocVecPooled( data
->TreePool
, len
);
7115 strlcpy( tn
->tn_Name
, msg
->Name
, len
);
7116 SET_FLAG(tn
->tn_IFlags
, TNIF_ALLOCATED
);
7119 tn
->tn_Name
= msg
->Name
;
7124 tn
->tn_Flags
= msg
->Flags
;
7127 ** Check out which list to use.
7129 switch( (IPTR
)msg
->ListNode
)
7131 case MUIV_NListtree_Insert_ListNode_Root
:
7132 li
= &data
->RootList
;
7135 case MUIV_NListtree_Insert_ListNode_Active
:
7136 li
= data
->ActiveList
;
7139 case MUIV_NListtree_Insert_ListNode_ActiveFallback
:
7140 if ( !( li
= data
->ActiveList
) )
7141 li
= &data
->RootList
;
7144 case MUIV_NListtree_Insert_ListNode_LastInserted
:
7145 li
= data
->LastInsertedList
;
7149 li
= CLN( msg
->ListNode
);
7150 D(DBF_LISTTREE
, "li = %p",li
);
7156 struct MUI_NListtree_TreeNode
*in
;
7159 ** If given list node is not a list, get parent
7160 ** of the given node to avoid trouble.
7162 if(isFlagClear(li
->ln_Flags
, TNF_LIST
))
7163 li
= CLN( GetParent( CTN( li
) ) );
7165 data
->LastInsertedList
= li
;
7167 tn
->tn_Parent
= CTN( li
);
7169 //DoQuiet( data, TRUE );
7170 //DeactivateNotify( data );
7173 ** Add the new created entry to the specified list.
7175 switch( (IPTR
)msg
->PrevNode
)
7177 case MUIV_NListtree_Insert_PrevNode_Head
:
7178 AddHead( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
);
7179 in
= CTN( INSERT_POS_HEAD
);
7182 case MUIV_NListtree_Insert_PrevNode_Tail
:
7183 AddTail( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
);
7184 in
= CTN( INSERT_POS_TAIL
);
7187 case MUIV_NListtree_Insert_PrevNode_Active
:
7188 if ( data
->ActiveNode
)
7190 if ( (APTR
)li
!= (APTR
)data
->ActiveNode
)
7192 Insert( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
, (struct Node
*)&data
->ActiveNode
->tn_Node
);
7193 in
= data
->ActiveNode
;
7197 AddHead( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
);
7198 in
= CTN( INSERT_POS_HEAD
);
7203 AddTail( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
);
7204 in
= CTN( INSERT_POS_TAIL
);
7208 case MUIV_NListtree_Insert_PrevNode_Sorted
:
7209 in
= GetInsertNodeSorted( data
, li
, tn
);
7211 if ( (IPTR
)in
== (IPTR
)INSERT_POS_HEAD
)
7213 AddHead( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
);
7217 Insert( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
, (struct Node
*)&in
->tn_Node
);
7222 Insert( (struct List
*)&li
->ln_List
, (struct Node
*)&tn
->tn_Node
, (struct Node
*)&msg
->PrevNode
->tn_Node
);
7227 //D(bug( "Inserting entry 0x%08lx into list 0x%08lx (0x%08lx) after node 0x%08lx - '%s' User: 0x%08lx", tn, li, msg->ListNode, msg->PrevNode, ( (LONG)in == INSERT_POS_HEAD ) ? "HEAD" : ( (LONG)in == INSERT_POS_TAIL ) ? "TAIL" : in->tn_Name, msg->User ) );
7230 /* Special AmiTradeCenter Debug (Enforcer Hits!!)
7232 UBYTE *x = (UBYTE *)user + 28;
7233 UBYTE *lix = (UBYTE *)li->ln_User + 28;
7234 UBYTE *inx = (UBYTE *)in->tn_User + 28;
7236 char *name = (char *)x;
7237 char *liname = (char *)lix;
7238 char *inname = (char *)inx;
7240 D(bug( "Inserting '%s' into list '%s' after node '%s' at pos %ld (%s %s)\n",
7242 ( (LONG)msg->ListNode == MUIV_NListtree_Insert_ListNode_Root ) ? "ROOT" : ( (LONG)msg->ListNode == MUIV_NListtree_Insert_ListNode_Active ) ? "ACTIVE" : liname,
7243 ( (LONG)in == INSERT_POS_HEAD ) ? "HEAD" : ( (LONG)in == INSERT_POS_TAIL ) ? "TAIL" : inname,
7244 ( li->ln_Flags & TNF_OPEN ) ? GetVisualInsertPos( data, li, in ) : -1, ( tn->tn_Flags & TNF_OPEN ) ? "TNF_OPEN" : "", ( tn->tn_Flags & TNF_LIST ) ? "TNF_LIST" : "" ) );
7246 D(bug( "Inserting entry 0x%08lx - '%s' into list 0x%08lx (0x%08lx) - '%s' after node 0x%08lx (0x%08lx) - '%s'\n",
7247 tn, tn->tn_Name, li, msg->ListNode, li->ln_Name, in, msg->PrevNode, ( (LONG)in == INSERT_POS_HEAD ) ? "HEAD" : ( (LONG)in == INSERT_POS_TAIL ) ? "TAIL" : in->tn_Name ) );
7251 InsertTreeNodeVisible( data
, tn
, li
, in
);
7252 NLAddToTable( data
, &li
->ln_Table
, tn
);
7255 ** Make sure, that the inserted node is visible by opening
7256 ** all parents (if it should be set active).
7258 if(isFlagSet(msg
->Flags
, MUIV_NListtree_Insert_Flag_Active
))
7260 if(isFlagClear(tn
->tn_IFlags
, TNIF_VISIBLE
))
7261 DoMethod( obj
, MUIM_NListtree_Open
, MUIV_NListtree_Open_ListNode_Parent
, tn
, 0 );
7263 set( obj
, MUIA_NListtree_Active
, tn
);
7267 ** Add one to the global number of entries
7268 ** and the number of entries in list.
7273 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
7276 //ActivateNotify( data );
7277 //DoQuiet( data, FALSE );
7279 D(DBF_LISTTREE
, "Result: 0x%lx %ld",tn
,data
->NumEntries
);
7285 ** Free memory if failed to allocate
7288 FreeVecPooled( data
->TreePool
, tn
);
7292 DoMethod(obj
, MUIM_NListtree_Destruct
, msg
->Name
, user
, data
->TreePool
, 0);
7299 /****** NListtree.mcc/MUIM_NListtree_InsertStruct ****************************
7303 * MUIM_NListtree_InsertStruct -- Insert a structure such as a path
7304 * using a delimiter. (V1)
7309 * struct MUI_NListtree_TreeNode *treenode =
7310 * DoMethod(obj, MUIM_NListtree_InsertStruct,
7311 * STRPTR name, APTR userdata,
7312 * STRPTR delimiter, ULONG flags);
7317 * Insert a structure into the list such as a path or
7318 * something similar (like ListtreeName.mcc does). The name is
7319 * splitted using the supplied delimiter. For each name part a
7320 * new tree entry is generated. If you have Images/aphaso/Image.mbr,
7321 * the structure will be build es follows:
7327 * If a part of the structure is already present, it will be used to
7333 * name - Data containing (must not) one or more delimiters as
7334 * specified in delimiter (Images/aphaso/Image.mbr for
7337 * userdata - Your personal data.
7339 * delimiter - The delimiter(s) used in the name field (":/" or
7344 * Use normal insert flags here (see there).
7346 * In addition you can supply
7347 * MUIV_NListtree_InsertStruct_Flag_AllowDuplicates if you want the
7348 * last entry, Image.mbr in the above example, to occur multiple
7349 * times even if the name is the same.
7354 * A pointer to the last instance of newly inserted entries.
7359 * // Insert a directory path.
7360 * path = MyGetPath( lock );
7362 * DoMethod(obj, MUIM_NListtree_InsertStruct,
7363 * path, NULL, ":/", 0);
7372 * MUIA_NListtree_Insert
7375 ******************************************************************************
7379 ** Returns tokens delimited by delimiter on each call.
7381 INLINE STRPTR
mystrtok( STRPTR string
, STRPTR buf
, ULONG bufsize
, STRPTR delimiter
)
7395 strncpy( buf
, string
, MIN( (LONG
)bufsize
- 1, ( str
- string
) ) );
7396 buf
[MIN( (LONG
)bufsize
- 1, ( str
- string
) )] = 0;
7407 strncpy( buf
, string
, MIN( (LONG
)bufsize
- 1, ( str
- string
) ) );
7408 buf
[MIN( (LONG
)bufsize
- 1, ( str
- string
) )] = 0;
7415 IPTR
_NListtree_InsertStruct(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_InsertStruct
*msg
)
7417 struct MUI_NListtree_TreeNode
*temp
, *lasttn
= CTN( MUIV_NListtree_Insert_ListNode_Root
);
7418 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
7421 static const char *np
= "*** NULL POINTER ***";
7424 msg
->Name
= (char *)np
;
7426 if((token
= AllocVecPooled(data
->MemoryPool
, len
= (strlen(msg
->Name
) + 1))))
7432 p
= mystrtok( p
, token
, len
, msg
->Delimiter
);
7434 if ( ( !*p
&& isFlagSet(msg
->Flags
, MUIV_NListtree_InsertStruct_Flag_AllowDuplicates
) ) ||
7435 !( temp
= CTN( DoMethod( obj
, MUIM_NListtree_FindName
, lasttn
, token
, MUIV_NListtree_FindName_Flag_SameLevel
) ) ) )
7437 lasttn
= CTN( DoMethod( obj
, MUIM_NListtree_Insert
, token
, msg
->User
,
7438 lasttn
, MUIV_NListtree_Insert_PrevNode_Tail
, *p
? TNF_LIST
| msg
->Flags
: msg
->Flags
) );
7448 FreeVecPooled( data
->MemoryPool
, token
);
7451 return( (IPTR
)lasttn
);
7456 /****** NListtree.mcc/MUIM_NListtree_Remove **********************************
7460 * MUIM_NListtree_Remove -- Remove the specified entry(ies). (V1)
7465 * DoMethod(obj, MUIM_NListtree_Remove,
7466 * struct MUI_NListtree_TreeNode *listnode,
7467 * struct MUI_NListtree_TreeNode *treenode,
7473 * Removes a node or nodes from the listtree. When the active entry
7474 * is removed, the successor will become active.
7479 * listnode - Specify the node which list is used to find the entry
7480 * which should be removed. The search is started at the
7481 * begin of this list.
7483 * MUIV_NListtree_Remove_ListNode_Root
7484 * The root list is used.
7486 * MUIV_NListtree_Remove_ListNode_Active
7487 * The list of the active node is used.
7490 * treenode - The node which should be removed. If there are children
7491 * of this node, they are also removed.
7493 * MUIV_NListtree_Remove_TreeNode_Head
7494 * The head of the list defined in 'listnode' is removed.
7496 * MUIV_NListtree_Remove_TreeNode_Tail
7497 * The tail of the list defined in 'listnode' is removed.
7499 * MUIV_NListtree_Remove_TreeNode_Active
7500 * Removes the active node.
7502 * MUIV_NListtree_Remove_TreeNode_All
7503 * All nodes of the list which is specified in 'listnode',
7504 * are removed. Other nodes of parent lists are not
7507 * MUIV_NListtree_Remove_TreeNode_Selected
7508 * All selected nodes are removed.
7514 * // Remove the active entry if delete is pressed!
7515 * DoMethod(bt_delete, MUIM_Notify, MUIA_Pressed, FALSE,
7516 * lt_list, 4, MUIM_NListtree_Remove,
7517 * MUIV_NListtree_Remove_ListNode_Active,
7518 * MUIV_NListtree_Remove_TreeNode_Active, 0);
7527 * MUIM_NListtree_Insert, MUIA_NListtree_DestructHook,
7531 ******************************************************************************
7534 IPTR
_NListtree_Remove(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Remove
*msg
)
7536 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
7537 struct MUI_NListtree_ListNode
*li
;
7538 struct MUI_NListtree_TreeNode
*tn
;
7543 D(DBF_LISTTREE
, "NList Remove listnode: 0x%lx treenode: 0x%lx",msg
->ListNode
,msg
->TreeNode
);
7545 DeactivateNotify( data
);
7548 ** Removed, because of problems when deleting entries in a loop (all selected)
7550 //DoQuiet( data, TRUE );
7552 data
->TempActiveNode
= data
->ActiveNode
;
7557 switch( (IPTR
)msg
->ListNode
)
7559 case MUIV_NListtree_Remove_ListNode_Root
:
7560 li
= &data
->RootList
;
7563 case MUIV_NListtree_Remove_ListNode_Active
:
7564 li
= data
->ActiveList
;
7568 li
= CLN( msg
->ListNode
);
7577 switch( (IPTR
)msg
->TreeNode
)
7579 case MUIV_NListtree_Remove_TreeNode_Head
:
7580 tn
= CTN( GetHead( (struct List
*)&li
->ln_List
) );
7583 case MUIV_NListtree_Remove_TreeNode_Tail
:
7584 tn
= CTN( GetTail( (struct List
*)&li
->ln_List
) );
7587 case MUIV_NListtree_Remove_TreeNode_Active
:
7588 tn
= data
->ActiveNode
;
7591 case MUIV_NListtree_Remove_TreeNode_All
:
7593 pos
= GetVisualPos( data
, CTN( GetHead( (struct List
*)&li
->ln_List
) ) );
7595 // make sure we are quiet, and the selection change
7596 // is not propagated
7597 DoQuiet( data
, TRUE
);
7598 data
->IgnoreSelectionChange
= 1;
7600 while((tn
= CTN( GetHead((struct List
*)&li
->ln_List
))))
7601 RemoveNodes( data
, li
, tn
, pos
);
7603 // reactive selection list
7604 data
->IgnoreSelectionChange
= 0;
7605 DoQuiet(data
, FALSE
);
7611 case MUIV_NListtree_Remove_TreeNode_Selected
:
7613 if(data
->SelectedTable
.tb_Entries
> 0)
7615 // make sure we are quiet, and the selection change
7616 // is not propagated
7617 DoQuiet( data
, TRUE
);
7618 data
->IgnoreSelectionChange
= 1;
7622 tn
= data
->SelectedTable
.tb_Table
[0];
7623 pos
= GetVisualPos( data
, tn
);
7624 RemoveNodes( data
, CLN( tn
->tn_Parent
), tn
, pos
);
7626 while(data
->SelectedTable
.tb_Entries
> 0);
7628 // reactive selection list
7629 data
->IgnoreSelectionChange
= 0;
7631 if(data
->TempActiveNode
!= NULL
&&
7632 NLFindInTable(&data
->SelectedTable
, data
->TempActiveNode
) == -1)
7634 TreeNodeSelectAdd(data
, data
->TempActiveNode
);
7635 SET_FLAG(data
->TempActiveNode
->tn_Flags
, TNF_SELECTED
);
7637 MakeNotify(data
, MUIA_NListtree_SelectChange
, (APTR
)TRUE
);
7640 DoQuiet( data
, FALSE
);
7654 BOOL dorefresh
= FALSE
;
7656 pos
= GetVisualPos( data
, tn
);
7658 D(DBF_LISTTREE
, "Node: 0x%08lx - Name: %s - pos: %ld", tn
, tn
->tn_Name
, pos
);
7660 if(isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
7663 RemoveNodes( data
, li
, tn
, pos
);
7668 D(DBF_LISTTREE
, "Activenode: 0x%lx Trmpactivenode: 0x%lx",data
->ActiveNode
,data
->TempActiveNode
);
7670 /* sba: Notification is deactivated so we get not informed if the active node changed,
7671 ** do this by hand now
7673 if (data
->TempActiveNode
!= data
->ActiveNode
)
7675 nnset(data
->Obj
, MUIA_NListtree_Active
, data
->TempActiveNode
);
7676 data
->ForceActiveNotify
= 1;
7682 if(isFlagClear(msg->Flags, MUIV_NListtree_Remove_Flag_NoActive))
7684 if ( data->TempActiveNode == tn )
7685 data->TempActiveNode = NULL;
7687 D(bug( "Set Active node: 0x%8lx\n",data->TempActiveNode) );
7689 MakeSet( data, MUIA_NListtree_Active, data->TempActiveNode );
7691 if ( data->TempActiveNode && ( data->MultiSelect != MUIV_NListtree_MultiSelect_None ) )
7693 TreeNodeSelect( data, data->TempActiveNode, MUIV_NListtree_Select_On, 0, 0 );
7697 data
->TempActiveNode
= NULL
;
7700 ** Removed, because of problems when deleting entries in a loop (all selected)
7702 //DoQuiet( data, FALSE );
7703 ActivateNotify( data
);
7705 /* sba: the active note could be changed, but the notify calling was disabled */
7706 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
7714 /****** NListtree.mcc/MUIM_NListtree_Clear ***********************************
7718 * MUIM_NListtree_Clear -- Clear the complete listview. (V1)
7723 * DoMethod(obj, MUIM_NListtree_Clear, NULL, 0)
7728 * Clear the complete listview, calling destruct hook for each entry.
7737 * // Clear the listview!
7738 * DoMethod( nlisttree, MUIM_NListtree_Clear, NULL, 0 );
7743 * For now, when using this method, you MUST supply NULL for the list
7744 * node and 0 for flags for future compatibility.
7745 * This will definitely change!
7752 * MUIM_NListtree_Remove, MUIA_NListtree_DestructHook,
7755 ******************************************************************************
7758 IPTR
_NListtree_Clear(struct IClass
*cl
, Object
*obj
, UNUSED
struct MUIP_NListtree_Clear
*msg
)
7760 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
7761 struct MUI_NListtree_ListNode
*ln
= NULL
;
7765 ln
= &data
->RootList
;
7771 switch( (ULONG)msg->ListNode )
7773 case MUIV_NListtree_Clear_ListNode_Root:
7774 ln = &data->RootList;
7777 case MUIV_NListtree_Clear_ListNode_Active:
7778 ln = data->ActiveList;
7782 ln = CLN( msg->ListNode );
7791 ** Quick clear the NList object, call the destruct hook for
7792 ** each entry (QuickRemoveNodes()), delete the tree pool and
7793 ** allocate it new, reset the root list and delete the table
7794 ** memory pointer which refers to the old pool. Then initialize
7795 ** active node and list.
7797 DoMethod( obj
, MUIM_NList_Clear
, 0 );
7799 QuickRemoveNodes( data
, ln
);
7801 if(data
->TreePool
!= NULL
)
7803 #if defined(__amigaos4__)
7804 FreeSysObject(ASOT_MEMPOOL
, data
->TreePool
);
7806 DeletePool(data
->TreePool
);
7810 #if defined(__amigaos4__)
7811 data
->TreePool
= AllocSysObjectTags(ASOT_MEMPOOL
, ASOPOOL_MFlags
, MEMF_SHARED
|MEMF_CLEAR
,
7812 ASOPOOL_Puddle
, 16384,
7813 ASOPOOL_Threshold
, 4096,
7814 ASOPOOL_Name
, "NListtree.mcc tree pool",
7815 ASOPOOL_LockMem
, FALSE
,
7818 data
->TreePool
= CreatePool(MEMF_CLEAR
, 16384, 4096);
7821 NewList( (struct List
*)&data
->RootList
.ln_List
);
7822 data
->RootList
.ln_Table
.tb_Table
= NULL
;
7823 data
->RootList
.ln_Table
.tb_Entries
= 0;
7824 data
->RootList
.ln_Table
.tb_Size
= 0;
7825 data
->NumEntries
= 0;
7827 data
->ActiveNode
= MUIV_NListtree_Active_Off
;
7828 data
->ActiveList
= &data
->RootList
;
7838 /****** NListtree.mcc/MUIM_NListtree_Exchange ********************************
7842 * MUIM_NListtree_Exchange -- Exchanges two tree nodes. (V1)
7847 * DoMethod(obj, MUIM_NListtree_Exchange,
7848 * struct MUI_NListtree_TreeNode *listnode1,
7849 * struct MUI_NListtree_TreeNode *treenode1,
7850 * struct MUI_NListtree_TreeNode *listnode2,
7851 * struct MUI_NListtree_TreeNode *treenode2,
7857 * Exchange two tree nodes.
7862 * listnode1 - Specify the list node of the entry which
7863 * should be exchanged.
7865 * MUIV_NListtree_Exchange_ListNode1_Root
7866 * The root list is used.
7868 * MUIV_NListtree_Exchange_ListNode1_Active
7869 * The active list (the list of the active node) is used.
7871 * treenode1 - Specify the node which should be exchanged.
7873 * MUIV_NListtree_Exchange_TreeNode1_Head
7874 * The head of the list defined in 'listnode1' is
7877 * MUIV_NListtree_Exchange_TreeNode1_Tail
7878 * The tail of the list defined in 'listnode1' is
7881 * MUIV_NListtree_Exchange_TreeNode1_Active
7882 * The active node is exchanged.
7884 * listnode2 - Specify the second list node which is used for exchange.
7886 * MUIV_NListtree_Exchange_ListNode2_Root
7889 * MUIV_NListtree_Exchange_ListNode2_Active
7890 * The list of the active node.
7892 * treenode2 - This node is the second entry which is exchanged.
7894 * MUIV_NListtree_Exchange_TreeNode2_Head
7895 * The node 'treenode1' is exchanged with the head of the
7896 * list defined in 'listnode2'.
7898 * MUIV_NListtree_Exchange_TreeNode2_Tail
7899 * The node 'treenode1' is exchanged with the tail of the
7900 * list defined in 'ln2'.
7902 * MUIV_NListtree_Exchange_TreeNode2_Active:
7903 * The node 'treenode1' is exchanged with the active node.
7905 * MUIV_NListtree_Exchange_TreeNode2_Up:
7906 * The node 'treenode1' is exchanged with the entry
7907 * previous to the one specified in 'treenode1'.
7909 * MUIV_NListtree_Exchange_TreeNode2_Down:
7910 * The node 'treenode1' is exchanged with the entry next
7911 * (the successor) to the one specified in 'treenode1'.
7918 * // Exchange the active entry with the successor.
7920 * MUIV_NListtree_Exchange_ListNode1_Active,
7921 * MUIV_NListtree_Exchange_TreeNode1_Active,
7922 * MUIV_NListtree_Exchange_ListNode2_Active,
7923 * MUIV_NListtree_Exchange_TreeNode2_Down,
7933 * MUIM_NListtree_Move, MUIM_NListtree_Insert,
7934 * MUIM_NListtree_Remove
7937 ******************************************************************************
7940 IPTR
_NListtree_Exchange(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Exchange
*msg
)
7942 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
7943 struct MUI_NListtree_ListNode
*ln1
, *ln2
;
7944 struct MUI_NListtree_TreeNode
*tn1
, *tn2
;
7945 struct Node
*insnode1
, *insnode2
;
7949 ** Handle all special events.
7951 switch( (IPTR
)msg
->ListNode1
)
7953 case MUIV_NListtree_Exchange_ListNode1_Root
:
7954 ln1
= &data
->RootList
;
7957 case MUIV_NListtree_Exchange_ListNode1_Active
:
7958 ln1
= data
->ActiveList
;
7962 ln1
= CLN( msg
->ListNode1
);
7966 switch( (IPTR
)msg
->TreeNode1
)
7968 case MUIV_NListtree_Exchange_TreeNode1_Head
:
7969 tn1
= CTN( GetHead( (struct List
*)&ln1
->ln_List
) );
7972 case MUIV_NListtree_Exchange_TreeNode1_Tail
:
7973 tn1
= CTN( GetTail( (struct List
*)&ln1
->ln_List
) );
7976 case MUIV_NListtree_Exchange_TreeNode1_Active
:
7977 tn1
= data
->ActiveNode
;
7981 tn1
= msg
->TreeNode1
;
7985 switch( (IPTR
)msg
->ListNode2
)
7987 case MUIV_NListtree_Exchange_ListNode2_Root
:
7988 ln2
= &data
->RootList
;
7991 case MUIV_NListtree_Exchange_ListNode2_Active
:
7992 ln2
= data
->ActiveList
;
7996 ln2
= CLN( msg
->ListNode2
);
8000 switch( (IPTR
)msg
->TreeNode2
)
8002 case MUIV_NListtree_Exchange_TreeNode2_Head
:
8003 tn2
= CTN( GetHead( (struct List
*)&ln1
->ln_List
) );
8006 case MUIV_NListtree_Exchange_TreeNode2_Tail
:
8007 tn2
= CTN( GetTail( (struct List
*)&ln1
->ln_List
) );
8010 case MUIV_NListtree_Exchange_TreeNode2_Active
:
8011 tn2
= data
->ActiveNode
;
8014 case MUIV_NListtree_Exchange_TreeNode2_Up
:
8015 if ( !( tn2
= CTN( GetPred( (struct Node
*)&tn1
->tn_Node
) ) ) )
8016 tn2
= CTN( tn1
->tn_Node
.mln_Pred
);
8019 case MUIV_NListtree_Exchange_TreeNode2_Down
:
8020 if ( !( tn2
= CTN( GetSucc( (struct Node
*)&tn1
->tn_Node
) ) ) )
8021 tn2
= CTN( tn1
->tn_Node
.mln_Succ
);
8025 tn2
= msg
->TreeNode2
;
8032 DoQuiet( data
, TRUE
);
8035 ** Get the nodes where to re-insert the removed nodes.
8036 ** If no previsous node available, then Insert() assumes
8037 ** AddHead() when "insnodeX" is NULL.
8039 insnode1
= GetPred( (struct Node
*)tn1
);
8040 insnode2
= GetPred( (struct Node
*)tn2
);
8042 if ( insnode1
== (struct Node
*)tn2
)
8043 insnode1
= GetPred( insnode1
);
8045 if ( insnode2
== (struct Node
*)tn1
)
8046 insnode2
= GetPred( insnode2
);
8048 //D(bug( "Node1: 0x%08lx - %s, Node2: 0x%08lx - %s", tn1, tn1->tn_Name, tn2, tn2->tn_Name ) );
8053 NLRemoveFromTable( data
, &ln1
->ln_Table
, tn1
);
8054 RemoveTreeNodeVisible( data
, tn1
, &pos1
);
8055 Remove( (struct Node
*)&tn1
->tn_Node
);
8060 NLRemoveFromTable( data
, &ln2
->ln_Table
, tn2
);
8061 RemoveTreeNodeVisible( data
, tn2
, &pos2
);
8062 Remove( (struct Node
*)&tn2
->tn_Node
);
8066 ** Set new parent entries and visibility.
8068 tn1
->tn_Parent
= CTN( ln2
);
8069 tn2
->tn_Parent
= CTN( ln1
);
8072 ** Insert first entry in the list.
8076 AddHead( (struct List
*)&ln2
->ln_List
, (struct Node
*)tn1
);
8077 InsertTreeNodeVisible( data
, tn1
, ln2
, CTN( INSERT_POS_HEAD
) );
8078 NLAddToTable( data
, &ln2
->ln_Table
, tn1
);
8082 Insert( (struct List
*)&ln2
->ln_List
, (struct Node
*)tn1
, insnode2
);
8083 InsertTreeNodeVisible( data
, tn1
, ln2
, CTN( insnode2
) );
8084 NLAddToTable( data
, &ln2
->ln_Table
, tn1
);
8088 ** Insert second entry in the list.
8092 if ( !insnode2
&& ( pos1
> pos2
) )
8094 Insert( (struct List
*)&ln1
->ln_List
, (struct Node
*)tn2
, (struct Node
*)tn1
);
8095 InsertTreeNodeVisible( data
, tn2
, ln1
, tn1
);
8096 NLAddToTable( data
, &ln1
->ln_Table
, tn2
);
8100 AddHead( (struct List
*)&ln1
->ln_List
, (struct Node
*)tn2
);
8101 InsertTreeNodeVisible( data
, tn2
, ln1
, CTN( INSERT_POS_HEAD
) );
8102 NLAddToTable( data
, &ln1
->ln_Table
, tn2
);
8107 Insert( (struct List
*)&ln1
->ln_List
, (struct Node
*)tn2
, insnode1
);
8108 InsertTreeNodeVisible( data
, tn2
, ln1
, CTN( insnode1
) );
8109 NLAddToTable( data
, &ln1
->ln_Table
, tn2
);
8114 if ( tn1
== data
->ActiveNode
)
8115 nnset( obj
, MUIA_NListtree_Active
, tn1
);
8116 else if ( tn2
== data
->ActiveNode
)
8117 nnset( obj
, MUIA_NListtree_Active
, tn2
);
8119 DoQuiet( data
, FALSE
);
8127 /****** NListtree.mcc/MUIM_NListtree_Move ************************************
8131 * MUIM_NListtree_Move -- Move an entry to the specified position. (V1)
8136 * DoMethod(obj, MUIM_NListtree_Move,
8137 * struct MUI_NListtree_TreeNode *oldlistnode,
8138 * struct MUI_NListtree_TreeNode *oldtreenode,
8139 * struct MUI_NListtree_TreeNode *newlistnode,
8140 * struct MUI_NListtree_TreeNode *newtreenode,
8146 * Move an entry to the position after a defined node.
8151 * oldlistnode - Specify the node which list is used to find the
8152 * entry. The search is started at the head of this
8155 * MUIV_NListtree_Move_OldListNode_Root
8156 * The root list is used as the starting point.
8158 * MUIV_NListtree_Move_OldListNode_Active
8159 * The active list (the list of the active node) is used as
8160 * the starting point.
8162 * oldtreenode - Specify the node which should be moved.
8164 * MUIV_NListtree_Move_OldTreeNode_Head
8165 * The head of the list defined in 'oldlistnode' is moved.
8167 * MUIV_NListtree_Move_OldTreeNode_Tail
8168 * The tail of the list defined in 'oldlistnode' is moved.
8170 * MUIV_NListtree_Move_OldTreeNode_Active
8171 * The active node is moved.
8173 * newlistnode - Specify the node which list is used to find the
8174 * entry. The search is started at the head of this
8177 * MUIV_NListtree_Move_NewListNode_Root
8180 * MUIV_NListtree_Move_NewListNode_Active
8181 * The list of the active node.
8183 * newtreenode - This node is the predecessor of the entry which is
8186 * MUIV_NListtree_Move_NewTreeNode_Head
8187 * The node is moved to the head of the list defined in
8190 * MUIV_NListtree_Move_NewTreeNode_Tail
8191 * The node is moved to the tail of the list defined in
8194 * MUIV_NListtree_Move_NewTreeNode_Active:
8195 * The node is moved to one entry after the active node.
8197 * MUIV_NListtree_Move_NewTreeNode_Sorted:
8198 * The node is moved to the list using the sort hook.
8200 * flags - Some flags to adjust moving.
8202 * MUIV_NListtree_Move_Flag_KeepStructure
8203 * The full tree structure from the selected entry to
8204 * the root list is moved (created at destination).
8211 * // Move an entry to the head of another list-node.
8213 * MUIV_NListtree_Move_OldListNode_Active,
8214 * MUIV_NListtree_Move_OldTreeNode_Active,
8216 * MUIV_NListtree_Move_NewTreeNode_Head,
8226 * MUIM_NListtree_Insert, MUIM_NListtree_Remove,
8227 * MUIM_NListtree_Exchange, MUIA_NListtree_CompareHook,
8228 * MUIM_NListtree_Copy
8230 ******************************************************************************
8233 IPTR
_NListtree_Move(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Move
*msg
)
8235 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
8236 struct MUI_NListtree_ListNode
*ln1
, *ln2
;
8237 struct MUI_NListtree_TreeNode
*tn1
, *tn2
;
8239 D(DBF_LISTTREE
, "MUIM_NListtree_Move");
8242 ** Handle all special events.
8244 switch( (IPTR
)msg
->OldListNode
)
8246 case MUIV_NListtree_Move_OldListNode_Root
:
8247 ln1
= &data
->RootList
;
8250 case MUIV_NListtree_Move_OldListNode_Active
:
8251 ln1
= data
->ActiveList
;
8255 ln1
= CLN( msg
->OldListNode
);
8259 switch( (IPTR
)msg
->OldTreeNode
)
8261 case MUIV_NListtree_Move_OldTreeNode_Head
:
8262 tn1
= CTN( GetHead( (struct List
*)&ln1
->ln_List
) );
8265 case MUIV_NListtree_Move_OldTreeNode_Tail
:
8266 tn1
= CTN( GetTail( (struct List
*)&ln1
->ln_List
) );
8269 case MUIV_NListtree_Move_OldTreeNode_Active
:
8270 tn1
= data
->ActiveNode
;
8274 tn1
= msg
->OldTreeNode
;
8278 switch( (IPTR
)msg
->NewListNode
)
8280 case MUIV_NListtree_Move_NewListNode_Root
:
8281 ln2
= &data
->RootList
;
8284 case MUIV_NListtree_Move_NewListNode_Active
:
8285 ln2
= data
->ActiveList
;
8289 ln2
= CLN( msg
->NewListNode
);
8293 switch( (IPTR
)msg
->NewTreeNode
)
8295 case MUIV_NListtree_Move_NewTreeNode_Head
:
8296 tn2
= CTN( INSERT_POS_HEAD
);
8299 case MUIV_NListtree_Move_NewTreeNode_Tail
:
8300 tn2
= CTN( INSERT_POS_TAIL
);
8303 case MUIV_NListtree_Move_NewTreeNode_Active
:
8304 tn2
= data
->ActiveNode
;
8307 case MUIV_NListtree_Move_NewTreeNode_Sorted
:
8308 tn2
= GetInsertNodeSorted( data
, ln2
, tn1
);
8312 tn2
= msg
->NewTreeNode
;
8319 DoQuiet( data
, TRUE
);
8321 //D(bug( "1: L: %s, N: %s - 2: L: %s, N: %s\n", ln1->ln_Name, tn1->tn_Name, ln2->ln_Name, ( (ULONG)tn2 == INSERT_POS_TAIL ) ? "TAIL" : ( (ULONG)tn2 == INSERT_POS_HEAD ) ? "HEAD" : tn2->tn_Name ) );
8324 ** Remove the entry visible and from list.
8326 NLRemoveFromTable( data
, &ln1
->ln_Table
, tn1
);
8327 RemoveTreeNodeVisible( data
, tn1
, NULL
);
8328 Remove( (struct Node
*)&tn1
->tn_Node
);
8332 ** Create structure identical to source.
8334 if(isFlagSet(msg
->Flags
, MUIV_NListtree_Move_Flag_KeepStructure
))
8336 tn1
= CTN( CreateParentStructure( data
, msg
->MethodID
, &ln2
, &tn2
, tn1
, 0 ) );
8342 ** Insert entry into list.
8344 InsertTreeNode( data
, ln2
, tn1
, tn2
);
8349 if ( tn1
== data
->ActiveNode
)
8350 nnset( obj
, MUIA_NListtree_Active
, tn1
);
8352 DoQuiet( data
, FALSE
);
8355 D(DBF_LISTTREE
, "MUIM_NListtree_Move End");
8362 /****** NListtree.mcc/MUIM_NListtree_Copy ************************************
8366 * MUIM_NListtree_Copy -- Copy an entry (create it) to the spec. pos. (V1)
8371 * DoMethod(obj, MUIM_NListtree_Copy,
8372 * struct MUI_NListtree_TreeNode *srclistnode,
8373 * struct MUI_NListtree_TreeNode *srctreenode,
8374 * struct MUI_NListtree_TreeNode *destlistnode,
8375 * struct MUI_NListtree_TreeNode *desttreenode,
8381 * Copy an entry to the position after a defined node. The complete
8382 * child structure will be copied.
8387 * srclistnode - Specify the node which list is used to find the
8388 * entry. The search is started at the head of this
8391 * MUIV_NListtree_Copy_SourceListNode_Root
8392 * The root list is used as the starting point.
8394 * MUIV_NListtree_Copy_SourceListNode_Active
8395 * The active list (the list of the active node) is used as
8396 * the starting point.
8398 * srctreenode - Specifies the node which should be copied.
8400 * MUIV_NListtree_Copy_SourceTreeNode_Head
8401 * The head of the list defined in 'srclistnode' is copied.
8403 * MUIV_NListtree_Copy_SourceTreeNode_Tail
8404 * The tail of the list defined in 'srclistnode' is copied.
8406 * MUIV_NListtree_Copy_SourceTreeNode_Active
8407 * The active node is copied.
8409 * destlistnode - Specify the node which list is used to find the
8410 * entry. The search is started at the head of this
8413 * MUIV_NListtree_Copy_DestListNode_Root
8416 * MUIV_NListtree_Copy_DestListNode_Active
8417 * The list of the active node.
8419 * desttreenode - This node is the predecessor of the entry which is
8422 * MUIV_NListtree_Copy_DestTreeNode_Head
8423 * The node is copied to the head of the list defined in
8426 * MUIV_NListtree_Copy_DestTreeNode_Tail
8427 * The node is copied to the tail of the list defined in
8430 * MUIV_NListtree_Copy_DestTreeNode_Active:
8431 * The node is copied to one entry after the active node.
8433 * MUIV_NListtree_Copy_DestTreeNode_Sorted:
8434 * The node is copied to the list using the sort hook.
8436 * flags - Some flags to adjust moving.
8438 * MUIV_NListtree_Copy_Flag_KeepStructure
8439 * The full tree structure from the selected entry to
8440 * the root list is copied (created) at destination.
8447 * // Copy the active entry to the head of
8448 * // another list node.
8450 * MUIV_NListtree_Copy_SourceListNode_Active,
8451 * MUIV_NListtree_Copy_SourceTreeNode_Active,
8453 * MUIV_NListtree_Copy_DestTreeNode_Head,
8463 * MUIM_NListtree_Insert, MUIM_NListtree_Remove,
8464 * MUIM_NListtree_Exchange, MUIA_NListtree_CompareHook,
8465 * MUIM_NListtree_Move
8468 ******************************************************************************
8471 IPTR
_NListtree_Copy(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Copy
*msg
)
8473 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
8474 struct MUI_NListtree_ListNode
*ln1
, *ln2
;
8475 struct MUI_NListtree_TreeNode
*tn1
, *tn2
;
8479 ** Handle all special events.
8481 switch( (IPTR
)msg
->SourceListNode
)
8483 case MUIV_NListtree_Copy_SourceListNode_Root
:
8484 ln1
= &data
->RootList
;
8487 case MUIV_NListtree_Copy_SourceListNode_Active
:
8488 ln1
= data
->ActiveList
;
8492 ln1
= CLN( msg
->SourceListNode
);
8496 switch( (IPTR
)msg
->SourceTreeNode
)
8498 case MUIV_NListtree_Copy_SourceTreeNode_Head
:
8499 tn1
= CTN( GetHead( (struct List
*)&ln1
->ln_List
) );
8502 case MUIV_NListtree_Copy_SourceTreeNode_Tail
:
8503 tn1
= CTN( GetTail( (struct List
*)&ln1
->ln_List
) );
8506 case MUIV_NListtree_Copy_SourceTreeNode_Active
:
8507 tn1
= data
->ActiveNode
;
8511 tn1
= msg
->SourceTreeNode
;
8515 switch( (IPTR
)msg
->DestListNode
)
8517 case MUIV_NListtree_Copy_DestListNode_Root
:
8518 ln2
= &data
->RootList
;
8521 case MUIV_NListtree_Copy_DestListNode_Active
:
8522 ln2
= data
->ActiveList
;
8526 ln2
= CLN( msg
->DestListNode
);
8530 switch( (IPTR
)msg
->DestTreeNode
)
8532 case MUIV_NListtree_Copy_DestTreeNode_Head
:
8533 tn2
= CTN( INSERT_POS_HEAD
);
8536 case MUIV_NListtree_Copy_DestTreeNode_Tail
:
8537 tn2
= CTN( INSERT_POS_TAIL
);
8540 case MUIV_NListtree_Copy_DestTreeNode_Active
:
8541 tn2
= data
->ActiveNode
;
8544 case MUIV_NListtree_Copy_DestTreeNode_Sorted
:
8545 tn2
= GetInsertNodeSorted( data
, ln2
, tn1
);
8549 tn2
= msg
->DestTreeNode
;
8556 struct MUI_NListtree_TreeNode
*savetn1
= tn1
;
8558 //D(bug( "1: L: %s, N: %s - 2: L: %s, N: %s\n", ln1->ln_Name, tn1->tn_Name, ln2->ln_Name, ( (ULONG)tn2 == INSERT_POS_TAIL ) ? "TAIL" : tn2->tn_Name ) );
8561 ** Create structure identical to source.
8563 if(isFlagSet(msg
->Flags
, MUIV_NListtree_Copy_Flag_KeepStructure
))
8565 tn1
= CTN( CreateParentStructure( data
, msg
->MethodID
, &ln2
, &tn2
, tn1
, 0 ) );
8569 tn1
= DuplicateNode(data
, tn1
);
8572 tn1
= CreateChildStructure( data
, ln2
, CLN( tn1
), CLN( savetn1
), 0 );
8577 if ( tn1 == data->ActiveNode )
8578 nnset( obj, MUIA_NListtree_Active, tn1 );
8587 /****** NListtree.mcc/MUIM_NListtree_Rename **********************************
8591 * MUIM_NListtree_Rename -- Rename the specified node. (V1)
8596 * struct MUI_NListtree_TreeNode *treenode =
8597 * DoMethod(obj, MUIM_NListtree_Rename,
8598 * struct MUI_NListtree_TreeNode *treenode,
8599 * STRPTR newname, ULONG flags);
8604 * Rename the specified node.
8606 * If you want to rename the tn_User field (see flags below), the construct
8607 * and destruct hooks are used!
8608 * If you have not specified these hooks, only the pointers will be copied.
8613 * treenode - Specifies the node which should be renamed.
8615 * MUIV_NListtree_Rename_TreeNode_Active:
8616 * Rename the active tree node.
8618 * newname - The new name or pointer.
8622 * MUIV_NListtree_Rename_Flag_User
8623 * The tn_User field is renamed.
8625 * MUIV_NListtree_Rename_Flag_NoRefresh
8626 * The list entry will not be refreshed.
8631 * Returns the pointer of the renamed tree node.
8636 * // Rename the active tree node.
8637 * DoMethod(obj, MUIM_NListtree_Rename,
8638 * MUIV_NListtree_Rename_TreeNode_Active,
8639 * "Very new name", 0);
8648 * MUIA_NListtree_ConstructHook, MUIA_NListtree_DestructHook
8651 ******************************************************************************
8654 IPTR
_NListtree_Rename(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Rename
*msg
)
8656 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
8657 struct MUI_NListtree_TreeNode
*tn
;
8661 ** Handle special events.
8663 if ( (IPTR
)msg
->TreeNode
== (IPTR
)MUIV_NListtree_Rename_TreeNode_Active
)
8664 tn
= data
->ActiveNode
;
8669 ** User wants to rename the user field instead of name field.
8671 if(isFlagSet(msg
->Flags
, MUIV_NListtree_Rename_Flag_User
))
8673 //D(bug( "Node: 0x%08lx - %s - Renaming user field\n", tn, tn->tn_Name ) );
8675 DoMethod(obj
, MUIM_NListtree_Destruct
, tn
->tn_Name
, tn
->tn_User
, data
->TreePool
, 0);
8678 ** Construct new user data
8680 tn
->tn_User
= (APTR
)DoMethod(obj
, MUIM_NListtree_Construct
, tn
->tn_Name
, msg
->NewName
, data
->TreePool
, 0);
8684 //D(bug( "Node: 0x%08lx - %s - Renaming name field from \"%s\" to \"%s\"\n", tn, tn->tn_Name, tn->tn_Name, msg->NewName ) );
8687 ** Should we duplicate the supplied node name?
8689 if(isFlagSet(data
->Flags
, NLTF_DUPNODENAMES
))
8691 int len
= strlen( msg
->NewName
) + 1;
8693 FreeVecPooled( data
->TreePool
, tn
->tn_Name
);
8695 tn
->tn_Name
= (STRPTR
)AllocVecPooled( data
->TreePool
, len
);
8696 strlcpy( tn
->tn_Name
, msg
->NewName
, len
);
8697 SET_FLAG(tn
->tn_IFlags
, TNIF_ALLOCATED
);
8700 tn
->tn_Name
= msg
->NewName
;
8703 if(isFlagClear(msg
->Flags
, MUIV_NListtree_Rename_Flag_NoRefresh
) && isFlagSet(tn
->tn_IFlags
, TNIF_VISIBLE
))
8704 DoMethod( obj
, MUIM_NList_Redraw
, GetVisualPos( data
, tn
) );
8711 /****** NListtree.mcc/MUIM_NListtree_FindName ********************************
8715 * MUIM_NListtree_FindName -- Find node using name match. (V1)
8720 * struct MUI_NListtree_TreeNode *treenode =
8721 * DoMethod(obj, MUIM_NListtree_FindName,
8722 * struct MUI_NListtree_TreeNode *listnode,
8723 * STRPTR name, ULONG flags);
8728 * Find a node which name matches the specified one using the list node as
8733 * listnode - Specify the node which list is used to find the name.
8735 * MUIV_NListtree_FindName_ListNode_Root
8736 * Use the root list as the base list.
8738 * MUIV_NListtree_FindName_ListNode_Active
8739 * Use the list of the active node as the base.
8741 * name - Specify the name of the node to find. But you can search
8742 * for anything in tn_Name or tn_User field here by simply
8743 * supplying the searched data and handling it in your
8748 * MUIV_NListtree_FindName_Flag_SameLevel
8749 * Only nodes on the same level are affected.
8751 * MUIV_NListtree_FindName_Flag_Visible
8752 * The node is only returned if it is visible (only visible
8753 * entries are checked).
8755 * MUIV_NListtree_FindName_Flag_Activate
8756 * If found, the entry will be activated.
8758 * MUIV_NListtree_FindName_Flag_Selected
8759 * Find only selected nodes.
8761 * MUIV_NListtree_FindName_Flag_StartNode
8762 * The specified entry in listnode is the start point for
8763 * search and must not be a list node. It can also be a
8768 * Returns the found node if available, NULL otherwise.
8773 * // Find 2nd node by name.
8774 * struct MUI_NListtree_TreeNode *treenode =
8775 * DoMethod(obj, MUIM_NListtree_FindName,
8776 * listnode, "2nd node",
8777 * MUIV_NListtree_FindName_SameLevel|
8778 * MUIV_NListtree_FindName_Visible);
8780 * if ( treenode == NULL )
8782 * PrintToUser( "No matching entry found." );
8792 * MUIM_NListtree_FindUserData, MUIM_NListtree_GetEntry,
8793 * MUIA_NListtree_FindNameHook
8796 ******************************************************************************
8799 IPTR
_NListtree_FindName(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_FindName
*msg
)
8801 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
8802 struct MUI_NListtree_ListNode
*ln
;
8803 struct MUI_NListtree_TreeNode
*tn
;
8807 ** Handle special events.
8809 switch( (IPTR
)msg
->ListNode
)
8811 case MUIV_NListtree_FindName_ListNode_Root
:
8812 ln
= &data
->RootList
;
8815 case MUIV_NListtree_FindName_ListNode_Active
:
8816 ln
= data
->ActiveList
;
8820 ln
= CLN( msg
->ListNode
);
8824 //D(bug( "StartNode: 0x%08lx - %s - Searching for \"%s\"\n", ln, ln->ln_Name, msg->Name ) );
8826 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindName_Flag_Reverse
))
8828 if((tn
= FindTreeNodeByNameRev(data
, ln
, msg
->Name
, msg
->Flags
)))
8829 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindName_Flag_Activate
))
8830 nnset( obj
, MUIA_NListtree_Active
, tn
);
8834 if((tn
= FindTreeNodeByName(data
, ln
, msg
->Name
, msg
->Flags
)))
8835 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindName_Flag_Activate
))
8836 nnset( obj
, MUIA_NListtree_Active
, tn
);
8844 /****** NListtree.mcc/MUIM_NListtree_FindUserData ****************************
8848 * MUIM_NListtree_FindUserData -- Find node upon user data. (V1)
8853 * struct MUI_NListtree_TreeNode *treenode =
8854 * DoMethod(obj, MUIM_NListtree_FindUserData,
8855 * struct MUI_NListtree_TreeNode *listnode,
8856 * APTR userdata, ULONG flags);
8861 * Find a node which user data matches the specified one using the list
8862 * node as start point..
8863 * This method is designed as a second possibility for searching.
8864 * Because you are able to search for anything, you may set special
8865 * hooks for searching two different fields in two different hooks with
8866 * these two methods.
8870 * listnode - Specify the node which list is used to find the user data.
8872 * MUIV_NListtree_FindUserData_ListNode_Root
8873 * Use the root list as the base list.
8875 * MUIV_NListtree_FindUserData_ListNode_Active
8876 * Use the list of the active node as the base.
8878 * userdata - Specify the user data of the node to find. You can search
8879 * for anything in tn_Name or tn_User field here by simply
8880 * supplying the searched data and handling it in your
8881 * own FindUserDataHook.
8885 * MUIV_NListtree_FindUserData_Flag_SameLevel
8886 * Only nodes on the same level are affected.
8888 * MUIV_NListtree_FindUserData_Flag_Visible
8889 * The node is only returned if it is visible (only visible
8890 * entries are checked).
8892 * MUIV_NListtree_FindUserData_Flag_Activate
8893 * If found, the entry will be activated.
8895 * MUIV_NListtree_FindUserData_Flag_Selected
8896 * Find only selected nodes.
8898 * MUIV_NListtree_FindUserData_Flag_StartNode
8899 * The specified entry in listnode is the start point for
8900 * search and must not be a list node. It can also be a
8905 * Returns the found node if available, NULL otherwise.
8910 * // Find node by user data.
8911 * struct MUI_NListtree_TreeNode *treenode =
8912 * DoMethod(obj, MUIM_NListtree_FindUserData,
8913 * listnode, "my data",
8914 * MUIV_NListtree_FindUserData_SameLevel|
8915 * MUIV_NListtree_FindUserData_Visible);
8917 * if ( treenode == NULL )
8919 * PrintToUser( "No matching entry found." );
8929 * MUIM_NListtree_FindName, MUIM_NListtree_GetEntry,
8930 * MUIA_NListtree_FindUserDataHook
8933 ******************************************************************************
8936 IPTR
_NListtree_FindUserData(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_FindUserData
*msg
)
8938 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
8939 struct MUI_NListtree_ListNode
*ln
;
8940 struct MUI_NListtree_TreeNode
*tn
;
8944 ** Handle special events.
8946 switch( (IPTR
)msg
->ListNode
)
8948 case MUIV_NListtree_FindUserData_ListNode_Root
:
8949 ln
= &data
->RootList
;
8952 case MUIV_NListtree_FindUserData_ListNode_Active
:
8953 ln
= data
->ActiveList
;
8957 ln
= CLN( msg
->ListNode
);
8961 //D(bug( "StartNode: 0x%08lx - %s - Searching for \"%s\"\n", ln, ln->ln_Name, (STRPTR)msg->User ) );
8963 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindUserData_Flag_Reverse
))
8965 if((tn
= FindTreeNodeByUserDataRev(data
, ln
, msg
->User
, msg
->Flags
)))
8966 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindUserData_Flag_Activate
))
8967 nnset( obj
, MUIA_NListtree_Active
, tn
);
8971 if((tn
= FindTreeNodeByUserData(data
, ln
, msg
->User
, msg
->Flags
)))
8972 if(isFlagSet(msg
->Flags
, MUIV_NListtree_FindUserData_Flag_Activate
))
8973 nnset( obj
, MUIA_NListtree_Active
, tn
);
8981 /****** NListtree.mcc/MUIM_NListtree_GetEntry ********************************
8985 * MUIM_NListtree_GetEntry -- Get another node in relation to this. (V1)
8990 * struct MUI_NListtree_TreeNode *rettreenode =
8991 * DoMethod(obj, MUIM_NListtree_GetEntry,
8992 * struct MUI_NListtree_TreeNode *treenode,
8993 * LONG pos, ULONG flags);
8998 * Get another node in relation to the specified list or node.
9003 * treenode - Define the node which is used to find another one.
9004 * This can also be a list node, if the position is
9005 * related to a list.
9007 * MUIV_NListtree_GetEntry_ListNode_Root
9008 * The root list is used.
9010 * MUIV_NListtree_GetEntry_ListNode_Active:
9011 * The list with the active entry is used.
9013 * pos - The relative position of the node 'treenode'.
9015 * MUIV_NListtree_GetEntry_Position_Head
9016 * The head of the list is returned.
9018 * MUIV_NListtree_GetEntry_Position_Tail
9019 * The tail of the list is returned.
9021 * MUIV_NListtree_GetEntry_Position_Active
9022 * The active node is returned. If there is no active entry,
9025 * MUIV_NListtree_GetEntry_Position_Next
9026 * The node next to the specified node is returned. Returns NULL
9027 * if there is no next entry.
9029 * MUIV_NListtree_GetEntry_Position_Previous
9030 * The node right before the specified node is returned.
9031 * Returns NULL if there is no previous entry (if 'treenode'
9032 * is the head of the list.
9034 * MUIV_NListtree_GetEntry_Position_Parent
9035 * The list node of the specified 'treenode' is returned.
9039 * MUIV_NListtree_GetEntry_Flag_SameLevel:
9040 * Only nodes in the same level are affected.
9042 * MUIV_NListtree_GetEntry_Flag_Visible:
9043 * The position is counted on visible entries only.
9048 * Returns the requested node if available, NULL otherwise.
9053 * // Get the next entry.
9054 * struct MUI_NListtree_TreeNode *treenode =
9055 * DoMethod(obj, MUIM_NListtree_GetEntry, treenode,
9056 * MUIV_NListtree_GetEntry_Position_Next, 0);
9060 * PrintToUser( "Next entry found!" );
9070 * MUIM_NList_GetEntry
9073 ******************************************************************************
9076 IPTR
_NListtree_GetEntry(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_GetEntry
*msg
)
9078 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9079 struct MUI_NListtree_TreeNode
*tn
= NULL
;
9080 struct MUI_NListtree_ListNode
*ln
;
9084 ** Handle special events.
9086 switch( (IPTR
)msg
->Node
)
9088 case MUIV_NListtree_GetEntry_ListNode_Root
:
9089 ln
= &data
->RootList
;
9092 case MUIV_NListtree_GetEntry_ListNode_Active
:
9093 ln
= data
->ActiveList
;
9097 ln
= data
->ActiveList
;
9101 ln
= CLN( msg
->Node
);
9105 switch( (IPTR
)(SIPTR
)msg
->Position
)
9107 case MUIV_NListtree_GetEntry_Position_Head
:
9109 if(isFlagSet(ln
->ln_Flags
, TNF_LIST
))
9110 tn
= CTN( GetHead( (struct List
*)&ln
->ln_List
) );
9113 case MUIV_NListtree_GetEntry_Position_Tail
:
9115 if(isFlagSet(ln
->ln_Flags
, TNF_LIST
))
9116 tn
= CTN( GetTail( (struct List
*)&ln
->ln_List
) );
9119 case MUIV_NListtree_GetEntry_Position_Active
:
9121 tn
= data
->ActiveNode
;
9124 case MUIV_NListtree_GetEntry_Position_Next
:
9126 tn
= CTN( GetSucc( (struct Node
*)&ln
->ln_Node
) );
9129 case MUIV_NListtree_GetEntry_Position_Previous
:
9131 tn
= CTN( GetPred( (struct Node
*)&ln
->ln_Node
) );
9134 case MUIV_NListtree_GetEntry_Position_Parent
:
9136 tn
= GetParent( CTN( ln
) );
9139 case MUIV_NListtree_GetEntry_Position_Root
:
9141 tn
= CTN( (APTR
)&data
->RootList
);
9145 tn
= GetEntryByTotalPos( ln
, msg
->Position
, &pos
, msg
->Flags
);
9149 //D(bug( "ListNode: 0x%08lx - Pos: 0x%08lx, Flags: 0x%08lx ==> Entry: 0x%08lx\n", msg->Node, msg->Position, msg->Flags, tn ) );
9156 /****** NListtree.mcc/MUIM_NListtree_GetNr ***********************************
9160 * MUIM_NListtree_GetNr -- Get the position number of a tree node. (V1)
9165 * ULONG number = DoMethod(obj, MUIM_NListtree_GetNr,
9166 * struct MUI_NListtree_TreeNode *treenode, ULONG flags);
9171 * Get the position number of the specified tree node.
9176 * treenode - Specify the node to count the position of.
9178 * MUIV_NListtree_GetNr_TreeNode_Active:
9179 * The position is counted related to the active node.
9181 * MUIV_NListtree_GetNr_TreeNode_Root:
9182 * The position is counted related to the root list.
9186 * MUIV_NListtree_GetNr_Flag_CountAll
9187 * Returns the number of all entries.
9189 * MUIV_NListtree_GetNr_Flag_CountLevel
9190 * Returns the number of entries of the list the
9191 * specified node is in.
9193 * MUIV_NListtree_GetNr_Flag_CountList
9194 * Returns the number of entries in the specified
9195 * treenode if it holds other entries/is a list.
9197 * MUIV_NListtree_GetNr_Flag_ListEmpty
9198 * Returns TRUE if the specified list node is empty.
9200 * MUIV_NListtree_GetNr_Flag_Visible
9201 * Returns the position number of an visible entry. -1 if the
9202 * entry is invisible. The position is counted on visible entries
9210 * // Check if the active (list) node is empty.
9211 * ULONG empty = DoMethod(obj, MUIM_NListtree_GetNr,
9212 * MUIV_NListtree_GetNr_TreeNode_Active,
9213 * MUIV_NListtree_GetNr_Flag_ListEmpty);
9215 * if ( empty == TRUE )
9217 * AddThousandEntries();
9226 * MUIM_NListtree_GetEntry
9228 ******************************************************************************
9231 IPTR
_NListtree_GetNr(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_GetNr
*msg
)
9233 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9234 struct MUI_NListtree_TreeNode
*tn
;
9235 struct MUI_NListtree_ListNode
*pln
;
9236 struct MUI_NListtree_ListNode
*ln
;
9240 D(DBF_LISTTREE
, "GetNr: NListtree entries %ld",data
->NumEntries
);
9243 ** Handle special events.
9245 if ( (IPTR
)msg
->TreeNode
== (IPTR
)MUIV_NListtree_GetNr_TreeNode_Active
)
9246 tn
= data
->ActiveNode
;
9247 else if ( (IPTR
)msg
->TreeNode
== (IPTR
)MUIV_NListtree_GetNr_TreeNode_Root
)
9248 tn
= CTN((APTR
)&data
->RootList
);
9253 pln
= CLN( GetParent( tn
) );
9255 if(isFlagSet(msg
->Flags
, MUIV_NListtree_GetNr_Flag_ListEmpty
))
9257 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
9258 ret
= IsListEmpty( (&ln
->ln_List
) );
9261 else if(isFlagSet(msg
->Flags
, MUIV_NListtree_GetNr_Flag_CountList
))
9263 if(isFlagSet(tn
->tn_Flags
, TNF_LIST
))
9264 ret
= ln
->ln_Table
.tb_Entries
;
9267 else if(pln
&& isFlagSet(msg
->Flags
, MUIV_NListtree_GetNr_Flag_CountLevel
))
9269 ret
= pln
->ln_Table
.tb_Entries
;
9272 else if(isFlagSet(msg
->Flags
, MUIV_NListtree_GetNr_Flag_CountAll
))
9274 ret
= data
->NumEntries
;
9277 else if(isFlagSet(msg
->Flags
, MUIV_NListtree_GetNr_Flag_Visible
))
9279 ret
= (IPTR
)GetVisualPos( data
, tn
);
9286 if ( GetEntryPos( &data
->RootList
, tn
, &pos
) )
9290 //D(bug( "Node: 0x%08lx - %s - Flags: 0x%08lx ==> Nr: %ld\n", tn, tn->tn_Name, msg->Flags, ret ) );
9292 return( (IPTR
)ret
);
9297 /****** NListtree.mcc/MUIM_NListtree_Sort ************************************
9301 * MUIM_NListtree_Sort -- Sort the specified list node. (V1)
9306 * DoMethod(obj, MUIM_NListtree_Sort,
9307 * struct MUI_NListtree_TreeNode *listnode,
9313 * Sort the specified list node using the sort hook.
9318 * listnode - List node to sort.
9320 * MUIV_NListtree_Sort_ListNode_Root
9321 * Sort the root list.
9323 * MUIV_NListtree_Sort_ListNode_Active
9324 * Sort the list node of the active entry.
9326 * MUIV_NListtree_Sort_TreeNode_Active
9327 * Sorts the childs of the active entry if a list.
9329 * flags - Control the part where sorting is done.
9331 * MUIV_NListtree_Sort_Flag_RecursiveOpen
9332 * Sort the list recursive. All open child nodes of the
9333 * node specified in 'listnode' will be sorted too.
9335 * MUIV_NListtree_Sort_Flag_RecursiveAll
9336 * Sort the list recursive with ALL child nodes of the
9337 * node specified in 'listnode'.
9343 * // Sort the list of the active node.
9344 * DoMethod(obj, MUIM_NListtree_Sort,
9345 * MUIV_NListtree_Sort_ListNode_Active, 0);
9353 * MUIA_NListtree_SortHook
9355 ******************************************************************************
9358 IPTR
_NListtree_Sort(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Sort
*msg
)
9360 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9361 struct MUI_NListtree_ListNode
*ln
;
9365 ** Handle special events.
9367 switch( (IPTR
)msg
->ListNode
)
9369 case MUIV_NListtree_Sort_ListNode_Active
:
9370 ln
= data
->ActiveList
;
9373 case MUIV_NListtree_Sort_ListNode_Root
:
9374 ln
= &data
->RootList
;
9377 case MUIV_NListtree_Sort_TreeNode_Active
:
9378 ln
= data
->ActiveList
;
9380 if ( data
->ActiveNode
)
9382 if(isFlagSet(data
->ActiveNode
->tn_Flags
, TNF_LIST
))
9383 ln
= CLN( data
->ActiveNode
);
9388 ln
= CLN( msg
->ListNode
);
9392 pos
= GetVisualPos( data
, CTN( ln
) ) + 1;
9394 DoQuiet( data
, TRUE
);
9395 DeactivateNotify( data
);
9397 ListNode_Sort( ln
, data
, msg
->Flags
);
9398 ReplaceTreeVisibleSort( data
, CTN( ln
), &pos
);
9400 ActivateNotify( data
);
9401 DoQuiet( data
, FALSE
);
9403 /* sba: the active note could be changed, but the notify calling was disabled */
9404 DoMethod(data
->Obj
, MUIM_NListtree_GetListActive
, 0);
9406 /* nnset( obj, MUIA_NListtree_Active, CTN( data->ActiveNode ) );*/
9413 /****** NListtree.mcc/MUIM_NListtree_TestPos *********************************
9417 * MUIM_NListtree_TestPos -- Get information about entry at x/y pos. (V1)
9422 * DoMethod(obj, MUIM_NListtree_TestPos, LONG xpos, LONG ypos,
9423 * struct MUI_NListtree_TestPos_Result *testposresult);
9428 * Find out some information about the currently displayed entry at a
9429 * certain position (x/y-pos).
9431 * This is very useful for Drag&Drop operations.
9436 * xpos - X-position.
9437 * ypos - Y-position.
9438 * testposresult - Pointer to a valid MUI_NListtree_TestPos_Result
9444 * tpr_TreeNode - The tree node under the requested position or NULL
9445 * if there is no entry displayed.
9447 * The tpr_Type field contains detailed information about the relative
9450 * MUIV_NListtree_TestPos_Result_Above
9451 * MUIV_NListtree_TestPos_Result_Below
9452 * MUIV_NListtree_TestPos_Result_Onto
9453 * MUIV_NListtree_TestPos_Result_Sorted
9455 * tpr_Column - The column unter the specified position or -1 if
9461 * // Entry under the cursor?
9462 * struct MUI_NListtree_TestPos_Result tpres;
9464 * DoMethod(obj, MUIM_NListtree_TestPos, msg->imsg->MouseX,
9465 * msg->imsg->MouseY, &tpres);
9467 * if ( tpres.tpr_Entry != NULL )
9469 * // Do something very special here...
9479 * MUIM_NList_TestPos
9482 ******************************************************************************
9485 IPTR
_NListtree_TestPos( UNUSED
struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_TestPos
*msg
)
9487 struct MUI_NListtree_TestPos_Result
*res
= (struct MUI_NListtree_TestPos_Result
*)msg
->Result
;
9488 struct MUI_NList_TestPos_Result lres
;
9490 lres
.char_number
= -2;
9492 DoMethod( obj
, MUIM_NList_TestPos
, msg
->X
, msg
->Y
, &lres
);
9494 if ( lres
.entry
!= -1 )
9496 DoMethod( obj
, MUIM_NList_GetEntry
, lres
.entry
, &res
->tpr_TreeNode
);
9498 if ( lres
.yoffset
< -3 ) res
->tpr_Type
= MUIV_NListtree_TestPos_Result_Above
;
9499 else if ( lres
.yoffset
> 3 ) res
->tpr_Type
= MUIV_NListtree_TestPos_Result_Below
;
9500 else res
->tpr_Type
= MUIV_NListtree_TestPos_Result_Onto
;
9502 res
->tpr_ListEntry
= lres
.entry
;
9503 res
->tpr_ListFlags
= lres
.flags
;
9504 res
->tpr_Column
= lres
.column
;
9508 res
->tpr_TreeNode
= NULL
;
9511 res
->tpr_ListEntry
= -1;
9512 res
->tpr_ListFlags
= 0;
9513 res
->tpr_Column
= -1;
9516 //D(bug( "X: %ld, Y: %ld ==> Node: 0x%08lx - %s - YOffset: %ld, Type: 0x%08lx\n", msg->X, msg->Y, res->tpr_TreeNode, res->tpr_TreeNode->tn_Name, lres.yoffset, res->tpr_Type ) );
9524 /****** NListtree.mcc/MUIM_NListtree_Redraw **********************************
9528 * MUIM_NListtree_Redraw -- Redraw the specified tree node. (V1)
9533 * DoMethod(obj, MUIM_NListtree_Redraw,
9534 * struct MUI_NListtree_TreeNode *treenode, ULONG flags);
9539 * Redraw the specified entry. See special values for completeness.
9544 * treenode - The tree node to be redrawn.
9546 * MUIV_NListtree_Redraw_Active
9547 * Redraw the active entry.
9549 * MUIV_NListtree_Redraw_All
9550 * Redraw the complete visible tree.
9555 * MUIV_NListtree_Redraw_Flag_Nr
9556 * The data specified in 'treenode' is the entry number,
9557 * not the tree node itself.
9564 * // Redraw the active entry.
9565 * DoMethod(obj, MUIM_NListtree_Redraw,
9566 * MUIV_NListtree_Redraw_Active, 0);
9575 * MUIM_NList_TestPos
9578 ******************************************************************************
9581 IPTR
_NListtree_Redraw(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Redraw
*msg
)
9583 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9585 D(DBF_DRAW
, "redraw treenode %08lx flags %08lx", msg
->TreeNode
, msg
->Flags
);
9587 if(((IPTR
)msg
->TreeNode
!= (IPTR
)MUIV_NListtree_Redraw_Active
) && ((IPTR
)msg
->TreeNode
!= (IPTR
)MUIV_NListtree_Redraw_All
) && isFlagClear(msg
->Flags
, MUIV_NListtree_Redraw_Flag_Nr
))
9589 LONG pos
= GetVisualPos(data
, msg
->TreeNode
);
9591 D(DBF_DRAW
, "treenode %08lx has visual position %ld", msg
->TreeNode
, pos
);
9592 // redraw the given node only if it is visible
9594 DoMethod(obj
, MUIM_NList_Redraw
, pos
);
9598 D(DBF_DRAW
, "EXTERNAL REDRAW REQUESTED!");
9599 DoMethod(obj
, MUIM_NList_Redraw
, (IPTR
)msg
->TreeNode
);
9607 /****** NListtree.mcc/MUIM_NListtree_Select **********************************
9611 * MUIM_NListtree_Select -- Select the specified tree node. (V1)
9616 * DoMethod(obj, MUIM_NListtree_Select,
9617 * struct MUI_NListtree_TreeNode *treenode, LONG seltype,
9618 * LONG selflags, LONG *state);
9623 * Select or unselect a tree entry or ask an entry about its state.
9624 * See special values for completeness.
9629 * treenode - The tree node to be selected/unselected/asked.
9631 * MUIV_NListtree_Select_Active For the active entry.
9632 * MUIV_NListtree_Select_All For all entries.
9633 * MUIV_NListtree_Select_Visible For all visible entries.
9635 * seltype - Type of selection/unselection/ask
9637 * MUIV_NListtree_Select_Off Unselect entry.
9638 * MUIV_NListtree_Select_On Select entry.
9639 * MUIV_NListtree_Select_Toggle Toggle entries state.
9640 * MUIV_NListtree_Select_Ask Just ask about the state.
9642 * selflags - Some kind of specials.
9644 * MUIV_NListtree_Select_Flag_Force
9645 * Adding this flag to seltype forces the selection by
9646 * bypassing the multi test hook.
9648 * state - Pointer to a longword. If not NULL, it will be filled
9649 * with the current selection state of the entry.
9656 * // Select the active entry.
9659 * DoMethod(obj, MUIM_NListtree_Select,
9660 * MUIV_NListtree_Select_Active, MUIV_NListtree_Select_On,
9663 * // We must check this, because the multi test hook may
9664 * // cancel our selection.
9665 * if (retstate == MUIV_NListtree_Select_On) {
9672 * If ( treenode == MUIV_NListtree_Select_All ) and
9673 * ( seltype == MUIV_NListtree_Select_Ask ), state will be filled
9674 * with the total number of selected entries.
9676 * NEW for final 18.6:
9677 * If (treenode == MUIV_NListtree_Select_Active ) and
9678 * ( seltype == MUIV_NListtree_Select_Ask ), state will be the
9679 * active entry, if any, or NULL.
9681 * If only the active entry is selected, has a cursor mark (see
9682 * MUIM_NListtree_NextSelected for that), you will receive 0 as
9683 * the number of selected entries.
9690 * MUIA_NListtree_MultiTestHook
9693 ******************************************************************************
9696 IPTR
_NListtree_Select(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Select
*msg
)
9698 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9703 SET_FLAG(data
->Flags
, NLTF_SELECT_METHOD
);
9706 ** Handle special events.
9708 switch( (IPTR
)msg
->TreeNode
)
9710 case MUIV_NListtree_Select_Active
:
9711 if ( msg
->SelType
== MUIV_NListtree_Select_Ask
)
9713 state
= (LONG
)(SIPTR
)data
->ActiveNode
;
9717 if ( data
->ActiveNode
)
9719 TreeNodeSelect( data
, data
->ActiveNode
, msg
->SelType
, msg
->SelFlags
, &state
);
9724 case MUIV_NListtree_Select_All
:
9726 if ( msg
->SelType
== MUIV_NListtree_Select_Ask
)
9728 state
= data
->SelectedTable
.tb_Entries
;
9732 TreeNodeSelectAll( data
, &data
->RootList
, msg
->SelType
, msg
->SelFlags
, &state
);
9736 case MUIV_NListtree_Select_Visible
:
9737 TreeNodeSelectVisible( data
, &data
->RootList
, msg
->SelType
, msg
->SelFlags
, &state
);
9741 TreeNodeSelect( data
, msg
->TreeNode
, msg
->SelType
, msg
->SelFlags
, &state
);
9747 *msg
->State
= state
;
9750 CLEAR_FLAG(data
->Flags
, NLTF_SELECT_METHOD
);
9753 return( (IPTR
)state
);
9758 /****** NListtree.mcc/MUIM_NListtree_NextSelected ****************************
9762 * MUIM_NListtree_NextSelected -- Get next selected tree node. (V1)
9767 * DoMethod(obj, MUIM_NListtree_NextSelected,
9768 * struct MUI_NListtree_TreeNode **treenode);
9773 * Iterate through the selected entries of a tree. This method steps
9774 * through the contents of a (multi select) list tree and returns
9775 * every entry that is currently selected. When no entry is selected
9776 * but an entry is active, only the active entry will be returned.
9778 * This behaviour will result in not returning the active entry when
9779 * you have some other selected entries somewhere in your list. Since
9780 * the active entry just acts as some kind of cursor mark, this seems
9781 * to be the only sensible possibility to handle multi selection
9782 * together with keyboard control.
9787 * treenode - A pointer to a pointer of struct MUI_NListtree_TreeNode
9788 * that will hold the returned entry. Must be set to
9789 * MUIV_NListtree_NextSelected_Start at start of iteration
9790 * and is set to MUIV_NListtree_NextSelected_End when
9791 * iteration is finished.
9793 * MUIV_NListtree_NextSelected_Start Set this to start iteration.
9794 * MUIV_NListtree_NextSelected_End Will be set to this, if
9795 * last selected entry reached.
9802 * // Iterate through a list
9803 * struct MUI_NListtree_TreeNode *treenode;
9805 * treenode = MUIV_NListtree_NextSelected_Start;
9809 * DoMethod(listtree, MUIM_NListtree_NextSelected, &treenode);
9811 * if (treenode==MUIV_NListtree_NextSelected_End)
9814 * printf("selected: %s\n", treenode->tn_Name);
9824 * MUIM_NListtree_PrevSelected, MUIM_NListtree_Select
9827 ******************************************************************************
9830 IPTR
_NListtree_NextSelected(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_NextSelected
*msg
)
9832 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9833 LONG curr
= data
->SelectedTable
.tb_Current
;
9835 //D(bug( "TreeNode: 0x%08lx ", *msg->TreeNode ) );
9837 if ( (IPTR
)*msg
->TreeNode
== (IPTR
)MUIV_NListtree_NextSelected_Start
)
9842 if ( ( curr
> -1 ) && data
->SelectedTable
.tb_Entries
)
9844 if ( curr
< data
->SelectedTable
.tb_Entries
)
9846 data
->SelectedTable
.tb_Current
= curr
;
9847 *msg
->TreeNode
= data
->SelectedTable
.tb_Table
[curr
];
9849 else if(((IPTR
)*msg
->TreeNode
== (IPTR
)MUIV_NListtree_NextSelected_Start
) &&
9850 (data
->ActiveNode
!= MUIV_NListtree_Active_Off
))
9852 *msg
->TreeNode
= data
->ActiveNode
;
9856 *msg
->TreeNode
= CTN( MUIV_NListtree_NextSelected_End
);
9861 *msg
->TreeNode
= CTN( MUIV_NListtree_NextSelected_End
);
9864 //D(bugn( "==> Entry: 0x%08lx\n", *msg->TreeNode ) );
9870 /****** NListtree.mcc/MUIM_NListtree_PrevSelected ****************************
9874 * MUIM_NListtree_PrevSelected -- Get previous selected tree node. (V1)
9879 * DoMethod(obj, MUIM_NListtree_PrevSelected,
9880 * struct MUI_NListtree_TreeNode **treenode);
9885 * Iterate reverse through the selected entries of a tree. This method
9886 * steps through the contents of a (multi select) list tree and returns
9887 * every entry that is currently selected. When no entry is selected
9888 * but an entry is active, only the active entry will be returned.
9890 * This behaviour will result in not returning the active entry when
9891 * you have some other selected entries somewhere in your list. Since
9892 * the active entry just acts as some kind of cursor mark, this seems
9893 * to be the only sensible possibility to handle multi selection
9894 * together with keyboard control.
9899 * treenode - A pointer to a pointer of struct MUI_NListtree_TreeNode
9900 * that will hold the returned entry. Must be set to
9901 * MUIV_NListtree_PrevSelected_Start at start of iteration
9902 * an the end and is set to MUIV_NListtree_PrevSelected_End
9903 * when first selected entry is reached and iteration is
9906 * MUIV_NListtree_PrevSelected_Start Set this to start iteration.
9907 * MUIV_NListtree_PrevSelected_End Will be set to this, if
9908 * last selected entry reached.
9915 * // Iterate through a list (reverse)
9916 * struct MUI_NListtree_TreeNode *treenode;
9918 * treenode = MUIV_NListtree_PrevSelected_Start;
9922 * DoMethod(listtree, MUIM_NListtree_PrevSelected, &treenode);
9924 * if (treenode==MUIV_NListtree_PrevSelected_End)
9927 * printf("selected: %s\n", treenode->tn_Name);
9937 * MUIM_NListtree_NextSelected, MUIM_NListtree_Select
9940 ******************************************************************************
9944 IPTR
_NListtree_PrevSelected(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_PrevSelected
*msg
)
9946 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
9947 LONG curr
= data
->SelectedTable
.tb_Current
;
9949 //D(bug( "TreeNode: 0x%08lx ", *msg->TreeNode ) );
9951 if((IPTR
)*msg
->TreeNode
== (IPTR
)MUIV_NListtree_PrevSelected_Start
)
9952 curr
= data
->SelectedTable
.tb_Entries
;
9956 if ( curr
< data
->SelectedTable
.tb_Entries
)
9960 data
->SelectedTable
.tb_Current
= curr
;
9961 *msg
->TreeNode
= data
->SelectedTable
.tb_Table
[curr
];
9963 else if(((IPTR
)*msg
->TreeNode
== (IPTR
)MUIV_NListtree_NextSelected_Start
) &&
9964 (data
->ActiveNode
!= MUIV_NListtree_Active_Off
))
9966 *msg
->TreeNode
= data
->ActiveNode
;
9970 *msg
->TreeNode
= CTN( MUIV_NListtree_PrevSelected_End
);
9975 *msg
->TreeNode
= CTN( MUIV_NListtree_PrevSelected_End
);
9978 //D(bugn( "==> Entry: 0x%08lx\n", *msg->TreeNode ) );
9985 /****** NListtree.mcc/MUIM_NListtree_CopyToClip ******************************
9989 * MUIM_NListtree_CopyToClip -- Called for every clipboard copy action. (V1)
9994 * DoMethodA(obj, MUIM_NListtree_CopyToClip,
9995 * struct MUIP_NListtree_CopyToClip *ctcmessage);
10000 * Do a copy to clipboard from an entry/entry content.
10005 * TreeNode - Tree node to copy contents from. Use
10006 * MUIV_NListtree_CopyToClip_Active to copy the
10009 * Pos - Entry position.
10011 * Unit - Clipboard unit to copy entry contents to.
10024 * MUIA_NListtree_CopyToClipHook
10027 ******************************************************************************
10030 IPTR
_NListtree_CopyToClip(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_CopyToClip
*msg
)
10032 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
10034 // make sure anything is selected at all or calling CopyToClip doesn't make
10036 if(msg
->TreeNode
!= NULL
&& msg
->TreeNode
->tn_Name
!= NULL
)
10038 STRPTR string
= NULL
;
10039 BOOL alloc
= FALSE
;
10041 if(data
->CopyToClipHook
!= NULL
)
10043 if((SIPTR
)(string
= (STRPTR
)MyCallHook(data
->CopyToClipHook
, data
, MUIA_NListtree_CopyToClipHook
, msg
->TreeNode
, msg
->Pos
, msg
->Unit
)) == (SIPTR
)MUIV_NListtree_CopyToClip_Active
)
10044 string
= msg
->TreeNode
->tn_Name
;
10050 string
= msg
->TreeNode
->tn_Name
;
10051 if((str
= AllocVecPooled(data
->MemoryPool
, strlen(string
) + 1)) != NULL
)
10058 // copy the string and remove all escape sequences
10066 while(++*s
!= ']');
10078 //D(bug( "String: %s, Unit: %ld, pos: %ld\n", string, msg->Unit, msg->Pos ) );
10080 StringToClipboard(msg
->Unit
, string
);
10083 FreeVecPooled(data
->MemoryPool
, string
);
10092 /****** NListtree.mcc/MUIM_NListtree_MultiTest *******************************
10096 * MUIM_NListtree_MultiTest -- Called for every selection. (V1)
10101 * DoMethodA(obj, MUIM_NListtree_MultiTest,
10102 * struct MUIP_NListtree_MultiTest *multimessage);
10107 * This method must not be called directly. It will be called by
10108 * NListtree just before multiselection. You can overload it and
10109 * return TRUE or FALSE whether you want the entry to be multi-
10110 * selectable or not.
10125 * MUIM_NListtree_Select, MUIA_NListtree_MultiTest
10128 ******************************************************************************
10133 /****** NListtree.mcc/MUIM_NListtree_Active **********************************
10137 * MUIM_NListtree_Active -- Called for every active change. (V1)
10142 * DoMethodA(obj, MUIM_NListtree_Active,
10143 * struct MUIP_NListtree_Active *activemessage);
10148 * This method must not be called directly. It will be called by
10149 * NListtree if the active entry changes. This is an addition to
10150 * MUIA_NListtree_Active
10165 * MUIA_NListtree_Active
10168 ******************************************************************************
10173 /****** NListtree.mcc/MUIM_NListtree_DoubleClick *****************************
10177 * MUIM_NListtree_DoubleClick -- Called for every double click. (V1)
10182 * DoMethodA(obj, MUIM_NListtree_DoubleClick,
10183 * struct MUIP_NListtree_DoubleClick *doubleclickmsg);
10188 * This method must not be called directly. It will be called by
10189 * NListtree if an double click event occurs. This is an addition to
10190 * MUIA_NListtree_DoubleClick
10205 * MUIA_NListtree_DoubleClick
10208 ******************************************************************************
10213 /****** NListtree.mcc/MUIM_NListtree_DropType ********************************
10217 * MUIM_NListtree_DropType --
10222 * DoMethod(obj, MUIM_NListtree_DropType, LONG *pos, LONG *type,
10223 * LONG minx, LONG maxx, LONG miny, LONG maxy,
10224 * LONG mousex, LONG mousey);
10229 * This method MUST NOT be called directly !
10231 * It will be called by NListree while the DragReport, with
10232 * default *pos and *type values depending on the drag pointer
10233 * position that you can modify as you want.
10235 * For further information see method MUIM_NList_DropDraw.
10250 * MUIM_NList_DropType
10253 ******************************************************************************
10258 /****** NListtree.mcc/MUIM_NListtree_DropDraw ********************************
10262 * MUIM_NListtree_DropDraw --
10267 * DoMethod(obj, MUIM_NListtree_DropDraw, LONG pos, LONG type,
10268 * LONG minx, LONG maxx, LONG miny, LONG maxy);
10273 * This method MUST NOT be called directly!
10275 * It will be called by NListtree, and will draw the drop mark
10276 * previously fixed (pos and type) by MUIM_NListtree_DropType
10277 * within the minx, maxx, miny, maxy in the _rp(obj) rasport.
10279 * For further information see method MUIM_NList_DropDraw.
10294 * MUIM_NList_DropDraw
10297 ******************************************************************************
10304 /****i* NListtree.mcc/MUIM_NListtree_GetListActive ***************************
10308 * MUIM_NListtree_GetListActive -- Set the active list in data structure. (V1)
10313 * DoMethod(obj, MUIM_NListtree_GetListActive, 0);
10318 * Set current active list in the internal data structure depending on the
10319 * currently active entry.
10326 * data->ActiveList will be set to data->ActiveEntry->tn_Parent.
10331 * DoMethod(obj, MUIM_NListtree_GetListActive, 0);
10336 * Only internal used function for notification of MUIA_NList_Active.
10343 * MUIA_NList_Active
10346 ******************************************************************************
10349 IPTR
_NListtree_GetListActive(struct IClass
*cl
, Object
*obj
, UNUSED
struct MUIP_NListtree_GetListActive
*msg
)
10351 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
10352 struct MUI_NListtree_TreeNode
*tn
;
10355 ** Get pointer to the selected node.
10356 ** Set active node in global
10359 DoMethod( obj
, MUIM_NList_GetEntry
, MUIV_NList_GetEntry_Active
, &tn
);
10361 D(DBF_LISTTREE
, "Got Active notify from NList 0x%08lx - %s (0x%08lx - Name: %s) force=%ld", tn
, (tn
!= NULL
&& tn
->tn_Name
!= NULL
) ? tn
->tn_Name
: (STRPTR
)"NULL", data
->ActiveNode
, (data
->ActiveNode
!= NULL
&& data
->ActiveNode
->tn_Name
!= NULL
) ? data
->ActiveNode
->tn_Name
: (STRPTR
)"NULL", data
->ForceActiveNotify
);
10363 if ( tn
!= data
->ActiveNode
|| data
->ForceActiveNotify
)
10365 //DoMethod( obj, MUIM_NListtree_Active, tn, pos );
10367 //MakeNotify( data, MUIA_NListtree_Active, tn );
10368 MakeSet( data
, MUIA_NListtree_Active
, tn
);
10369 data
->ForceActiveNotify
= 0;
10376 IPTR
_NListtree_GetDoubleClick(struct IClass
*cl
, Object
*obj
, UNUSED
struct MUIP_NListtree_GetListActive
*msg
)
10378 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
10382 if ( data
->DoubleClick
!= MUIV_NListtree_DoubleClick_NoTrigger
)
10384 struct MUI_NListtree_TreeNode
*tn
;
10387 ** Get pointer to the selected node.
10389 DoMethod( obj
, MUIM_NList_GetEntry
, data
->LDClickEntry
, &tn
);
10391 if ( (SIPTR
)tn
!= -1 )
10393 DoMethod( obj
, MUIM_NListtree_DoubleClick
, tn
, data
->LDClickEntry
, data
->LDClickColumn
);
10394 MakeNotify( data
, MUIA_NListtree_DoubleClick
, tn
);
10395 //DoMethod( obj, MUIM_Set, MUIA_NListtree_DoubleClick, tn );
10405 /****i* NListtree.mcc/MUIM_NListtree_Data ************************************
10409 * MUIM_NListtree_Data -- Get/Set some internal data. (V1)
10414 * DoMethod(obj, MUIM_NListtree_Data, dataqual, set);
10419 * Get some internal data or set if "set" is != NULL.
10425 * MUIV_NListtree_Data_MemPool
10426 * MUIV_NListtree_Data_VersInfo (not implemented)
10427 * MUIV_NListtree_Data_Sample (not implemented)
10432 * The requested data.
10437 * result = DoMethod(obj, MUIM_NListtree_Data,
10438 * MUIV_NListtree_Data_MemPool, NULL);
10447 ******************************************************************************
10450 IPTR
_NListtree_Data(struct IClass
*cl
, Object
*obj
, struct MUIP_NListtree_Data
*msg
)
10452 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
10456 case MUIV_NListtree_Data_MemPool
:
10457 return( (IPTR
)data
->MemoryPool
);
10459 case MUIV_NListtree_Data_VersInfo
:
10460 case MUIV_NListtree_Data_Sample
:
10470 IPTR
_NListtree_SelectChange(struct IClass
*cl
, Object
*obj
, struct MUIP_NList_SelectChange
*msg
)
10472 struct NListtree_Data
*data
= INST_DATA(cl
, obj
);
10473 struct MUI_NListtree_TreeNode
*tn
;
10475 D(DBF_LISTTREE
, "NList selection change: Entry %ld changed to %ld%s", msg
->pos
, msg
->state
,
10476 isFlagSet(msg
->flags
, MUIV_NList_SelectChange_Flag_Multi
) ? " while holding down mouse button" : "");
10478 if (data
->IgnoreSelectionChange
)
10480 D(DBF_LISTTREE
, " which is ignored");
10484 DoMethod( obj
, MUIM_NList_GetEntry
, msg
->pos
, &tn
);
10486 if ( msg
->state
== MUIV_NList_Select_Active
)
10488 if ( tn
!= data
->ActiveNode
)
10491 ** !! Setting this NOT makes problems with getting the active entry
10492 ** in applications. Handle carefully if changed/removed !!
10494 //MakeNotify( data, MUIA_NListtree_Active, tn );
10495 //data->ActiveNode = tn;
10497 /* sba: Changed to not notify, because the new active element is not drawn
10498 ** here (current NList restriction) a MUIA_NList_Active trigger
10499 ** will follow and we will use this for the notification
10501 nnset( obj
, MUIA_NListtree_Active
, tn
);
10503 /* sba: the MUIA_NList_Notification only notifies if neccessary, but as the
10504 ** notifications stayed out we set a flag to force it
10506 data
->ForceActiveNotify
= 1;
10510 else if ( msg
->state
== MUIV_NList_Select_On
)
10512 if ( NLFindInTable( &data
->SelectedTable
, tn
) == -1 )
10514 TreeNodeSelectAdd( data
, tn
);
10515 SET_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
10517 MakeNotify( data
, MUIA_NListtree_SelectChange
, (APTR
)TRUE
);
10521 else if ( msg
->state
== MUIV_NList_Select_Off
)
10523 if ( NLFindInTable( &data
->SelectedTable
, tn
) != -1 )
10525 TreeNodeSelectRemove( data
, tn
);
10526 CLEAR_FLAG(tn
->tn_Flags
, TNF_SELECTED
);
10528 MakeNotify( data
, MUIA_NListtree_SelectChange
, (APTR
)TRUE
);
10537 /****i* NListtree.mcc/_Dispatcher ******************************************
10541 * _Dispatcher -- Call methods depending on the supplied MethodID (V1)
10560 ******************************************************************************
10564 DISPATCHER(_Dispatcher
)
10566 switch( msg
->MethodID
)
10569 ** Base class methods.
10571 case OM_NEW
: return( _New ( cl
, obj
, (APTR
)msg
) );
10572 case OM_DISPOSE
: return( _Dispose ( cl
, obj
, (APTR
)msg
) );
10573 case OM_SET
: return( _Set ( cl
, obj
, (APTR
)msg
) );
10574 case OM_GET
: return( _Get ( cl
, obj
, (APTR
)msg
) );
10577 ** MUI base class methods.
10579 case MUIM_Setup
: return( _Setup ( cl
, obj
, (APTR
)msg
) );
10580 case MUIM_Cleanup
: return( _Cleanup ( cl
, obj
, (APTR
)msg
) );
10581 case MUIM_Show
: return( _Show ( cl
, obj
, (APTR
)msg
) );
10582 case MUIM_Hide
: return( _Hide ( cl
, obj
, (APTR
)msg
) );
10583 case MUIM_Draw
: return( _Draw ( cl
, obj
, (APTR
)msg
) );
10584 case MUIM_AskMinMax
: return( _AskMinMax ( cl
, obj
, (APTR
)msg
) );
10585 case MUIM_HandleEvent
: return( _HandleEvent ( cl
, obj
, (APTR
)msg
) );
10588 ** MUI/NList drag&drop methods.
10590 case MUIM_DragQuery
: return( _DragNDrop_DragQuery ( cl
, obj
, (APTR
)msg
) );
10591 case MUIM_DragBegin
: return( _DragNDrop_DragBegin ( cl
, obj
, (APTR
)msg
) );
10592 case MUIM_DragReport
: return( _DragNDrop_DragReport ( cl
, obj
, (APTR
)msg
) );
10593 case MUIM_DragFinish
: return( _DragNDrop_DragFinish ( cl
, obj
, (APTR
)msg
) );
10594 case MUIM_DragDrop
: return( _DragNDrop_DragDrop ( cl
, obj
, (APTR
)msg
) );
10595 case MUIM_NList_DropType
: return( _DragNDrop_DropType ( cl
, obj
, (APTR
)msg
) );
10596 case MUIM_NList_DropDraw
: return( _DragNDrop_DropDraw ( cl
, obj
, (APTR
)msg
) );
10597 case MUIM_NListtree_DropDraw
: return( _DragNDrop_NDropDraw ( cl
, obj
, (APTR
)msg
) );
10599 case MUIM_NList_Display
: return( _NList_Display(cl
, obj
, (APTR
)msg
) );
10604 case MUIM_NList_ContextMenuBuild
: return( _ContextMenuBuild ( cl
, obj
, (APTR
)msg
) );
10605 case MUIM_ContextMenuChoice
: return( _ContextMenuChoice ( cl
, obj
, (APTR
)msg
) );
10609 ** NListtree methods sorted by kind.
10611 case MUIM_NListtree_Open
: return( _NListtree_Open ( cl
, obj
, (APTR
)msg
) );
10612 case MUIM_NListtree_Close
: return( _NListtree_Close ( cl
, obj
, (APTR
)msg
) );
10614 case MUIM_NListtree_Insert
: return( _NListtree_Insert ( cl
, obj
, (APTR
)msg
) );
10615 case MUIM_NListtree_InsertStruct
: return( _NListtree_InsertStruct ( cl
, obj
, (APTR
)msg
) );
10616 case MUIM_NListtree_Remove
: return( _NListtree_Remove ( cl
, obj
, (APTR
)msg
) );
10617 case MUIM_NListtree_Clear
: return( _NListtree_Clear ( cl
, obj
, (APTR
)msg
) );
10619 case MUIM_NListtree_Move
: return( _NListtree_Move ( cl
, obj
, (APTR
)msg
) );
10620 case MUIM_NListtree_Copy
: return( _NListtree_Copy ( cl
, obj
, (APTR
)msg
) );
10621 case MUIM_NListtree_Rename
: return( _NListtree_Rename ( cl
, obj
, (APTR
)msg
) );
10622 case MUIM_NListtree_Exchange
: return( _NListtree_Exchange ( cl
, obj
, (APTR
)msg
) );
10624 case MUIM_NListtree_FindName
: return( _NListtree_FindName ( cl
, obj
, (APTR
)msg
) );
10625 case MUIM_NListtree_FindUserData
: return( _NListtree_FindUserData ( cl
, obj
, (APTR
)msg
) );
10627 case MUIM_NListtree_GetEntry
: return( _NListtree_GetEntry ( cl
, obj
, (APTR
)msg
) );
10628 case MUIM_NListtree_GetNr
: return( _NListtree_GetNr ( cl
, obj
, (APTR
)msg
) );
10630 case MUIM_NListtree_Sort
: return( _NListtree_Sort ( cl
, obj
, (APTR
)msg
) );
10631 case MUIM_NListtree_Redraw
: return( _NListtree_Redraw ( cl
, obj
, (APTR
)msg
) );
10632 case MUIM_NListtree_TestPos
: return( _NListtree_TestPos ( cl
, obj
, (APTR
)msg
) );
10634 case MUIM_NListtree_Select
: return( _NListtree_Select ( cl
, obj
, (APTR
)msg
) );
10635 case MUIM_NListtree_NextSelected
: return( _NListtree_NextSelected ( cl
, obj
, (APTR
)msg
) );
10636 case MUIM_NListtree_PrevSelected
: return( _NListtree_PrevSelected ( cl
, obj
, (APTR
)msg
) );
10638 case MUIM_NListtree_CopyToClip
: return( _NListtree_CopyToClip ( cl
, obj
, (APTR
)msg
) );
10640 case MUIM_NListtree_Construct
: return( _NListtree_Construct ( cl
, obj
, (APTR
)msg
) );
10641 case MUIM_NListtree_Destruct
: return( _NListtree_Destruct ( cl
, obj
, (APTR
)msg
) );
10642 case MUIM_NListtree_Display
: return( _NListtree_Display ( cl
, obj
, (APTR
)msg
) );
10643 case MUIM_NListtree_Compare
: return( _NListtree_Compare ( cl
, obj
, (APTR
)msg
) );
10646 ** Methods, user can use for info or overload
10647 ** to control NListtree.
10649 case MUIM_NListtree_Active
: return( TRUE
);
10650 case MUIM_NListtree_DoubleClick
: return( TRUE
);
10651 case MUIM_NListtree_MultiTest
: return( TRUE
);
10652 case MUIM_NListtree_DropType
: return( TRUE
);
10656 ** Internal methods.
10658 case MUIM_NListtree_GetListActive
: return( _NListtree_GetListActive ( cl
, obj
, (APTR
)msg
) );
10659 case MUIM_NListtree_GetDoubleClick
: return( _NListtree_GetDoubleClick ( cl
, obj
, (APTR
)msg
) );
10660 case MUIM_NListtree_Data
: return( _NListtree_Data ( cl
, obj
, (APTR
)msg
) );
10662 case MUIM_NList_SelectChange
: return( _NListtree_SelectChange ( cl
, obj
, (APTR
)msg
) );
10665 case MUIM_NList_Remove
:
10668 D(DBF_LISTTREE
, "MUIM_NList_Remove");
10669 rc
= DoSuperMethodA(cl
, obj
, msg
);
10670 D(DBF_LISTTREE
, "MUIM_NList_Remove_End");
10676 case MUIM_NList_UseImage:
10680 res = DoSuperMethodA(cl, obj, msg);
10682 D(bug( "USEIMAGE ==> result: 0x%08lx obj: 0x%08lx, imgnum: %ld, flags: 0x%08lx\n", res, m->obj, m->imgnum, m->flags ) );
10687 case MUIM_NList_CreateImage:
10689 struct MUIP_NList_UseImage *m = (struct MUIP_NList_UseImage *)msg;
10692 res = DoSuperMethodA(cl, obj, msg);
10694 D(bug( "CREATEIMAGE ==> result: 0x%08lx obj: 0x%08lx, flags: 0x%08lx\n", res, m->obj, m->flags ) );
10701 return( DoSuperMethodA( cl
, obj
, msg
) );