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: /** {@inheritDoc} */ @Override protected void customizeViewer() { DiagramViewerFeatures features = viewer.getFeatures(); features.setIndicatorSpacing(new Dimension2D(12, 12)); features.setBackgroundColor(LIGHTGRAY); }