Skip to content

Latest commit

 

History

History
744 lines (492 loc) · 28.4 KB

reference.adoc

File metadata and controls

744 lines (492 loc) · 28.4 KB

Reference

Editor Placement

Diagram / Direct Editor

A direct editor is activated by

  • double-clicking on the diagram element,

  • pressing kbd:[F2] while the diagram element is focused,

  • or starting to type while the diagram element is focused.

The editor replaces the label and is sized to fit its contents.

For single-line editors, the editor closes on pressing kbd:[Enter].

Editor contents are committed to the model when the editor is closed. The editor closes when it loses focus, e.g. by a click outside the editor.

Design

Direct editors are specified as tool in the odesign editor. newDirectEditor

We provide the following variants:

  • XtextEdgeLabelDirectEditModelDescription Edge Label Direct Editor for Model content

  • XtextEdgeLabelDirectEditValueDescription Edge Label Direct Editor for Value content

  • XtextDirectEditModelDescription Direct Editor for Model content

  • XtextDirectEditValueDescription Direct Editor for Value content

They can be added to the tools section the same as a regular Direct Edit Label tool. Accordingly, they need to be selected as Label Direct Edit on the Behavior page of the edited Sirius element.

behaviorLabelDirectEditSelection

The label is independent of the edited text, i.e. the label can show a different text than the direct editor.

If the set value operation feature is empty, it is interpreted as to replace var:self.

Capabilities

Direct editors

If the editor contains model contents, it supports to limit the editable features, to ignore some nested features, and to define pre-selected features. If the Sirius element is an edge, the editor requires to select an edgeLabelPosition.

Property View / Property Editor

The Eclipse Properties View contains the property editors.

Editor contents are committed when the editor is hidden. This happens when the end-user selects a different property page or a different diagram element.

Design

Property editors are specified as property widgets in the odesign editor. newPropertyWidget

We provide the following variants:

  • XtextSingleLineModelDescription Text (aka single-line) Widget for Model content

  • XtextMultiLineModelDescription Text Area (aka multi-line) Widget for Model content

  • XtextSingleLineValueDescription Text (aka single-line) Widget for Value content

  • XtextMultiLineValueDescription Text Area (aka multi-line) Widget for Value content

They can be added as a widget to a Properties Sirius element the same as regular widgets.

Capabilities

Property editors

If the editor contains model contents, it supports to limit the editable features, to ignore some nested features, and to define pre-selected features.

Editor Contents

Editing Models

The editor can contain semantic elements from the same model the edited diagram is based on.

A typical use-case may allow the end-user to edit several features of a semantic element in-line with complete Xtext support.

Example

As an example, think of a UML class attribute displayed as + age: int = 0. If the end-user opens the direct editor of the attribute, they can change all these features (visibility, name, type, default value) with complete Xtext support, e.g.

  • Proposing all possible visibilities

  • Validating the name (e.g. do not allow spaces)

  • Proposing and checking the available types

  • Allow no, a literal, or a referenced default value

Details

The editor assumes the model of the edited diagram is persisted with the same Xtext grammar as supplied to the editor (except for explicit differences).

If the Xtext language provides a formatter, the editor will apply the formatter before showing the editor to the end-user.

Any changes in the editor are applied to the underlying model of the edited diagram (except non-editable features and ignored nested features). The changes are committed to the Sirius edit session, but only persisted if and when the edited diagram is saved.

The editor maintains references between the edited semantic element (and its descendants) and the rest of the model in both directions, if possible. The editor does not prevent the end-user from breaking references, e.g. by changed referenced names or deleting referenced elements.

In order to provide appropriate auto-completion and other Xtext features, the editor maintains a complete copy of the edited diagram’s model (and optionally all other Ecore resources of the Sirius session). However, only the subsection relevant to the selected semantic element (and limited by the editable features, if applicable) is shown to, and editable by, the end-user.

Determining the correct subsection is quite complicated, especially if the subsection borders in grammar terminals or contains unset features. This may lead to incorrectly selected subsections. However, the result should only be affected by the grammar, therefore the developer can test this during development.

The editor reintegrates its contents into the edited diagram’s model on model level, not on text level. This means if the end-user modified any part of the model not contained within the edited semantic element, these changes are not committed. The editor also omits changes to non-editable features or ignored nested features from the commit.

Editing Values

The editor can interpret simple String feature of semantic elements as Xtext models.

A typical use-case may allow the end-user to edit the description feature of a semantic element as markup text with complete Xtext support.

Example

