Under the Hood - PatrikValkovic/pathvis GitHub Wiki
This page describes main architectural decisions, that we made. Please consider this as documentation page for concepts of the app.
Graph
App works on general graph, where nodes are represent as instances of Node
class and edges are represent as instances of Edge
class. Edges have self from
and self to
attributes, which mean the direction of the edge. Nodes have methods to manipulate with edges (self edges
, self addEdge
, self removeEdge
), that manipulate with inner list of edges. Node stores only edges, that starts in that node (not ending there). Based on the previous paragraph, library use oriented multigraph representation. Whole graph is stored inside GraphContainer
class.
There is options, to extend Node
and Edge
classes dynamically. Every object that manipulate with the graph (that includes algorithms, spaces, renderers and generators) can define ownEdge:
or :ownNode
methods on the class. That method accept base Node class and must return the extended class. This is usually done by defining new class and then by calling ^ CreatedClass clone superclass: aBaseClass
, but the way is on you. Just note, that this method can be called repeatedly and aBaseClass don't need to be Node class itself, so method should use only parameter and should not modify global classes.
Algorithms
Algorithms must inherit from Algorithm class. Class must redefine run
method that is invoked when user press the start button. During the run, algorithm must use self notify
method (which return instance of Notificator
) to notify renderer about changes. Each call of notify represent one step in the simulation. Sent information should contains at least textual description of what happen.
Spaces
Spaces are the most general concept. They are responsible for synchronizations between algorithms and renderers and cover up renderers, renderes and generators. All spaces must inherit from Space
class.
Spaces should rewrite following methods on the class:
- readyTouse (default false): Should return true, if is space prepared for use. For example abstract spaces, thats are abstract or base for another spaces, should return false. App then uses all spaces, that reeturns true from this method.
- spaceName: It must return name of the space in readable string format. This field is used as label in situation, where is space used.
- description: Optional field, that should describe the space. Default value is empty string.
Spaces should rewrite following method on the instance:
- generators: Method must returns collection of generator classes, that are suited for the space. The straightforward approach is to inherit from
GraphGenerator
class custom class, from which will inherit all generators suited for the space. Then you can simple call^ GeneratorForThisSpace subclasses
. - notificatorClass: Method must return notificator class, that will be used in the algorithm.
- rendererClass: Method must return renderer class, that will be used as renderer.
Renderers
Renderes are responsible for visually rendering of the space and the graph inside it. Renderers should inherit from Renderer
class, but it is not required. Renderer is fully managed by the space itself (or the space notificator), so for algorithm is renderer fully transparent.
If you want to change design of the space, simple inherit from space renderer, rewrite all desired methods and use it in the own space (which should also inherit from original space).
Generators
Purpose of generators are generating of graph. Not all generators are suited for all spaces, so space have generators
methods, that returns collection of generators, with which can space work. Generators have generate
method, that must returns instance of GraphContainer
class with created graph.
Because spaces, algorithms, generators and renderers can customize Node
and Edge
classes, generators cannot create instances directly, but they must call self nodeClass
and self edgeClass
methods, that will return customized classes. For example self nodeClass new position: 1@1
.
Notificators
Notificators are classes, that inherits from Notificator
class and are chained with specific Space. Their reponsibility is to inform space about changes, that were made in the algorithm, so the space can be rerendered. Base interface for notificators are defined in Notificator
class in protocol messages
. Inherited notificators can define own methods, but the Notificator
interfaces is the only one exposed to algorithms.
Notificator class are chained with the space with notificatorClass
method, that must returns class of the custom notificator.
Engine
Engine
is the base class, that tailors algorithms, renderers and spaces together. The engine contain basic workflow, that can be customized by different generators, spaces or algorithms. For this purposes, Engine provide following methods:
- generator:aGenerator - set custom generator
- algorithm:aAlgorithm - set custom algorithm
- space:aSpace - set custom space
After setting of the property, Engine will care of disposing old objects and recreate new configuration with the new properties.