21.5. Working with the Property Provider

The property provider will allow a user to add custom properties to the Python Code object. These properties will be available in the in the UI and will also be available through the scripting API.

Jump to a Property Provider topic:

Usage

To use the property provider, you simply set the PropertyProvider property on the Python Code object to an instance of a class that implements IPropertyProvider interface. There’s a class template provided in the Property Provider tab in the Python Code UI. You can use this template as is to add custom properties or make changes as necessary to customize.

The Provider class in the Property Provider does the following for you:

  1. Implements the IPropertyProvider interface

  2. Adds a helper AnsGroup class that groups the properties in the details view.

  3. Exposes some other helper methods that allow you to:

    • Access the properties that you have created via scripting API.

    • Control different aspects of your properties, such as whether they are visible, read-only, etc.

Property Controls

You can create properties of four different control types.

  • Expression

  • Double

  • ApplyCancel

  • Options

These property control types can be further extended, and custom properties can be created using these base properties. An example of this is the scoping property, which you will see being added as an example in the property provider tab. You can access the python code that extends these base properties in “INSTALL_DIR/aisol/DSPages/Python/mech_templates/property_templates.py”. These property templates show how we can combine Options, and ApplyCancel property to create a scoping property that you may see in an object like Pressure.


Note:  The expression control is for a string property. It does not imply connection to Mechanical expressions.


Working with Properties

Let us work through an example to understand the various aspects of the Provider class in the provider tab.

Adding New Properties

Let us first start by adding new properties using the Provider class. The idea here is that you create groups using the provider instance, then you add properties to those groups, and you connect the provider instance back to the Python Code object. After you have written the code to do this, last step is to Reload the properties using option in the context tab in the Ribbon or right click context menu in the tree.

You will see some helper code in a function named reload_props in the property provider tab that shows how to create a group and add new properties to it.

def reload_props(): 
    #Create an instance of the provider. 
    provider = Provider()

    # Add a group with the group name Group 1 to the provider 
    group = provider.AddGroup("Group 1") 

    # Use the group returned to add a property called Property 1 with control type Double 
    prop = group.AddProperty("Property 1", Control.Double) 

    # Double properties have a member called ValidRange that can be assigned a tuple that 
    # controls the validity of the property 
    prop.ValidRange = (1.0, 4.0) 

    # Create an instance of a scoping property in the same group as the double property.  
    # Here we pass in property type as a string because this type is a custom property 
    # Created using templates that extend the base properties. 
    scoping_prop = group.AddProperty("Scoping Property", "Scoping", "property_templates") 

    # Add a group with the group name Group 2 to the provider 
    group_2 = provider.AddGroup("Group 2") 

    # add a double property to this group 
    double_prop_2 = group_2.AddProperty("Property 2", Control.Double) 

    #Finally, we set the PropertyProvider member on this to the provider instance. "this" 
    # refers to the current Python Code object that you are working with. 
    this.PropertyProvider = provider

Important:  Property and group names must be unique, this will come into play later when we access the properties from the property provider.


Removing Properties

To remove properties, you simply remove the code that is adding the property to the group in the provider and reload the properties again. In our example, let’s remove "Group 2" and "Property 2," to do that we will remove the following lines from the reload_props() function.

#Add a group with the group name Group 2 to the provider 
group_2 = provider.AddGroup("Group 2") 
#add a double property to this group 
double_prop_2 = group.AddProperty("Property 2", Control.Double) 

Important:  This action will remove the properties that you have removed from your code but will also reset the other properties which means any values assigned to the properties will be lost when you reload.


Accessing the Properties

You can access the properties using the path to the property from the Python Code object. The path to a property is constructed by concatenating the property group name and property name, separated by a forward slash. For example, if you have a property named "Property 1," in group named “My Group”, the path of this property would be "My Group/Property 1."

For example, if you want to access the double property’s value, you would do the following:

prop_val = this.GetCustomPropertyByPath("Group 1/Property 1").Value

