From 8423321bff790db26ed50f9ec2dff3bcdd2fed98 Mon Sep 17 00:00:00 2001 From: gfontorbe Date: Thu, 22 Feb 2024 09:42:14 +0000 Subject: [PATCH] =?UTF-8?q?Deploy=20preview=20for=20PR=2034=20=F0=9F=9B=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index.html | 58 ++++++------ .../pr-34/docs/custom-interactions/index.html | 68 ++++++++++++++ .../index.html | 54 +++++------ pr-previews/pr-34/docs/features/index.html | 34 +++---- .../index.html | 47 +++++----- pr-previews/pr-34/docs/index.html | 37 +++----- pr-previews/pr-34/docs/index.xml | 22 +++-- .../pr-34/docs/introduction/index.html | 27 ++++++ .../pr-34/docs/micro-layout/index.html | 36 ++++---- .../index.html | 46 +++++----- pr-previews/pr-34/docs/overview/index.html | 32 ++++--- pr-previews/pr-34/docs/smodel/index.html | 44 ++++----- pr-previews/pr-34/docs/styling/index.html | 29 +++--- .../pr-34/docs/svg-rendering/index.html | 36 ++++---- .../index.html | 91 +++++-------------- pr-previews/pr-34/index.html | 4 +- pr-previews/pr-34/index.xml | 22 +++-- pr-previews/pr-34/search/en.data.min.json | 2 +- pr-previews/pr-34/sitemap.xml | 2 +- pr-previews/pr-34/tags/index.html | 25 +++-- 20 files changed, 386 insertions(+), 330 deletions(-) rename pr-previews/pr-34/docs/{actions_and_protocols => actions-and-protocols}/index.html (87%) create mode 100644 pr-previews/pr-34/docs/custom-interactions/index.html rename pr-previews/pr-34/docs/{dependency_injection => dependency-injection}/index.html (88%) rename pr-previews/pr-34/docs/{getting_started => getting-started}/index.html (93%) create mode 100644 pr-previews/pr-34/docs/introduction/index.html rename pr-previews/pr-34/docs/{model_sources => model-sources}/index.html (90%) rename pr-previews/pr-34/docs/{user_interaction => user-interaction}/index.html (58%) diff --git a/pr-previews/pr-34/docs/actions_and_protocols/index.html b/pr-previews/pr-34/docs/actions-and-protocols/index.html similarity index 87% rename from pr-previews/pr-34/docs/actions_and_protocols/index.html rename to pr-previews/pr-34/docs/actions-and-protocols/index.html index fb5a54f..ed12537 100644 --- a/pr-previews/pr-34/docs/actions_and_protocols/index.html +++ b/pr-previews/pr-34/docs/actions-and-protocols/index.html @@ -1,38 +1,37 @@ Communication and Protocols | Sprotty +Actions Actions are plain JSON serializable objects so that they can easily be passed through all kinds of APIs."> -
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Communication and Protocols

Sprotty uses actions to communicate between ModelSource and ActionDispatcher regardless if the model source is local or remote. The core of this communication follows specific protocols. This Chapter will give an overview of these protocols and their used actions.

Actions -

Actions are plain JSON serializable objects so that they can easily be passed through all kinds of APIs. They can be distinguished through their KIND string property. +

Actions are plain JSON serializable objects so that they can easily be passed through all kinds of APIs. They can be distinguished through their KIND string property. In this section, the most important actions for understanding the basic communication protocols are described. For more info on existing actions see actions.ts

ComputedBoundsAction -

Sent from the client to the model source to transmit the result of bounds computation for micro-layout. +

Sent from the client to the model source to transmit the result of bounds computation for micro-layout. This is sent as a response to a RequestBoundsAction

RequestBoundsAction -

Sent from the model source to the client to request bounds for the given model. This triggers the micro-layout computation.

RequestModelAction -

Sent from client to model source to request a new model. Usually, this is the first action sent to initiate the communication. +

Sent from the model source to the client to request bounds for the given model. This triggers the micro-layout computation.

RequestModelAction +

Sent from client to model source to request a new model. Usually, this is the first action sent to initiate the communication. Optionally this can contain an options object containing configuration for the DiagramServer, like properties for needsClientLayout and needsServerLayout.

SetModelAction -

Sent from the model source to the client to set the model. It contains the schema for the new graph. +

Sent from the model source to the client to set the model. It contains the schema for the new graph. Should a model already exist in the client, it is overwritten.

UpdateModelAction -

Sent from model source to client to update the current model. Allows animating the transition from the old to the new model and contains properties for the transition.

Protocols -

Based on where layouting should be done there are 3 different protocols through which the DiagramServer and client can communicate. +

Sent from model source to client to update the current model. Allows animating the transition from the old to the new model and contains properties for the transition.

Protocols +

Based on where layouting should be done there are 3 different protocols through which the DiagramServer and client can communicate. On the client-side, this can be configured through the configureViewerOptions in the dependency injection container.

