Skip to content

Commit

Permalink
Split custom interactions documentation
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Fontorbe <guillaume.fontorbe@typefox.io>
  • Loading branch information
gfontorbe committed Feb 13, 2024
1 parent 4126b4e commit 4946763
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 92 deletions.
95 changes: 95 additions & 0 deletions hugo/content/docs/custom-interactions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: 'Creating Custom Interaction'
---

{{< toc >}}

## 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`.

```Typescript
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`](../overview#action-dispatcher) to be handled there.

```Typescript
@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](../dependency_injection) like this:

```Typescript
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:

```Typescript
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](no-link-yet).

## 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](/projection_bar_example.png)

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:

```Typescript
<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:

```css
.svg-projection {
background-color: rgba(255, 153, 0, 0.5);
}
```
92 changes: 0 additions & 92 deletions hugo/content/docs/user-interaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,95 +31,3 @@ The `CTRL` key in the following is equal to the `CMD` key on Mac.
|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.
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`.

```Typescript
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`](../overview#action-dispatcher) to be handled there.

```Typescript
@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](../dependency_injection) like this:

```Typescript
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:

```Typescript
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](no-link-yet).

### 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](/projection_bar_example.png)

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:

```Typescript
<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:

```css
.svg-projection {
background-color: rgba(255, 153, 0, 0.5);
}
```
2 changes: 2 additions & 0 deletions hugo/data/menu/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ main:
ref: "docs/model-sources"
- name: Communication and Protocols
ref: "docs/actions-and-protocols"
- name: Creating Custom Interactions
ref: "docs/custom-interactions"
- name: Reference
sub:
- name: SModel
Expand Down

0 comments on commit 4946763

Please sign in to comment.