As an example, think of an entity model containing classes that may have descriptions. By its metamodel, the description is merely a String. An Xtext value editor (primed with an Xtext implementation of HTML) for the description allows the end-user to describe the class with complete Xtext support for HTML.

Details

Any changes in the editor are stored in the semantic element’s String feature as-is. The changes are committed to the Sirius edit session, but only persisted if and when the edited diagram is saved.

Editor Infos[1]

Injector

An injector describes a complete Xtext configuration for a language.

In order to avoid class loading issues, we provide injectors via Eclipse extension point com.altran.general.integration.xtextsirius.runtime.xtextLanguageInjector.

xtextLanguageInjector.exsd (in digestible form)
<extension point="com.altran.general.integration.xtextsirius.runtime.xtextLanguageInjector">
  <!-- [0..*] injectors -->
  <injector
    id="«unique id of this injector to be referenced from odesign model»"
    class="«fully qualified name of instance of com.altran.general.integration.xtextsirius.runtime.xtextLanguageInjector»"
  />
</extension>

For each injector, we need to define an id (to be referenced from the odesign model) and a class that implements com.altran.general.integration.xtextsirius.runtime.IXtextLanguageInjector.

IXtextLanguageInjector.java
package com.altran.general.integration.xtextsirius.runtime;

import com.google.inject.Injector;

public interface IXtextLanguageInjector {
	public static final String EXTENSION_POINT_ID = "com.altran.general.integration.xtextsirius.runtime.xtextLanguageInjector";

	public Injector getInjector();

	/**
	 * Whether we should use a specialized injector that avoids mandatory
	 * horizontal and vertical scrollbars.
	 *
	 * <p>
	 * By default, the Xtext embedded editor always shows horizontal and
	 * vertical scrollbars; they are disabled (greyed out) if not required. We
	 * can hide unnecessary scrollbars, but this requires a specialized injector
	 * that binds its own implementation for
	 * <tt>{@link com.google.inject.Provider Provider}<{@link org.eclipse.xtext.ui.editor.embedded.EmbeddedEditorFactory.Builder EmbeddedEditorFactory.Builder}></tt>.
	 * This fails if the injector already has a binding for this type.
	 * </p>
	 *
	 * @return {@code true} if we should use a specialized constructor,
	 *         {@code false} otherwise.
	 */
	default boolean useSpecializedInjectorForProperties() {
		return true;
	}

}

A typical implementation is provided below.

FowlerdslLanguageInjector.java
import org.eclipse.xtext.example.fowlerdsl.ui.internal.StatemachineActivator;

import com.altran.general.integration.xtextsirius.runtime.IXtextLanguageInjector;
import com.google.inject.Injector;

public class FowlerdslLanguageInjector implements IXtextLanguageInjector {

 @Override
 public Injector getInjector() {
  // note we're using the activator from the UI plugin generated by Xtext.
  //
  // Replace both the activator class and the parameter
  // with the respective ones of your language.
  return StatemachineActivator.getInstance()
    .getInjector(StatemachineActivator.ORG_ECLIPSE_XTEXT_EXAMPLE_FOWLERDSL_STATEMACHINE);
 }
}

We refer to the id via the InjectorId property.

Single-line vs. Multi-line

The editor can display one single line or several lines.

Effects for single-line editors:

  • All newline characters from the original content are replaced by the same amount of spaces.

  • It is not possible to enter a newline.

  • kbd:[Enter] closes the direct editor.

For direct editors, we define this info via the Lines property. It will adjust its size automatically.

For property editors, we define this info by selecting the appropriate widget. For Text Area widgets, we can define the number of lines to be shown via the Line Count property.

PrefixText and SuffixText

In order to provide appropriate auto-completion and other Xtext features, a value editor requires a complete model. However, the String feature may contain only a subsection of a complete model. Therefore, the developer may provide text that should be pre-pended and appended to the String feature’s value in order to complete the model. The end-user still sees and edits only the String feature’s value.

Example

Think of a simplified version of HTML implemented as Xtext language. A complete model might look like this:

<html>
<head>
	<title>This is a test</title>
</head>
<body>
	<p>Some paragraph</p>
	<ul>
		<li>This is <b>important</b></li>
		<li>And something's <i>useful</i></li>
	</ul>
	<p>Some other not so <i>very interesting,</i> but yet <b>highlighted</b> paragraph</p>
</body>
</html>

This language should be used for the description feature of classes in an entity model.

