Programmatically Add Script

I am trying to programmatically add a script to a window (from within my module) on the InternalFrameActivated listener. It seems that I could leverage the ComponentScriptEditor class, but I am not having luck in that direction. What would be the most sensible approach to this task? I understand this is far in the weeds, but I like to experiment.

To not do this.

Adding scripts to windows and components is a task for the future user running the designer.

On top of that, the techniques used by Ignition to hold these scripts, while relatively stable, are implementation details that can be changed by IA at any future release.

What, exactly, do you think you need this for?

1 Like

As a module developer I have strived to implement code that reduces setup and provides functionality. The company I work for has many clients, and consequently many projects. My module requires a script to be applied to each window that needs the module functionality, which can be tedious. I have written the script in a way that makes it window-agnostic, meaning I can paste the same script into every window. If I could do this programmatically instead of via the designer, the module would be easier to install and consequently more easily sold.

This functionality could also be useful for some agentic modules I have planned in the future.

what do you mean by adding a script to the window?
gateway event script on startup?

Prop binding script?

Adding a script to a listener on the window

You should be writing a java listener for this task, and adding it to windows at runtime when your module functionality is invoked.

Are you supplying a Vision component? If so, have the component ensure the window listener is attached when its startup method is called.

The script is built to tell a client tag which window has become focused. I cannot pair this with the module’s overall functionality because the component is rooted in a popup and relies on the tag to tell it which window is active.

It still doesn't belong in the user's event script. It belongs in a window event listener. Provide a script function that attaches the desired listener to a given window if not already attached. Or provide custom openWindow() script functions that do this in addition to the normal window open operations.

Perhaps explore the use of FPMIApp.setWindowOpener(). (Would require some reflection, I presume.)

Could I override the normal behavior of an existing event listener and add my tag writing functionality under the hood? Or would it be better to attach a brand new listener? Furthermore, is it possible to attach a listener to a window that is not currently open?

You need to use a separate listener, leaving the IA listener to do its normal thing.

You need to add your listener to an open window. There's no way to add to a closed window.

Perhaps you should write a java scheduled task that checks every few seconds for the existence of windows that do not have the listener, and just fix them.

How would I replicate the behavior of InternalFrameActivated in a new listener? I need that exact behavior in order for the module to work as intended.

Or perhaps I can avoid this entirely if there is a java-accessible property for the currently active/focused window?

It is a standard Java Swing Listener:

Without diving into the whole rest of this thread, I'll mention VisionDesktop.addDesktopListener()

Which is the API the 'current window' system client tag uses to know when to reevaluate, for instance:
appContext.getPrimaryDesktop().addDesktopListener(this);

Oooooo! That would notify the module when any new window is opened, which could then add the necessary listener on the fly, reliably.

Does the DesktopListener()keep track of the focused window or just the last window opened?

It doesn't keep track of anything; it's just a listener interface. If you want to track any state you have to do it yourself.

One more small issue finishing this setup. The InternalFrameEvent can only return the local window name instead of the Vision window path. What would be the best way to get the Vision window path from the InternalFramEvent or it’s respective local window name?

If it's an instance of FPMIWindow it'll have a com.inductiveautomation.factorypmi.application.FPMIWindow#getPath method.