-
Notifications
You must be signed in to change notification settings - Fork 23
Architectural Overview
The base architecture is inspired by Flux and other reactive web frameworks. The key feature is a unidirectional cyclic event flow. As opposed to the classical model-view-controller pattern, the event flow is always clear, will not form feedback loops and should be a lot easier to test.
The diagram is stored in a model. All elements inherit from SModelElement
. An SModelElement
has a unique string ID, a type to look up its View
. The graph model is a tree, induced by the properties parent
and children
. The root of is always an instance of SModelRoot
, which holds an index of the model to allow fast lookup of elements by ID.
As sprotty also suitable for a client/server scenario, the graph model has to be serializable. The serialized JSON type of an SModelElement
is called its schema. In the schema, cross references are represented as IDs of the referred element. For example, an SEdgeSchema
refers to its source
using the id
of its source SNode
. To deserialize schema the corresponding model is the task of an SModelFactory
.
SModelExtensions
are interfaces that describe additional data of an SModelElement
that is needed for some Feature
, e.g.
-
Selectable
: An element can be selected -
Moveable
: An element can be moved. -
BoundsAware
: An element with a width and height that can be updated -
Scrollable
: An element that has stores an additonalPoint
that describes its scrolling state. -
Zoomable
: An element that can be zoomed in and out. Zoom state is described by a number. -
Viewport
: AnSModelRoot
that is both,Zoomable
andScrollable
.
Actions
describe a certain operation on the graph model. As plain JSON objects they can be serialized. They are the protocol messages that are exchanged between client and server. In actions, model elements are referred to by ID.
The ActionDispatcher
receives actions either from the Viewer
or from the server. It converts them to commands using the CommandRegistry
and passes them to the CommandStack
.
An IActionHandler
takes an action and converts it to a command, as such adding the behavior. It can also have side effects such as sending requests or notifications to the server.
Commands
correspond to Actions
and describe the actual behavior of the operation. They have the typical methods execute()
, undo()
and redo()
, each of which take the current model and a command execution context as parameter, and return the new model or a promise for it. The latter serves to chain asynchronous commands, e.g. animations.
Animated commands use an Animation
to report updates to the Viewer
on every rendering pass, during duration
milliseconds from the start of the execution, before they resolve their promise. An example is the MoveCommand
that smoothly interpolates the positions between start and end position.
The CommandStack
executes the commands it receives from the ActionDispatcher
. It chains the promises returned by the execution methods and keeps an undo and a redo stack. It is merges the current commands with the last one, e.g. to only keep the start and end point of a move by drag operation. Once the new graph model is available, it is forwarded to the Viewer
.
The Viewer
creates a virtual DOM from the new graph model. Builds the virtual DOM from the Views
and uses it to patch the current DOM. The viewer is also responsible to add event listeners and animations using its Decorators
.
A View
knows how to turn a graph model element and its children into a virtual DOM node.
The Viewer
uses the ViewRegistry
to look up the View
for a graph model element using its ID.
VNodeDecorators
are applied by the Viewer
to the View
elements, e.g. in order to register event listeners and animations.
Sprotty collects events from the DOM centrally in the MouseTool
or KeyTool
. These dispatch them to their registered Listeners
, which usually belong to some Feature
. Listeners
are registered using dependency injection.
A Feature
usually stands for some sort of interaction of the user with the diagram. It typically consists of
- A singleton
Symbol
as an identifier. The methodSModelElement#hasFeature(feature: Symbol)
should return true if the model element supports this feature. - An
SModelExtension
to store additional information in the model to support the feature, i.e. the (x,y)-position of a moveable element. -
Actions
to trigger the interaction -
Commands
to execute the interaction -
Listeners
that listen to the events that trigger the interaction on the DOM elements. - A
Module
to register all the above to the client infrastructure.