I'm an arborist and I'm all right...

BlitzMax Forums/Brucey's Modules/I'm an arborist and I'm all right...

Brucey(Posted 2010) [#1]
Interesting things you can do with trees :
SuperStrict
 
Framework wx.wxApp
Import wx.wxFrame
Import wx.wxTreeCtrl
Import wx.wxTextDropTarget
Import wx.wxTextDataObject
Import wx.wxDropSource

New MyApp.Run()
 
Type MyApp Extends wxApp

	Method OnInit:Int()
	
		Local sz:MyFrame = MyFrame(New MyFrame.Create(Null, wxID_ANY, "Drag Drop Example", -1, -1, 250, 280))
		sz.Show(True)
 
		Return True
	End Method

End Type

Type MyFrame Extends wxFrame
 
	Field treectrl:wxTreeCtrl
	Field dragItem:wxTreeItemId
	
	Method OnInit()
		
		treectrl = New wxTreeCtrl.Create(Self, -1)
		
		Local root:wxTreeItemId = treeCtrl.AddRoot("Root")
		For Local i:Int = 1 To 10
			treectrl.AppendItem(root, "Node Number " + i)
		Next
		
		treeCtrl.ExpandAll()
		
		Centre()
 
		Local target:MyTextDropTarget = New MyTextDropTarget.CreateTarget(Self)
		treeCtrl.SetDropTarget(target)

		treeCtrl.ConnectAny(wxEVT_COMMAND_TREE_BEGIN_DRAG, _OnDrag, Null, Self)

	End Method
	
	Function _OnDrag(event:wxEvent)
		MyFrame(event.sink).OnDrag(wxTreeEvent(event))
	End Function
	
	Method OnDrag(event:wxTreeEvent)

		dragItem = event.GetItem()
		
		If Not dragItem.Equals(treectrl.GetRootItem()) Then
		
			Local tdo:wxTextDataObject = New wxTextDataObject.Create(treectrl.getItemText(dragItem))
			Local tds:wxDropSource = New wxDropSource.Create(tdo, treectrl)
			tds.DoDragDrop(wxDrag_AllowMove)
			
		End If

	End Method
	
End Type


Type MyTextDropTarget Extends wxTextDropTarget

	Field s:MyFrame
	Field ctrl:wxTreeCtrl
	
	Method CreateTarget:MyTextDropTarget(owner:MyFrame)
		s = owner
		ctrl = s.treectrl
		Super.Create()
		Return Self
	End Method

	Method OnDropText:Int(x:Int, y:Int, data:String)
	
		Local flags:Int
		
		' find the item we drop onto
		Local item:wxTreeItemId = ctrl.HitTest(x, y, flags)

		' everything is okay to do the drop?
		'  - source is okay
		'  - target is okay
		'  - target <> source
		'  - target <> root
		If s.dragItem And s.dragItem.isOk() And item.isOk() And Not item.Equals(s.dragItem) And Not item.Equals(ctrl.GetRootItem()) Then
			
			' create a new item
			Local newItem:wxTreeItemId = Ctrl.InsertItem(ctrl.GetItemParent(item), item, data)
			' copy its user data, if any
			ctrl.SetItemData(newItem, ctrl.GetItemData(s.dragItem))
			
			' remove the original item
			ctrl.DeleteItem(s.dragItem)
		
			' select the 'moved' item
			ctrl.SelectItem(newItem)
		End If

		Return False
	End Method

End Type


So much interestingness, so little code :-p


plash(Posted 2010) [#2]
Weird.. it works on Windows but not Linux.


Brucey(Posted 2010) [#3]
Works on Mac too... :-)


JoshK(Posted 2010) [#4]
Is it possible to drag an item from one tree to another?

Is it possible to drag an item from a tree to a property in a property grid control?


JoshK(Posted 2010) [#5]
I improved your code a bit by selecting the dragged node when dragging. Is it possible to display a line where the node will be dropped? It isn't very obvious right now:
SuperStrict
 
Framework wx.wxApp
Import wx.wxFrame
Import wx.wxTreeCtrl
Import wx.wxTextDropTarget
Import wx.wxTextDataObject
Import wx.wxDropSource
Import brl.standardio
Import brl.random

New MyApp.Run()
 
Type MyApp Extends wxApp

	Method OnInit:Int()
	
		Local sz:MyFrame = MyFrame(New MyFrame.Create(Null, wxID_ANY, "Drag Drop Example", -1, -1, 250, 280))
		sz.Show(True)
 
		Return True
	End Method

End Type

Type MyFrame Extends wxFrame
 
	Field treectrl:wxTreeCtrl
	Field dragItem:wxTreeItemId
	
	Method OnInit()
		
		treectrl = New wxTreeCtrl.Create(Self, -1,0,0,wxTR_HAS_BUTTONS)
		
		Local root:wxTreeItemId = treeCtrl.AddRoot("Root")
		For Local i:Int = 1 To 10
			treectrl.AppendItem(root, "Node Number " + i)
		Next
		
		treeCtrl.ExpandAll()
		
		Centre()
 
		Local target:MyTextDropTarget = New MyTextDropTarget.CreateTarget(Self)
		treeCtrl.SetDropTarget(target)

		treeCtrl.ConnectAny(wxEVT_COMMAND_TREE_BEGIN_DRAG, _OnDrag, Null, Self)

	End Method
	
	Function _OnDrag(event:wxEvent)
		MyFrame(event.sink).OnDrag(wxTreeEvent(event))
	End Function
	
	Method OnDrag(event:wxTreeEvent)
		
		dragItem = event.GetItem()
		
		treectrl.SelectItem(dragitem)
		
		If Not dragItem.Equals(treectrl.GetRootItem()) Then
		
			Local tdo:wxTextDataObject = New wxTextDataObject.Create(treectrl.getItemText(dragItem))
			Local tds:wxDropSource = New wxDropSource.Create(tdo, treectrl)
			tds.DoDragDrop(wxDrag_AllowMove)
			
		End If
	End Method
	
End Type


Type MyTextDropTarget Extends wxTextDropTarget

	Field s:MyFrame
	Field ctrl:wxTreeCtrl
	
	Method CreateTarget:MyTextDropTarget(owner:MyFrame)
		s = owner
		ctrl = s.treectrl
		Super.Create()
		Return Self
	End Method

	Method OnDropText:Int(x:Int, y:Int, data:String)
	
		Local flags:Int
		
		' find the item we drop onto
		Local item:wxTreeItemId = ctrl.HitTest(x, y, flags)

		' everything is okay to do the drop?
		'  - source is okay
		'  - target is okay
		'  - target <> source
		'  - target <> root
		If s.dragItem And s.dragItem.isOk() And item.isOk() And Not item.Equals(s.dragItem) And Not item.Equals(ctrl.GetRootItem()) Then
			
			' create a new item
			Local newItem:wxTreeItemId = Ctrl.InsertItem(ctrl.GetItemParent(item), item, data)
			' copy its user data, if any
			ctrl.SetItemData(newItem, ctrl.GetItemData(s.dragItem))
			
			' remove the original item
			ctrl.DeleteItem(s.dragItem)
		
			' select the 'moved' item
			ctrl.SelectItem(newItem)
		End If

		Return False
	End Method

End Type



rs22(Posted 2010) [#6]
Is SetItemDropHighlight of any use to you?


Winni(Posted 2010) [#7]
Works on Mac too... :-)


I don't know what it is, but trying to compile anything as a multi-threaded app no longer works since the BMX 1.40 update:

Undefined symbols:
  "_threads_GetThreadData", referenced from:
      _444 in appstub.debug.mt.macos.x86.a(debugger_mt.stdio.bmx.debug.mt.macos.x86.o)
  "_threads_SetThreadData", referenced from:
      _444 in appstub.debug.mt.macos.x86.a(debugger_mt.stdio.bmx.debug.mt.macos.x86.o)
  "_threads_AllocThreadData", referenced from:
      _442 in appstub.debug.mt.macos.x86.a(debugger_mt.stdio.bmx.debug.mt.macos.x86.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status


Single-threaded compilation works fine.


ima747(Posted 2010) [#8]
try rebuilding all your modules, single and multi-threaded. I dunno why but I get similar glitches some times and I have to rebuild both to get MT building working again... I blame gremlins personally.


JoshK(Posted 2010) [#9]
Is SetItemDropHighlight of any use to you?

Looking at the docs, I don't think so, unless you can tell me why.

Is there any way to give better visualization of the tree drag and drop operation? You can only drag a node onto another node, and there is no visual feedback for where it will be inserted.


Winni(Posted 2010) [#10]
try rebuilding all your modules, single and multi-threaded.


That's what I usually do after an upgrade. But 1.40 really seems to have some gremlins aboard, at least for multi-threaded builds. The funny thing is that in most cases it helps to build first a single-threaded version and then it's also possible to create a multi-threaded build.