Is there any way via scripting to directly get a handle to the parent template “root container” from a component inside the template? I’m trying to create a script that can handle being fired from a variable number of nested containers/groups inside a template. I don’t want to rely on a relative path since it needs to be updated whenever you create a new nested container between the component firing the script and the root template. My current solution is to loop through “parents” until I find a type of ‘VisionTemplate’ which works fine but messy. This feels like a situation where there is a built in method/function that I’m missing…
Your solution is exactly what I do, interested like you though if there’s a cleaner one!
If it is some event that is happening you can use:
rootContainer = system.gui.getParentWindow(event).getRootContainer()
See: https://docs.inductiveautomation.com/display/DOC81/system.gui.getParentWindow
You want SwingUtilities, in a script module like so:
from javax.swing import SwingUtilities
from com.inductiveautomation.factorypmi.application.components.template import VisionTemplate
def getTemplateRoot(component):
return SwingUtilities.getAncestorOfClass(VisionTemplate, component)
Then you can call it anywhere with:
someModule.getTemplateRoot(event.source)
This doesn’t work for templates as it gets the Window’s rootContainer object, not the Template’s rootContainer
This is great, thanks Phil!
Is it possible to access custom methods on objects returned via this function? I’ve tried a few different flavors but always get an AttributeError. I’ve confirmed the custom method works when called via event.source.parent.<customMethodName>()
and I also confirmed they are both pointing to the same object (same type and same name value).
I created another version of your script above that looks to see if the template is contained within a TemplateRepeater and it works great to find the repeater. This repeater has a custom method to refresh some custom props. I want to call this method from within the template, but currently the handle returned to the repeater object doesn’t work with calling the custom method for some reason (but calling repeater_handle.name
returns the proper name just fine…). Only way I can currently call the custom method from within the template is with a million parents (event.source.parent.parent.parent.parent.parent.customMethod()
). Hoping there is a way to get this to work with the handle returned from the function…
Well, yes, with some help. Java Swing methods that work on this level are unaware of the special behavior of Vision Components. If you install my Simulation Aids module, it installs a generic fix for this in the Jython interpreter. And then your component methods and custom properties will work in jython no matter how you get a hold of the object. (:
If you want your brain fried, look at this topic (start here but go back through the whole thing for context):
Interesting. You weren’t kidding, that topic is quite the rabbit hole… I’ll check out your Simulation Aids module. Thanks Phil!