Drag and drop from Tree View to List

Hi, I am trying to drag and drop from tree view to list

example image

Script i am using in tree view in mouse pressed

from java.awt.dnd import DragSource,DragGestureListener
from java.awt.dnd import DragSourceListener 
from java.awt.dnd import DnDConstants
from java.awt.datatransfer import Transferable
from java.awt.datatransfer import StringSelection
	
def addDrag(self):	
	class MyDragGestureListener(DragGestureListener):
		def  __init__(self,selectedPath):
			DragGestureListener.__init__(self)
			
		def dragGestureRecognized(self,DragGestureEvent): 
			transferable = StringSelection("");
			myDragDrop.startDrag(DragGestureEvent, DragSource.DefaultCopyDrop, transferable, myDragSourceListener)
	
	class MyDragSourceListener(DragSourceListener):
		def __init__(self,selectedPath):
				DragSourceListener.__init__(self)
		
	class MyDragDrop(DragSource): 
		def __init__(self,selectedPath):
			DragSource.__init__(self)
			self.selectedPath = selectedPath
			
	myDragGestureListener = MyDragGestureListener(event.source)
	myDragSourceListener = MyDragSourceListener(event.source)
	myDragDrop =  MyDragDrop(event.source)
	myDragDrop.createDefaultDragGestureRecognizer(event.source,DnDConstants.ACTION_COPY_OR_MOVE, myDragGestureListener)

example screen shot

when i drag i am getting this error

Exception in thread "AWT-EventQueue-0" java.awt.dnd.InvalidDnDOperationException: Drag and drop in progress
	at java.desktop/sun.awt.dnd.SunDragSourceContextPeer.setDragDropInProgress(Unknown Source)
	at java.desktop/java.awt.dnd.DragSource.startDrag(Unknown Source)
	at java.desktop/java.awt.dnd.DragSource.startDrag(Unknown Source)
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor256.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
	at org.python.core.PyObject.__call__(PyObject.java:422)
	at org.python.core.PyMethod.__call__(PyMethod.java:187)
	at org.python.pycode._pyx136.dragGestureRecognized$3(<event:mousePressed>:14)
	at org.python.pycode._pyx136.call_function(<event:mousePressed>)
	at org.python.core.PyTableCode.call(PyTableCode.java:173)
	at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
	at org.python.core.PyBaseCode.call(PyBaseCode.java:197)
	at org.python.core.PyFunction.__call__(PyFunction.java:485)
	at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
	at org.python.core.PyMethod.__call__(PyMethod.java:228)
	at org.python.core.PyMethod.__call__(PyMethod.java:218)
	at org.python.core.PyMethod.__call__(PyMethod.java:213)
	at org.python.core.PyObject._jcallexc(PyObject.java:3565)
	at org.python.core.PyObject._jcall(PyObject.java:3598)
	at org.python.proxies.__builtin__$MyDragGestureListener$58.dragGestureRecognized(Unknown Source)
	at java.desktop/java.awt.dnd.DragGestureRecognizer.fireDragGestureRecognized(Unknown Source)
	at java.desktop/sun.awt.windows.WMouseDragGestureRecognizer.mouseDragged(Unknown Source)
	at com.inductiveautomation.factorypmi.application.components.util.EventDelegateDispatcher$MouseEventDispatcher.mouseDragged(EventDelegateDispatcher.java:145)
	at java.desktop/java.awt.AWTEventMulticaster.mouseDragged(Unknown Source)
	at java.desktop/java.awt.AWTEventMulticaster.mouseDragged(Unknown Source)
	at java.desktop/java.awt.Component.processMouseMotionEvent(Unknown Source)
	at java.desktop/javax.swing.JComponent.processMouseMotionEvent(Unknown Source)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" NotImplementedError: 'MyDragSourceListener' object does not implement abstract method 'dragEnter' from 'java.awt.dnd.DragSourceListener'
