Get Template Root from Component Inside the Template

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!

1 Like

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)
3 Likes

This doesn’t work for templates as it gets the Window’s rootContainer object, not the Template’s rootContainer

1 Like

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):

1 Like

Interesting. You weren’t kidding, that topic is quite the rabbit hole… I’ll check out your Simulation Aids module. Thanks Phil!