Drag and Drop in Ignition

Is it possible to have drag 'n drop in Ignition?
For example: there are two text input components on the screen and I want to drag 'n drop the text from text component 1 to text component 2?
I know that there’s a mouseDragged event in component scripting. So I can read the text in the text component 1, but I don’t know how to ‘drop’ that text to text component 2?
I’ve searched the forum, but didn’t find any usefull info…
Has anyone already done something like that?

Hi zxcslo

its not exactly what you want but this script on each component will allow a copy and paste, you’ll need a custom property called “Copy” on the root container, try it with a couple of text fields using the mouse released function. You might want to define a global script and have “copy” as a memory tag and then you can use it across windows

[code]

def copy(event):
import system,app
text = event.source.text
event.source.parent.Copy = text
def paste(event):
import system,app
text = event.source.parent.Copy
event.source.text = text

menu = system.gui.createPopupMenu({“Paste”:paste,“Copy”:copy})
menu.show(event)[/code]

Thank you, Chris.
As I didn’t find anything useful about drag and drop, I was also trying this copy/paste ‘solution’.
It’s OK, working, but it’s not as ‘elegant’ as drag and drop. :slight_smile:
As good as Ignition is, I find hard to believe, that there is not possible to use drag and drop for something like this… :scratch:

Zxcxlo

The only thing I can think of at the moment is to automate the copy and paste functions depending on whether the drag starts in a component or end in a component, but that’s not straight forward. It’s easy to know when you are dragging within a component but not into or out of a component. If you know that one field will only be pasted and one will only be copied, i.e. a one way drag that that might be doable, but two way needs thought.

If you have two text boxes named Text Box Source and Text Box Destination and a custom property on the root container named clipboard:

In the mouseDragged event for Text Box Source

if len(event.source.parent.clipboard) < 1:
	event.source.parent.clipboard = event.source.text

and in the mouseEntered event for Text Box Destination

if len(event.source.parent.clipboard) > 0: event.source.text = event.source.parent.clipboard event.source.parent.clipboard = ""

Edit: nmudge’s solution is much easier. Nice one Nick. :thumb_left:

Add the following script to each Text Field component you want drag and drop enabled on. Add it to the component’s mouseEntered event handler:

event.source.setDragEnabled(True)

Once this is done you can select text in one Text Field and drag and drop it into another Text Field.

This works because drag and drop is supported by Java Swing, which is the underlying framework of the Vision Module.

Best,

I’ve gota learn me some more Java, thats neat.

Thank you guys for this.
@nmudge: setDragEnabled is working only for text components (text input, textlist). Which is cool… but…
In my OP I meant ‘general’ drag-n-drop. Or mybe there’s another name for it (?). Text component was just for example.
I my real project I need to detect, when the user presses mouse button on the component (label, template, button, circle, square, picture,…) and start dragging. OK, that I can detect with mouseDragged event. Then I need to detect on the other component (which can be also anything; label, picture, template, circle, line,…) when the mouse is over it and mouse button released (which was pressed over another component), so that I can react to it - do some actions (set some tags in the PLC, read from database,…).
I don’t know Java, but I know (from reading it on Internet) that Java has some methods for drag and drop (setSource, setDestination, …). Maybe it is possible in some way to do/use that in Ignition also?

I’d like to resurrect this thread because I am looking for an elegant way of dragging a row from a power table and drop onto an equipment schedule component. On drop, I would auto-generate the scheduled event on the machine and date/time dropped and auto-set the end datetime to some calculated duration based on the contents of the row.

Anyone have ideas on how this would be scripted?

1 Like

I have the same problem. I need drop a item from treview a power table. I doit a listener in power table but i can’t do a droper from treview. I like look Tag Browse Tree do

I also would like to feed this zombie :grinning:
I would like to be able to drag-and-drop from a tag browse tree onto a template object on a vision window and have it “bind” the template to the dragged tag path. I have this working with a click on the tag tree and then a click on a target on the template, but drag-and-drop would be so much more intuitive.