To get the value of the scoping property in the example, you must do things a bit differently because it’s an extended property. The way the extended property is written, it uses the strings "Geometry Selection," "Named Selection," "Define By" in all scoping property instances and uses the property name provided to make the property names unique. For example, if you created a scoping property with name "Scope 1," to access the geometry selection property value of that property you would use the name "Group Name/Scope 1/Geometry Selection."

To access the geometry selection value of the scoping property that was created in the previous example, do the following:

geom_sel_val = this.GetCustomPropertyByPath("Group 1/Scoping Property/Geometry Selection").Value 
Parameterization

You can make your custom properties parameterizable. However, this is only supported for Double properties. To make your properties parameterizable, you need to set the CanParameterize property on the property instance to True. As a default, this will turn the property into an input parameter. To make this property an output parameter, you must set the property ParamterType to ParamterType.Output. Taking the script from the first example if you wanted to make Property 1 an input parameter and Property 2 an output parameter you would make the following changes.

#Use the group returned to add a property called Property 1 with control type #Double 
prop = group.AddProperty("Property 1", Control.Double) 

#Will make prop an input parameterizable property 
prop.CanParameterize = True 

#add a double property to this group 
double_prop_2 = group2.AddProperty("Property 2", Control.Double) 

#Will make double_prop_2 an output parameter 
double_prop_2.CanParameterize = True 
double_prop_2.ParameterType = ParameterType.Output

Controlling the Properties

You can use the callback functions exposed in the Provider class to control certain aspects about your custom properties. The callback functions are there to simply help you, you can override these with your own functions for your properties.

These callback functions are connected to the property delegates in the AddProperty function in the AnsGroup class.

IsValidCallback

The IsValid callback allows you to control the validity of your property based on some conditions. This validity will also control the state of your object. If your property is in invalid, your Python Code object will show as under-defined in the Tree. The invalidity of your object will also be indicated by the property being highlighted yellow in the details pane.

This callback could be something like a valid range as seen in the screen shot below.

You will see the definition above in the Provider class. In case the instance of the property is a DoubleProperty the ValidRange property on the property instance is used to decide whether the property is valid.

IsReadOnlyCallback

The IsReadOnlyCallback allows you to control whether your property should be read-only or not in the details pane. This is useful if you want your property be something that just provides some information. Similar to the IsValid callback a template for this is provided as a function in the Provider class as seen in the screenshot below:

The above callback as a default returns False, however can be customized. For example, if you wanted to make property with the name “Property 1” to be read-only. The following code can be added to the function definition to achieve that. The new definition will look like this:

IsVisible Callback

The IsVisble callback allows you to control whether your property shows up in the details view. You return a boolean value based on some conditions from the function in the Provider class.

SetValue Callback

The SetValue callback allows you to control what the internal value of the property is based on what value the property is being set to. For example, if you want to put an upper limit on what the value for a DoubleProperty should be, you can do this via validating the property. However, you can also use the SetValue callback, where if the user enters a value larger than the upper limit, you set the internal value to the upper limit. Let the upper limit be 20, if the user sets the value to 21, you can force the value to be set to 20. The following code can accomplish this for a property with the name “Property 1”:

GetValue Callback

The GetValue callback allows you to control what the value of the property is when queried using the Value property on the property instance.

Defining Callback Handlers

You can define your own functions that handle these callbacks. For example, you create prop1 which is of type Double and you want to user your own function to handle the IsValid callback. After you get the instance of your property from the AddProperty method, you set the IsValid delegate to your function definition. Your function signature should match the function signature in the Provider class except the self argument. Here is what this would look like in the Property Provider tab:

def my_is_valid(val): 
    # your validity code here 
    return True 
prop1 = group.AddProperty("Property 1", Control.Double)  
prop1.IsValidCallback = my_is_valid 

The example above, creates prop1 which has a custom IsValidCallback handler “my_is_valid” which validates whether the value of the property is equal to 1.