## Properties view customization

### Introduction

In UML, the main information is represented in graphical diagrams. However, it is not always possible to represent graphically the whole semantic of UML, not talking of all the cosmetic properties. For example, it is pretty easy to represent and to edit a Class' name graphically. While we still can represent the 'is abstract' property graphically (By using the italic font for the Class' name), it is harder to edit this property directly from the diagram. Worse, the 'is leaf' property doesn't even have a graphical representation. Thus, we often need a different view for representing all the properties of a UML Element, without polluting the graphical view.

As UML is highly extensible, through the mean of Profiles, it is also important to be able to represent and edit the profile's properties, without managing everything from the diagram view.

Eclipse provides a standard view for these properties: the Properties Page. This view is a table representing all the properties available for the selected Element, including the ones that cannot be represented or edited graphically. This view is pretty useful, but is neither really user-friendly nor optimal, as it may require up to four clicks to simply edit a comment's body. Moreover, it can only be extended via Java code, which requires some technical skills and prevents a dynamic modification of the view, as the Java code needs to be recompiled after each modification.

There is an extension of the base Property View framework, still in the standard Eclipse implementation, which fixes some of these problems. It is called the 'Eclipse Tabbed Properties View' framework. It provides a better look and feel for the property view, with more flexibility, and a better usability. However, it keeps being difficult to customize, as it still hard-coded in Java.

Papyrus provides its own Property View framework, based on the Tabbed Property View framework. The Papyrus Property View can be extended in two ways:

- Dynamically, for the layout of the property view: show/hide a property, reorder the properties, add/remove a tab'
- Statically, through Java code, for advanced operations: create a new widget for editing the properties, add a custom Content Provider for selecting a reference value'

This document aims at detailing all the features related to the property view customization, both dynamically and statically.

### The customization tool

Most customizations can be done through the Property view customization Editor. It provides native support for EMF Models, UML models and profiles. It also provides a set of basic widgets and property editors.

### Edit a configuration