However, the model may contain several such classes, and the description of all of them should end up in only one HTML file (in a later generation step). Instead of storing a complete model into every class' description (and bothering the end-user with it), the description contains only the following part:

	<p>Some paragraph</p>
	<ul>
		<li>This is <b>important</b></li>
		<li>And something's <i>useful</i></li>
	</ul>
	<p>Some other not so <i>very interesting,</i> but yet <b>highlighted</b> paragraph</p>

In order to complete the model for Xtext, the developer supplies the editor with

prefixTextExpression

<html><head><title>Title</title><head><body>

suffixTextExpression

ocl:'</body>'.concat('</html>')
(the expression does not make sense really, it’s only to show we actually can use expressions.)

This way, Xtext works on a complete model, but only the relevant parts are available to the end-user.

We provide these infos via the prefixTextExpression / suffixTextExpression properties. As hinted by the name, these fields accept both a simple string as well as any expression supported by Sirius.

Editable Features

The editor can limit which features of a semantic element are editable by the end-user.

A typical use-case hides the feature defining the source and/or target of an edge from being edited textually.

Example

Assume the following Xtext grammar snippet defining an UML-like Association, to be displayed as edge:

Association:
	name=ID
	code=INT?
	('[' guard=Guard ']')?
	source=[Class] '-->' target=[Class]
;

Example model:

	driver 23 Car --> Person

The label would show driver 23.

The end-user should not be able to change the source and/or target of the association, but use an Xtext editor for the label to edit the other features.

Therefore, the developer supplies the following list of editableFeatures:

  • Association.name

  • Association.code

  • Association.guard

Limitations

Limiting the editable features works by finding the first and last of the features in the text stream, and limit the editable area of the model to this subpart.

Therefore, if the model looks like

	driver 23 [someCondition] Car --> Person

and the editableFeatures are limited to

  • Association.name

  • Association.guard

the editor would still include the code subpart, because it’s in between the name and guard subpart.

	driver 23 [someCondition]
Details

If the list of editableFeatures is empty, all features are considered to be editable.

If the list of editableFeatures is not empty, we omit all features not contained in the list from committing back to the original model.

Design

The Editable Features property contains a read-only list of features. Edit it by activating the btn:[…​] button. This opens a pop-up window listing all available and currently selected features.

Ignored Nested Features

The editor can omit some nested features from committing back to the original model.

Typically, this is combined with a specialized edit grammar to also hide the ignored nested features from the end-user. It might also be necessary to declare these features transient.

Example

Assume the following Xtext grammar snippet defining an UML-like Association, to be displayed as edge:

Association:
	name=ID
	target=TypeRef
;

// also used at lots of other places
TypeRef:
	lowerBound=INT '..' upperBound=INT type=[Type]?
;

Example model:

	wheels 1..4 RubberWheel

The end-user should not be able to change the target type of the Association, but use an Xtext editor for the label to edit the other features.

Therefore, the developer supplies the following (single-entry) list of ignoredNestedFeatures:

  • target.type

Thus, the editor ignores all end-user changes to target.type.

The end-user would probably be very annoyed about changing something in the editor, and being ignored. We can remove this annoyance by using a specialized grammar to remove the type part:

Association:
	name=ID
	target=AssociationTypeRef
;

AssociationTypeRef returns TypeRef:
	lowerBound=INT '..' upperBound=INT
;

// also used at lots of other places
TypeRef:
	lowerBound=INT '..' upperBound=INT type=[Type]?
;
Details

Only changing the grammar would not be sufficient, as this would delete typeRef.type on every edit.

Design

The Ignored Nested Features property contains a read-only list of strings. Edit it by activating the btn:[…​] button. This opens a pop-up window listing all current entries on the right, and a text box on the left to add new ones. Unfortunately, we cannot provide a list of all possible entries, as they depend on the structure of the actually edited model at run-time.

Each entry is a dot-separated concatenation of EStructuralFeature names. the first segment is a feature of the edited semantic element.

Pre-selected Features

The editor can set the initial text selection to defined features.

A typical use-case pre-selects the name of the edited semantic element.

Example

Assume the following Xtext grammar snippet defining a statemachine event:

Event:
  'event' name=ID code=INT
;

Most of the time, the end-user wants to change the name of the event.

Therefore, the developer supplies the following (single-entry) list of selectedFeatures:

  • Event.name

Thus, when the end-user presses kbd:[F2] on the Event shape, the editor selects the bold text in this example:

event MyEventName 23

Limitations