configureViewerOptions(context, {
     needsClientLayout: false,
     needServerLayout: true,
@@ -41,7 +40,7 @@
 

On the server-side layout options need to be set in the DiagramServer

diagramServer.setNeedsClientLayout(false);
 diagramServer.setNeedsServerLayout(true);
 

1. No Layout Computation / Server-Only Layout -

In this scenario, the server needs to provide a model with complete layout information, so that no further processing by the client is required. +

In this scenario, the server needs to provide a model with complete layout information, so that no further processing by the client is required.

 sequenceDiagram
 participant C as Client
@@ -54,7 +53,7 @@
     S->>C: UpdateModelAction
 end
 
First the client requests and receives the model from the server. After that, the server can update the model whenever necessary.

2. Client-Only Layout -

The server sends RequestBoundsAction (highlighted in yellow) to the client instead of updating the model directly. The client does not forward the resulting ComputedBoundsAction to the server because that would be an unnecessary round-trip. The updated bounds are applied locally in the client instead.

+

The server sends RequestBoundsAction (highlighted in yellow) to the client instead of updating the model directly. The client does not forward the resulting ComputedBoundsAction to the server because that would be an unnecessary round-trip. The updated bounds are applied locally in the client instead.

 sequenceDiagram
 participant C as Client
 participant S as Server
@@ -70,7 +69,7 @@
     end
 end
 
This is very similar to scenario 1 (with server-only layout). However, instead of SetModelAction and UpdateModelAction we use the RequestBoundsAction which contains the full graph

3. Client and Server Layout -

This is similar to the second scenario above, but here the ComputedBoundsAction is processed on the server so it can apply its own layout engine to the updated model.

+

This is similar to the second scenario above, but here the ComputedBoundsAction is processed on the server so it can apply its own layout engine to the updated model.

 sequenceDiagram
 participant C as Client
 participant S as Server
@@ -85,4 +84,7 @@
     C ->> S: ComputedBoundsAction
     S ->> C: UpdateModelAction
 end
-

\ No newline at end of file +

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/custom-interactions/index.html b/pr-previews/pr-34/docs/custom-interactions/index.html new file mode 100644 index 0000000..9164ecd --- /dev/null +++ b/pr-previews/pr-34/docs/custom-interactions/index.html @@ -0,0 +1,68 @@ +Creating Custom Interaction | Sprotty + +
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Creating Custom Interaction

Buttons and Button Handlers +

Buttons in Sprotty work similarly to the other model elements, but they enable you to directly hook up handlers that react to the push of a button. +As in the other examples with other types of nodes, we first need to define the model and view class and define its type ID. in addition, we also need to define a button handler of type IButtonHandler.

const container = new ContainerModule((bind, unbind, isBound, rebind) => { 
+        const context = { bind, unbind, isBound, rebind };
+        configureModelElement(context, 'graph', SGraph, SGraphView);
+        configureModelElement(context, 'button:custom', SButton, CustomButtonView);
+
+        configureButtonHandler({bind, isBound}, 'button:custom', CustomButtonHandler);
+
+        configureViewerOptions(context, {
+            needsClientLayout: true,
+            baseDiv: 'sprotty'
+        });
+
+    });
+

A button handler is a simple injectable class with a buttonPressed(button: SButton): Action[] method. +The actions that this method returns are passed to the ActionDispatcher to be handled there.

@injectable()
+export class CustomButtonHandler implements IButtonHandler {
+    buttonPressed(button: SButton): Action[] {
+        alert('button on' + button.parent.id + ' pressed');
+        return [];
+    }
+}
+

Mouse and Keyboard Listeners +

Sprotty also offers the ability to attach mouse and keyboard listeners by registering MouseListener or KeyListener. +This can be simply done by binding the custom listener to the respective listener type in your DI-container like this:

    bind(CustomMouseListener).toSelf().inSingletonScope();
+    bind(TYPES.MouseListener).toService(CustomMouseListener);
+

These listeners are global, meaning they react to every interaction with the diagram. A very simple mouse Listener would look like this:

export class CustomMouseListener extends MouseListener {
+    doubleClick(target: SModelElementImpl, event: MouseEvent): (Action | Promise<Action>)[] {
+        alert('double clicked ' + target.id)
+        return [];
+    }
+}
+

If only specific types of nodes are supposed to be interacted with through this custom listener, it’s recommended to create a custom feature.

Projection Bars +

Another interactive Sprotty feature is the ProjectedViewportView. +This view automatically adds a vertical and horizontal scrollbar to our diagram view in which our current viewport is shown, like in the following image.

projection bar example

To activate this feature, instead of using SGraphImpl and SGraphView for our root element, as we did in the other examples, we use ViewportRootElement and ProjectedViewportView. +The scrollbars created through ProjectedViewportView can be styled via the .sprotty-viewport and .sprotty-projection-bar CSS classes.

As we can see in the image, these scrollbars can contain projections of our nodes, which show their horizontal and vertical position. +Double-clicking on a projection will center the view on the node the projection belongs to.

To add projections we add the Projectable type to the nodes in our model schema like this:

 <SNode & Projectable>{
+            id: 'svg',
+            type: 'node:svg',
+            text: '',
+            projectionCssClasses: ['svg-projection']
+}
+

The Projectable interface requires us to specify the projectionCssClasses property, which defines the CSS classes the framework will apply to the HTML div element that represents the projection in the projection bar. If no projectionCssClasses property value is specified, no projection will be created. +As projections are simple HTML div elements positioned on the projection bar, they can easily be styled as follows:

.svg-projection { 
+    background-color: rgba(255, 153, 0, 0.5); 
+}
+
\ No newline at end of file diff --git a/pr-previews/pr-34/docs/dependency_injection/index.html b/pr-previews/pr-34/docs/dependency-injection/index.html similarity index 88% rename from pr-previews/pr-34/docs/dependency_injection/index.html rename to pr-previews/pr-34/docs/dependency-injection/index.html index 7f19955..07b7ab7 100644 --- a/pr-previews/pr-34/docs/dependency_injection/index.html +++ b/pr-previews/pr-34/docs/dependency-injection/index.html @@ -2,29 +2,28 @@ Why dependency injection? DI allows us to: not care about the instantiation and life-cycle of service components manage singletons like the various registries without using the global scope easily mock components in tests exchange default implementations with custom ones with minimum code changes modularize the configuration of specific features and scenarios and merge these modules for the final application The container The DI-container is the main point of configuration.">Sprotty configuration and dependency injection | Sprotty +not care about the instantiation and life-cycle of service components manage singletons like the various registries without using the global scope easily mock components in tests exchange default implementations with custom ones with minimum code changes modularize the configuration of specific features and scenarios and merge these modules for the final application The container The DI-container is the main point of configuration."> -
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Sprotty configuration and dependency injection

As seen in the getting started guide, Sprotty relies heavily on dependency injection (DI) through InversifyJs for the configuration of its various components. This chapter will take a closer look at how to work with this.

Why dependency injection? -

DI allows us to:

  • not care about the instantiation and life-cycle of service components
  • manage singletons like the various registries without using the global scope
  • easily mock components in tests
  • exchange default implementations with custom ones with minimum code changes
  • modularize the configuration of specific features and scenarios and merge these modules for the final application

The container -

The DI-container is the main point of configuration. The standard in Sprotty is to name this file di.config.ts.

export const createContainer = (containerId: string) => {
+hidden-mobile" itemprop=breadcrumb>

Sprotty configuration and dependency injection

As seen in the getting started guide, Sprotty relies heavily on dependency injection (DI) through InversifyJs for the configuration of its various components. This chapter will take a closer look at how to work with this.

Why dependency injection? +

DI allows us to:

  • not care about the instantiation and life-cycle of service components
  • manage singletons like the various registries without using the global scope
  • easily mock components in tests
  • exchange default implementations with custom ones with minimum code changes
  • modularize the configuration of specific features and scenarios and merge these modules for the final application

The container +

The DI-container is the main point of configuration. The standard in Sprotty is to name this file di.config.ts.

export const createContainer = (containerId: string) => {
     const myModule = new ContainerModule((bind, unbind, isBound, rebind) => {
         bind(TYPES.ModelSource).to(LocalModelSource).inSingletonScope();
         const context = { bind, unbind, isBound, rebind };
@@ -41,7 +40,7 @@
     container.load(myModule, edgeIntersectionModule);
     return container;
 };
-

The container is built from multiple modules. Through loadDefaultModules() all modules are loaded for default Sprotty functionalities. We can also load other optional modules like the edgeIntersectionModule for extra functionality.

Most important is our own module where the core of the configuration happens. Here we can configure singleton scope classes like our model source or rebind default Sprotty components (for example the logger) to a custom implementation. We use Symbols for bindings instead of using classes directly. All Symbols can be found in the TYPES object.

Using configureModelElement we can link our model to specific view components through the type property. Meaning if we have the following SNode, +

The container is built from multiple modules. Through loadDefaultModules() all modules are loaded for default Sprotty functionalities. We can also load other optional modules like the edgeIntersectionModule for extra functionality.

Most important is our own module where the core of the configuration happens. Here we can configure singleton scope classes like our model source or rebind default Sprotty components (for example the logger) to a custom implementation. We use Symbols for bindings instead of using classes directly. All Symbols can be found in the TYPES object.

Using configureModelElement we can link our model to specific view components through the type property. Meaning if we have the following SNode, in our model, Sprotty will try to convert this data structure to an instance of the actual SNodeImpl class and render it with the TaskNodeView.

<SNode & TaskNode>{
             type: 'task',
             id: 'task01',
@@ -50,12 +49,12 @@
             ...
 }
 

Lastly, we need to configure our viewer options. Here we configure all the DOM elements needed by Sprotty, for example the base div inside of which our diagram is rendered, or the hidden div used by the first render cycle for determining micro layout. Another thing configured here is the layout. Specifically, if layout calculation should be done on client-side, server-side or both. This also determines the protocol spoken by the client and server.

Features -

Model elements can further be configured through features.

configureModelElement(context, 'task', SNodeImpl, TaskNodeView, {
+

Model elements can further be configured through features.

configureModelElement(context, 'task', SNodeImpl, TaskNodeView, {
     enable: [customFeature],
     disable: [moveFeature]
 });
 

the configureModelElement method takes an optional object as the last parameter containing arrays for enabled and disabled features, which in turn contain Symbols representing those features. Through this, we can disable default functionality like dragging or selecting nodes and add functionality, either custom or loaded from other non-default modules.

Creating custom components -

As described previously Sprotty uses InversifyJs for dependency injection. That means when creating custom features, views, etc. we have to use this too. +

As described previously Sprotty uses InversifyJs for dependency injection. That means when creating custom features, views, etc. we have to use this too. As an example, let’s look at Sprotty’s PolylineEdgeView.

@injectable()
 export class PolylineEdgeView extends RoutableView {
 
@@ -64,10 +63,10 @@
 }
 

The most important thing for our component to be made available in Sprotty is annotating it with @injectable(). Otherwise the dependency injection won’t work.

Now, as seen in the example above, we can just bind it in the container like this:

configureModelElement(context, 'edge', SEdge, PolylineEdgeView);
 

After that we can use all features of inversifyJs and inject other components registered in our container with @inject(...)

For more information on inversifyJs have a look to their documentation

Dependency Injection specialties -

Multi bindings -

Sometimes there is more than one implementation bound to a specific interface in Sprotty. This is when we use multi-bindings. Here is an example of the VNodeDecorator.

@multiInject(TYPES.VNodePostprocessor)@optional() protected postprocessors: VNodePostprocessor[]
+

Multi bindings +

Sometimes there is more than one implementation bound to a specific interface in Sprotty. This is when we use multi-bindings. Here is an example of the VNodeDecorator.

@multiInject(TYPES.VNodePostprocessor)@optional() protected postprocessors: VNodePostprocessor[]
 

Provider Bindings -

Sprotty’s circular event flow introduces a cyclic dependency between the components ActionDispatcher, CommandStack and Viewer. To handle these, we have to use provider bindings like this:

// action-dispatcher.ts
+

Sprotty’s circular event flow introduces a cyclic dependency between the components ActionDispatcher, CommandStack and Viewer. To handle these, we have to use provider bindings like this:

// action-dispatcher.ts
 export type IActionDispatcherProvider = () => Promise<IActionDispatcher>;
 
// di.config.ts 
 bind(TYPES.IActionDispatcher).to(ActionDispatcher).inSingletonScope();
@@ -78,4 +77,7 @@
         });
     };
 });
-
\ No newline at end of file + \ No newline at end of file diff --git a/pr-previews/pr-34/docs/features/index.html b/pr-previews/pr-34/docs/features/index.html index 36bc535..3353970 100644 --- a/pr-previews/pr-34/docs/features/index.html +++ b/pr-previews/pr-34/docs/features/index.html @@ -5,26 +5,25 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Features

Features can be viewed as a set of functionalities that a given element can support. They can enrich the behavior and usability of the diagram model.

SModelElements can have default features that will apply to all model elements that are instance of this SModelElement.Default features are specified in the DEFAULT_FEATURES field, which can be overridden in inherited classes. This way, the default features will be enabled for all instances of the class.

Let’s have a look at the SNodeImpl class and how it implements default features:

export class SNodeImpl extends SConnectableElementImpl implements Selectable, Fadeable, Hoverable {
+hidden-mobile" itemprop=breadcrumb>

Features

Features can be viewed as a set of functionalities that a given element can support. They can enrich the behavior and usability of the diagram model.

SModelElements can have default features that will apply to all model elements that are instance of this SModelElement.Default features are specified in the DEFAULT_FEATURES field, which can be overridden in inherited classes. This way, the default features will be enabled for all instances of the class.

Let’s have a look at the SNodeImpl class and how it implements default features:

export class SNodeImpl extends SConnectableElementImpl implements Selectable, Fadeable, Hoverable {
     static readonly DEFAULT_FEATURES = [connectableFeature, deletableFeature, selectFeature, boundsFeature,
         moveFeature, layoutContainerFeature, fadeFeature, hoverFeedbackFeature, popupFeature];
     ...
 }
-

It is possible to fine-tune the behavior in the dependency injection container by enabling or disabling features for a given model element type.

configureElement('my-node-type', SNodeImpl, RectangularNodeView, {enable: [layoutableChildFeature], disable: [moveFeature]})
+

It is possible to fine-tune the behavior in the dependency injection container by enabling or disabling features for a given model element type.

configureElement('my-node-type', SNodeImpl, RectangularNodeView, {enable: [layoutableChildFeature], disable: [moveFeature]})
 

To ensure that the required additional properties are present on the model element, Sprotty comes with a set of interfaces to ensure correct implementation in the model element class. These interfaces must extend SModelExtension.

alignFeature

Controls the position adjustment of an element. It is given by the alignment: Point property of an element. It applies a translate to the svg element. This translation is applied in addition to the translation that may be applied by the layout engine.

Interface: Alignable

export interface Alignable extends SModelExtension {
@@ -107,4 +106,7 @@
 

Controls if an element has an editable label. The element must have the editableLabel property.

Interface: WithEditableLabel

export interface WithEditableLabel extends SModelExtension {
     readonly editableLabel?: EditableLabel & SModelElementImpl;
 }
-
\ No newline at end of file + \ No newline at end of file diff --git a/pr-previews/pr-34/docs/getting_started/index.html b/pr-previews/pr-34/docs/getting-started/index.html similarity index 93% rename from pr-previews/pr-34/docs/getting_started/index.html rename to pr-previews/pr-34/docs/getting-started/index.html index c9dde9b..1d91495 100644 --- a/pr-previews/pr-34/docs/getting_started/index.html +++ b/pr-previews/pr-34/docs/getting-started/index.html @@ -2,31 +2,30 @@ The main steps to integrate Sprotty into our application are as follows: Set-up your application. Define your model by creating sub-interfaces of SModelElement. Implement views to generate SVGs for each type of model element. Configure the diagram through dependency injection. Connect to a model source, either local or remote Fast-Forward With Yeoman If you’d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:">Getting Started | Sprotty +Set-up your application. Define your model by creating sub-interfaces of SModelElement. Implement views to generate SVGs for each type of model element. Configure the diagram through dependency injection. Connect to a model source, either local or remote Fast-Forward With Yeoman If you’d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:"> -
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Getting Started

Our ‘Getting Started’ example consists of a simple application that displays a list of tasks, their status, and the relationship between them in a HTML page.

The main steps to integrate Sprotty into our application are as follows:

  1. Set-up your application.
  2. Define your model by creating sub-interfaces of SModelElement.
  3. Implement views to generate SVGs for each type of model element.
  4. Configure the diagram through dependency injection.
  5. Connect to a model source, either local or remote

Fast-Forward With Yeoman -

If you’d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:

npm install -g yo generator-sprotty
+hidden-mobile" itemprop=breadcrumb>

Getting Started

Our ‘Getting Started’ example consists of a simple application that displays a list of tasks, their status, and the relationship between them in a HTML page.

The main steps to integrate Sprotty into our application are as follows:

  1. Set-up your application.
  2. Define your model by creating sub-interfaces of SModelElement.
  3. Implement views to generate SVGs for each type of model element.
  4. Configure the diagram through dependency injection.
  5. Connect to a model source, either local or remote

Fast-Forward With Yeoman +

If you’d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:

npm install -g yo generator-sprotty
 yo sprotty
 

Answer a few questions and you’ll get a ready-to-use example project.

Setting-up Our Application -

Our example application is based on TypeScript. In this application we will set up our project to be ready for receiving Sprotty.

  1. Create a new directory and navigate to it

  2. Initialize the project by running

    npm init -y
    +

    Our example application is based on TypeScript. In this application we will set up our project to be ready for receiving Sprotty.

    1. Create a new directory and navigate to it

    2. Initialize the project by running

      npm init -y
       

      This will create a package.json file.

    3. Modify package.json to add a build script and necessary dependencies

      {
           "scripts": {
           "build": "esbuild ./index.ts --bundle --sourcemap --outfile=./out/index.js"
      @@ -76,7 +75,7 @@
           stroke-width: 1px;
       }
       

    Our project is now set-up and ready for integrating Sprotty diagrams.

    Define Your Model -

    Sprotty comes with a set of model classes that you can reuse for your application. e.g. SNodeImpl and SEdgeImpl for graphs and SChildElementImpl for other views. However, it is often necessary to add application-specific properties to model elements, so their graphical views can be parameterized.

    We will define a new interface for our nodes called TaskNode, extending Sprotty’s SNode interface with application-specific properties. Create a new file models.ts at the root of the project:

    import { SNode } from "sprotty-protocol"
    +

    Sprotty comes with a set of model classes that you can reuse for your application. e.g. SNodeImpl and SEdgeImpl for graphs and SChildElementImpl for other views. However, it is often necessary to add application-specific properties to model elements, so their graphical views can be parameterized.

    We will define a new interface for our nodes called TaskNode, extending Sprotty’s SNode interface with application-specific properties. Create a new file models.ts at the root of the project:

    import { SNode } from "sprotty-protocol"
     
     export interface TaskNode extends SNode {
         name: string;
    @@ -84,7 +83,7 @@
         isFinished: boolean;
     }
     

    Implement Views -

    A view maps a model element to its graphical representation. You can create your own views by creating a class implementing IView or extending a view already available in Sprotty.

    In the following example we use the JSX syntax to create a SVG group with a rect and a text element. Add a new file views.tsx (note the tsx extension) at the root of the project:

    /** @jsx svg */
    +

    A view maps a model element to its graphical representation. You can create your own views by creating a class implementing IView or extending a view already available in Sprotty.

    In the following example we use the JSX syntax to create a SVG group with a rect and a text element. Add a new file views.tsx (note the tsx extension) at the root of the project:

    /** @jsx svg */
     import { svg } from 'sprotty/lib/lib/jsx';
     import { injectable } from 'inversify';
     import { VNode } from 'snabbdom';
    @@ -130,7 +129,7 @@
         text-anchor: middle;
     }
     

    Configure the Diagram -

    The configuration of our Sprotty application is done via Dependency Injection using InversifyJS. We recommend defining your InversifyJS container in a file named di.config.ts at the root of the project which could look like this:

    import { Container, ContainerModule } from 'inversify';
    +

    The configuration of our Sprotty application is done via Dependency Injection using InversifyJS. We recommend defining your InversifyJS container in a file named di.config.ts at the root of the project which could look like this:

    import { Container, ContainerModule } from 'inversify';
     import { configureModelElement, configureViewerOptions, loadDefaultModules, LocalModelSource, PolylineEdgeView, SEdgeImpl, SGraphImpl, SGraphView, SNodeImpl, TYPES } from 'sprotty';
     import { TaskNodeView } from './views';
     
    @@ -156,7 +155,7 @@
     };
     

    Views are registered using configureModelElement which takes a context, a type, an element class, and a view. loadDefaultModules is used to include Sprotty’s default modules, while container.load can be used to include extra modules required by our application.

    Connect to a Model Source -

    Sprotty supports two kinds of model sources:

    • LocalModelSource allows to create models directly in TypeScript or JavaScript
    • WebSocketDiagramServer delegates to a remote source that is connected via a web socket

    In this example, we consider the local variant. To enable the model source, we add the following line to our module definition (see previous section):

    bind(TYPES.ModelSource).to(LocalModelSource).inSingletonScope()
    +

    Sprotty supports two kinds of model sources:

    • LocalModelSource allows to create models directly in TypeScript or JavaScript
    • WebSocketDiagramServer delegates to a remote source that is connected via a web socket

    In this example, we consider the local variant. To enable the model source, we add the following line to our module definition (see previous section):

    bind(TYPES.ModelSource).to(LocalModelSource).inSingletonScope()
     

    Afterwards you can use the LocalModelSource to initialize and update the model. For example, the following graph consists of three task nodes with a connection between the first two. Create a new file model-source.ts at the root of the project:

    import { SGraph, SEdge, SNode } from "sprotty-protocol";
     import { TaskNode } from "./models";
     
    @@ -213,4 +212,4 @@
     
     document.addEventListener("DOMContentLoaded", () => run());
     

    That’s it! Run npm run build and open your HTML file, you should see the following diagram! There is some level of interactivity by default, try it out! Select nodes by clicking on them and move them around by dragging, adjust the zoom-level with the mouse wheel, navigate the diagram by panning via left-click and drag outside of a node. -Getting started diagram

\ No newline at end of file +Getting started diagram

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/index.html b/pr-previews/pr-34/docs/index.html index 3e5d20a..960c93a 100644 --- a/pr-previews/pr-34/docs/index.html +++ b/pr-previews/pr-34/docs/index.html @@ -1,27 +1,18 @@ -Documentation | Sprotty +Docs | Sprotty
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Documentation

Sprotty is a next-generation, open-source diagramming framework built with web-technologies.

Some selected features:

  • Fast, scalable SVG rendering that is compatible with all modern browsers and stylable with CSS
  • Animations built into the core
  • Support for a distributed runtime with client and server
  • Fast, reactive client architecture implemented in TypeScript
  • Java or Node.js based server architecture
  • Configuration via dependency injection
  • Integrations with Xtext, Langium, the Language Server Protocol, VS Code and Theia
  • Can be run as a rich-client as well as in the browser

Where to start? -

If you are new with Sprotty, we recommend taking a look at our Getting Started section before diving further.

Want to contribute? -

Visit the Sprotty repository and have a look at the contribution guidelines to take part in Sprotty’s development.

\ No newline at end of file +hidden-mobile" itemprop=breadcrumb>

Docs

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/index.xml b/pr-previews/pr-34/docs/index.xml index 4ff87a5..10be5a6 100644 --- a/pr-previews/pr-34/docs/index.xml +++ b/pr-previews/pr-34/docs/index.xml @@ -1,12 +1,14 @@ -Documentation on Sprotty/docs/Recent content in Documentation on SprottyHugo -- gohugo.ioen-usOverview/docs/overview/Mon, 01 Jan 0001 00:00:00 +0000/docs/overview/Action Dispatcher Action Model Source Command Stack Command SModel (SprottyModel) Viewer View Registry View The base architecture of Sprotty revolves around an unidirectional cyclic flow of information between three major components: the ActionDispatcher, the CommandStack, and the Viewer. This leads to a clear and easily testable flow of data which prevents feedback loops. -flowchart TD; ActionDispatcher CommandStack Viewer ActionDispatcher -->|Command| CommandStack CommandStack -->|SModel| Viewer Viewer -->|Action| ActionDispatcher Action Dispatcher The main role of the ActionDispatcher is to receive an Action and produce a corresponding command to be transmitted to the CommandStack using ActionHandlers.Getting Started/docs/getting_started/Mon, 01 Jan 0001 00:00:00 +0000/docs/getting_started/Our &lsquo;Getting Started&rsquo; example consists of a simple application that displays a list of tasks, their status, and the relationship between them in a HTML page. +Docs on Sprotty/docs/Recent content in Docs on SprottyHugo -- gohugo.ioen-usCommunication and Protocols/docs/actions-and-protocols/Mon, 01 Jan 0001 00:00:00 +0000/docs/actions-and-protocols/Actions ComputedBoundsAction RequestBoundsAction RequestModelAction SetModelAction UpdateModelAction Protocols 1. No Layout Computation / Server-Only Layout 2. Client-Only Layout 3. Client and Server Layout Sprotty uses actions to communicate between ModelSource and ActionDispatcher regardless if the model source is local or remote. The core of this communication follows specific protocols. This Chapter will give an overview of these protocols and their used actions. +Actions Actions are plain JSON serializable objects so that they can easily be passed through all kinds of APIs.Creating Custom Interaction/docs/custom-interactions/Mon, 01 Jan 0001 00:00:00 +0000/docs/custom-interactions/Buttons and Button Handlers Mouse and Keyboard Listeners Projection Bars Buttons and Button Handlers Buttons in Sprotty work similarly to the other model elements, but they enable you to directly hook up handlers that react to the push of a button. As in the other examples with other types of nodes, we first need to define the model and view class and define its type ID. in addition, we also need to define a button handler of type IButtonHandler.Features/docs/features/Mon, 01 Jan 0001 00:00:00 +0000/docs/features/alignFeature boundsFeature connectableFeature creatingOnDragFeature decorationFeature deletableFeature edgeLayoutFeature editFeature editLabelFeature expandFeature exportFeature fadeFeature hoverFeedbackFeature layoutableChildFeature layoutContainerFeature moveFeature nameFeature openFeature popupFeature selectFeature viewportFeature withEditLabelFeature Features can be viewed as a set of functionalities that a given element can support. They can enrich the behavior and usability of the diagram model. +SModelElements can have default features that will apply to all model elements that are instance of this SModelElement.Default features are specified in the DEFAULT_FEATURES field, which can be overridden in inherited classes.Getting Started/docs/getting-started/Mon, 01 Jan 0001 00:00:00 +0000/docs/getting-started/Our &lsquo;Getting Started&rsquo; example consists of a simple application that displays a list of tasks, their status, and the relationship between them in a HTML page. The main steps to integrate Sprotty into our application are as follows: -Set-up your application. Define your model by creating sub-interfaces of SModelElement. Implement views to generate SVGs for each type of model element. Configure the diagram through dependency injection. Connect to a model source, either local or remote Fast-Forward With Yeoman If you&rsquo;d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:SModel/docs/smodel/Mon, 01 Jan 0001 00:00:00 +0000/docs/smodel/External Model Internal Model Elements Classes Inheritance SModelElementImpl SParentElementImpl SChildElementImpl SModelRootImpl ModelIndexImpl Graph Elements SGraphImpl SNodeImpl SPortImpl SEdgeImpl SLabelImpl SCompartmentImpl SGraphIndex ViewportRootElement SConnectableElementImpl SShapeElementImpl SRoutableElementImpl The SModel (short for SprottyModel) is the core data structure of Sprotty. It is a tree of model elements that can be rendered by a View. The root of the model is always an instance of SModelRootImpl or one of its derived class. -First, we need to distinguish between two models: the internal model and the external model.Features/docs/features/Mon, 01 Jan 0001 00:00:00 +0000/docs/features/alignFeature boundsFeature connectableFeature creatingOnDragFeature decorationFeature deletableFeature edgeLayoutFeature editFeature editLabelFeature expandFeature exportFeature fadeFeature hoverFeedbackFeature layoutableChildFeature layoutContainerFeature moveFeature nameFeature openFeature popupFeature selectFeature viewportFeature withEditLabelFeature Features can be viewed as a set of functionalities that a given element can support. They can enrich the behavior and usability of the diagram model. -SModelElements can have default features that will apply to all model elements that are instance of this SModelElement.Default features are specified in the DEFAULT_FEATURES field, which can be overridden in inherited classes.Sprotty configuration and dependency injection/docs/dependency_injection/Mon, 01 Jan 0001 00:00:00 +0000/docs/dependency_injection/Why dependency injection? The container Features Creating custom components Dependency Injection specialties Multi bindings Provider Bindings As seen in the getting started guide, Sprotty relies heavily on dependency injection (DI) through InversifyJs for the configuration of its various components. This chapter will take a closer look at how to work with this. +Set-up your application. Define your model by creating sub-interfaces of SModelElement. Implement views to generate SVGs for each type of model element. Configure the diagram through dependency injection. Connect to a model source, either local or remote Fast-Forward With Yeoman If you&rsquo;d like to skip the manual steps below and create a Sprotty-based project right away, you can use the Yeoman generator:Introduction/docs/introduction/Mon, 01 Jan 0001 00:00:00 +0000/docs/introduction/Sprotty is a next-generation, open-source diagramming framework built with web-technologies. +Some selected features: +Fast, scalable SVG rendering that is compatible with all modern browsers and stylable with CSS Animations built into the core Support for a distributed runtime with client and server Fast, reactive client architecture implemented in TypeScript Java or Node.js based server architecture Configuration via dependency injection Integrations with Xtext, Langium, the Language Server Protocol, VS Code and Theia Can be run as a rich-client as well as in the browser Where to start?Micro-layout/docs/micro-layout/Mon, 01 Jan 0001 00:00:00 +0000/docs/micro-layout/Layout Configuration Layout Options Alignment Padding Size Using SCompartments for Complex Layouts Layouting Nested Nodes The micro-layout refers to the layout of elements inside of a node, i.e. the layout of nested labels, buttons, etc. It is not to be confused with the macro-layout which refers to the layout of the entire graph, e.g. the position of nodes. +Layout Configuration Any model element that implements or extends the SNode or SCompartment interface has an optional property layout that specifies the general layout of its children elements.Model Sources/docs/model-sources/Mon, 01 Jan 0001 00:00:00 +0000/docs/model-sources/General usage Local Model Source Diagram Server Creating a Custom Model Source Proxy When drawing a diagram with Sprotty we need a place to define and update the schema of the diagram to draw. Sprotty uses model sources to do this. Sprotty currently offers two different model sources: The LocalModelSource for local models and the DiagramServer for remote ones. flowchart TD; ActionDispatcher ModelSource LocalModelSource DiagramServerProxy DiagramServer ActionDispatcher <-.->|Action| ModelSource ModelSource --- LocalModelSource ModelSource --- DiagramServerProxy DiagramServerProxy <-.Overview/docs/overview/Mon, 01 Jan 0001 00:00:00 +0000/docs/overview/Action Dispatcher Action Model Source Command Stack Command SModel (SprottyModel) Viewer View Registry View The base architecture of Sprotty revolves around an unidirectional cyclic flow of information between three major components: the ActionDispatcher, the CommandStack, and the Viewer. This leads to a clear and easily testable flow of data which prevents feedback loops. +flowchart TD; ActionDispatcher CommandStack Viewer ActionDispatcher -->|Command| CommandStack CommandStack -->|SModel| Viewer Viewer -->|Action| ActionDispatcher Action Dispatcher The main role of the ActionDispatcher is to receive an Action and produce a corresponding command to be transmitted to the CommandStack using ActionHandlers.SModel/docs/smodel/Mon, 01 Jan 0001 00:00:00 +0000/docs/smodel/External Model Internal Model Elements Classes Inheritance SModelElementImpl SParentElementImpl SChildElementImpl SModelRootImpl ModelIndexImpl Graph Elements SGraphImpl SNodeImpl SPortImpl SEdgeImpl SLabelImpl SCompartmentImpl SGraphIndex ViewportRootElement SConnectableElementImpl SShapeElementImpl SRoutableElementImpl The SModel (short for SprottyModel) is the core data structure of Sprotty. It is a tree of model elements that can be rendered by a View. The root of the model is always an instance of SModelRootImpl or one of its derived class. +First, we need to distinguish between two models: the internal model and the external model.Sprotty configuration and dependency injection/docs/dependency-injection/Mon, 01 Jan 0001 00:00:00 +0000/docs/dependency-injection/Why dependency injection? The container Features Creating custom components Dependency Injection specialties Multi bindings Provider Bindings As seen in the getting started guide, Sprotty relies heavily on dependency injection (DI) through InversifyJs for the configuration of its various components. This chapter will take a closer look at how to work with this. Why dependency injection? DI allows us to: -not care about the instantiation and life-cycle of service components manage singletons like the various registries without using the global scope easily mock components in tests exchange default implementations with custom ones with minimum code changes modularize the configuration of specific features and scenarios and merge these modules for the final application The container The DI-container is the main point of configuration.SVG Rendering/docs/svg-rendering/Mon, 01 Jan 0001 00:00:00 +0000/docs/svg-rendering/Virtual DOM Views Layouting Client Layout Server Layout Sprotty transforms a given SModel to its representation in the DOM in the form of a hierarchy of SVG elements. An SModel is composed of SModelElements, and each SModelElement has a type property that is associated to a single corresponding View. The ViewRegistry keeps a map of the correspondence between an element type and a view. These model elements are organized in the virtual DOM before being rendered as actual SVG elements in the DOM.Micro-layout/docs/micro-layout/Mon, 01 Jan 0001 00:00:00 +0000/docs/micro-layout/Layout Configuration Layout Options Alignment Padding Size Using SCompartments for Complex Layouts Layouting Nested Nodes The micro-layout refers to the layout of elements inside of a node, i.e. the layout of nested labels, buttons, etc. It is not to be confused with the macro-layout which refers to the layout of the entire graph, e.g. the position of nodes. -Layout Configuration Any model element that implements or extends the SNode or SCompartment interface has an optional property layout that specifies the general layout of its children elements.Model Sources/docs/model_sources/Mon, 01 Jan 0001 00:00:00 +0000/docs/model_sources/General usage Local Model Source Diagram Server Creating a Custom Model Source Proxy When drawing a diagram with Sprotty we need a place to define and update the schema of the diagram to draw. Sprotty uses model sources to do this. Sprotty currently offers two different model sources: The LocalModelSource for local models and the DiagramServer for remote ones. flowchart TD; ActionDispatcher ModelSource LocalModelSource DiagramServerProxy DiagramServer ActionDispatcher <-.->|Action| ModelSource ModelSource --- LocalModelSource ModelSource --- DiagramServerProxy DiagramServerProxy <-.Communication and Protocols/docs/actions_and_protocols/Mon, 01 Jan 0001 00:00:00 +0000/docs/actions_and_protocols/Actions ComputedBoundsAction RequestBoundsAction RequestModelAction SetModelAction UpdateModelAction Protocols 1. No Layout Computation / Server-Only Layout 2. Client-Only Layout 3. Client and Server Layout Sprotty uses actions to communicate between ModelSource and ActionDispatcher regardless if the model source is local or remote. The core of this communication follows specific protocols. This Chapter will give an overview of these protocols and their used actions. -Actions Actions are plain JSON serializable objects so that they can easily be passed through all kinds of APIs.User Interaction/docs/user_interaction/Mon, 01 Jan 0001 00:00:00 +0000/docs/user_interaction/Interacting with a Sprotty Diagram Creating Custom Interaction Buttons and Button Handlers Mouse and Keyboard Listeners Projection Bars Interacting with a Sprotty Diagram Sprotty offers multiple mouse and keyboard interactions by default listed in the following tables. The CTRL key in the following is equal to the CMD key on Mac. -Mouse left-click: toggle selection CTRL-click: add to/remove from selection left-click : drag move selection (when on selected element) left-click : drag pan viewport (when on diagram background) mouse wheel: zoom Touchpad click toggle selection drag move selection (when on selected element) two-finger pan up/down zoom zoom zoom Keys CTRL-SHIFT-A select all CTRL-SHIFT-C center selection, or if nothing is selected center the entire diagram CTRL-SHIFT-E export diagram to SVG CTRL-SHIFT-F zoom selection to fill the entire canvas, or if nothing is selected zoom the entire diagram CTRL-Z undo CTRL-SHIFT-Z redo Creating Custom Interaction Buttons and Button Handlers Buttons in Sprotty work similarly to the other model elements, but they enable you to directly hook up handlers that react to the push of a button.Styling/docs/styling/Mon, 01 Jan 0001 00:00:00 +0000/docs/styling/Predefined Styling Available Views Default CSS Classes Using Subtypes for Styling Styling on a Per-Element Basis Styling from Custom Views Styling on User Interaction Sprotty is designed to be highly customizable. Styling of diagram elements is done using CSS, preferably using CSS classes. There are several ways to apply styles to an element depending on the level of granularity you need. -Predefined Styling Available Views Sprotty comes with a handful of views that can be used to represent nodes, edges, and labels of your diagram. \ No newline at end of file +not care about the instantiation and life-cycle of service components manage singletons like the various registries without using the global scope easily mock components in tests exchange default implementations with custom ones with minimum code changes modularize the configuration of specific features and scenarios and merge these modules for the final application The container The DI-container is the main point of configuration.Styling/docs/styling/Mon, 01 Jan 0001 00:00:00 +0000/docs/styling/Predefined Styling Available Views Default CSS Classes Using Subtypes for Styling Styling on a Per-Element Basis Styling from Custom Views Styling on User Interaction Sprotty is designed to be highly customizable. Styling of diagram elements is done using CSS, preferably using CSS classes. There are several ways to apply styles to an element depending on the level of granularity you need. +Predefined Styling Available Views Sprotty comes with a handful of views that can be used to represent nodes, edges, and labels of your diagram.SVG Rendering/docs/svg-rendering/Mon, 01 Jan 0001 00:00:00 +0000/docs/svg-rendering/Virtual DOM Views Layouting Client Layout Server Layout Sprotty transforms a given SModel to its representation in the DOM in the form of a hierarchy of SVG elements. An SModel is composed of SModelElements, and each SModelElement has a type property that is associated to a single corresponding View. The ViewRegistry keeps a map of the correspondence between an element type and a view. These model elements are organized in the virtual DOM before being rendered as actual SVG elements in the DOM.User Interaction/docs/user-interaction/Mon, 01 Jan 0001 00:00:00 +0000/docs/user-interaction/ Interacting with a Sprotty Diagram Interacting with a Sprotty Diagram Sprotty offers multiple mouse and keyboard interactions by default listed in the following tables. The CTRL key in the following is equal to the CMD key on Mac. +Mouse left-click: toggle selection CTRL-click: add to/remove from selection left-click : drag move selection (when on selected element) left-click : drag pan viewport (when on diagram background) mouse wheel: zoom Touchpad click toggle selection drag move selection (when on selected element) two-finger pan up/down zoom zoom zoom Keys CTRL-SHIFT-A select all CTRL-SHIFT-C center selection, or if nothing is selected center the entire diagram CTRL-SHIFT-E export diagram to SVG CTRL-SHIFT-F zoom selection to fill the entire canvas, or if nothing is selected zoom the entire diagram CTRL-Z undo CTRL-SHIFT-Z redo \ No newline at end of file diff --git a/pr-previews/pr-34/docs/introduction/index.html b/pr-previews/pr-34/docs/introduction/index.html new file mode 100644 index 0000000..f768f15 --- /dev/null +++ b/pr-previews/pr-34/docs/introduction/index.html @@ -0,0 +1,27 @@ +Introduction | Sprotty + +
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Introduction

Sprotty is a next-generation, open-source diagramming framework built with web-technologies.

Some selected features:

  • Fast, scalable SVG rendering that is compatible with all modern browsers and stylable with CSS
  • Animations built into the core
  • Support for a distributed runtime with client and server
  • Fast, reactive client architecture implemented in TypeScript
  • Java or Node.js based server architecture
  • Configuration via dependency injection
  • Integrations with Xtext, Langium, the Language Server Protocol, VS Code and Theia
  • Can be run as a rich-client as well as in the browser

Where to start? +

If you are new with Sprotty, we recommend taking a look at our Getting Started section before diving further.

Want to contribute? +

Visit the Sprotty repository and have a look at the contribution guidelines to take part in Sprotty’s development.

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/micro-layout/index.html b/pr-previews/pr-34/docs/micro-layout/index.html index a3a61a6..01e3f9d 100644 --- a/pr-previews/pr-34/docs/micro-layout/index.html +++ b/pr-previews/pr-34/docs/micro-layout/index.html @@ -5,22 +5,21 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Micro-layout

The micro-layout refers to the layout of elements inside of a node, i.e. the layout of nested labels, buttons, etc. It is not to be confused with the macro-layout which refers to the layout of the entire graph, e.g. the position of nodes.

Layout Configuration -

Any model element that implements or extends the SNode or SCompartment interface has an optional property layout that specifies the general layout of its children elements. Sprotty implements three layout configurations by default:

  • stack: children elements are stacked on top of each other (default layout)
  • hbox: children elements are arranged horizontally
  • vbox: children elements are arranged vertically

The layout property aims at arranging children elements that do not have a meaning in terms of graph hierarchy (i.e. labels, buttons, …). Please note that children that are instances of SNodeImpl do not respect the layout property by default (more on that later).

First and foremost, the micro-layout engine needs to be activated in the inversify container. This is done by setting the needsClientLayout property to true in the inversify container configuration:

const module = new ContainerModule((bind, unbind, isBound, rebind) => {
+hidden-mobile" itemprop=breadcrumb>

Micro-layout

The micro-layout refers to the layout of elements inside of a node, i.e. the layout of nested labels, buttons, etc. It is not to be confused with the macro-layout which refers to the layout of the entire graph, e.g. the position of nodes.

Layout Configuration +

Any model element that implements or extends the SNode or SCompartment interface has an optional property layout that specifies the general layout of its children elements. Sprotty implements three layout configurations by default:

  • stack: children elements are stacked on top of each other (default layout)
  • hbox: children elements are arranged horizontally
  • vbox: children elements are arranged vertically

The layout property aims at arranging children elements that do not have a meaning in terms of graph hierarchy (i.e. labels, buttons, …). Please note that children that are instances of SNodeImpl do not respect the layout property by default (more on that later).

First and foremost, the micro-layout engine needs to be activated in the inversify container. This is done by setting the needsClientLayout property to true in the inversify container configuration:

const module = new ContainerModule((bind, unbind, isBound, rebind) => {
     const context = {bind, unbind, isBound, rebind};
     ...
     configureViewerOptions(context, {
@@ -107,7 +106,7 @@
         },
     ]
 };
-

This results in the following visuals:

layout-configuration

If you want different layout configurations, you can implement your own micro-layout engine and inject it via Dependency Injection.

Layout Options +

This results in the following visuals:

layout-configuration

If you want different layout configurations, you can implement your own micro-layout engine and inject it via Dependency Injection.

Layout Options

It is possible to fine-tune the micro-layout by using the property layoutOptions.

<SNode> {
     ...
     layout: 'vbox',
@@ -276,4 +275,7 @@
 };
 

Layouting Nested Nodes

By design, nested SNode do not obey the layout property of an SNode parent. This is because nested nodes are usually used to represent a graph hierarchy, and the layout of the children of a node is not relevant for the structure of the graph. In general, the position of those nodes should be the responsibility of the macro-layout engine.

However, if you still need the micro-layout engine to control the position of nested nodes, this can be achieved by enabling the layoutableChildFeature in the inversify container.

configureModelElement(context, 'your node type', SNodeImpl, YourNodeView, {enable: [layoutableChildFeature]})
-
\ No newline at end of file +
\ No newline at end of file diff --git a/pr-previews/pr-34/docs/model_sources/index.html b/pr-previews/pr-34/docs/model-sources/index.html similarity index 90% rename from pr-previews/pr-34/docs/model_sources/index.html rename to pr-previews/pr-34/docs/model-sources/index.html index f5a8bb1..9d83906 100644 --- a/pr-previews/pr-34/docs/model_sources/index.html +++ b/pr-previews/pr-34/docs/model-sources/index.html @@ -1,22 +1,21 @@ -Model Sources | Sprotty +Model Sources | Sprotty -
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Model Sources

When drawing a diagram with Sprotty we need a place to define and update the schema of the diagram to draw. Sprotty uses model sources to do this. Sprotty currently offers two different model sources: The LocalModelSource for local models and the DiagramServer for remote ones.
 flowchart TD;
@@ -29,12 +28,12 @@
 ModelSource --- LocalModelSource
 ModelSource --- DiagramServerProxy
 DiagramServerProxy <-.->|Action| DiagramServer
-
Regardless of where your model-source is located, Sprotty handles them in a similar fashion. All communication between ActionDispatcher and model source is always through actions and is bi-directional. +Regardless of where your model-source is located, Sprotty handles them in a similar fashion. All communication between ActionDispatcher and model source is always through actions and is bi-directional. This is a powerful feature of Sprotty as it allows both flexibility regarding where and how the Diagram is generated, as well as changing or updating and reacting to interactions with the diagram simultaneously.

The following sections will explain how to use and work with the different types of model sources.

General usage -

Regardless of the model source we are using, the first thing we have to do is to register our model source in the front-end DI-container like this:

bind(TYPES.ModelSource).to(ModelSourceClassOrProxy).inSingletonScope();
+

Regardless of the model source we are using, the first thing we have to do is to register our model source in the front-end DI-container like this:

bind(TYPES.ModelSource).to(ModelSourceClassOrProxy).inSingletonScope();
 

After that, we can retrieve the model source with the following code to further configure and use it.

const modelSource = container.get<LocalModelSource>(TYPES.ModelSource);
 

Local Model Source -

A LocalModelSource instance allows us to set and modify the model through function calls, and keeps the model schema saved locally. +

A LocalModelSource instance allows us to set and modify the model through function calls, and keeps the model schema saved locally. To see how to use this model source, let’s have a look at the following example:

import {SNode} from 'sprotty-protocol';
 export default runExample() {
     const container = createContainer('sprotty-showcase');
@@ -69,7 +68,7 @@
 The model in this context means instances of the classes containing logic Sprotty uses for rendering. The model schema is used by Sprotty to generate the model.
 Due to this, we should use the interfaces for our nodes, edges, etc. from sprotty-protocol and not the classes from the sprotty main package.
 For disambiguation, model classes are suffixed with Impl in Sprotty, while interfaces (contained in the package sprotty-protocol) are not. This means that SNode is an interface, while SNodeImpl is a class.

After defining the model schema we can then use methods like addElements() from our LocalModelSource to add new nodes at the click of a button. The LocalModelSource then handles updating the model and notifying the ActionDispatcher about the update, so that the view can receive an animated update.

Through methods like the ones outlined above, the LocalModelSource can also be used as a facade over the action-based API of Sprotty. It handles actions for bounds calculation and model updates.

Diagram Server -

When the model needs to be generated from a remote source, like in a worker or from a server, we can use Sprotty’s DiagramServer model source. It communicates with the client through Action objects which can be serialized to plain JSON.

On the client-side, instead of registering an actual ModelSource we can use a DiagramServerProxy. The Proxy handles the communication and forwards actions to the ActionDispatcher. Out of the box, Sprotty offers the WebSocketDiagramServerProxy for communicating through WebSockets with the DiagramServer. +

When the model needs to be generated from a remote source, like in a worker or from a server, we can use Sprotty’s DiagramServer model source. It communicates with the client through Action objects which can be serialized to plain JSON.

On the client-side, instead of registering an actual ModelSource we can use a DiagramServerProxy. The Proxy handles the communication and forwards actions to the ActionDispatcher. Out of the box, Sprotty offers the WebSocketDiagramServerProxy for communicating through WebSockets with the DiagramServer. Should a different form of communication be necessary we would have to create a custom proxy.

Using the WebSocketDiagramServerProxy is quite simple. We just need to call listen on the ModelSource and pass it the WebSocket we’re communicating with.

const modelSource = container.get<WebSocketDiagramServerProxy>(TYPES.ModelSource);
 modelSource.listen(websocket);
 

For creating the DiagramServer itself, let’s look at an example.

// Creating a new websocket server
@@ -101,7 +100,7 @@
     readonly ServerActionHandlerRegistry?: ServerActionHandlerRegistry
 }
 

There are 3 components to the DiagramServices. One is mandatory, the other two are optional:

  • The DiagramGenerator which the server uses to create the schema of the Diagram
  • Optionally the ModelLayoutEngine, like the ElkLayoutEngine from sprotty-elk, if we want to do server-side layouting
  • Optionally the ServerActionHandlerRegistry for overwriting the default handling of incoming actions

Creating a Custom Model Source Proxy -

In case communication between the DiagramServer and client does not work through WebSockets, for example when the DiagramServer is running in a worker or the sprotty client is in a vscode webview (see sprotty-vscode), we can easily implement our own proxy instead.

export class WebWorkerDiagramProxy extends DiagramServerProxy {
+

In case communication between the DiagramServer and client does not work through WebSockets, for example when the DiagramServer is running in a worker or the sprotty client is in a vscode webview (see sprotty-vscode), we can easily implement our own proxy instead.

export class WebWorkerDiagramProxy extends DiagramServerProxy {
     constructor(private worker: Worker) {
         super()
         const proxy = this;
@@ -117,4 +116,7 @@
 }
 

Following the example above, first we need to extend DiagramServerProxy. This already gives us most of our needed functionality and makes this proxy a ModelSource. Then we need to listen for incoming messages and pass them to the messageReceived() function, which deserializes and passes them to the ActionDispatcher. -Lastly, we need to implement the sendMessage() method to allow actions coming from the ActionDispatcher to be transferred to the DiagramServer.

Now our custom model source proxy is able to propagate all actions between the ActionDispatcher and our DiagramServer running in the worker, which gives us access to all of sprotty’s functionality.

\ No newline at end of file +Lastly, we need to implement the sendMessage() method to allow actions coming from the ActionDispatcher to be transferred to the DiagramServer.

Now our custom model source proxy is able to propagate all actions between the ActionDispatcher and our DiagramServer running in the worker, which gives us access to all of sprotty’s functionality.

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/overview/index.html b/pr-previews/pr-34/docs/overview/index.html index fdcc4b2..5aafd99 100644 --- a/pr-previews/pr-34/docs/overview/index.html +++ b/pr-previews/pr-34/docs/overview/index.html @@ -2,21 +2,20 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Overview

The base architecture of Sprotty revolves around an unidirectional cyclic flow of information between three major components: the ActionDispatcher, the CommandStack, and the Viewer. This leads to a clear and easily testable flow of data which prevents feedback loops.

 flowchart TD;
 ActionDispatcher
 CommandStack
@@ -74,4 +73,7 @@
 DOM -->|event| Viewer
 

View Registry

The Viewer uses the ViewRegistry to look up the View for a graph model element using its ID.

View -

A View knows how to turn a graph model element and its children into a virtual DOM node. It uses JSX technology and contains a render method producing one or a group of SVG elements.

\ No newline at end of file +

A View knows how to turn a graph model element and its children into a virtual DOM node. It uses JSX technology and contains a render method producing one or a group of SVG elements.

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/smodel/index.html b/pr-previews/pr-34/docs/smodel/index.html index 3afc276..7f49de9 100644 --- a/pr-previews/pr-34/docs/smodel/index.html +++ b/pr-previews/pr-34/docs/smodel/index.html @@ -5,21 +5,20 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

SModel

The SModel (short for SprottyModel) is the core data structure of Sprotty. It is a tree of model elements that can be rendered by a View. The root of the model is always an instance of SModelRootImpl or one of its derived class.

First, we need to distinguish between two models: the internal model and the external model.

The internal model is used only in the CommandStack and the Viewer. It is a tree of model elements representing the current state of what is visible in the diagram. After a change has been applied via a Command. the CommandStack sends an updated version of the internal model to the Viewer which in turns renders the updated model using the provided View implementations.

The external model is used to transfer information between the model source and the Sprotty frontend. The external model must be serializable as JSON so that it can be easily transferred via network messages. Changes to the external model are applied through Actions, which contain the external model or parts of it. When the model source resides in the backend, the content of the diagram are controlled by a DiagramServer, which holds a copy of the external model.

External Model +hidden-mobile" itemprop=breadcrumb>

SModel

The SModel (short for SprottyModel) is the core data structure of Sprotty. It is a tree of model elements that can be rendered by a View. The root of the model is always an instance of SModelRootImpl or one of its derived class.

First, we need to distinguish between two models: the internal model and the external model.

The internal model is used only in the CommandStack and the Viewer. It is a tree of model elements representing the current state of what is visible in the diagram. After a change has been applied via a Command. the CommandStack sends an updated version of the internal model to the Viewer which in turns renders the updated model using the provided View implementations.

The external model is used to transfer information between the model source and the Sprotty frontend. The external model must be serializable as JSON so that it can be easily transferred via network messages. Changes to the external model are applied through Actions, which contain the external model or parts of it. When the model source resides in the backend, the content of the diagram are controlled by a DiagramServer, which holds a copy of the external model.

External Model

The external model is tree of JSON-serializable objects. To facilitate its implementation, Sprotty provides a set of interfaces (in the sprotty-protocol package) that can be used to describe the external model. These interfaces have a class counterpart that is used in the internal model. The complete list of interfaces provided by Sprotty can be found here.

Internal Model Elements

The internal model is a tree of model elements implemented as classes. To avoid ambiguity with interfaces used in the external model, classes are named with the suffix Impl.

Classes Inheritance

@@ -56,23 +55,26 @@
 SCompartmentImpl --> SShapeElementImpl
 SGraphIndex --> ModelIndexImpl
 

SModelElementImpl -

This is the base class for all elements of the diagram model. This ensures that all elements in the model have a type and an id.

Properties:

  • type: string: The type of the element. This value is used in the Sprotty configuration to specify the corresponding view for all elements of this type.
  • id: string: The globally unique identifier of the element.
  • features: FeatureSet - optional: A set of features that are enabled on the element. The list of features can be further configured in the dependency injection container.
  • cssClasses: string[] - optional: A list of CSS classes that should be applied to the element.

SParentElementImpl +

This is the base class for all elements of the diagram model. This ensures that all elements in the model have a type and an id.

Properties:

  • type: string: The type of the element. This value is used in the Sprotty configuration to specify the corresponding view for all elements of this type.
  • id: string: The globally unique identifier of the element.
  • features: FeatureSet - optional: A set of features that are enabled on the element. The list of features can be further configured in the dependency injection container.
  • cssClasses: string[] - optional: A list of CSS classes that should be applied to the element.

SParentElementImpl

A parent element may contain children elements, thus the diagram model forms a tree.

Properties:

  • children: SChildElementImpl[]: The children of the element. Defaults to an empty array.

Inheritance:

SModelElementImpl

SChildElementImpl

A child element is contained in a parent element. All elements except for the model root are derived from SChildElementImpl. Every child element is also a parent element, thus it can contain children elements itself.

Properties:

  • parent: SParentElementImpl: The parent of the element.

Inheritance:

SParentElementImplSModelElementImpl

SModelRootImpl

This is the base class for the root element of the diagram model. It inherits from SParentElementImpl, therefore, actual model elements are contained in its children property.

Properties:

  • canvasBounds: Bounds: The bounds of the canvas. This is used to determine the size of the diagram. Defaults to Bounds.EMPTY (i.e. {x: 0, y: 0, width: -1, height: -1}).
  • revision: number- optional: The revision number of the model. This is incremented by Sprotty whenever the model is changed. This is used in the DiagramServer to ensure that the correct version of the model is used.

Inheritance:

SParentElementImplSModelElementImpl

ModelIndexImpl

An index of all model elements. It is used to optimize the lookup of elements by their id.

Graph Elements

The base architecture of Sprotty does not assume that the visualization is based on nodes and edges. However, since it is a very common use-case, Sprotty provides a set of classes that can be used to build a graph-based diagram.

SGraphImpl

Root element of the diagram model.

Properties:

  • layoutOptions: ModelLayoutOptions - optional: Options for the layout of the diagram.

Inheritance:

ViewportRootModelSModelRootImplSParentElementSModelElementImpl

SNodeImpl -

Model element for Nodes, which are the main entity in a graph. A node can be connected to another node via an edge. Such connection can be direct (i.e. the source or target of the edge is the node itself) or indirect (i.e. the source or target of the edge is a child port of the node).

Properties:

  • children: SChildElementImpl[]
  • layout: string - optional
  • selected: boolean: Indicates if the node is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the node should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the node. Defaults to 1.

Inheritance:

SConnectableElementImplSShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SPortImpl -

A port is a connection point for edges. It should always be contained in an SNodeImpl.

Properties:

  • selected: boolean: Indicates if the port is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the port should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the port. Defaults to 1.

Inheritance:

SConnectableElementImplSShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SEdgeImpl -

These are the connectors for the diagram model. An edge has a source and a target. Each of which can either be a node or a port. The source and target elements are referenced by their id (inherited from SRoutableElementImpl) and can be resolved via the index stored in the root element.

Properties;

  • selected: boolean: Indicates if the edge is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the edge should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the edge. Defaults to 1.

Inheritance:

SRoutableElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SLabelImpl +

Model element for Nodes, which are the main entity in a graph. A node can be connected to another node via an edge. Such connection can be direct (i.e. the source or target of the edge is the node itself) or indirect (i.e. the source or target of the edge is a child port of the node).

Properties:

  • children: SChildElementImpl[]
  • layout: string - optional
  • selected: boolean: Indicates if the node is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the node should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the node. Defaults to 1.

Inheritance:

SConnectableElementImplSShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SPortImpl +

A port is a connection point for edges. It should always be contained in an SNodeImpl.

Properties:

  • selected: boolean: Indicates if the port is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the port should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the port. Defaults to 1.

Inheritance:

SConnectableElementImplSShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SEdgeImpl +

These are the connectors for the diagram model. An edge has a source and a target. Each of which can either be a node or a port. The source and target elements are referenced by their id (inherited from SRoutableElementImpl) and can be resolved via the index stored in the root element.

Properties;

  • selected: boolean: Indicates if the edge is selected. Defaults to false.
  • hoverFeedback: boolean: Indicates if the edge should show hover feedback. Defaults to false.
  • opacity: number: The opacity of the edge. Defaults to 1.

Inheritance:

SRoutableElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SLabelImpl

A label represents some text to be displayed and attached to a node, compartment, port, or edge.

Properties:

  • text: string: The text of the label.
  • selected: boolean: Indicates if the label is selected. Defaults to false.
  • alignment: Point: The alignment of the label. Defaults to Point.ORIGIN.
  • opacity: number: The opacity of the label. Defaults to 1.
  • edgePlacement: EdgePlacement - optional: The placement of the label on an edge. Defaults to EdgePlacement.NONE.
    • rotate: boolean - true, if the label should be rotated to touch the edge tangentially
    • side: EdgeSide - where is the label relative to the line’s direction. Possible values are ‘bottom’, ’top’, ’left’, ‘right’, and ‘on’.
    • position: number - between 0 (source anchor) and 1 (target anchor)
    • offset: number - space between label and edge/connected nodes
    • moveMode: 'edge' | 'free' | 'none' - optional constrains where the label can be moved when move feature is enabled for the respective Label. edge means the label can be moved along the edge, free means the label can be moved freely, none means the label cannot moved. -Defaults to edge.

Inheritance:

SShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SCompartmentImpl -

A compartment is used to group multiple child elements of a node or compartment, such as labels. Usually, a vbox or hbox layout is used to arrange these children.

Properties:

  • layout: string - optional: The layout of the compartment.
  • opacity: number: The opacity of the compartment. Defaults to 1.

Inheritance:

SShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SGraphIndex +Defaults to edge.

Inheritance:

SShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SCompartmentImpl +

A compartment is used to group multiple child elements of a node or compartment, such as labels. Usually, a vbox or hbox layout is used to arrange these children.

Properties:

  • layout: string - optional: The layout of the compartment.
  • opacity: number: The opacity of the compartment. Defaults to 1.

Inheritance:

SShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

Default features:

SGraphIndex

A specialized model index that tracks outgoing and incoming edges.

Inheritance:

ModelIndexImpl

ViewportRootElement

Model root element that defines a viewport, so it transforms the coordinate system of its children with a scroll and zoom factor.

Properties:

  • scroll: Point: The scroll offset of the viewport. Defaults to {x: 0, y: 0}.
  • zoom: number: The zoom factor of the viewport. Defaults to 1.
  • position: Point: The position of the viewport. Defaults to {x: 0, y: 0}.
  • size: Dimension: The size of the viewport. Defaults to {width: -1, height: -1}.

Inheritance: SModelRootImplSParentElementImplSModelElementImpl

SConnectableElementImpl

A connectable element is one that can have outgoing and incoming edges. It can be the source or target element of an edge. There are two kinds of connectable elements: SNodes and SPorts.

Properties:

  • strokeWidth: number: The stroke width of the element. Defaults to 0.

Inheritance:

SShapeElementImplSChildElementImplSParentElementImplSModelElementImpl

SShapeElementImpl

Abstract class for elements with a position and size.

Properties:

  • position: Point: The position of the element. Defaults to {x: 0, y: 0}.
  • size: Dimension: The size of the element. Defaults to {width: -1, height: -1}.
  • layoutOptions: ModelLayoutOptions - optional: Options for the layout of the element.

Inheritance:

SChildElementImplSParentElementImplSModelElementImpl

SRoutableElementImpl -

Abstract class for edges.

Properties:

  • routerKind: string - optional: The kind of router to use for the edge. Sprotty provides an implementation of ‘polyline’, ‘manhattan’, and ‘bezier’ routers.
  • routingPoints: Point[] - optional: The routing points of the edge. Defaults to an empty array.
  • sourceId: string: The id of the source element.
  • targetId: string: The id of the target element.
  • sourceAnchorCorrection: number - optional: The correction of the source anchor. This can be used to apply an offset to the anchor position of the source element. Defaults to 0.
  • targetAnchorCorrection: number - optional: The correction of the target anchor. This can be used to apply an offset to the anchor position of the target element. Defaults to 0.

To offset the anchor point of an edge

Inheritance:

SChildElementImplSParentElementImplSModelElementImpl

\ No newline at end of file +

Abstract class for edges.

Properties:

  • routerKind: string - optional: The kind of router to use for the edge. Sprotty provides an implementation of ‘polyline’, ‘manhattan’, and ‘bezier’ routers.
  • routingPoints: Point[] - optional: The routing points of the edge. Defaults to an empty array.
  • sourceId: string: The id of the source element.
  • targetId: string: The id of the target element.
  • sourceAnchorCorrection: number - optional: The correction of the source anchor. This can be used to apply an offset to the anchor position of the source element. Defaults to 0.
  • targetAnchorCorrection: number - optional: The correction of the target anchor. This can be used to apply an offset to the anchor position of the target element. Defaults to 0.

To offset the anchor point of an edge

Inheritance:

SChildElementImplSParentElementImplSModelElementImpl

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/styling/index.html b/pr-previews/pr-34/docs/styling/index.html index fa9301b..ff13bc4 100644 --- a/pr-previews/pr-34/docs/styling/index.html +++ b/pr-previews/pr-34/docs/styling/index.html @@ -5,21 +5,20 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Styling

Sprotty is designed to be highly customizable. Styling of diagram elements is done using CSS, preferably using CSS classes. There are several ways to apply styles to an element depending on the level of granularity you need.

Predefined Styling +hidden-mobile" itemprop=breadcrumb>

Styling

Sprotty is designed to be highly customizable. Styling of diagram elements is done using CSS, preferably using CSS classes. There are several ways to apply styles to an element depending on the level of granularity you need.

Predefined Styling

Available Views

Sprotty comes with a handful of views that can be used to represent nodes, edges, and labels of your diagram. These views correspond to the most common SVG elements such as rect, circle, text, and path.

The following views can be used for visualizing nodes and ports:

  • CircularNodeView: A circular representation of a node. Produces a circle SVG element.
  • RectangularNodeView: A rectangular representation of a node. Produces a rect SVG element.
  • DiamondNodeView: A diamond-shaped representation of a node. Produces a polygon SVG element.

For representing edges, the following views are available:

  • PolylineEdgeView: A succession of straight lines between two nodes. Produces a path SVG element.
  • JumpingPolylineEdgeView: A succession of straight lines between two nodes with an arc where two or more edges intersect. Produces a path SVG element.
  • PolylineEdgeViewWithGapsOnIntersections: A succession of straight lines between two nodes with a gap where two or more edges intersect. Produces a path SVG element.
  • BezierCurveEdgeView: An succession of Bezier curves. Produces a path SVG element.

For representing labels, the following view is available:

  • SLabelView: A simple text label. Produces a text SVG element.

Default CSS Classes

Those default views assume that your are using the default implementations of diagram elements, namely SGraphImpl, SNodeImpl, SPortImpl, SEdgeImpl, and SLabelImpl.

The default views listed above use the following CSS classes to style the SVG elements:

  • sprotty-graph: class for the root SVG element of the diagram.
  • sprotty-node: class for the SVG element representing a node.
  • sprotty-port: class for the SVG element representing a port.
  • sprotty-edge: class for the SVG element representing an edge.
  • sprotty-label: class for the SVG element representing a label.

By using those CSS classes, you can easily style all nodes, ports, edges, and labels of your diagram in a uniform way.

Using Subtypes for Styling @@ -66,4 +65,4 @@ </g>; } } -

Note the class-selected={node.selected}. This will apply the CSS class selected to the SVG element when the selected property of the node is true.

Similarly, you can see that the class-mouseover={node.hoverFeedback} applies the CSS class mouseover to the SVG element when the hoverFeedback property of the node is true. For this the hoverFeedbackFeature must be enabled on the node.

\ No newline at end of file +

Note the class-selected={node.selected}. This will apply the CSS class selected to the SVG element when the selected property of the node is true.

Similarly, you can see that the class-mouseover={node.hoverFeedback} applies the CSS class mouseover to the SVG element when the hoverFeedback property of the node is true. For this the hoverFeedbackFeature must be enabled on the node.

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/svg-rendering/index.html b/pr-previews/pr-34/docs/svg-rendering/index.html index 56e7884..05feef9 100644 --- a/pr-previews/pr-34/docs/svg-rendering/index.html +++ b/pr-previews/pr-34/docs/svg-rendering/index.html @@ -2,21 +2,20 @@
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

SVG Rendering

Sprotty transforms a given SModel to its representation in the DOM in the form of a hierarchy of SVG elements. An SModel is composed of SModelElements, and each SModelElement has a type property that is associated to a single corresponding View. The ViewRegistry keeps a map of the correspondence between an element type and a view. These model elements are organized in the virtual DOM before being rendered as actual SVG elements in the DOM.

Virtual DOM +hidden-mobile" itemprop=breadcrumb>

SVG Rendering

Sprotty transforms a given SModel to its representation in the DOM in the form of a hierarchy of SVG elements. An SModel is composed of SModelElements, and each SModelElement has a type property that is associated to a single corresponding View. The ViewRegistry keeps a map of the correspondence between an element type and a view. These model elements are organized in the virtual DOM before being rendered as actual SVG elements in the DOM.

Virtual DOM

The virtual DOM is a tree-based, partial or complete representation of the DOM content. In our context, the virtual DOM contains a representation of our diagram SVG elements and their hierarchy. For every update made to the diagram, Sprotty generates a new SModel through the CommandStack and forwards it to the Viewer. Updates are often limited to a specific node or group of nodes and it would be unnecessarily expensive to have to re-render the entire diagram for each update. It is more efficient to apply minimal updates to directly impacted DOM elements. Sprotty relies on Snabbdom for handling elements in the virtual DOM and applying minimal changes the DOM through patching.

Views

Views are at the center of Sprotty’s rendering mechanism. They are classes implementing the IView interface and have a render() method that describes the SVG elements to be rendered for a given SModelElement type. Views use the TSX syntax, which allow combining HTML and TypeScript code to define elements, and therefore needs to reside inside of files with the .tsx extension.

Let’s have a look at the definition of the NodeView from the Class Diagram example:

@injectable()
 export class NodeView extends RectangularNodeView {
@@ -34,9 +33,12 @@
         </g>;
     }
 }
-

The class NodeView extends RectangularNodeView which is a default View in Sprotty, ultimately implementing IView. Don’t forget to add the class decorator @injectable(), which is necessary for the Dependency Injection mechanism.

The render() method is the core of the View. It takes node – that is the model element to be rendered - as an argument, a RenderingContext, and an optional args object. View implementations should first check whether the node should be rendered at all. This is an optimization step, as we only want to render SVG elements that are inside of the visible viewport and not hidden by some other user-defined filter. +

The class NodeView extends RectangularNodeView which is a default View in Sprotty, ultimately implementing IView. Don’t forget to add the class decorator @injectable(), which is necessary for the Dependency Injection mechanism.

The render() method is the core of the View. It takes node – that is the model element to be rendered - as an argument, a RenderingContext, and an optional args object. View implementations should first check whether the node should be rendered at all. This is an optimization step, as we only want to render SVG elements that are inside of the visible viewport and not hidden by some other user-defined filter. Eventually, the render() method returns a VNode which is Snabbdom’s virtual representation of a DOM element. This VNode can hold one and only one root element, therefore we need to group our SVG elements inside of a container element g. The SVG elements can be styled using CSS classes using Snabbdom’s notation. Classes are dynamically toggled with expressions of the form class-X={boolean expression}, with the class- prefix followed by the name of the class and a boolean expression to determine if the class should be toggled or not. In our example, the rect element created by the NodeView could have a class of sprotty-node, node-package, node-class, mouseover, selected, or any combination of those depending of the respective boolean expressions. It is then easy to style elements with CSS based on class names.

Other attributes like width, height, and position are also defined here. Please note that the position is set at x="0" y="0" since the actual position will be determined by the layout engine later on.

Finally, we render children of the node with the renderChildren() method from the RenderingContext. We strongly advocate for keeping the View’s responsibility to render only the SVG that is specific for the given node. Any child (e.g. labels, buttons, children nodes) should be rendered in their own View. This keeps the code better organized and removes the complexity of having to implement the layout of nested elements such as labels in the View itself and instead delegates this responsibility to the layout engine.

Layouting

It is important to distinguish two types of layout:

  1. The client layout (or micro-layout) which deals with the layout of a node’s children.
  2. The server layout (or macro-layout) which deals with the overall shape of the diagram, placement of nodes and edges.

Client Layout -

The client layout, a.k.a. micro-layout, occurs first. In this phase, Sprotty computes the position and size for elements that add some visual information such as labels to nodes and edges. Different layouts are selected using the layout property of a SNode or SCompartment. The values of the layout property can be:

  • hbox for an horizontal layout.
  • vbox for a vertical layout.
  • stack for a stacking of children elements.

The micro-layout is computed in two phases:

  1. A RequestBoundAction is received and the model is rendered invisibly (e.g. by assigning a width and height of zero to the elements). The locally used fonts and CSS styles are applied during this rendering phase. The resulting size information is used to invoke the selected layouts and the updated bounds are written into a ComputedBoundAction.
  2. The bounds stored in the ComputedBoundAction are applied to the model and initiates the visible rendering of the updated model with SetModelAction or UpdateModelAction.

In depth documentation about the micro-layouting can be found here

Server Layout -

The server layout, a.k.a. macro-layout takes place after the client layout. This is configured with an implementation of the ILayoutEngine interface. This takes care of the general shape of the diagram and computes the position of nodes and edges. Sprotty provides a package to use the Eclipse Layout Kernel(ELK), a JAVA-based automatic layout engine with several standard algorithms, but it is also of course possible to implement your own.

\ No newline at end of file +

The client layout, a.k.a. micro-layout, occurs first. In this phase, Sprotty computes the position and size for elements that add some visual information such as labels to nodes and edges. Different layouts are selected using the layout property of a SNode or SCompartment. The values of the layout property can be:

  • hbox for an horizontal layout.
  • vbox for a vertical layout.
  • stack for a stacking of children elements.

The micro-layout is computed in two phases:

  1. A RequestBoundAction is received and the model is rendered invisibly (e.g. by assigning a width and height of zero to the elements). The locally used fonts and CSS styles are applied during this rendering phase. The resulting size information is used to invoke the selected layouts and the updated bounds are written into a ComputedBoundAction.
  2. The bounds stored in the ComputedBoundAction are applied to the model and initiates the visible rendering of the updated model with SetModelAction or UpdateModelAction.

In depth documentation about the micro-layouting can be found here

Server Layout +

The server layout, a.k.a. macro-layout takes place after the client layout. This is configured with an implementation of the ILayoutEngine interface. This takes care of the general shape of the diagram and computes the position of nodes and edges. Sprotty provides a package to use the Eclipse Layout Kernel(ELK), a JAVA-based automatic layout engine with several standard algorithms, but it is also of course possible to implement your own.

\ No newline at end of file diff --git a/pr-previews/pr-34/docs/user_interaction/index.html b/pr-previews/pr-34/docs/user-interaction/index.html similarity index 58% rename from pr-previews/pr-34/docs/user_interaction/index.html rename to pr-previews/pr-34/docs/user-interaction/index.html index 6c015f9..838a5f5 100644 --- a/pr-previews/pr-34/docs/user_interaction/index.html +++ b/pr-previews/pr-34/docs/user-interaction/index.html @@ -1,72 +1,25 @@ -User Interaction | Sprotty +User Interaction | Sprotty -
+
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

User Interaction

Interacting with a Sprotty Diagram -

Sprotty offers multiple mouse and keyboard interactions by default listed in the following tables. -The CTRL key in the following is equal to the CMD key on Mac.

Mouse
left-click:toggle selection
CTRL-click:add to/remove from selection
left-click : dragmove selection (when on selected element)
left-click : dragpan viewport (when on diagram background)
mouse wheel:zoom
Touchpad
clicktoggle selection
dragmove selection (when on selected element)
two-finger pan up/downzoom
zoomzoom
Keys
CTRL-SHIFT-Aselect all
CTRL-SHIFT-Ccenter selection, or if nothing is selected center the entire diagram
CTRL-SHIFT-Eexport diagram to SVG
CTRL-SHIFT-Fzoom selection to fill the entire canvas, or if nothing is selected zoom the entire diagram
CTRL-Zundo
CTRL-SHIFT-Zredo

Creating Custom Interaction -

Buttons and Button Handlers -

Buttons in Sprotty work similarly to the other model elements, but they enable you to directly hook up handlers that react to the push of a button. -As in the other examples with other types of nodes, we first need to define the model and view class and define its type ID. in addition, we also need to define a button handler of type IButtonHandler.

const container = new ContainerModule((bind, unbind, isBound, rebind) => { 
-        const context = { bind, unbind, isBound, rebind };
-        configureModelElement(context, 'graph', SGraph, SGraphView);
-        configureModelElement(context, 'button:custom', SButton, CustomButtonView);
-
-        configureButtonHandler({bind, isBound}, 'button:custom', CustomButtonHandler);
-
-        configureViewerOptions(context, {
-            needsClientLayout: true,
-            baseDiv: 'sprotty'
-        });
-
-    });
-

A button handler is a simple injectable class with a buttonPressed(button: SButton): Action[] method. -The actions that this method returns are passed to the ActionDispatcher to be handled there.

@injectable()
-export class CustomButtonHandler implements IButtonHandler {
-    buttonPressed(button: SButton): Action[] {
-        alert('button on' + button.parent.id + ' pressed');
-        return [];
-    }
-}
-

Mouse and Keyboard Listeners -

Sprotty also offers the ability to attach mouse and keyboard listeners by registering MouseListener or KeyListener. -This can be simply done by binding the custom listener to the respective listener type in your DI-container like this:

    bind(CustomMouseListener).toSelf().inSingletonScope();
-    bind(TYPES.MouseListener).toService(CustomMouseListener);
-

These listeners are global, meaning they react to every interaction with the diagram. A very simple mouse Listener would look like this:

export class CustomMouseListener extends MouseListener {
-    doubleClick(target: SModelElementImpl, event: MouseEvent): (Action | Promise<Action>)[] {
-        alert('double clicked ' + target.id)
-        return [];
-    }
-}
-

If only specific types of nodes are supposed to be interacted with through this custom listener, it’s recommended to create a custom feature.

Projection Bars -

Another interactive Sprotty feature is the ProjectedViewportView. -This view automatically adds a vertical and horizontal scrollbar to our diagram view in which our current viewport is shown, like in the following image.

projection bar example

To activate this feature, instead of using SGraphImpl and SGraphView for our root element, as we did in the other examples, we use ViewportRootElement and ProjectedViewportView. -The scrollbars created through ProjectedViewportView can be styled via the .sprotty-viewport and .sprotty-projection-bar CSS classes.

As we can see in the image, these scrollbars can contain projections of our nodes, which show their horizontal and vertical position. -Double-clicking on a projection will center the view on the node the projection belongs to.

To add projections we add the Projectable type to the nodes in our model schema like this:

 <SNode & Projectable>{
-            id: 'svg',
-            type: 'node:svg',
-            text: '',
-            projectionCssClasses: ['svg-projection']
-}
-

The Projectable interface requires us to specify the projectionCssClasses property, which defines the CSS classes the framework will apply to the HTML div element that represents the projection in the projection bar. If no projectionCssClasses property value is specified, no projection will be created. -As projections are simple HTML div elements positioned on the projection bar, they can easily be styled as follows:

.svg-projection { 
-    background-color: rgba(255, 153, 0, 0.5); 
-}
-
\ No newline at end of file +hidden-mobile" itemprop=breadcrumb>

User Interaction

Interacting with a Sprotty Diagram +

Sprotty offers multiple mouse and keyboard interactions by default listed in the following tables. +The CTRL key in the following is equal to the CMD key on Mac.

Mouse
left-click:toggle selection
CTRL-click:add to/remove from selection
left-click : dragmove selection (when on selected element)
left-click : dragpan viewport (when on diagram background)
mouse wheel:zoom
Touchpad
clicktoggle selection
dragmove selection (when on selected element)
two-finger pan up/downzoom
zoomzoom
Keys
CTRL-SHIFT-Aselect all
CTRL-SHIFT-Ccenter selection, or if nothing is selected center the entire diagram
CTRL-SHIFT-Eexport diagram to SVG
CTRL-SHIFT-Fzoom selection to fill the entire canvas, or if nothing is selected zoom the entire diagram
CTRL-Zundo
CTRL-SHIFT-Zredo
\ No newline at end of file diff --git a/pr-previews/pr-34/index.html b/pr-previews/pr-34/index.html index 00de064..fa1e7c2 100644 --- a/pr-previews/pr-34/index.html +++ b/pr-previews/pr-34/index.html @@ -1,8 +1,8 @@ Sprotty
\ No newline at end of file