|
|
Building an editor
|
|
|
==================
|
|
|
|
|
|
Building an editor involves to main steps:
|
|
|
|
|
|
1. Creating and registering the new editor and
|
|
|
2. Populating the editor.
|
|
|
|
|
|
The following sections include step-by-step guides and useful
|
|
|
information for completing both parts. Throughout this introduction the
|
|
|
component editor located in `org.fortiss.af3.component.ui.editor.fx` is
|
|
|
used as an example. Consult its code whenever something is unclear, as
|
|
|
it is likely that the new editor will be similar in many aspects.
|
|
|
|
|
|
Creating and registering the editor
|
|
|
-----------------------------------
|
|
|
|
|
|
The following steps create a new editor and register it within the AF3
|
|
|
runtime. Once completed, the new editor can be opened but it will not
|
|
|
contain any elements yet as it is still to be populated.
|
|
|
|
|
|
1. Create a new package for the FX editor (e.g.
|
|
|
`org.fortiss.af3.component.ui.editor.fx`).
|
|
|
2. Create the new editor class deriving from `LWFXEFEditorBase` (see
|
|
|
`ComponentStructureFXEditor`).
|
|
|
3. Create a new `EditorBinding` and register it in the `plugin.xml`
|
|
|
(see `ComponentStructureFXEditorBinding`). Be sure to implement the
|
|
|
`getEditorClass`, `getLabel` and `getPriority` methods!
|
|
|
4. Add a model factory implementing `IModelFactory` and implement its
|
|
|
`getRoot()` method (see `component.ui.editor.fx.ModelFactory`). Let
|
|
|
other methods return null or empty lists.
|
|
|
5. Add a visual factory implementing `IVisualFactory` and returning
|
|
|
null in all methods
|
|
|
6. Create a sub-package `controller` and add a `DiagramController`
|
|
|
class deriving from `EObjectBasedDiagramControllerBase`. Nothing
|
|
|
needs to be implemented here.
|
|
|
7. Add a controller factory implementing `IControllerFactory` and
|
|
|
return an instance of `DiagramController` in
|
|
|
`createDiagramController`. Other methods may return null.
|
|
|
8. Return instances of the factory class in the respective methods of
|
|
|
the editor class.
|
|
|
9. Start AF3 and test if the new editor is appearing (with an empty
|
|
|
background canvas).
|
|
|
|
|
|
Populating the editor
|
|
|
---------------------
|
|
|
|
|
|
Having created and registered editor, it is now time to populate it.
|
|
|
|
|
|
### Models, views and controllers
|
|
|
|
|
|
Editors are implemented using the MVC pattern with models, views and
|
|
|
controllers. Hence, each editor has a `ModelFactory`, a `VisualFactory`
|
|
|
and a `ControllerFactory` defining models, visuals and controllers for
|
|
|
each of the elements to be shown and edited. For a standard
|
|
|
boxes-and-wires diagram this includes **contents** (boxes), **links**
|
|
|
(wires) and **anchorages** (ports used to connect wires to boxes). The
|
|
|
following sections describe how to create the respective models, visuals
|
|
|
and controllers for each of them.
|
|
|
|
|
|
### Layout data
|
|
|
|
|
|
Whenever dealing with graphical editors it is of *utmost* importance to
|
|
|
know where elements are to be located. This information can be accessed
|
|
|
via the `LayoutDataUtils` and `LayoutDataUIUtils` classes. They provide
|
|
|
methods to e.g. retrieve the position and the bounds of a node
|
|
|
(`LayoutDataUtils.getNodePosition(ILayoutedModelElement layouted)` and
|
|
|
`LayoutDataUtils.getNodeBounds(ILayoutedModelElement layouted)`
|
|
|
respectively). For an exhaustive listing of all methods consult the
|
|
|
classes’ outline.
|
|
|
|
|
|
### Populating the editor (*finally*)
|
|
|
|
|
|
Now onto populating the editor with contents, anchorages and links. Each
|
|
|
of them will require the implementation of the classes and methods
|
|
|
mentioned in the respective section. Instead of going through each of
|
|
|
the methods in detail, it is advised to consult the implementation of
|
|
|
the respective methods for the component editor.
|
|
|
|
|
|
#### Content
|
|
|
|
|
|
Implement the following methods:
|
|
|
|
|
|
- `ModelFactory.getContentModels()`
|
|
|
- `VisualFactory.createContentVisual()`
|
|
|
- `ControllerFactory.createContentController()`
|
|
|
|
|
|
Custom visuals and controller classes to extend in case you want to
|
|
|
build a standard boxes-and-wires editor:
|
|
|
|
|
|
- `LayoutedRectangularContentVisualBase` (e.g. `SubComponentVisual`)
|
|
|
- `EObjectBasedRectangularResizableContentControllerBase` (e.g.
|
|
|
`SubComponentController`)
|
|
|
|
|
|
In case you need custom shapes, you have to extend the
|
|
|
`org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.base.ContentVisualBase`
|
|
|
directly. Orient yourself at the implementation of
|
|
|
`org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.rectangular.RectangularContentVisualBase`
|
|
|
to know which methods to override and how.
|
|
|
|
|
|
#### Anchorages
|
|
|
|
|
|
There are two types of anchorages to take care of:
|
|
|
|
|
|
- **Diagram anchorages** are attached to the parent element of the
|
|
|
content shown in the diagram and are displayed directly on the
|
|
|
editor’s background without being attached to any element.
|
|
|
- **Content anchorages** are attached to contents (i.e. boxes,
|
|
|
ellipses etc.) shown in the editor and are displayed at the border
|
|
|
of the respective shape.
|
|
|
|
|
|
Implement the following methods:
|
|
|
|
|
|
- `ModelFactory.getContentAnchorageModels()`
|
|
|
- `ModelFactory.getDiagramAnchorageModels()`
|
|
|
- `VisualFactory.createContentAnchorageVisual()`
|
|
|
- `VisualFactory.createDiagramAnchorageVisual()`
|
|
|
- `ControllerFactory.createContentAnchorageController()`
|
|
|
- `ControllerFactory.createDiagramAnchorageController()`
|
|
|
|
|
|
Custom visuals and controller classes to extend:
|
|
|
|
|
|
- `LayoutedCircularContentAnchorageVisualBase` (e.g
|
|
|
`SubComponentPortVisual`)
|
|
|
- `LayoutedCircularDiagramAnchorageVisualBase` (e.g
|
|
|
`DiagramComponentPortVisual`)
|
|
|
- `LayoutedModelElementBasedContentAnchorageController` (e.g
|
|
|
`SubComponentPortController`)
|
|
|
- `LayoutedModelElementBasedDiagramAnchorageController` (e.g
|
|
|
`DiagramComponentPortController`)
|
|
|
|
|
|
In order to specify which ports can be linked and which do not check the
|
|
|
implementation of the `canConnect` method in the connection compositor
|
|
|
of the editor’s contents (e.g.
|
|
|
`ComponentConnectionCompositor.canConnect(EObject source, EObject target, IHierarchicElement parent, IConnectionCompositionContext context)`).
|
|
|
|
|
|
#### Links
|
|
|
|
|
|
Implement the following methods:
|
|
|
|
|
|
- `ModelFactory`
|
|
|
- `getLinkModels()`
|
|
|
- `getLinkStart()`
|
|
|
- `getLinkEnd()`
|
|
|
- `VisualFactory.createLinkVisual()`
|
|
|
- `ControllerFactory.createLinkController()`
|
|
|
|
|
|
Make sure to implement all three methods of the `ModelFactory` at the
|
|
|
same time, as they depend on each other.
|
|
|
|
|
|
Custom visuals and controller classes to implement:
|
|
|
|
|
|
- `LayoutedLineLinkVisualBase` (e.g. `ChannelVisual`)
|
|
|
- `LayoutedModelElementBasedLinkBendPointController` (e.g.
|
|
|
`ChannelController`)
|
|
|
|
|
|
Customizing the editor (optional)
|
|
|
---------------------------------
|
|
|
|
|
|
Once created, registered and populated the editor can be further
|
|
|
customized by overriding the `customizeViewer` method of your `FXEditor`
|
|
|
(e.g. `ComponentStructureFXEditor.customizeViewer()`). The following
|
|
|
code snipped shows how to set the indicator spacing and the background
|
|
|
color:
|
|
|
|
|
|
|
|
|
```java
|
|
|
/** {@inheritDoc} */
|
|
|
@Override
|
|
|
protected void customizeViewer() {
|
|
|
DiagramViewerFeatures features = viewer.getFeatures();
|
|
|
features.setIndicatorSpacing(new Dimension2D(12, 12));
|
|
|
features.setBackgroundColor(LIGHTGRAY);
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|