Basics
EditorModelExtensions
EditorModelExtensions are the core mechanism for extending the functionality of the editor through plugins. They allow you to customize how your model is represented, displayed, and interacted with within the editor.
Extensions are defined in XML files located within the model/extensions/ directory of your plugin. Each extension is declared in its own XML file, like so:
model/
plugin.xml
extensions/
elements.xml
application-project.xml
prime-diagrams.xml
Each extension file starts with the <editorModelExtension>
root element and specifies a unique name:
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>elements</name>
</editorModelExtension>
ElementTreeNode: Building the Model's Tree View
ElementTreeNode Components are responsible for defining how elements in your model are represented within the editor's tree view. They dictate the structure and content of the tree, allowing users to navigate and understand the model's hierarchy.
You define these components within the <elementTreeNodes>
section of your extension:
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>elements</name>
<elementTreeNodes>
<elementTreeNode>
<name>Component</name>
<!-- ElementClass this node represents -->
<elementClass>elements::Component</elementClass>
<children>
<!-- nested nodes -->
<elementTreeList>
<!-- label for the nested elements -->
<name>dataElements</name>
<!-- ElementTreeNode used for the nested elements -->
<childNodeType>elements::DataElement</childNodeType>
<!-- Reference used as data source -->
<compositionReference>elements::Component::dataElements</compositionReference>
</elementTreeList>
</children>
<options>
<!-- Define an icon for this tree node to represent the target ElementClass -->
<mrp.material.symbols.icon>graph_2</mrp.material.symbols.icon>
</options>
</elementTreeNode>
<elementTreeNode>
<name>DataElement</name>
<elementClass>elements::DataElement</elementClass>
<!-- ... -->
<options>
<mrp.material.symbols.icon>data_table</mrp.material.symbols.icon>
</options>
</elementTreeNode>
</elementTreeNodes>
</editorModelExtension>
In this example:
- The
Component
tree node represents elements ofelements::Component
class. - It can have child nodes, specifically a list named
dataElements
. - This
dataElements
list will display children of typeelements::DataElement
, sourced from theelements::Component::dataElements
composition reference.
ElementDetailComponent: Displaying and Modifying Element Details
ElementDetailComponents define the user interface for displaying and modifying the properties of a selected model element. This is where users interact with the specific attributes and relationships of an element.
Configure these components within the <elementDetailComponents>
section of your extension:
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>elements</name>
<elementDetailComponents>
<elementDetailComponent>
<name>Component</name>
<!-- Set autogenerate to `false` to completely customize the detail view. -->
<autogenerate>true</autogenerate>
<elementClass>elements::Component</elementClass>
<options>
<!-- Add the color option to link a specific color hue to elements of this type. -->
<color.lch.hue>270</color.lch.hue>
</options>
</elementDetailComponent>
<elementDetailComponent>
<name>DataElement</name>
<autogenerate>true</autogenerate>
<elementClass>elements::DataElement</elementClass>
<options>
<color.lch.hue>270</color.lch.hue>
</options>
</elementDetailComponent>
</elementDetailComponents>
</editorModelExtension>
Here:
- An ElementDetailComponent named
Component
is defined for theelements::Component
class. - When
autogenerate
is set totrue
(as shown), the editor automatically generates a default detail view based on the element's schema. - Setting
autogenerate
tofalse
allows you to provide a custom UI for the detail view, offering complete control over its appearance and functionality.
Actions: Enabling model interactions
Actions allow you to define operations that users can perform on model elements, such as creating and deleting elements. These actions are defined once in your extension and then linked to specific tree nodes or lists where they should be available.
Defining actions
Actions are defined within the <actions>
section of your editorModelExtension:
<editorModelExtension
xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>elements</name>
<actions>
<editorAction type="editorElements::CreateAction" xsi:type="createAction">
<!-- Unique identifier -->
<name>createComponentDataElements</name>
<!-- Detail Component used to edit the new instance -->
<elementDetailComponent>elements::DataElement</elementDetailComponent>
<!-- Composition reference to which to add the new instance. -->
<reference>elements::Component::dataElements</reference>
</editorAction>
<editorAction type="editorElements::DeleteAction" xsi:type="deleteAction">
<name>deleteDataElement</name>
<elementClass>elements::DataElement</elementClass>
</editorAction>
</actions>
</editorModelExtension>
In this example:
createComponentDataElements
is aCreateAction
that creates a new DataElement and adds it to thedataElements
reference of a Component. Theelements::DataElement
detail component will be used for editing the new instance.deleteDataElement
is aDeleteAction
specifically forelements::DataElement
instances.
Assigning Actions to Tree Nodes and Lists
Once defined, actions are linked to elementTreeNode or elementTreeList entries within the <actions>
tag:
<editorModelExtension
xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>elements</name>
<actions>
<!-- ... -->
</actions>
<elementTreeNodes>
<elementTreeNode>
<name>Component</name>
<elementClass>elements::Component</elementClass>
<actions>
<editorAction>elements::createComponentDataElements</editorAction>
</actions>
<children>
<elementTreeList>
<name>dataElements</name>
<actions>
<editorAction>elements::createComponentDataElements</editorAction>
</actions>
<childNodeType>elements::DataElement</childNodeType>
<compositionReference>elements::Component::dataElements</compositionReference>
</elementTreeList>
</children>
</elementTreeNode>
<elementTreeNode>
<name>DataElement</name>
<elementClass>elements::DataElement</elementClass>
<actions>
<editorAction>elements::deleteDataElement</editorAction>
</actions>
</elementTreeNode>
</elementTreeNodes>
</editorModelExtension>
Activation condition: Controlling Plugin Availability
You can control when an editorModelExtension
(and thus its associated plugin functionality) becomes active within the
editor. This is achieved by adding an <activation>
element to your extension.
- Activate when an Ontology is loaded.
- Activate when an instance of an ElementType is detected.
To activate an extension only when a specific ontology is present in the dataRegistry,
use the ActivateIfOntologyPresent
type:
<editorModelExtension
xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>prime-diagrams</name>
<activation type="editorElements::ActivateIfOntologyPresent" xsi:type="activateIfOntologyPresent">
<ontology>elements</ontology>
</activation>
</editorModelExtension>
This configuration ensures that the prime-diagrams
extension will only be active if the elements
ontology
is supported by the expansion-resources defined by the project.
To activate an extension when an instance of a particular ElementClass
is detected in the model,
use the ActivateIfElementTypePresent
type:
<editorModelExtension
xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>application-project</name>
<activation type="editorElements::ActivateIfElementTypePresent" xsi:type="activateIfElementTypePresent">
<elementType>elements::Application</elementType>
</activation>
</editorModelExtension>
This means the application-project
extension will become active only if an instance of elements::Application
exists within the model being edited.