Pre-selecting features works by finding the first and last of the features in the text stream, and set the initial text selection to this subpart. Thus, if the developer selected two features, but a third one is in between them, all of the three features will be selected.

Design

The Selectable Features property contains a read-only list of features. Edit it by activating the btn:[…​] button. This opens a pop-up window listing all available and currently selected features.

Position of Affected Edge Label

Unfortunately, we cannot assign different Direct Edit Label tools to different edge labels (begin, center, end).

Therefore, if the developer attaches a direct editor to an edge, the developer needs to specify which edge label should be equipped with Xtext powers. This info is contained in the Edge Label Mappings property. The read-only list is edited by activating the btn:[…​] button. This opens a pop-up window listing all available and currently selected edge labels.

PrefixTerminals and SuffixTerminals

By default, the editor uses some heuristics to determine which terminals should be included at the beginning and end of the edited text.

This behavior can be overridden by the developer. For all value editors, the developer may define a prefixTerminalsExpression and/or a suffixTerminalsExpression in the odesign file.

For both of them, the following rules apply:

  1. If the field is empty (aka. not set, aka. null), the heuristics will be used.

  2. If the field contains an interpreter expression (e.g. starting with aql:), the resulting string of the interpreter call is used for terminals matching.

  3. If the field contains anything else, the entered string is used for terminals matching.

Thus, if we want to disable the heuristics and don’t include any preceding terminals, our prefixTerminalsExpression looks like:

aql:''
Caution
The editor does not modify the resulting string in any way! Therefore, the editor also tries to match whitespace characters to terminals (as there might be grammars with semantic whitespace).
Example

Assume the following grammar as example. It uses the usual C-like whitespace and comment rules:

Event:
  'event' name=ID '[' code=INT ']' ('guarded' 'by' guard=[Guard])?
;

Example model contents:

event ford [23]

event    arthur [42] guarded by Trillian

event zaphod [4223] /* caution, very random! */ guarded by HeartOfGold

For editing Event, assume:

editableFeatures
  • code

  • name

prefixTerminalsExpression
event

Thus, we always want to include the event terminal.

suffixTerminalsExpression
aql:']'.concat(if(self.guard <> null) 'guarded' else ''))

Thus, we always want to include the ] terminal. If the edited Event had a guard, we do not want to edit it. However, we want to show the end-user that a guard is present, thus include the guarded terminal. Note that there are no spaces in the resulting string.

The resulting editor contents for all three Events will look like:

event ford [23]
event    arthur [42] guarded
event zaphod [4223] /* caution, very random! */ guarded
Terminals Matching

We discuss the terminals matching process for suffixTerminalsExpression below. It works accordingly for prefixTerminalsExpression.

We ignore all whitespace and comment contents, as defined by the editor grammar. Terminals matching starts at the last editable feature in the text. From there, we look at all following tokens, and include them as long as their combined text matches the resulting string of suffixTerminalsExpression. As soon as we find a non-terminal token, we quit terminals matching.

The example would work the same way if the suffixTerminalsExpression was:

]guarded

Explanation: For event ford, it would successfully match ] but quit terminals matching afterwards, because the next token would not be a terminal (in this case, it would be the following Event rule).

Caution
Sometimes, Xtext considers terminals to be part of a feature. In this case the terminal is always contained in the edited text. Adjusting the grammar might help: Wrap the feature in additional parentheses in order to give some hints to Xtext.

Cancel on Validation Error

By default, we ignore validation errors in the text entered by the end-user. If we activated this property, validation errors are treated like syntax errors.

This might be especially useful to prevent duplicate EKeys.

Available implementations

This feature is available in all editors.

Enable Formatter

This info controls whether an IFormatter2 should be applied to the edited text before displaying it to the end-user.

We only support IFormatter2, not the older formatters provided by Xtext.

Of course, the formatter needs to be registered to the Xtext language.

Available implementations

This feature is available in all editors.

Additional Model Operations

As with regular Sirius operations, we can execute other operations after the Xtext/Sirius editor set value operation. (Executing other operations before the set value operation is not supported.)

This can be useful to post-process the changed model, e.g. to adjust explicit imports to the changes inside the editor.

Handling Syntax Errors

If the end-user closed an editor with unparseable content (i.e. containing syntax errors), no changes will be committed and the following error dialog is displayed:

Syntax Error Dialog

syntaxError

The dialog shows the complete entered text, to give the end-user a chance to keep his entry by copying the text. It also shows all error messages of the parser with hints to the invalid position.


1. These are actually properties of the editor — but this term is already used a lot.