Dynamic property palette
The property palette can be created and changed dynamically during the runtime of a PythonPart. In this chapter we are going to focus on various methods, which can control the look and layout of the elements of the property palette.
Control properties
The ControlProperties are the internal data structure for creating the PythonPart property palette. The properties are responsible for a.o.:
- text shown on the left side of the palette
- value checking (min/max value, value list)
- background color of the control field
- hiding/showing and enabling/disabling a control
To modify these control properties during the runtime of the PythonPart, use the methods provided in the ControlPropertiesUtil. Using this utility, properties mentioned above can be changed in the script when the palette is initialized or with each property modification done by the user.
In a standard PythonPart the ControlPropertiesUtil object is passed as an argument to the following functions:
- initialize_control_properties - called before the property palette is displayed
- modify_control_properties - called after each change within the property palette
Implement them in your script to get the access to the methods provided in the utility.
In an interactor PythonPart the ControlPropertiesUtil must be constructed first.
from ControlPropertiesUtil import ControlPropertiesUtil
...
ctrl_prop_util = ControlPropertiesUtil(control_props_list, build_ele_list) #(1)!
- The
control_props_list
andbuild_ele_list
are python lists containing ControlProperties and BuildingElement objects respectively. These lists are passed by the framework directly to the create_interactor function based on the .pyp file when the PythonPart is initialized.
After the utility is constructed, its methods can be used as follows:
if ...:
ctrl_prop_util.set_text("Distance", "Distance from left") #(1)!
else:
ctrl_prop_util.set_text("Distance", "Distance from right")
- In this case the text shown in the palette for the parameter Distance is changed
from the default value defined in the
<Text>
tag in the .pyp file intoDistance from left
.
Hide or disable a control
Sometimes it's useful to disable or hide a control inside the property palette dynamically e.g., based on a value of another parameter. This behaviour can be implemented directly in the .pyp file or in the script.
The visibility and enable state of an input control can be managed with the tags
<Enable>
and <Visible>
. Dynamically, as well as statically. Here is how it can be done:
<Enable>True</Enable> <!--(1)!-->
<Visible>0</Visible>
<Enable>CheckBox1 == True</Enable> <!--(2)!-->
<Visible>RadioButtonValue in [1, 5]</Visible>
<Enable>ObjectName == __StringTable.get_string("1220", "Column")</Enable> <!--(3)!-->
<Enable>$list_row != HideListRow</Enable> <!--(4)!-->
<Visible>StirrupList[$list_row].Select</Visible>
<Visible>__is_visible_control("Length") and Length > 0</Visible> <!--(5)!-->
<Enable>__is_input_mode()</Enable> <!--(6)!-->
<Visible> <!--(7)!-->
if Length < 1000:
return True:
if Width ><!--(8)!--> 1000:
return True
return False
</Visible>
-
By a constant value
-
By logical Python formula that includes other parameters
-
By a logical Python formula that includes access to the string table
-
By a logical Python formula that includes access to the list row
-
By a logical Python formula that includes a check for the visibility of a parameter
-
By a logical Python formula that includes a check to the input mode. The function
__is_input_mode()
returns False for PythonPart modification -
By a multi-line Python condition returning False and True like
-
Because the .pyp file uses the xml syntax, the expressions
<
and>
must be used instead of<
and>
operators.
If the complexity of the enable or visible condition if high, it may be useful to implement the behavior in a function within the .py file. Using the utility class ControlPropertiesUtil mentioned before, the function must be assigned to the control defined by the parameter name using the method set_enable_function or set_visible_function
def initialize_control_properties(build_ele, ctrl_prop_util, _doc):
...
def visible_length(...) -> bool: #(1)!
#perform operations to determine the visibility
return ...
def enable_length(...) -> bool:
#perform operations to determine the visibility
return ...
ctrl_prop_util.set_visible_function("Length", visible_length)
ctrl_prop_util.set_enable_function("Length", enable_length)
-
Provide the right parameter in (...) depending on the type of the parameter value:
value type parameter single value ()
list of values (row_index: int)
single namedtuple (field_name: str)
list of namedtuple (row_index: int, field_name: str)
Example
Examples can be found here:
- …\etc\Examples\PythonParts\PaletteExamples\Visibility.pyp
- …\etc\PythonPartsExampleScripts\PaletteExamples\Visibility.py
- …\etc\Examples\PythonParts\PaletteExamples\NamedTuple.pyp
- …\etc\PythonPartsExampleScripts\PaletteExamples\NamedTuple.py
- …\etc\Examples\PythonParts\PaletteExamples\ValueList.pyp
- …\etc\PythonPartsExampleScripts\PaletteExamples\ValueList.py
Active page
Sometimes it's useful to do display the handles or some preview data depending on which page of the property palette is currently active. This behavior can be implemented with the set_active_palette_page_index function.
In a standard PythonPart just implement the function set_active_palette_page_index into your script. You can copy the implementation from the source code below or refer to the template located in ...\etc\PythonPartsFramework\PythonPartsScriptTemplates\
In an interactor PythonPart the function can be implemented as a method of the interactor class. When the page is changed by the user, the method is called and the index of the active page is passed to it as an argument. You can copy the implementation from the source code below, or refer to the template located in ...\etc\PythonPartsFramework\PythonPartsScriptTemplates\
Dynamic text
If the text inside the property palette needs to be dynamic, this can be implemented
in the script by using ControlPropertiesUtil
as described in the chapter before. However, it is also possible to implement
this behavior directly in the .pyp file using the <TextDyn>
tag. The same can be done for the
<ValueTextDyn>
tag, which creates a dynamic value text.
A single line Python expression can be implemented in this tag like this:
<TextDyn>__StringTable.get_string(1003, "Placement") + ("Right" if DistanceHeader else "Left")<!--(1)!--></TextDyn>
- Functions from the math package are possible and can be used by math.xxx.
A multi-line Python expression can also be implemented. The Python source code for the expression
must be left aligned in the .pyp file. Because the .pyp file uses the XML syntax, <
and
>
operators must be used instead of <
and >
.
In case of a list parameter, the row index can be accessed with $list_row
.
Example
For a complete usage of dynamic text, see the example:
- …\etc\Examples\PythonParts\PaletteExamples\OptionalTags\TextDyn.pyp
- …\etc\PythonPartsExampleScripts\PaletteExamples\OptionalTags\TextDyn.pyp