Template events

Hello,

I’ve been working on my first project using Ignition. Ignition is my introduction to Python, however I do see that the scripting environment is a very powerfull tool over other Scada softwares (after all the struggle learning basic Python).

For the project I could make most of the stuff using a few templates, if I could figure out how to invoke events from a template (assuming it is possible). I would really like to make something similar to the ActionPerformed event on the Button component.
As this is my introduction to Python I am still learning, however I do a lot of programming in C# and do know how delegates/event patterns work, I just can’t seem to figure it out in Ignition/Python. Any help/examples would be very much appreciated, thanks.

Templates can certainly contain event-producing objects. The event code in those objects can follow the parent chain up to the holder of the template and work with those components, too. Including invoking custom methods on those components. So Ignition isn’t providing a direct way to have custom events per template instance, but it is achievable.
If you have a specific function you are attempting to achieve, please elaborate.

A special function would be a custom button that doesn’t know how to implement its behavior.
My current approach is your suggestion. I have buttons and textfields working on the data in a Power Table and I have implemented a chain in each template that finds the Power Table which name is bound to custom properties of the templates. However, this approach just seems wrong to me (if I can add events to a template) as each template needs to know what it is doing and if I need e.g. two buttons doing different things but should have somehow identical appearance, the design of these would have to be maintained in two templates instead of one.

Think I found a temporary workaround for my question. If anyone should be interrested then heres the code. The code was tested on the actionPerformed event on a button inside a template.

# Defining a variables similar to the event variables that can be
#	used when defining the function.
#	source = the template that generated the event.
#	container = the container one level above the template container.
source = event.source.getTemplate()
container = source.parent.parent

# Setting up the action event.
exec("def OnActionPerformed():" +
	source.OnAction)

# Calling the method defined above.
OnActionPerformed()

The solution works very well and allows me to define the function through the custom string property “OnAction” on the template. Code below shows the string value for the property.

container.getComponent('Label').newMethod()

the getTemplate() function is a custom function I have on all containers and groups inside templates, that just returns the container one level above untill it reaches the templates root container that returns self.

If someone has the right approach for this please share.

In regards to: “So Ignition isn’t providing a direct way to have custom events per template instance, but it is achievable”, could you elaborate on how this is possible given the following example:

I have a template that contains a single button component. I would like to have a default script run on the ActionPerformed event of the button component. However, for some instances of this template I would like to override the default script. I tried creating a Custom Method on the template, which the button component’s ActionPerformed event calls. But I can’t access the Custom Method from a template instance to override it. It is only available from the template master.

Is there a way to achieve this without having to pass in the override script as a custom property (string)?

Thank you
Dan

This is the crux. The template instance must have a way to tell the template to override. There's no built-in way to do this, but you could define a boolean template parameter to switch the behavior. Place the custom code in a custom method on the instance holder, with the following in the button's actionPerformed event:

if event.source.parent.overrideButton:
    event.source.parent.parent.parent.myCustomOverrideMethod(event)
else:
    ... whatever the default action needs to be ...

Adjust the number of 'parent' references as needed (the instance holder is two levels up from the template's root container, IIRC).
On instances where the default action suffices, leave overrideButton false in the instance. For the others, define myCustomOverrideMethod() and set overrideButton true.

I understand how to add a custom boolean for enabling the override, but I don’t quite understand how to define the custom method for specific instances. I want to be able to define a custom override method that could be unique for each instance of the template. But the scripting dialog does not allow me to add a custom method at the instance level (or am I missing something).
So if the custom override method can only be defined for the template and not for the instance, then I don’t follow how to achieve this.

Thank you for your assistance.
Dan

Well, shoot. I hadn't noticed that deficiency in the simple template holder. Both the repeater and the canvas allow custom methods. You'll have to place the template instance (by itself) in another container layer and put the custom method on the container.

1 Like

Yes, that solution works. I can add a custom method for override to a container that the template instance is placed in. It’s obviously not as clean as if the method was added directly to the template instance, but it works. Maybe a good new feature idea would be to allow custom methods on template instances.

Thanks for your help

1 Like

That’s exactly what my workaround does except the string property OnAction in my example defines where that override method exists, e.g.

container.myOverrideMethod()

This would call myOverrideMethod on the parent container.

Note that the custom method call had access to the event object from the action performed event making the following valid as well

system.gui.closeParentWindow(event)

Your solution uses exec(). Evil and slow and totally disconnected from any code editor. Hard to create, hard to troubleshoot, and very hard to secure.

Slow maybe, nothing noticed when pressing a button. Evil why? Not more evil than a custom method if not exposed to any client inputs! Disconnected, YES, that’s exactly the point.

I agree adding a custom override method on the template would be more efficient, unfortunately this is not possible.