Project Views
Project Views are a fundamental aspect of customizing the editor's user interface. They define how your model is presented to the user, including the layout of the editing area, the types of visual representations available (like diagrams), and the navigation options within the project.
By configuring Project Views, you can tailor the editor experience to the specific needs of different metamodels and user workflows.
Project View Components: Defining Editor Layouts
Project View Components dictate the primary layout of the editor's main editing area. They are activated when a user selects a model element in the project navigation (typically a root element like a program or module). The user can then switch between views provided by the ProjectViewComponents.
Each projectViewComponent
targets a specific ElementClass
(the type of model element it applies to) and a category
(which defines the structural layout of the view).
ProjectViewComponents
are typically designed to target model root elements, such asprograms
ormodules
, as they define the overall view for a significant part of the model.- The editor provides three standard, built-in view categories:
tree-detail
: This is a two-pane layout, featuring the model's tree view on the left and the details panel of the selected element on the right.3-pane
: This layout offers three panes: the tree view on the left, the element details on the right, and a central pane typically used for a diagrammatic representation of the model.diagram
: This view dedicates the entire editing area to a full-size diagram of the model, maximizing the visual workspace.
- If more than one
projectViewComponent
is applicable to the currently selected model element and view category, the editor will display tabs, allowing the user to easily switch between these different view implementations. - If autogenerate is enabled, the expanders will generate a default implementation for each view.
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>application-project</name>
<projectViewComponents>
<projectViewComponent>
<name>ComponentTreeDetail</name>
<autogenerate>true</autogenerate>
<category>tree-detail</category>
<elementClass>elements::Component</elementClass>
</projectViewComponent>
<projectViewComponent>
<name>Component3Pane</name>
<autogenerate>true</autogenerate>
<category>3-pane</category>
<elementClass>elements::Component</elementClass>
</projectViewComponent>
<projectViewComponent>
<name>ComponentDiagram</name>
<autogenerate>true</autogenerate>
<category>diagram</category>
<elementClass>elements::Component</elementClass>
</projectViewComponent>
</projectViewComponents>
</editorModelExtension>
In this example, three different view components are defined for the elements::Component
element class, each
corresponding to a standard view category.
Project Facets: Enhancing Project Navigation
Project Facets provide the navigation options presented within the project navigation sidebar.
The editor automatically creates a navigation option for each program in the project by matching projectFacets that target that program element. If no specific facet is defined for a program, the editor will utilize a default navigation implementation.
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>application-project</name>
<projectFacets>
<projectFacet>
<name>Application</name>
<!-- This facet provide navigation for Application -->
<elementClass>elements::Application</elementClass>
<views>
<!-- define view categories for this facet -->
<projectViewCategory>tree-detail</projectViewCategory>
<projectViewCategory>3-pane</projectViewCategory>
<projectViewCategory>diagram</projectViewCategory>
</views>
<options>
<!-- Define an icon with the option -->
<mrp.material.symbols.icon>monitor</mrp.material.symbols.icon>
</options>
</projectFacet>
</projectFacets>
</editorModelExtension>
In this configuration:
- A
projectFacet
namedApplication
is defined forelements::Application
elements. - When an
elements::Application
instance is present in the project, a navigation entry for that Application will appear. - Clicking this navigation entry will expose the
tree-detail
,3-pane
, anddiagram
views, assuming corresponding projectViewComponents are defined. A monitor icon from the Material Symbols library will be displayed in the navigation option.
Diagram Components: Visualizing Your Model
Diagram Components are essential for providing visual representations of your model. When defined, the editor generates
a customizable component that can render diagrams. These diagrams are typically displayed within the 3-pane
and diagram
views, offering users an intuitive way to understand complex model structures.
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>prime-diagrams</name>
<diagramComponents>
<diagramComponent>
<name>DataElementsClass</name>
<title>Data Elements</title>
<projectViews>
<elementClass>elements::Component</elementClass>
</projectViews>
</diagramComponent>
</diagramComponents>
</editorModelExtension>
Custom Views: Beyond Standard Layouts
While the standard views cover many use cases, you might occasionally need to create entirely custom editor views that don't fit these predefined layouts. This section outlines a common pattern for implementing such custom views.
The pattern involves three main steps:
- Create a new custom view category: This separates your custom view from the standard categories, providing a unique identifier.
- Create a customized facet: This facet will link your custom view to a specific navigation entry, potentially always present or conditionally active.
- Create a
ProjectViewComponent
to implement the custom editor view: This component will contain the actual logic and UI for your specialized view.
Custom Project View Categories
To define a new view category for your custom view, you'll need to:
a. Define a settings directory: Ensure your expansionSettings.xml
includes a settingsDirectory
that points to where your view category XML file will reside.
<expansionSettings>
<!-- ... -->
<settingsDirectories>
<settingsDirectory>
<directory>../conf</directory>
</settingsDirectory>
</settingsDirectories>
</expansionSettings>
b. Define the ProjectViewCategory
XML: Create an XML file within your conf/projectViewCategory/
directory
(or wherever your settingsDirectory points) to define your new category.
<projectViewCategory xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>build-expand</name>
<title>Expand</title>
<options>
<!-- Define icon with option -->
<mrp.material.symbols.icon>construction</mrp.material.symbols.icon>
</options>
</projectViewCategory>
Here, build-expand
is the internal name, and "Expand" is the user-facing title.
Customized Facet
To make your custom view accessible, you'll typically define a ProjectFacet
that targets your new projectViewCategory
.
If you omit the elementClass
for a projectFacet
, it will always be present in the project navigation, making it a good
choice for global custom tools or views.
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>build-pages</name>
<projectFacets>
<projectFacet>
<name>build</name>
<views>
<!-- Target your custom view category -->
<projectViewCategory>build-expand</projectViewCategory>
</views>
<options>
<mrp.material.symbols.icon>build</mrp.material.symbols.icon>
</options>
</projectFacet>
</projectFacets>
</editorModelExtension>
This build
facet will always appear in the navigation, and when selected, it will show the build-expand
view.
Customizing Facet Behavior (TypeScript):
Generated facets will have methods that you can customize in TypeScript to control their applicability and the model they represent.
-
isApplicable()
method: This method determines if the facet should be shown in the navigation for a given project. You can add custom logic to make it conditional.export class BuildFacet implements ProjectFacet {
//...
static async isApplicable(project: ProjectData): Promise<boolean> {
// anchor:custom-is-applicable:start
// Add custom logic here to determine if this facet is applicable.
// For example, check for specific elements in the project or flags.
// anchor:custom-is-applicable:end
return true
}
} -
model() method: This method is crucial. It defines the ModelProjection that the facet represents when selected. The selection must be a valid element that your custom ProjectViewComponent is designed to handle.
export class BuildFacet implements ProjectFacet {
//...
async model(): Promise<ModelProjection> {
// anchor:custom-model:start
// Return a representation of the 'model' that your custom view expects.
// In this case, we have a Project ElementClass that acts as target element.
return new ProjectModel({
name: this.project.name,
baseUrl: this.project.baseUrl
})
// anchor:custom-model:end
}
}
Custom project view
Finally, you need to create the ProjectViewComponent
that will implement the actual UI and logic for your custom editor
view. This component targets your custom projectViewCategory
and the ElementClass
that your facet's model()
method returns.
<editorModelExtension xmlns="https://schemas.normalizedsystems.org/xsd/editorElements/4/0/0">
<name>build-pages</name>
<projectViewComponents>
<projectViewComponent>
<name>Expand</name>
<autogenerate>false</autogenerate>
<category>build-expand</category>
<elementClass>build::Project</elementClass>
</projectViewComponent>
</projectViewComponents>
</editorModelExtension>
The ProjectViewComponent is expanded as an Angular Component and can be customized as necessary.