Exception in thread "AWT-EventQueue-0" NotImplementedError: 'MyDragSourceListener' object does not implement abstract method 'dragOver' from 'java.awt.dnd.DragSourceListener'
Exception in thread "AWT-EventQueue-0" NotImplementedError: 'MyDragSourceListener' object does not implement abstract method 'dragOver' from 'java.awt.dnd.DragSourceListener'
Exception in thread "AWT-EventQueue-0" NotImplementedError: 'MyDragSourceListener' object does not implement abstract method 'dragOver' from 'java.awt.dnd.DragSourceListener'
Exception in thread "AWT-EventQueue-0" NotImplementedError: 'MyDragSourceListener' object does not implement abstract method 'dragDropEnd' from 'java.awt.dnd.DragSourceListener'

can anyone please correct my script please

Consider using DragSourceAdapter as your base, instead of DragSourceListener

There's also some example code on the forums you can use as a base, if you haven't already found it.

Okay a little bit of work and understanding, and taking @PGriffith's tip, and I was able to accomplish this.

This will do multi or single selection, and will handle dragging folders. The drop listener also filters out duplicate paths.

You'll want to add this code to a custom function on your Tree View component that you call from the InternalFrameActivated event on the window.

def addDragSource(self):
	from java.awt.dnd import DragSourceAdapter, DragGestureListener, DragSource, DnDConstants
	from java.awt.datatransfer import DataFlavor, Transferable
	
	#A custom transferable which allows a List to be transfered
	#via Drag and Drop.
	class customTransferable(Transferable):
		_transferData = None
		def __init__(self,data):
			self._transferData = data
		
		def getTransferData(self,flavor):
			return self._transferData
		
		def getTransferDataFlavors(self):
			return [DataFlavor(list,'List')]
		
		def isDataFlavorSupported(self,flavor):
			if not DataFlavor(list,'List'):
				return False
			return True
	
	#Custom listener to build the transferable when a drag gesture is recognized.
	#Takes in a component (assumes PMITreeView)		
	class customDragGestureListener(DragGestureListener):
		_comp = None
		_selectedPaths = []
		def __init__(self,comp):
			self._comp = comp
			
		def dragGestureRecognized(self,e):
			dataFlavor = DataFlavor(list,'List')
			
			self.addPaths(self._comp.selectedPaths)
			
			transferable = customTransferable(self._selectedPaths)
			e.startDrag(DragSource.DefaultCopyDrop,transferable)
	
		def addPaths(self,paths):
			for path in paths:
				if not self._comp.separationCharacter in path:
					#this is a root folder, add all sub paths of this folder
					subPaths = [subPath for subPath in self._comp.data.getColumnAsList(0) if path in subPath]
					self.addPaths(subPaths) 
				#if path is found in first columnn then it is a folder.
				#only add paths that aren't in 
				elif path in self._comp.data.getColumnAsList(0):
					#build subPaths list
					subPaths = [row['path'] + '/{}'.format(row['text'])	for row in system.dataset.toPyDataSet(self._comp.data) if row['path'] == path]
					self.addPaths(subPaths)
				elif not path in self._selectedPaths:
					self._selectedPaths.append(path)
				
	
	ds = DragSource.getDefaultDragSource()
	ds.createDefaultDragGestureRecognizer(self, DnDConstants.ACTION_COPY, customDragGestureListener(self))

Then add this to the List component. You will also need to call this from InternalFrameActivated

def addDropTarget(self):
	from java.awt.dnd import DropTargetAdapter, DropTarget
	from java.awt.datatransfer import DataFlavor
	class customDropListener(DropTargetAdapter):
		_comp = None
		def __init__(self,comp):
			self._comp = comp
		def drop(self,e):
			e.acceptDrop(e.getDropAction())
			self._comp.addData(e.getTransferable().getTransferData(DataFlavor(list,'List')))
			e.dropComplete(True)
			
	DropTarget(self,customDropListener(self))

I also used a custom addData function on the List here for the filtering.

def addData(self,data):
	paths = self.data.getColumnAsList(0)
	
	if not paths and not self.data.columnCount:
		#this takes care of an empty dataset
		self.data = system.dataset.addColumn(self.data,[],'Paths',str)
	newRows = [[path] for path in data if not path in paths]
	self.data = system.dataset.addRows(self.data,newRows)
5 Likes

@lrose

one question

I have the tree view in a template and i am using that template in window. how to call the tree view custom function in window InternalFrameActivated?