Hi, I search a piece of code which explains me how can I use Drag and Drop with TreeGadget for sorting differents items...
Thank you in advance...
D'n'D & Treegadget
Look at Freak's Codesnippets 'TreeDrag': http://freak.purearea.net/code/code.html
It is actually much easier now with 4.10 and the Drag & Drop library.
Here is a short example (this code is fully crossplatform)
The Drag & Drop is actually the easiest part here. What needs a bit more code
is the actual moving of the old item to the new place, because we need to move
nodes including all their children.
Run the code and drag around the items. Items named "Directory" can contain
other items.
Here is a short example (this code is fully crossplatform)
The Drag & Drop is actually the easiest part here. What needs a bit more code
is the actual moving of the old item to the new place, because we need to move
nodes including all their children.
Run the code and drag around the items. Items named "Directory" can contain
other items.
Code: Select all
; ------------------------------------------------------------------
;
; Example for Drag & Drop inside a TreeGadget to reorder items.
;
; Requires 4.10 beta or newer to run
;
; ------------------------------------------------------------------
#Tree = 0
#Window = 0
; If you want to do multiple drag&drop in different Gadgets of your program,
; you can use different values here so the events do not collide.
; (ie so the user cannot drag to the wrong gadget)
#PrivateType = 0
If OpenWindow(#Window, 0, 0, 300, 500, "TreeGadget Drag & Drop", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Window))
TreeGadget(#Tree, 10, 10, 280, 480)
; Add some items. We will be able to move items into the
; "Directory" ones.
;
For i = 0 To 20
If i % 5 = 0
AddGadgetItem(#Tree, -1, "Directory" + Str(i), 0, 0)
Else
AddGadgetItem(#Tree, -1, "Item" + Str(i), 0, 0)
EndIf
Next i
; this enables dropping our private type with a move operation
EnableGadgetDrop(#Tree, #PB_Drop_Private, #PB_Drag_Move, #PrivateType)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget
;
; The DragStart event tells us that the user clicked on an item and
; wants to start draging it. We save this item for later use and
; start our private drag
;
If EventGadget() = #Tree And EventType() = #PB_EventType_DragStart
SourceItem = GetGadgetState(#Tree)
DragPrivate(#PrivateType, #PB_Drag_Move)
EndIf
ElseIf Event = #PB_Event_GadgetDrop
;
; Here we get a drop event. Make sure it is on the right gadget and of right type,
; especially if you have multiple Drag & Drop stuff in your program.
;
If EventGadget() = #Tree And EventDropType() = #PB_Drop_Private And EventDropPrivate() = #PrivateType
TargetItem = GetGadgetState(#Tree)
; nothing to do if source and target are equal
;
If SourceItem <> TargetItem
; Find out to which index and sublevel to move the item
;
If TargetItem = -1
; if dropped on the empty area, append at the end
TargetItem = CountGadgetItems(#Tree)
TargetLevel = 0
ElseIf Left(GetGadgetItemText(#Tree, TargetItem), 4) = "Item"
; if dropped on an "Item", move right after this item
TargetLevel = GetGadgetItemAttribute(#Tree, TargetItem, #PB_Tree_SubLevel)
TargetItem + 1
Else
; if dropped on a "Directory", move into the directory and to the end of it
; all this can be easily done by examining the sublevel
TargetLevel = GetGadgetItemAttribute(#Tree, TargetItem, #PB_Tree_SubLevel) + 1
TargetItem + 1
While GetGadgetItemAttribute(#Tree, TargetItem, #PB_Tree_SubLevel) >= TargetLevel
TargetItem + 1
Wend
EndIf
; Find out how many children our source item has, as we want to
; move them all. If you do not allow moving of directory nodes, it gets
; much simpler as there is only one delete + add then.
;
; childnodes are all directly following ones with a higher level
;
SourceLevel = GetGadgetItemAttribute(#Tree, SourceItem, #PB_Tree_SubLevel)
ChildCount = 0
For i = SourceItem+1 To CountGadgetItems(#Tree)-1
If GetGadgetItemAttribute(#Tree, i, #PB_Tree_SubLevel) > SourceLevel
ChildCount + 1
Else
Break
EndIf
Next i
; Note: because by adding new items, the index of our old ones changes,
; we need to make a distinction here wether we move before or after our old item.
; Note also that we cannot move an item into one of its childs, which we
; prevent by this check as well.
;
; We copy first the source item and all children to the new location and then
; delete the source item.
;
If TargetItem > SourceItem + ChildCount + 1
;
; The target index is higher than the source one, so the source items are not
; affected by adding the new items in this case...
;
For i = 0 To ChildCount
; copy everything here (also colors and GetGadgetItemData() etc if you use that)
Text$ = GetGadgetItemText(#Tree, SourceItem+i)
Level = GetGadgetItemAttribute(#Tree, SourceItem+i, #PB_Tree_SubLevel) - SourceLevel + TargetLevel
AddGadgetItem(#Tree, TargetItem+i, Text$, 0, Level)
Next i
; We apply the state of each item AFTER all items are copied.
; This must be in a separate loop, as else the "expanded" state of the items is
; not preserved, as the childs were not added yet in the above loop.
For i = 0 To ChildCount
SetGadgetItemState(#Tree, TargetItem+i, GetGadgetItemState(#Tree, SourceItem+i))
Next i
; remove the source item. This automatically removes all children as well.
RemoveGadgetItem(#Tree, SourceItem)
; select the target. Note that the index is now 'ChildCount+1' less
; because of the remove of the source which was before the target
SetGadgetState(#Tree, TargetItem-ChildCount-1)
ElseIf TargetItem <= SourceItem
;
; Second case: Target is lower than source. This means that each time
; we add a target item, the source items index increases by 1 as well,
; this is why we read the source items with the "SourceItem+i*2"
;
For i = 0 To ChildCount
Text$ = GetGadgetItemText(#Tree, SourceItem+i*2)
Level = GetGadgetItemAttribute(#Tree, SourceItem+i*2, #PB_Tree_SubLevel) - SourceLevel + TargetLevel
AddGadgetItem(#Tree, TargetItem+i, Text$, 0, Level)
Next i
; Loop for the states. Note that here the index of the sourceitems is
; 'ChildCount+1' higher than before because of the added targets
;
For i = 0 To ChildCount
SetGadgetItemState(#Tree, TargetItem+i, GetGadgetItemState(#Tree, SourceItem+ChildCount+1+i))
Next i
; remove source and select target. Here the target index is not affected by the remove as it is lower
RemoveGadgetItem(#Tree, SourceItem+ChildCount+1)
SetGadgetState(#Tree, TargetItem)
EndIf
EndIf
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
End
quidquid Latine dictum sit altum videtur
- DoubleDutch
- Addict
- Posts: 3220
- Joined: Thu Aug 07, 2003 7:01 pm
- Location: United Kingdom
- Contact:
I've used this example loads of times now - it's a great little routine. 

https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
https://reportcomplete.com <- School end of term reports system
Re: D'n'D & Treegadget
Exactly what I searched for.
Many thanks.
BTW: Works also on PB 5.60 (Just CreateGadgetList(9 has to be removed)
Just one thing: Any idea how to get it dropped at the very first position?
The only thing i can think of is: always inserting draged stuff before the item you droped on. But this does not work with directories...
Many thanks.
BTW: Works also on PB 5.60 (Just CreateGadgetList(9 has to be removed)
Just one thing: Any idea how to get it dropped at the very first position?
The only thing i can think of is: always inserting draged stuff before the item you droped on. But this does not work with directories...
Bye Karl
Re: D'n'D & Treegadget
OK, one more thing is missing: Handling of item images.
BTW: Is there some way to obtain the ImageID of a Treeitem so it can be reused in Addgadgetitem?
BTW: Is there some way to obtain the ImageID of a Treeitem so it can be reused in Addgadgetitem?
Bye Karl