spring-flo.md 35.3 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
# Welcome to the Spring Flo wiki!
Spring Flo is a set of [Angular JS](https://angularjs.org/) directives for a diagram editor able to represent a DSL graphically and synchronize graphical and textual representation of that DSL. Graphical representation is done with a [Joint JS](http://jointjs.com/) graph object, textual representation can be either a plain HTML element (such as `<textarea>`) or a feature rich editor based on [CodeMirror](https://codemirror.net/) available via the Flo directive.

## How to embed Spring Flo in your application:
Spring Flo can be used in any angular application via the `flo-editor` directive. The controller for the directive creates/populates `flo` ([Flo](#flo)) and `definition` ([Definition](#definition)) objects. These objects are how a consuming client interoperates with Flo. The `definition` object is a two-way binding to read/write the DSL textual representation. The `flo` object is a two-way binding for working with the graphical representation of the DSL (including controlling editor features such as zooming, grid, layout etc.).

There is a sample project in the samples subfolder of the spring-flo repo: https://github.com/spring-projects/spring-flo/tree/master/samples/spring-flo-sample - this sample will be referenced throughout the documentation below to give a pointer to a real use of each feature.

The initial step of embedding Flo into angular application is simply to use the `flo-editor` directive on a page or in angular template. 
```html
<flo-editor></flo-editor>
```
The above results in a page with a skeleton for the editor: empty palette and empty canvas. See the [sample usage](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/index.html) for a more sophisticated configuration. Flo defines UI for the editor and graph interactions but needs domain knowledge from the client to be actually useful. There are actually three services the consuming client can provide to control the behaviour of Flo, only one of which is mandatory:

1. Service that defines the types of element being represented by the graph and converts both ways between the domain DSL textual format and the graph format (required)
2. Service that defines the visual representation of the nodes and links on the graph
3. Service that controls graph editing capabilities

Implementations should be provided by the client as angular services that adhere to a specific contract as detailed in [Extension Points](https://github.com/spring-projects/spring-flo/wiki#all-the-extension-points). The services are: [Metamodel Service](#metamodel-service) (required), [Render Service](#render-service) and [Editor Service](#editor-service).

Many of the service functions have sensible defaults. In this section we will discuss the important ones, only some of which are mandatory.

In order to populate the palette with content, Flo needs to know about your domain. What are the 'things' you are linking together in your graph? Implementing the [Metamodel Service](#metamodel-service) [load()](#load) function will provide that information to Flo. 
```javascript
app.factory('MyPageMetamodelService', ['$log', function($log) {
  return {
    load: function() { $log.info('Return descriptions of the domain specific model elements'); }
  };
}]);
```
The sample includes a more complete [metamodel service](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/metamodel-service.js). Once defined, the services can be supplied by name to the parents scope (via parent controller `$scope.metamodelServiceName = 'MyPageMetamodelService';`.) or directly to the `flo-editor` directive (via `metamodel-service-name` attribute on `<flo-editor>` element). Lets modify the `flo-editor` directive:
```html
<flo-editor metamodel-service-name="MyPageMetamodelService">
</flo-editor>
```
This is also how the sample [index.html](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/index.html) does it. Once the Metamodel Service is hooked up to the editor the palette will be populated based on the metamodel object obtained from the Metamodel Service. You should then be able to drop nodes on the canvas, connect nodes with links, move them around. Note that visual representation of nodes and links might be far from what is desired. Implementing a [Render Service](#render-service) enables you to customize that look and feel (in the absence of a provided render service, Flo performs some very basic rendering). A basic render service will implement the [createNode()](#createnodemetadata-properties-optional) and [createLink()](#createlinksource-target-metadata-properties-optional) functions (see also [Joint JS API Docs](http://jointjs.com/api)) to get the right look and feel for the shapes on the palette and canvas.
```javascript
app.factory('MyPageRenderService', ['$log', function($log) {
  return {
    createNode: function(metadata) { $log.info('Create and return new Joint JS joint.dia.Element for a graph node'); },
    createLink: function(source, target, metadata, props) { $log.info('Create and return new Joint JS joint.dia.Link for a link between graph nodes'); }
  };
}]);
```
The sample includes a more complete [render service](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/render-service.js). As with the metamodel service, connect it to the `flo-editor` directive
```html
<flo-editor
  metamodel-service-name="MyPageMetamodelService" 
  render-service-name="MyPageRenderService">
</flo-editor>
```
With basic rendering taken care of, we could further customize:

- Adding "handles" around the shape when it is selected. "handles" are small shapes usually placed around the shape interaction with which would perform some editing actions on the associated shape such as delete, resize or edit properties. 
- Provide validation of the graph with validation indicators (errors/warnings) on nodes and links.
- An editor action toolbar might be nice.

Some of these features are supported by implementing more functions on the render-service but some require implementing the final key service, the [Editor Service](#editor-service):

```javascript
app.factory('MyPageEditorService', ['$log', function($log) {
  return {
    createHandles: function(flo, createHandle, selected) { $log.info('Create handles around selected element'); },
    validateLink: function(flo, cellViewS, portS, cellViewT, portT, end, linkView) { $log.info('Validate link');},
    validateNode: function(flo, node) { $log.info('Validate Node'); },
    preDelete: function(flo, deletedElement) { $log.info('Delete links incident with element being deleted '); },
    interactive: true, /* Consult Joint JS Paper #interactive property doc. Make elements interactive */
    allowLinkVertexEdit: false /* Disallow creation and editing of 'bend-points' in links */
  };
}]);
```
The sample includes a more complete [editor service](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/editor-service.js). Rendering for handles and validation markers (decorations) must be provided by the Render Service since they are required by Editor Service. There is no out-of-the-box rendering defined in Spring-Flo for rendering handles and error marker decoration shapes. Consequently, if you define `validateNode()` and `createHandles()` in the Editor Service then `createDecoration()` and `createHandle` must be implemented in the Render Service.
```javascript
app.factory('MyPageRenderService', ['$log', function($log) {
  return {
    createHandle: function(kind, parent) { $log.info('Implement handle node creation'); },
    createDecoration: function(kind, parent) { $log.info('Implement error decoration node creation'); },
    createNode: function(metadata) { $log.info('Create and return new Joint JS joint.dia.Element for a graph node'); },
    createLink: function(source, target, metadata, props) { $log.info('Create and return new Joint JS joint.dia.Link for a link between graph nodes'); }
  };
}]);
```
New toolbar actions can be added in HTML in the `flo-editor` directive via transclusion, this is how that might look with our editor service also plugged in:
```html
<flo-editor
  metamodel-service-name="MyPageMetamodelService" 
  render-service-name="MyPageRenderService"
  editor-service-name="MyPageEditorService">
  <div>
    <button ng-click="flo.deleteSelectedNode()" ng-disabled="!flo.getSelection()">Delete</button>
    <button ng-click="flo.noPalette = !flo.noPalette" ng-class="{on:!flo.noPalette}">Palette</button>
  </div>
</flo-editor>
```
Note the `flo` object references in various handler attributes in HTML. The controller for `flo-editor` directive will populate `flo` object with functions for manipulating the Flo editor content.

The graph editor should be fully functional at this stage, but what about the text DSL?

Functions converting graph to text DSL and text DSL to graph must be provided by the client in order for this to work. These two function ([graphToText()](#graphtotextflo-definition) and [textToGraph()](#texttographflo-definition)) must be implemented inside the Metamodel Service, let's add them to the definition we had earlier:
```javascript
app.factory('MyPageMetamodelService', ['$log', function($log) {
  return {
    load: function() { $log.info('Implement load and return metamodel object!'); },
    textToGraph: function(flo, definition) { $log.info('Convert text (definition.text) to graph (flo.getGraph())'); },
    graphToText: function(flo, definition) { $log.info('Convert graph (flo.getGraph()) to text (definition.text)'); }
  };
}]);
```
The sample includes basic implementations of [graph-to-text](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/graph-to-text.js) and [text-to-graph](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/text-to-graph.js) for a 'demo' DSL, those are used by the [sample metamodel service](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/metamodel-service.js).
The Flo editor internally maintains the text DSL in the `definition` object it only remains to be exposed in the UI. The text DSL can be displayed either by plain HTML elements such as `<textarea>` or advanced [CodeMirror](https://codemirror.net/) based `dsl-editor` directive. Lets modify the HTML to have the text DSL UI with help from the `dsl-editor` directive.
```html
<flo-editor
  metamodel-service-name="MyPageMetamodelService" 
  render-service-name="MyPageRenderService"
  editor-service-name="MyPageEditorService">
  <div>
    <button ng-click="flo.deleteSelectedNode()" ng-disabled="!flo.getSelection()">Delete</button>
    <button ng-click="flo.noPalette = !flo.noPalette" ng-class="{on:!flo.noPalette}">Palette</button>
  </div>
  <textarea dsl-editor></textarea>
</flo-editor>
```

The HTML above translates into a page with toolbar for buttons (Layout and Show/Hide Palette), text area for DSL and the Flo editor for graph representation of the DSL.

## All the extension points:

### Metamodel Service
This service enables the domain in which Flo is being used to specify what kinds of element are being connected together in the graph and also how the graph should be converted to-and-from a textual representation. [Sample metamodel service is here](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/metamodel-service.js).
#### textToGraph(flo, definition)
Sets the graph contents for the `flo` object based on the textual representation of the DSL from `definition` object. Text is transformed into the corresponding Joint JS graph content. The graph is to be populated via `flo` objects functions such as `flo.createLink()` and `flo.createNode()` and cleared with `flo.clearGraph`
#### graphToText(flo, definition)
Convert the current graph available from the `flo` object into a textual representation which is then set (as the `text` property) on the `definition` object.
#### load()
Returns a promise that resolves to a `metamodel` object. The `metamodel` object layout is a map of element `group` names to a map of elements that belong to this `group`. The map of elements that belong to the `group` is a mapping between element's `name` and element's [Metadata Object](https://github.com/spring-projects/spring-flo/wiki#element-metadata)
#### refresh() _(Optional)_
Refreshes the meta-model and returns a promise that is resolved to the same result as [load()](#load). Refresh should also fire event to `metamodel` change listeners.
#### encodeTextToDSL(text) _(Optional)_
Encodes DSL element property value text to the DSL required format. Example is converting multiline text into a single line required by the DSL format. Used to display the property value in a human readable format.
#### decodeTextFromDSL(dsl) _(Optional)_
Decodes DSL element property value text from DSL format. Example is converting single line text into a multiline text, i.e. replacing escaped line breaks. Used to set a property value for DSL element entered by the user via UI.
#### subscribe(listener) _(Optional)_
Adds a listener to `metamodel` events. (See [Metamodel Listener](#metamodel-listener))
#### unsubscribe(listener) _(Optional)_
Removes `metamodel` events listener. (See [Metamodel Listener](#metamodel-listener))
#### isValidPropertyValue(element, key, value) _(Optional)_
Check if the the value being specified for the key on the specified element is allowed. For example: if the key takes an integer, don't allow alphabetic characters.

### Render Service
The service is responsible for visual representation of graph elements based on the metadata (coming from [Metamodel Service](#metamodel-service)). This service is **optional**. [Sample render service is here](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/render-service.js).
#### createNode(metadata, properties) _(Optional)_
Creates an instance of Joint JS graph node model object (`joint.dia.Element`). Parameters that may affect the kind of node model object are element's [metadata](#element-metadata) and map of properties (if any passed in).
#### createLink(source, target, metadata, properties) _(Optional)_
Creates an instance of Joint JS graph link model object (`joint.dia.Link`). Parameters that may affect the kind of link model object are element's [metadata](#element-metadata), map of properties (if any passed in), source and target elements
#### createHandle(kind, parent) _(Optional)_
Creates an instance of Joint JS graph node model object (`joint.dia.Element`). An example of a handle is a shape shown next to the parent shape interacting with which results in some editing action over the parent shape. Parameters that may affect the kind of handle model object are `kind` of type `string` (user defined, i.e. `delete`, `resize`, etc.) and handle's `parent` element. This function is only called by the framework if Editor Service `createHandles()` function is implemented.
#### createDecoration(kind, parent) _(Optional)_
Creates an instance of Joint JS graph node model object (`joint.dia.Element`). An example of decoration is a validation marker displayed over the parent shape. Parameters that may affect the kind of decoration model object are `kind` of type `string` and decoration's `parent` element. Note that `kind` parameter is coming from the framework (unlike for `createHandle` function). This function is only called by the framework if Editor Service `validateNode()` function is implemented. (At the moment decorations are only the validation error markers).
#### initializeNewNode(node, context) _(Optional)_
Performs any additional initialization of a newly created graph `node` when `node` is already added to the Joint JS graph and rendered on the canvas, e.g. element's SVG DOM structure is available. The `context` parameter is an object with `paper` and `graph` properties applicable for the `node`. Useful to perform any kind of initialization on a node when it's SVG DOM is appended to the page DOM. Examples: fit string label inside a shape, use angular directive on a shape, add DOM listeners etc.
#### initializeNewLink(link, context) _(Optional)_
Performs any additional initialization of a newly created graph `link` when `link` is already added to the Joint JS graph and rendered on the canvas, e.g. element's SVG DOM structure is available. The `context` parameter is an object with `paper` and `graph` properties applicable for the `link`.  Useful to perform any kind of initialization on a link when it's SVG DOM is appended to the page DOM. Examples: use angular directive on a shape, add DOM listeners etc.
#### initializeNewHandle(handle, context) _(Optional)_
Performs any additional initialization of a newly created graph `handle` when `handle` is already added to the Joint JS graph and rendered on the canvas, e.g. element's SVG DOM structure is available. The `context` parameter is an object with `paper` and `graph` properties applicable for the `handle`. Useful to perform any kind of initialization on a handle shape when it's SVG DOM is appended to the page DOM. Examples: fit string label inside a shape, use angular directive on a shape, add DOM listeners etc.
#### initializeNewDecoration(decoration, context) _(Optional)_
Performs any additional initialization of a newly created graph `decoration` when `decoration` is already added to the Joint JS graph and rendered on the canvas, e.g. element's SVG DOM structure is available. The `context` parameter is an object with `paper` and `graph` properties applicable for the `decoration`. Useful to perform any kind of initialization on a decoration shape when it's SVG DOM is appended to the page DOM. Examples: fit string label inside a shape, use angular directive on a shape, add DOM listeners etc.
#### getNodeView() _(Optional)_
Returns instance of `joint.dia.ElementView`. It can also be a function of the form `function(element)` that takes an element model and should return an object responsible for rendering that model onto the screen. Under normal circumstances this function does not need to be implemented and the Joint JS view object created by the framework should be enough. Implement this function if different nodes require different Joint Js views or view has some special rendering (i.e. embedded HTML elements). See [Joint JS Paper Options](http://jointjs.com/api#joint.dia.Paper:options)
#### getLinkView() _(Optional)_
Returns instance of Joint JS `joint.dia.LinkView`. Default is `joint.dia.LinkView`. It can also be a function of the form `function(link)` that takes a link model and should return an object responsible for rendering that model onto the screen. Under normal circumstances this function does not need to be implemented and the Joint JS view object created by the framework should be enough. Implement this function if different links require different Joint JS views or view has some special rendering (i.e. pattern applied to a line - `joint.shapes.flo.PatternLinkView`). See [Joint JS Paper Options](http://jointjs.com/api#joint.dia.Paper:options)
#### layout(paper) _(Optional)_
Responsible for laying out the Joint JS graph that can be derived from passed in `paper` parameter (`paper.model`).
#### handleLinkEvent(paper, event, link) _(Optional)_
Responsible for handling `event` that occurred on the `link` that belong to passed in Joint JS `paper` object. The `event` parameter is a `string` with possible values: `'add'`, `'remove'` or Joint JS native link change events such as `'change:source'`, `'change:target'`, etc. see [Joint JS Link Events](http://jointjs.com/api#joint.dia.Link:events)
#### isSemanticProperty(propertyPath, element) _(Optional)_
Returns `true` for `string` property attribute path `propertyPath` on an `element` if graphs needs to perform some visual update based on `propertyPath` value change (Not needed for properties under `props` on an `element`). Visual update is performed by [refreshVisuals()](#refreshVisuals). The property path `propertyPath` is relative to Joint JS element `attrs` property
#### refreshVisuals(element, propertyPath, paper) _(Optional)_
Performs some visual update of the graph or, which is more likely, the passed in `element` displayed on Joint JS `paper` based on the changed property specified by `propertyPath`
#### getLinkAnchorPoint(linkView, view, port, reference) _(Optional)_
This function allows you to customize what are the anchor points of links. The function must return a point (with `x` and `y` properties) where the link anchors to the element. The function takes the link view, element view, the `port` (SVG element) the link should stick to and a reference point (either the closest vertex or the anchor point on the other side of the link).

### Editor Service
The service responsible for providing Flo editor with rich editing capabilities such as handles around selected shapes, custom drag and drop behaviour, live and static validation. This service is **optional**. [Sample editor service is here](https://github.com/spring-projects/spring-flo/blob/master/samples/spring-flo-sample/src/main/resources/static/js/editor-service.js)
#### createHandles(flo, createHandle, selected) _(Optional)_
Called when node is selected and handles can be displayed. Handles are usually small shapes around the `selected` Joint JS node in `flo` editor interactions with which modify properties on `selected` node, i.e. resize or delete handles. Call `createHandle(selected, kind, clickHandlerFunction, coordinate)` function to create a handle. The `kind` parameter is a `string` kind of a handle, `clickHandlerFunction` is performed when handle has been clicked on and `coordinate` is the place to put the handle shape. Note that if this function is implemented then Render Service `createHandle(...)` function must be implemented as well. The framework will remove handles automatically when needed, hence no need to worry about this on the client side.
#### validatePort(paper, view, portView) _(Optional)_
Decide whether to create a link if the user clicks a port. The `portView` is the DOM element representing the port, `view` is the port's parent Joint JS view object show in Joint JS `paper` 
#### validateLink(flo, cellViewS, portS, cellViewT, portT, end, linkView) _(Optional)_
Decide whether to allow or disallow a connection between the source view/port (`cellViewS`/`portS`) and target view/port (`cellViewT`/`portT`). The `end` is either `'source'` or `'target'` and tells which end of the link is being dragged. This is useful for defining whether, for example, a link starting in a port POut of element A can lead to a port PIn of elmement B.
#### calculateDragDescriptor(flo, draggedView, targetUnderMouse, coordinate, context) _(Optional)_
Called when dragging of a node `draggedView` is in progress over `targetUnderMouse` Joint JS graph element (node or link) at `coordinate`. There are also `flo` object parameter and `context` object, which currently just has a `boolean` property `palette` to denote whether drag and drop occurring on the palette or canvas. The function should return a [Drag Descriptor Object](#drag-descriptor). 
#### handleNodeDropping(flo, dragDescriptor) _(Optional)_
Performs necessary graph manipulations when the node being dragged is dropped. The `dragDescriptor` [Drag Descriptor](#drag-descriptor) should have the mandatory information on what is being dragged and where it's being dropped. The `flo` object parameter would help to make necessary graph modifications
#### showDragFeedback(flo, dragDescriptor) _(Optional)_
Any custom visual feedback when dragging a node over some graph element (node or link) can be drawn by this function. `dragDescriptor` parameter has a [Drag Descriptor Object](#drag-descriptor) that has complete information about dragging in progress and `flo` object would help with drawing feedback using Joint JS
#### hideDragFeedback(flo, dragDescriptor) _(Optional)_
Removes any custom visual feedback drawn by [showDragFeedback()](#show-drag-feedback). Has the same parameters.
#### validateNode(flo, node) _(Optional)_
Returns a `javascript` array of `string` error messages that are the result of validating `node` Joint JS graph node on the canvas in `flo` editor
#### preDelete(flo, deletedElement) _(Optional)_
Called prior to removal of the specified `deletedElement` allowing extra tidyup before that happens. For example: removes any dependent Joint JS graph elements related to the element about to be deleted.
#### interactive _(Optional)_
If set to `false`, interaction with elements and links is disabled. If it is a function, it will be called with the cell view in action and the name of the method it is evaluated in (`'pointerdown'`, `'pointermove'`, ...). If the returned value of such a function is false interaction will be disabled for the action. For links, there are special properties of the interaction object that are useful to disable the default behaviour. These properties are: `vertexAdd`, `vertexMove`, `vertexRemove` and `arrowheadMove`. By setting any of these properties to false, you can disable the related default action on links.
#### allowLinkVertexEdit _(Optional)_
If set to `false` link vertex (or bend point) creation or editing (e.g. movement) is not allowed in the editor.

## Data structure reference:
### Flo
This object is created by the `flo-editor` directive controller and it contains various editor specific properties and functions.
#### scheduleUpdateGraphRepresentation()
Schedules an asynchronous update of the graph DSL representation based on the text DSL representation.
#### updateGraphRepresentation()
Asynchronously update the graph DSL representation based on the text DSL representation. A promise is returned which gets resolved when the update completes.
#### updateTextRepresentation()
Asynchronously update the text DSL representation (`definition` object) based on the graph DSL representation. A promise is returned which gets resolved when the update completes.
#### performLayout()
Arranges nodes and links of the graph on the canvas.
#### clearGraph()
Clears out canvas of all nodes and links. With syncing on this also causes the text DSL representation to clear.
#### getGraph()
Returns a reference to `joint.dia.Graph` object instance of the canvas contents (The graph model, see [Joint JS Graph API](http://jointjs.com/api#joint.dia.Graph)
#### getPaper()
Returns a reference to joint.dia.Paper object instance of the canvas (The graph view object, see [Joint JS Paper API](http://jointjs.com/api#joint.dia.Paper)
#### enableSyncing(enable)
Enables or disables textual and graph DSL representation synchronization mechanism based on the passed `boolean` parameter `enable`. Useful when textual DSL representation UI is collapsed.
#### getSelection()
Returns currently selected graph model element (node or link) on the canvas
#### zoomPercent(percent)
Angular getter/setter function for the zoom value on the canvas. Sets zoom percent value if the integer `number` parameter is supplied. Returns the integer percent value if parameter is missing (getter mode)
#### gridSize(gridSize)
Angular getter/setter function for the canvas grid size in pixels. Sets grid width value if the integer `number` parameter `gridSize` is supplied. Returns the current grid size value if parameter is missing (getter mode). Note that setting grid width to `1` turns the grid off. Invalid values for `gridSize` are ignored
#### getMinZoom()
Returns integer `number` minimum allowed value for the zoom percent. Useful to set the proper range for zoom controls. Needed by the zoom control on the canvas (if it is set to be shown). The value equals `5` by default (5%).
#### getMaxZoom()
Returns integer `number` maximum allowed value for the zoom percent. Useful to set the proper range for zoom controls. Needed by the zoom control on the canvas (if it is set to be shown). The value equals `400` by default (400%).
#### getZoomStep()
Returns integer `number` zoom percent increment/decrement step. Needed by the zoom control on the canvas (if it is set to be shown). The value equals `5` by default (5% increment/decrement value).
#### fitToPage()
Fits the whole graph into canvas's viewport (i.e. no need to scroll to look for content on the canvas). Adjusts the zoom level and scroll position appropriately
#### readOnlyCanvas(newValue)
Angular getter/setter function for the canvas "read-only" property. Read-only canvas does not allow for any user editing interaction of any shapes on the canvas. Sets the read-only property based on the passed in `newValue` parameter as the result the canvas toggles the behaviour for read-only state right away. Returns the current "read-only" state value if parameter is missing (getter mode).
#### createNode(metadata, properties, location)
Creates and returns the newly created Joint JS graph node (instance of `joint.dia.Element`) based on the graph node `metadata` object (see [Element Metadata](#element-metadata)), `properties` key-value pairs map, and location on the canvas (object with `x` and `y` properties). The new node is also added to the Flo canvas Joint JS `graph` and hence to the Joint JS `paper` and appears right away on the canvas before this function returns the result.
#### createLink(source, target, metadata, properties);
Creates and returns the newly created Joint JS graph link (instance of `joint.dia.Link`) between `source` and `target` nodes (of type `joint.dia.Element`) based on the graph link `metadata` object (see [Element Metadata](#element-metadata)), `properties` key-value pairs map. The new link is also added to the Flo canvas Joint JS `graph` and hence to the Joint JS `paper` and appears right away on the canvas before this function returns the result.
	
### Definition
This object holds data related to DSL's textual representation. Typically this object should at least have `text` property of type `string` for the DSL text, but it can also have other properties that might be added by client's Metamodel Service graph-text conversion functions.

### Metamodel Listener
Typically Metamodel object is loaded asynchronously via HTTP request. If metadata is cached by the service then it might be useful to register listeners. Flo editor palette would automatically rebuild itself if metamodel has changed
```javascript
{
  metadataError: function(data) {
    /* Error loading metadata has occurred */
  },
  metadataRefresh: function() {
    /* Metadata is about to be refreshed */
  },
  metadataChanged: function(data) {
    /* New metadata is available */
  }
}
```
### Drag Descriptor
API client is free to add extra properties to this object (i.e. may help drawing visual feedback)
```javascript
{
  context: context, /* String 'palette' or 'canvas' */
  source: {
    cell: draggedNode, /* Joint JS graph node being dragged */
    selector: selector, /* Optional. Joint JS CSS class selector for the subelement of the dragged node*/,
    port: portType /* Optional. Involved port DOM element type attribute value == port Joint JS markup 'type' property */
 },
 target: {
   cell: targetNode, /* Joint JS graph node target under mouse element */
   selector: selector, /* Optional. Joint JS CSS class selector for the element under mouse within the targetNode */
   port: portType /* Optional. Sub-element under mouse is a port. Port DOM element type attribute value == port Joint JS markup 'type' property */
 },
};
```

### Joint JS Graph Node Markup
```javascript
model: /* Joint JS model object for a module shape */
  ...
  attributes:
    ...    
    angle:  0,  /* Joint JS property - rotation angle */
            
    id:     "02be8001-ea1e-4f30-a94e-9503da5964b5"  /* Joint JS property - element model UUID
            
    position:       /* Joint JS property - coordinates of the shape's bounding rectangle */
      x:  119                                     
      y:  46
                
    size:           /* Joint JS property - size of the shape's bounding rectangle */
      height: 40                                  
      width:  120
                
    type:   "sinspctr.IntNode"  /* Flo property - internal, type (node, link, handle, decoration, etc) */
            
    z:      1   /* Joint JS property - z-index of the shape
            
    ports:              /* Joint JS property - internal, ports available on the shape */
      input:
        id: "input"
      output:
        id: "output"
      tap:
        id: "tap"
                    
      attrs:  /* Joint JS property - user defined rendering constructs and semantic properties */
            
        .               /*\                                                                 */
        .border         /* \                                                                */
        .box            /*  \                                                               */
        .input-port     /*   \                                                              */
        .label1         /*    \___User defined rendering constructs implied by the markup   */ 
        .label2         /*    /                                                             */
        .output-port    /*   /                                                              */
        .shape          /*  /                                                               */
        .stream-label   /* /                                                                */
        .tap-port       /*/                                                                 */
                                 
        metadata:                   /* Flo property. Node metadata supplied by Metamodel Service */
                                    
        props:                      /* Flo property. Semantic properties of the element. Name <-> value pair map */
          dir:    "/Users/x/tmp"
          file:   "temp.tmp"
          debug:  true
                    
      ...
  ...
...
```

### Element Metadata
Graphical element metadata supplied by Metamodel Service
```javascript
metadata: {
                
  get:    function(), /* function taking property key string as a parameter */ 
                      /* Returns promise that resolves to the metadata object of the property */
                      /* See snippet below showing the format of a property metadata */
                                                            
  group:  "source",   /* Category/Group of an element. Translates into palette groups of elements */

  name:   "file",     /* Name or Type of an element (should be unique within its group) */
                                                                                
  metadata:  { /* Additional metadata for the element */
    titleProperty: 'props/title', /* Property to be displayed at the top of all properties in properties Div */
    noEditableProps: false, /* If true then element doesn't have properties to edit and properties Div is not shown */
    allow-additional-properties: true, /* Allows user to create new properties for element in the properties Div */
  }

}
```
Element's property metadata is expected to be as follows
```javascript
  properties: {
        info: {
            defaultValue:       null,
            description:        "General information about the file",
            id:                 "info",
            name:               "info",
            shortDescription:   "File Info"
        },
            
        language: {
            defaultValue:       "English"
            description:        "Language of the file contents",
            id:                 "language",
            name:               "language",
            shortDescription:   "Text Language"
        },
        ...
```