Each property view configuration is defined in a different set of files. Each configuration can contain elements from different contexts, but we typically have one configuration per Ecore Metamodel or UML Profile (i.e. one configuration for UML, one for the Diagram Appearance tab, another one for the each DSML profile based')

To see the list of available configurations, open the properties view (Window -> Show View -> Other' -> General/Properties). Click on the white arrow in the upper right corner of the Properties view, and select 'Customize property view'. You should see a dialog with the list of all available configurations.

As the standard configurations are read-only, you cannot edit them directly. You will first need to make a copy of the configuration. You will then be able to edit the copy.

The Property View Editor has three panes:

- The Editor part
- The Preview part
- The Properties part

The Editor presents the elements defined by this configuration. The Preview displays an overview of the selected View, as it will be displayed in the property view at runtime. The properties view displays the properties of the selected element

#### The property view elements

The editor contains a Tree, containing the following elements :

- Context: it is a property view configuration. You will typically have one property view Context per Ecore Metamodel or UML Profile, but you can choose the granularity you want. A context has a list of tabs, and a list of views.
- Tab: describes a tab in the property view. A tab has a label, an (optional) image, and can be indented. It also has a priority.
- View: describes a property view associated to a selection. The view has a name, a constraint, a multiplicity and a list of sections. The constraint is used to determine for what kind of object the view should be displayed.
- Constraint: a query that inputs a selection, and outputs a boolean (true if the constraint matches the input object, false otherwise). It is possible to implement your own constraint type (In Java).
- Section: a section is a sub-part of a view. A view generally needs only one section, but there are cases where you need more than one section. A section is associated to a single tab, so, if you want to display more than one tab in a single view (For example, ' UML ' and ' Profile ' in the UML property view), you will need at least two sections in that view (One for each tab). Another (advanced) case is described in ' Dynamic sections '. A section has a name, a tab, and a Composite.
- Composite: this is the actual presentation element. The composite is a widget which can contain other widgets. A composite has a type, and a list of widgets.
- Layout: all composites need a layout. The default is ' PropertiesLayout ', which is a variant of the SWT standard GridLayout. A PropertiesLayout has a number of columns. The default is one column.
- Property Editor: a property editor is a widget which is used to edit a single property of the selected object. You will typically have one Property editor for each property that you want to edit in the property view. The property editor has a property, and a widget to edit that property.
- Standard Widget: a widget from the standard SWT Library. Few of them are currently available, because they are rarely needed.

The Tree allows reordering or removing easily the elements (Through drag & drop, delete). The editor also supports the Undo/Redo commands.

##### Preview

The preview displays a real-time overview of the selected View. However, some widgets can only be computed at runtime, which prevents a pertinent preview. This is the case of the 'Enum Radio' widget, for example, as the enumerated values are only known at runtime.

##### Property view

The property view is used to edit the properties of the element selected in the tree. The property view uses the Papyrus Property View framework, thus can be customized just the same way you would customize any other property view.

### Priorities between views

When more than one view match a selection, a priority mechanism will determine which one(s) should be displayed. The priorities are defined at the level of the view's constraints, i.e. if the constraint for a View A overrides a constraint for the View B, the View B won't be displayed. For example, a UML Class from a Class Diagram will match many views (The list is not exhaustive):

- SingleClass (From UML)
- MultipleClass (As the -1 multiplicity actually means 'any number of elements')
- SingleElement (And MultipleElement)
- SingleClassifier (And MultipleClassifier)
- *Style (From GMF Notation model)
- StereotypeDisplay (From UML Notation model)

The priorities are computed in two ways:

- Automatic, according to the Java constraints implementations
- Statically, according to the property view configuration

When the 'isOverrideable' property is set to false for a Constraint (In the property view model), only the static rules will be taken into account.

The automatic rules are the following:

- A constraint with a multiplicity of 1 always overrides the same constraint with a multiplicity of -1 (Or >1). Thus, 'MultipleClass' won't be displayed, because 'SingleClass' also matches our selection.
- An EMF (Or UML) 'Instance of' constraint always overrides a constraint matching a supertype. Thus, 'SingleClassifier' won't be displayed, because a Class is more specific than a Classifier. However, 'SingleElement' *will be* displayed, because it is not overrideable (isOverrideable=false).
- A stereotype constraint (HasStereotype) will *not* override its UML 'Instance of' constraint. However, a specific implementation of this constraint has been provided for Scade, which *will* override the UML metaclass (i.e., a Block will override a Class' property view, hiding the UML tab).
- For CompositeConstraints: if a composite constraint is a superset of another constraint, it will override it (It is more specific). For example, a Composite Constraint 'isA and isB' will override a constraint 'isB', but will not override a constraint 'isB and isC'.

Please note that each constraint has its own implementation of the overrides() method. See the advanced chapter for more information

The static rule is simple: when a Constraint explicitly overrides another constraint, it will always override it. This is especially useful when you've marked a constraint as 'overrideable=false', but still want to override it in a specific case (Remember that overrideable=false only applies to *automatic* constraint resolution).

Finally, in the previous example, the following views will be displayed:

- SingleClass (Overrides MultipleClass, Single/MultipleClassifier ; UML Tab)
- SingleElement (overrideable=false ; Profile tab)
- FillStyle, FontStyle, LineStyle (Appearance tab)
- StereotypeDisplay (overrideable=false ; Appearance tab)

#### Preferences

When you make a copy of a property view, it is not automatically activated. Thus, the modifications brought to the copy are not immediately visible on your property view. To activate a property view, you need to open the Papyrus preferences, from Window > Preferences.

When making a copy of an existing configuration, you should uncheck the default one, and check the new one.

#### Profile Tab Preference

In some case, the labels displayed in the' Applied Stereotypes' Widget are too long, as it is illustrated on the next figure.

That's why we propose tree preferences for it:

- Truncate Label: when activated, all the labels displayed in the Applied Stereotype Viewer will be truncated after the number of chars defined by the next field. To illustrate the truncation in the viewer, we add ... to indicate to the user than the label is truncated.
- Number of char to keep before truncating: all is already explained!
- Show the values of the stereotypes properties as children: When this preference is activated, we will stop to the display the properties values in the label of the properties itself (excepted for the null value). We will display the values as property's children.

Truncated Label illustration:

Property's values as children:

### Advanced Customization

The customization tool only allows basic operations, such as adding, removing or reordering properties.

The property view framework is much more powerful, but this requires some Java development. This chapter will focus on the advanced customization of the property view.

#### The Environment model

To associate Java implementations with the property view model, you need to declare an Environment model. You can create a new Environment model with the 'Environment Model' wizard in 'Example EMF Model Creation Wizards' category. Select 'Environment' as the Model Object.

Once you've added your Java class declarations, you should register the environment model so that the property view knows about it. Add an extension to org.eclipse.papyrus.properties.environment, and select your model file.

#### Create a new widget

You can create new widgets for the property view. There are four kinds of graphical elements: CompositeWidget, Layout, StandardWidget and PropertyEditor. The widgets contain three common fields:

- Label: The label displayed in the Customization editor when the user selects a widget type.
- Namespace: The XWT namespace associated to the Widget.
- WidgetClass: The simple name of the Java class implementing the Widget.

The PropertyEditor contains two additional fields:

- Multiplicity: The multiplicity of the properties it can handle (1 for single-valued properties, -1 for multivalued properties)
- Type: The type of the properties it can handle.

To implement a Composite, Layout or Standard widget, you should simply follow the SWT rules, i.e. extend either Composite, Canvas or Layout, and have a (Composite, int) constructor. To define a PropertyEditor, you have two options:

- Extend Composite, have a (Composite, int) constructor, and implement the CustomizablePropertyEditor interface (From org.eclipse.papyrus.properties.widgets)
- Extend directly AbstractPropertyEditor (From org.eclipse.papyrus.properties.widgets)

#### Constraints

Adding a Constraint is similar to creating a new Widget. You have two options to implement a new Constraint:

- Implement the Constraint interface (From org.eclipse.papyrus.properties.constraints)
- Extend the AbstractConstraint class (From org.eclipse.papyrus.properties.constraints)

The important methods are the following (depending on whether you're implement Constraint or extending AbstractConstraint):

- setDescriptor/setConstraintDescriptor:
  - Configures the constraint.
- match(Object)/match(IStructuredSelection) : Boolean
  - Indicates whether this constraint matches the given given or not
- overrides(Constraint) : Boolean
  - Indicates whether this constraint overrides another constraint or not. A constraint should override another constraint when it is more specific.
- equivalent(Constraint) : Boolean
  - This is only used by AbstractConstraint. Two constraints are equivalent if they have the same parameters (ConstraintDescriptor). Two equivalent constraints can have different multiplicities.

The equivalent() and overrides() methods are used to automatically resolve constraints conflicts (Two different constraints matching the same element). Once the Constraint is implemented, don't forget to register it in your environment model.

#### ModelElement

The ModelElement is the interface between the property view and your domain model. It is used to retrieve information about the object(s) being edited from the property. These informations will be used to configure the widget. AbstractModelElement provides a base implementation for this interface.

All methods from this interface take a single parameter, which is the name of the property being edited.

- getObservable(String) / doGetObservable(String) :

This method returns an IObservable which will be used to read and write a single property from the represented object. It should return an IObservableValue for single-valued properties, and IObservableList for multi-valued properties.

- getContentProvider(String) :

This method is only used for reference and enumerated properties. It should return a list of values which can be set to the edited property. Unlike IStructuredContentProvider, this provider will not rely on a StructuredViewer to retrieve an input object: the method getElement() will be called without any parameter, so the implementation should be able to retrieve its own typically. This will typically be achieved by passing a context object in the provider's constructor.

- getLabelProvider(String) :

This method is used to display an element's label for a few widgets. Note that the same instance of label provider can be used by more than one Viewer for a given property. For example, the MultiReference widget will display three viewers, each using the same label provider. Each viewer will try to dispose the LabelProvider as soon as they are themselves disposed (For example, when closing the selection dialog from MultiReference). Thus, you should probably not implement the dispose() method, to avoid inconsistent providers.

- getValidator(String) :

This method returns an IValidator, if there's one which is set up for the current property.

#### ModelElement Factory

The ModelElements are associated to DataContextElements through a ModelElementFactory. The ModelElementFactory is defined on the DataContextRoot. All children of a DataContextRoot will share the same ModelElementFactory.

To add a new ModelElement, you should also create a new ModelElementFactory, and register it in your Environment model. Then, you can set this factory to your DataContextRoot.

Note: to display the Data contexts, you need to check the toggle button on top of the editor:

#### Content Providers and Widgets

Note: The ContentProviders have been refactored in Papyrus 0.9, to be simplified. However, most of this chapter should remain true.

The ContentProvider is a complex features, which often evolves in the Papyrus property view. The ModelElement has been designed to be compatible with many kinds of different widgets (Combo-box, Tree-based dialogs'). The problem is that these widgets typically use different kinds of JFace ContentProvider (IStructuredContentProvider for flat display, ITreeContentProvider for Tree display). In the Property view, we needed to unify these providers.

Thus, it is recommended to use a IHierarchicContentProvider, which extends ITreeContentProvider, with an additional method: isValidValue(Object). In a Tree, we typically have two kinds of elements: the elements which can potentially be selected, and their containers, which often cannot. The isValidValue() method is used to distinguish between these values.

When a flat widget (e.g. ReferenceCombo) is used, only the valid values will be displayed. When a tree-based widget (e.g. ReferenceDialog) is used, a sub-tree will be displayed, excluding the sub-trees which don't contain any valid value. Moreover, the invalid values won't be selectable (For example, in the ReferenceDialog, the 'ok' button will be grayed).

#### Dynamic sections

Sometimes, the property view should not depend on a selection, but on a specific property of the selected element. In such a case, it is frequent that this specific property might be edited by the property view itself. However, the property view is only refreshed when the selection changes.

To overcome this problem, Papyrus offers a 'Dynamic section' feature, which allows refreshing dynamically one or more sections of the property view. For example, when you're editing a View's constraint in the Property view Editor, the constraint's properties directly depend on the constraint's type. When you select an UML constraint, the constraint's parameter is the name of a UML Metaclass. When you select an EMF constraint, the constraint has two parameters: Namespace URI of the Metamodel, and the name of the Metaclass. Changing the constraint type should also change the constraint's parameters editors.

This can be achieved with dynamic sections, i.e. a section with a constraint. The constraint will be executed once at the beginning, and once again each time a property from the property view changes. If the constraint is matched, the section will be displayed. Otherwise, it will be hidden. A view with dynamic sections will typically look like the following:

- A single unconstrained section containing the common parameters
- One dynamic (i.e. constrained) section for each specific case

Please note that tabs cannot be added nor removed dynamically. For example, when you apply a stereotype on a UML Element, the tab associated to the stereotype's property view cannot be displayed until you select the element again.

#### Property view Header

The Eclipse Tabbed Property View offers an extension point to define the label provider for the property view header. However, this label provider will be specific to the editor. For generic editors, it is not always possible to provide a pertinent label provider: they will always be too generic, and won't be able to handle specific elements. For example, a generic EMF Model Editor with the customizable property view will only be able to display standard EMF labels and icons. To overcome this problem, Papyrus offers a configurable label provider for the header: org.eclipse.papyrus.properties.provider.SelectionLabelProvider

This label provider uses the selected element to find the most appropriate label provider, then dispatches the getText and getIcon calls to it. This label provider can be configured through an extension point: org.eclipse.papyrus.properties.labelprovider

This extension point takes an implementation of IFilteredLabelProvider and a priority. The IFilteredLabelProvider is a label provider with an additional method: boolean accept(IStructuredSelection). For each selection, the label provider accepting the selection, and having the highest priority will be used to display a header for it. It will then be possible to define a generic label provider for all java objects, with the lowest priority; another generic label provider for all EMF Objects, and a really specific label provider for a given metamodel (with the highest priority). In Papyrus, we have such an example for UML. The Papyrus UML Diagrams use the GMF model, which doesn't have icons. We wanted to have a different icon for each type of Diagram: this is not possible with a standard EMF label provider, which associates an icon to an EClass, independently of its instances' attributes.

So, we registered the standard EMF Label Provider with a medium priority, which can handle any kind of EObject, and a UML Label Provider, which can only handle UML Elements and GMF Diagrams, with a higher priority.

The lower the priority number, the higher the priority actually is:

- 100: Lowest priority. The standard EMF Object label provider has a priority of 100, and is called iff no other label provider can accept an EObject.
- 50: Medium priority. The Papyrus UML Label Provider has a priority of 50.
- 10: High priority.
- 0: Highest priority.

If no label provider matches the selection, the default JFace LabelProvider is used.

#### Binding and Validation

View Properties support JFace Databinding, which connects our UI to our model. For the validation there are two kinds of validators:

- Widget validators: they check that our input is the kind of data expected by our widget before synchronizing it ( e.g IntegerEditor must have a correct integer for input)

- Model validators: they check that our input verifies our model constraint, they must be instantiate in UmlModelElement#getValidator();

If there are errors during the binding a control decoration is shown next to the widget. It also supports three level of severity (Ok, Warning, Error).

#### Field coloration

Properties views have fields' coloration. If you modify a value the background of the field will be orange, when you validate a change the background will turn green for couple of seconds if the synchronization was successful, it will turn red otherwise.

#### Editors label

Editors label in properties view can be customized with this following possibilities managed by priority:

1. A 'customLabel' specified in the '*.xwt' files
2. By using internationalized name (using `NamedElement#getLabel()` function)
3. By default: A label deduce from the Property of the DataContext. The deduced label is the name of the property with the first letter in upper case.

Examples:

Custom label:

Internationalized name of a stereotype property:

Label decude from the property of the DataContext:

### Generation Tool

Editing an existing property view can be useful, but most of the time, you'll want a brand new configuration for your own profile or meta-model. Thus, the framework provides a tool to automatically generate the initial property view, which you can then customize using the customization tool. The generator can create a property view configuration from either a UML Profile or an Ecore Meta-model. The wizard is available in the Papyrus category: File -> New -> Other' -> Papyrus/Property view configuration.

The wizard provides two default generators:

- Generate a property view from a UML Profile
- Generate a property view from an Ecore Meta-model

The source file must be located in your workspace. A default target file named will be filled with the .ctx extension (This is the extension for a property view configuration).

Press next: a combo asks you which strategy to use.

A basic method: all the elements from the profile or meta-model will be extracted, with no dependencies to other models.

Same CTX file: you are asked to choose which models you want to extract, and will be saved in the same file

Different CTX file(s): you are asked to choose which models you want to extract and they will be saved in different files, (each profile name will be the name of the generated ctx file)

Press next: a table with all the elements extracted from your profile or meta-model is displayed. This table contains four columns:

- Field: the name of the element or property
- Display single: whether this property should be displayed when a single instance of this element is selected
- Display multiple: whether this property should be displayed when more than one instance of this element is selected
- Description: the description of the property (Most of the time, it will be N/A, as the default generators cannot extract the documentation from the source model).

Press finish: two files or more files according to the chosen strategy and a folder are generated:

- The *.ctx file, corresponding to your property view configuration
- The ui/ folder, containing a set of XWT files, which contain the graphical information of your property views
- The *FieldSelection.xmi file, which reminds the choices you've made about displaying each property. This file is currently unused.

You can now open the *.ctx file and customize your property view.

### Deploying a property view

Papyrus provides a simple tool to deploy a property view locally (Right click on a CTX file -> Deploy/Undeploy)

### Interaction between Components

Papyrus provides a way to synchronize several widgets between them. Indeed, this is possible by modifying the XWT files corresponding to the desired components.

#### How to use it ?

To set up the interaction between several components, two global variables were created in "AbstractPropertyEditor":

- listeningPropertyPaths: list of properties to listen,
- listenerClasses: list of classes used to define the behaviors to be adopted when modifying the values of the properties.

A class is defined as: 'bundle name'/'path of the class'

So we need to use these names as attributes in the desired XWT files.

Next, create a class that inherits from "IPropertiesListener" or use an existing class such as "ReadOnlyStringPropertiesListener". The purpose of this class is to define the behavior of the chosen editor according to the associated input.

It is at the ListenerClasses attribute that will be defined this class. The link will be made between the editor and the "PropertiesListener".

Here is an example of adding attributes to an XWT file:

#### Examples

An example "InteractionComponent_Example.zip" is provided in the plugin org.eclipse.papyrus.views.properties.doc, in the folder resource.examples. it is intended to show how the mechanism should be used.

There are 3 examples of interaction between components.

##### First example

For this example, create and select a class. In the 'Properties' view, a new 'tab' is present "InteractionComponent". In this tab, if the name is not empty it is not possible to modify the label. This property is readOnly. This is the listener "ReadOnlyStringPropertiesListener" that is used.

When the 'Name' is empty, the 'Label' can be modified:

Otherwise it is read-only:

##### Second example

It is still necessary to use a class, this time the modification is done on a boolean. Modifying the 'isAbstract' property activates/deactivates the 'isActive' property. This is the listener "ReadOnlyBooleanPropertiesListener" that is used.

When 'isAbstract' is 'true', 'isActive' can be changed:

Otherwise it is read-only:

##### Third example

Here you have to create a constraint and select it.

The enumerated 'Visibility' activates/deactivates the property 'Context'.

If the value is 'Public', the modification is possible, otherwise the property is read-only. The listener used is "ReadOnlyVisibilityPropertiesListener".

When 'Visibility' is 'Public', 'Context' can be changed:

Otherwise it is read-only:

## Multiplicity Editor

### Description

The multiplicity editor contains two modes of edition:

- The simple mode which allows to edit the lower and the upper values from a unique editor
- The advanced mode which allows to edit the lower and the upper values from two editors of ValueSpecification.

### Usage

#### Simple mode

The simple mode is represented as the following:

This editor must be filled by the following pattern:

Value filled | Lower value | Upper value
--- | --- | ---
1 | `null` (default value is 1) | `null` (default value is 1)
x..y | `LiteralInteger` with value x | `LiteralUnlimitedNatural` with value y
x..* | `LiteralInteger` with value x | `LiteralUnlimitedNatural` with value -1 (interpreted as `*`)
x | `LiteralInteger` with value x | `LiteralUnlimitedNatural` with value x

The values set as lower and upper are always positive (except the `*` for the upper which is valued as -1).

This editor is usable only when the lower ValueSpecification is a `LiteralInteger` or `null` and when the upper ValueSpecification is a `LiteralUnlimitedNatural` or `null`. On the other hand, this editor will be displayed like the following:

#### Advanced mode

##### Simple ValueSpecification editor

The advanced mode with simple ValueSpecificatiton editors is represented as the following:

The lower and the upper ValueSpecification can be created/edited/deleted by the buttons:

##### XText ValueSpecification editor

The advanced mode with XText ValueSpecification editors is represented as the following:

This editor use the XText ValueSpecification editors (explain here) with some specificities depending on lower or upper value edition.

The specificity of the lower ValueSpecification edition is when the value filled is an integer, this one will be handled as `LiteralInteger` instead of `LiteralUnlimitedNatural` or `LiteralInteger` (the `*` value will create an `OpaqueExpression`).

The specificity of the upper ValueSpecification edition is when the value filled is an integer or `*`:

- if the integer is positive or -1, a `LiteralUnlimitedNatural` will be created
- if the integer is negative, an `OpaqueExpression` will be created instead of `LiteralInteger`

#### Switch modes

This is possible to switch between the two modes by two ways:

- The button in the multiplicity editor:

- The multiplicity editor preferences in the property views preferences:

Regarless of the way used to switch modes, the mode used is saved in the preferences and will be used for each multiplicity in Papyrus.