Have at it :slight_smile:

Drag and drop in Java Swing is non-trivial if you have direct access to the source code. Doing it from the Jython environment in Ignition is another layer of complexity.

1 Like

@PGriffith thank you for this. Not trivial, but not too painful either.

Posting back here for posterity in case anyone tries to use this in v8 like I did. In v8, the ClientNodeListTransferable class is no longer implemented in the Easy Chart component, so the import statement in the sample code will not work.

	from java.awt.dnd import DropTargetListener, DropTarget
	from com.inductiveautomation.factorypmi.application.components.chart.easychart import ClientNodeListTransferable

In my case, I really only needed the DropTargetListener and DropTarget functions, and I used the selectedPaths dataset of the tag browse tree in the drop event of my listener to get the “binding” behavior I needed.

1 Like

Hi Dustin.

Please, could you share this example?

Thank

Sure.

I’ve attached a main window export that uses this drag and drop method.
On the vision window open event script, I call an initialization method for the drag-and-drop listeners on all the necessary components:
visionWindowOpened script:

root = event.source.rootContainer
root.initializeDragDropListeners()

root custom method:
image

    root = self	
    comps = [
		<paths to all of your components with listeners>
	]
	for comp in comps:
		try:
			comp.addListener()
		except:
			pass

addListener method on component (path in root custom method):
image

	from java.awt.dnd import DropTargetListener, DropTarget
	
	class DragDropListener(DropTargetListener):
		def __init__(self, comp):
			DropTargetListener.__init__(self)
			self.comp = comp
	
		def drop(self, e):
			comp = self.comp	## ref to the component
			## do stuff here
            ## notice that the *data* being dropped is not referenced here. 
            ## in the attached example the source components are updating root custom properties that represent tag paths and then the drop method is updating the necessary bindings on the target component

		def dragOver(self, e):
			pass
		def dragExit(self, e):
			pass
		def dragEnter(self, e):
			pass
			
	DragDropListener = DragDropListener(self)
	DropTarget(self, DragDropListener)
			

In this example, I stopped short of retrieving the dragged data in the drop method. I’m dragging UDT tag paths from a tag browse tree to a tuning dashboard (PIDbot, shout-out to @joseph.burns for his great work!) and I found it easier to update custom props on the root container when the tag browse tree selection changed. In this way, I can just reference the root container property in the drop-method.

Hopefully this is helpful.Window_TuningDashboard_2021-05-03_2134.zip (141.8 KB)

1 Like

Hi Dustin.

I tried open TuningDashborad but I got following error:
SerializationException: Unexpected parsing error during binary deserialization.
caused by IOExceptionWithCause: java.lang.ClassNotFoundException: com.jlbcontrols.pidbot.client.components.dash.TuningDashboardComponent
caused by ClassNotFoundException: com.jlbcontrols.pidbot.client.components.dash.TuningDashboardComponent

Ignition v8.1.1 (b2020120808)
Java: Azul Systems, Inc. 11.0.7

I´m noob working with Ignition, I´m looking for a table that updates by dynamically dragging tag. But I have a problem with “com.inductiveautomation.factorypmi.application.components.chart.easychart import ClientNodeListTransferable” like you explained. So I don´t know how I must modified this methods.

powertable_2021-05-04_1034.zip (16.3 KB)

I am grateful for your help.

1 Like

Dustin’s example uses a Third Party Ignition Module called Pidbot. You need to download and install it on your Ignition gateway in order to open windows that use components from the module.

You can download it here:

Ignition module installation instructions:
https://docs.inductiveautomation.com/display/DOC80/Installing+or+Upgrading+a+Module

2 Likes

Joe beat me to it with the link to PIDbot, which is a very cool module BTW, so having to download it to import the example window isn’t such a bad thing.

If you just need the drag-and-drop you should be able to copy and paste out whatever you need from the example and customize to fit your needs without the need for the tuning dashboard component. (Like dragging onto a table or other component)

1 Like