This interface defines a view of a Graph
model to which instances must always be attached. A GraphView
is associated n:1 with this model object.
Objects of type Graph, Node and Edge
represent the model entities in the graph domain. These entities may be
associated on a one-to-many basis with objects whose types are used for the
visualization inside a view. Simply put, each model class has a visual
counterpart whose instances may reference exactly one model object.
The following class diagram shows the visual component structure and dependencies in the Tensegrity Graph Framework.

The VisualGraph distinguishes among three kinds of
VisualGraphObject classes:
A VisualNode defines nodes in the VisualGraph and
corresponds to the Node in the
model scope.
A VisualEdge defines connected edges in the VisualGraph
and corresponds to the Edge in the
model scope.
An Isolated VisualEdge defines unconnected edges and does not
correspond to an Edge in the model
scope, since the model can only represent connected edges.
When you add a VisualGraphObject to a view, its
identifier is automatically assigned. Before adding, it, however, this identifier
should be set to -1. Upon removal, this identifier will be reset to -1.
Each VisualGraphObject may only be added
to at most one VisualGraph or
VisualSubgraph at a time. Attempting
to add the same object to more than one VisualGraph or
VisualSubgraph will cause an
exception to be thrown.
Besides adding and removing VisualNode and VisualEdge
instances to and from a VisualGraph, you should be aware
of a few notable methods defined in the VisualGraph interface:
deepCopy can be invoked on a VisualGraph to create
a deep, independent copy of it.
setRuleRegistry(RuleRegistry) allows you to apply a
RuleRegistry to a VisualGraph, thereby constraining
the way a user interacts with and programmatically invokes objects.
This helps you to customize applications with certain requirements that
determine how a VisualGraph can be manipulated at runtime.
portsReassignment allows processing of all ports in the
VisualGraph. All ports are visited with the supplied visitor
method and can be readjusted.
A visual graph type is closely coupled with the following graph model types:
| Model object | Associated view object |
|---|---|
Graph
| VisualGraph
|
GraphObject
| VisualGraphObject
|
Node
| VisualNode
|
Subgraph
| VisualSubgraph
|
Edge
| VisualEdge
|
Port
| VisualPort
|
PortDenotation
| VisualPortDenotation
|
Every time a view object is added to a VisualGraph,
an associated model object must be already present in the
Graph model. Every time a
VisualGraph object is removed, a model object must
also be present as well. These conditions can be summarized as follows:
First add model objects, then add the associated view objects.
First remove view objects, then remove the associated model objects.
VisualGraph objects can be nested inside another VisualGraph
to any depth whatsoever. This is possible because the interface specification
for VisualSubgraph derives from the interface
VisualNode.
It is possible to traverse a hierarchy of VisualSubgraph
objects by invoking the method visitSubgraphs(VisualGraphVisitor)
and providing a custom callback object that implements interface
VisualGraphVisitor.
VisualSubgraph objects can be nested inside
each other recursively. The nesting hierarchy, however, may not contain cycles.
Several methods in this interface specification are inherited from
the base interface VisualGraphObjectContainer,
which specifies generic handling of VisualGraph
and VisualSubgraph objects.
It is recommended that you configure and customize the behavior of
a VisualGraph by using the rules facility only. The rules
package offers the most flexible way of configuring
VisualGraphs.
Therefore a VisualGraph supports the registration of a
RuleRegistry.
In the context of VisualGraphs client code should register
an instance of a RuleRegistry ONLY at the top-level
VisualGraphView. This RuleRegistry will be
subsequently registered to all the added VisualGraphObjects and
nested VisualSubgraphs automatically by the GraphAPI. This means
that there can be only one active RuleRegistry within the entire
hierarchy of VisualGraphs.
For further information about the usage please see the documentation of
RuleRegistry.
The methods a VisualGraph provides in order to support the
RuleRegistry are listed below:
RuleRegistry getRuleRegistry()
Gets the RuleRegistry
that is the currently active set of rules for this
VisualGraph. Initially the
RuleRegistry of a VisualGraph is
null.
void setRuleRegistry(RuleRegistry)
Sets a RuleRegistry
as the currently active set of rules for this
VisualGraph.
The default rules are assigned to all objects in the VisualGraph.
void setRuleRegistry(RuleRegistry, boolean)
Sets a RuleRegistry
as the currently active set of rules for this
VisualGraph.
The default rules are assigned to all objects in the VisualGraph
that do not have a rule set already if and only if the
preserveAssignedRules flag is set to true.
Each model object can be referenced by multiple view objects which implement
the functionality that allows them to be visualized. This implicates that
view objects have coordinates and regions associated with them. Additionally,
they have a notion of being selectable and resizable, actions that are
typically found in visual editing. Finally, certain view classes, such as
VisualNode and VisualEdge, extend interfaces which allow them to be automatically
positioned by the layout engine. We will discuss these interfaces in more
detail later.
The visualization of a view object is done with the help of a so-called
Composite, a compound graphical object built upon Primitive parts.
As you might have already guessed, these objects are defined by the two
Java® interfaces Composite and Primitive. A graphical style, such
as a stroke, fill pattern or font, can be assigned to each graphical
Primitive where appropriate. These objects can then be grouped inside
any Composite parent container. In this way, primitives can be used to
compose complex graphical shapes.
In order to build even more complex visual shapes, ones that represent entire
visual subgraphs, we provide a specialized, derived interface named
CompositeGroup. Instances of this type are also Composite objects
capable of nesting other Composite objects as well, providing you with
the ability to nest arbitrarily complex levels of primitives.
There is a close dependency between the visually-scoped objects from the
Graph library and the Composite library. For example, objects of type
VisualNode use Composite instances for their rendering. The Tensegrity Graph Framework requires
that each VisualNode instance be associated 1:1 with a Composite instance.
Of course, this instance may be any subtype implementation as well. In
addition, instances of type VisualSubgraph have a 1:1 association with an
an instance of type CompositeGroup.
Table 1.2. View - Composite Associations
| Visual Class | Associated Composite | Description |
|---|---|---|
VisualNode | Composite |
Each VisualNode instance is associated with a
Composite instance.
|
VisualEdge | CompositeLine |
Each VisualEdge instance is associated with a CompositeLine instance.
|
VisualPort | Composite |
Each VisualPort instance is associated with a Composite instance
(but not on a fixed 1:1 basis).
|
VisualSubgraph | CompositeGroup |
Each instance of VisualSubgraph is associated with a CompositeGroup
instance. Since interface VisualSubgraph extends the VisualNode interface,
it is also possible to obtain the Composite instance that each
VisualNode (and hence each VisualSubgraph) is associated with. The fact
that interface CompositeGroup extends the Composite interface
reflects this substitution functionality.
|
The association between a Composite and a view object is permanent. This
means that once a view object has been created, its reference to
the associated Composite can no longer be changed.
Instances of VisualPort are an exception in that they are
not associated with Composite objects
on a fixed 1:1 basis.
This interface represents the aspects common to all visual graph
elements, including a VisualNode, VisualEdge
and VisualSubgraph. The first of these aspects includes the
identifiable nature of these elements. Every VisualGraphObject
has both an identifier unique to its context as well as a global identifier
that is unique within a hierarchy of VisualGraph objects.
Methods to access both of these identifiers are available.
Each VisualGraphObject implementation is constructed with an initial
identifier of -1. When a VisualGraphObject is added to a
GraphObjectContainer, the identifier is
changed internally by the container to a value that becomes unique within
that container context. The container may nest other containers recursively,
which might have the same identifier assigned to one of their managed objects.
Identifiers, therefore, are unique within the scope of a single
GraphObjectContainer only.
When a VisualGraphObject is removed from a
GraphObjectContainer, the identifier is
reset to -1.
Each VisualGraphObject can only be stored in one dedicated
VisualGraphObjectContainer at a time.
The identifiers that are internally assigned to a VisualGraphObject
corresponds with the identifier of the associated model object. In this way, a
mapping from model to view objects is possible. You can create multiple
VisualGraphObject instances that all reference the same model object.
Moreover, objects of this type are represented by a Composite, reference a
Graph model and possess behavior specified by custom
Rule objects.
[2].
The following a list of the important methods offered by this interface:
BaseComposite getBaseComposite()
Returns the instance of the BaseComposite that is associated
to the VisualGraphObject instance.
GraphObject getGraphObject()
Returns the instance of the GraphObject that corresponds
to the VisualGraphObject instance.
long getID()
Returns the id of this VisualGraph object. The id is local
to the VisualGraph and exists as well in the associated
graph-model objects. The id however is unique in the scope of
VisualGraphObjects of a single VisualGraph.
VisualGraphObjectContainer getParentContainer()
This method returns the VisualGraphObjectContainer this
VisualGraphObject instance currently resides in. In case
this VisualGraphObject instance is not added to a
VisualGraphObjectContainer this method returns
null.
void setPinned(boolean)
Marks this VisualGraphObject as pinned.
VisualGraphObjectContainer getRootContainer()
VisualGraphObjectContainer instances can be nested
inside of each other by means of the
VisualSubgraph class. This method returns the root
component of the nesting hierarchy, or the this
pointer if this instance is the root of the hierarchy.
In case this instance is not added to a parent
VisualGraphObjectContainer null is returned.
String getRule()
Gets the rule associated with this object.
void setRule(String)
Sets the rule name associated with this object.
RuleRegistry getRuleRegistry()
Retrieves the active RuleRegistry
for this VisualGraphObject instance.
void setRuleRegistry(RuleRegistry)
Stores the active RuleRegistry of the
rule in the visualgraphobject, so that it can be traced back.
long getUniqueID()
Returns the global id of this VisualGraphObject instance.
The returned id is unique within the complete graph hierarchy and is the
same as the unique id of the associated GraphObject.
boolean isPinned()
Return a boolean that indicates whether
this VisualGraphObject is pinned.
VisualGraphObject instances are visual representations of GraphObject instances.
Moreover, these visual types extend interface Layoutable so that they may be
automatically positioned by a LayoutController.
Methods intended for internal use only:
void registerVisualEventMediator()
void registerVetoableVisualEventMediator()
This interface represents the functionality of any potential
Node representation. By incorporating the
functionality of a Composite object, it becomes
possible to assign complex shapes and styles to an instance
of this class.
The associated model Node can be obtained by invoking the
getNode() method.
Here are important methods defined in the interface:
void adjustEdges()
Updates all adjacent edgs which are registered at ports of this visualnode. The edge will snap in to their ports in case their positions differ from their attached positions.
Composite getComposite()
Returns the instance of the Composite associated to the
VisualNode instance.
Node getNode()
Returns the reference to the node this VisualNode is associated
with. (there is a 1:n relationship between
Nodes and VisualNodes)
VisualNodeInfo getVisualNodeInfo()
Returns the VisualNodeInfo associated with this
VisualNode.
List getVisualPorts()
Returns a list of the VisualPorts of this
VisualNode.
This interface represents the functionality of any potential
Edge representation. By incorporating the
functionality of a Composite object, it becomes
possible to assign complex shapes and styles to an instance
of this class.
Here are the most important methods defined in the interface:
CompositeLine getComposite()
Returns the instance of the CompositeLine associated to the
VisualEdge instance.
Edge getEdge()
Returns the reference to the Edge
this VisualEdge is associated with.
(1:n relationship between edges and VisualEdges)
VisualEdgeInfo getVisualEdgeInfo()
Returns the VisualEdgeInfo associated with this
VisualEdge.
VisualNode getVisualSource()
Gets the VisualNode at the source end of this
VisualEdge.
VisualPort getVisualSourcePort()
Returns the VisualPort VisualPort at the source end of
this instance. The field may be null if the VisualEdge is
currently detached.
VisualNode getVisualTarget()
Gets the VisualNode at the target end of this
VisualEdge.
VisualPort getVisualTargetPort()
Returns the VisualPort VisualPort at the target-end of
this instance. The field may be null if the VisualEdge is
currently detached.
void updatePosition()
This method updates the position of this VisualEdge
instance according to the ports it is connected to.
If this VisualEdge is not connected to a
VisualPort then invoking the method will not trigger
and action.
This interface represents the visualization of a model Port
that is contained and managed by a VisualNode.
This interface defines the characteristics of a single visual connection point
to a VisualNode from which a VisualEdge instance is
attached. In other words, an VisualEdge connects to a
VisualNode via one of the many VisualPort instances owned
and managed by a VisualNode, and not to the VisualNode directly.
A VisualPort uses a so-called VisualPortDenotation, which defines
the angular interval where incoming and outgoing edges are allowed to connect to the
associated VisualPort.
Visual ports have identifiers which can be returned to clients who request them.
The identifiers of a VisualPort and its associated model object
always correspond and are unique within a single Graph,
VisualGraph, Subgraph and VisualSubgraph.
These identifiers are set to -1 when no longer contained by a
parent component.
Each active VisualPort managed by a single VisualNode
instance can be retrieved by invoking the method getVisualNode().
The number of VisualEdge objects that are
currently connected to a VisualPort can be retrieved
by invoking the method getRegisteredVisualEdgeCount().
The actual VisualEdge objects that are
connected can be retrieved by invoking getRegisteredVisualEdges().
A VisualPort can have a number of different drawing states
which are defined by the constants prefixed with DRAWINGSTATE_
and which can be set by invoking the method setDrawingState(int).
This method is invoked internally by the library and usually there should
not be any to need to invoke this method manually.
A VisualPort can either be direct (a so-called leaf-port) or
indirect (a so-called wrapped-port). From the perspective of a library user,
the difference is not significant. Wrapped-ports can themselves be wrapped
up recursively. The method getDepth() can be used to find out the
depth of nesting. The VisualNode that
holds the leaf-port (the port that doesnt wrap-up other ports) can be
queried by invoking the method getWrappedVisualNode().
The methods getCoordinate() and getBoundingBoxCoordinate()
are used to find out the geometric position of a VisualPort.
The later method returns the position in the CoordinateSystem of
the enclosing VisualNode and thus is the one
that is likely to be used in most cases.
This interface holds the methods that define the container role
for classes that manage VisualGraphObject instances. This
is the parent interface of both the VisualGraph and
VisualSubgraph interfaces.
A VisualGraphObjectContainter will manage VisualNode
and VisualEdge instances by providing implementations to add and
remove objects of these types.
void addVisualEdge(VisualEdge)
Adds a new VisualEdge to this
VisualGraphObjectContainer.
GraphObjectContainer getGraphObjectContainer()
Gets the associated
GraphObjectContainer of this instance.
The model instance can be associated with one or multiple
VisualGraphObjectContainer instances.
VisualGraphObjectContainer getParentContainer()
VisualGraphObjectContainer instances can be nested
inside of each other by means of the
VisualSubgraph class. This method returns the parent
component of this VisualGraphObjectContainer or
null if this instance is the root of the hierarchy.
VisualGraphObjectContainer getRootContainer()
VisualGraphObjectContainer instances can be nested
inside of each other by means of the
VisualSubgraph class. This method returns the root
component of the nesting hierarchy, or the this
pointer if this instance is the root of the hierarchy.
In case this instance is not added to a parent
VisualGraphObjectContainer null is returned.
Iterator getVisualEdges()
Retrieves an iterator for all properly connected VisualEdge in
the VisualGraphObjectContainer.
Iterator getVisualGraphObjects()
Retrieves an iterator for all VisualGraphObjects.
Iterator getVisualNodes()
Retrieves an iterator for all visualnodes.
void removeVisualEdge(VisualEdge)
Removes a VisualEdge from the
VisualGraphObjectContainer.
The VisualEdge must be in the graph
for this operation to succeed.
void visitSubgraphs(VisualGraphVisitor)
Recurse over all nested subgraphs starting from this visualsubgraph.
This interface defines a view of a Graph
model as well but adds additional functional specifications. Implementations
of class VisualGraphView represent the top-level containers within
a hierarchy of nested VisualGraphObjectContainer instances and are
responsible for the undo, redo, cut, copy and paste functionalities within a graph
document.
VisualGraphView derives from and thus aggregates many interfaces,
including VisualGraph, CompositeView and the
VisualGraphObjectContainer interfaces, allowing
clients to treat a VisualGraphView as one of many specific roles.
Also, it is important to note that a new VisualGraphView instance
requires a reference to a GraphController, which must be advised
to manage the newly created view after instantiation.
When new visual edges are introduced via edge-splitting, either manually
or by user interaction, these new edges will be assigned a default style.
This style can be configured for the entire view hierarchy by invoking the
setDefaultEdgeStyle(String) method.
The paste orientation specifies how pasting preserves the relative
order of connected VisualNode objects.
See method setPasteOrientation(int).
VisualEdge update modes determine how connected
VisualEdge objects should behave
when the position of a VisualNode
changes. Update modes can be set with method
setVisualEdgeUpdateMode(int).
A VisualGraphView supports user interaction with the mouse.
To do so it provides the methods listed below:
InteractionHighlightConfiguration getInteractionHighlightConfiguration()
Returns the InteractionHighlightConfiguration instance that is
used within this VisualGraphView to identify the geometries
and styles for highlighting interactions like edge-splitting etc. The
returned reference can then be manipulated in order to change styles and
geometries.
InteractionSettings getInteractionSettings()
Returns the current interaction settings class from this
VisualGraphView. Interaction settings have a higher priority
than the results of the callbacks from the active
InteractionControl class.
Other important methods defined in this interface are:
LayoutController getLayoutController()
Gets the LayoutController
that is associated with this instance. May be null.
void setVisualEdgeUpdateMode(int)
Sets the update-mode for VisualEdges. The update-mode
determines the behavior of VisualEdges when any of the
VisualNodes they are connected to are moved.
UPDATEMODE_SIMPLE
Update only fully connected VisualEdges. If a
VisualEdge is not fully connected on both ends, then moving
the VisualNode that has one end connected wont change any
of the VisualEdges coordinates.
UPDATEMODE_PLAIN
Similar to update mode UPDATEMODE_SIMPLE, but it will
also update objects of type VisualEdge that are connected to
exactly one of the ends of the corresponding VisualNode.
UPDATEMODE_ORTHOGONAL
Keep care of orthogonal (parallel to x or y-axis) segments of the
edge and distributes the changes horizontally and vertically to those
segments, thus preserving orthogonality.
This abstract class defines the methods to create instances of all graph view objects.
By calling the static method newInstance(), you can
obtain an instance that is assignable to this class.
A concrete implementation of this abstract class is
GraphViewFactoryImpl.
The following list contains a subset of the methods in this class.
VisualEdge newVisualEdge(Edge, VisualNode, VisualNode)
Creates a new VisualEdge associated with the given model
edge. The edge is connected to the given source and target
VisualNode object.
VisualGraph newVisualGraph(Graph)
Creates a new VisualGraph associated with the given model
graph.
VisualNode newVisualNode(Node, List, Composite)
Creates a new VisualNode associated with the given model
node and providing the given ports. This VisualNode
will be graphically represented by the given Composite.
VisualPort newVisualPort(VisualPortDenotation, int, int, Port)
Creates a new VisualPort associated with the given model port
and further described by denotation. It will be located at
position (coordHorizontal, coordVertical.
VisualPortDenotation newVisualPortDenotation(double[])
Creates a new VisualPortDenotation using the given interval.
Parameter boundedInterval has to be double-array of length
2, where the value stored at index 0 describes the beginning of the
interval and the value stored at index 1 describes the end of the
interval.
VisualSubgraph newVisualSubgraph(Subgraph, VisualGraph, CompositeGroup)
Creates a new VisualSubgraph that will be nested within the
given VisualGraph and visualized by the
CompositeGroup given by parameter
compositegroup.
Beside method newInstance the following static
methods are provided to ease the VisualNode
creation process.
VisualNode makeDefaultVisualNode(GraphViewFactory, Node, Composite)
This method creates a default VisualNode instance.
The instance is configured in a default way. A set of default
ports is assigned to the VisualNode. Typically this
set of default ports includes four ports at each side of the rectangular
bounding box of the VisualNode and an additional port
in the middle.
VisualNode makeDefaultVisualNode(GraphViewFactory, Node, Composite, VisualNodeInfo)
This method creates a default VisualNode instance
and associates a VisualNodeInfo object with it.
The instance is configured in a default way. A set of default
ports is assigned to the VisualNode. Typically this
set of default ports includes four ports at each side of the rectangular
bounding box of the VisualNode and an additional port
in the middle. The given VisualNodeInfo is associated to
the returned VisualNode.
Each and every view object must be associated with a corresponding model
object. As a consequence, the creation of a view object cannot take place before
the creation of its referenced model object. Along similar lines, no view
objects may be added to a VisualGraph whose model objects do not belong to same
Graph referenced by the VisualGraph
This system of adding model and view objects and later removing them follows
the LIFO (Last in, First out) system. Before you can remove a model object
from a Graph, you must first remove all view objects that reference it from
their parent view containers.
If you are not creating objects of type Subgraph and VisualSubgraph, you will
also not be using interface type VisualGraph directly. Instead, the interface
type VisualGraphView is used whenever an actual visualization (including painting)
is required. The following code snippet illustrates just how to create an
empty VisualGraphView with a typical configuration.
Example 1.3. Assembling A Simple VisualGraphView
VisualGraphView createVisualGraphView()
{
// set up references to the factories
GraphModelFactory modelfactory=
GraphModelFactory.newInstance();
GraphViewFactory viewfactory=
GraphViewFactory.newInstance();
GraphControllerFactory controllerfactory=
GraphControllerFactory.newInstance();
// create a model-scope Graph
Graph graph= modelfactory.newGraph();
// create a default controller
GraphController clientServerController=
controllerfactory.newClientServerGraphController(graph);
VisualGraphView visualgraphview=
viewfactory.newVisualGraphView(clientServerController);
// configure the visualgraphview in a typical way
visualgraphview.setBoundingBox(0, 0, 0, 0);
visualgraphview.enableClipping(true);
visualgraphview.setSelectPastedElements(true);
InteractionSettings settings=
visualgraphview.getInteractionSettings();
settings.setPortsEnabled(true);
settings.setAllowLoops(true);
visualgraphview.setDefaultEdgeStyle("TenseLine");
return visualgraphview;
}
This code not only creates a VisualGraphView instance but also the underlying
model container of type Graph. The resulting structure is capable of
representing model-scoped Node and Edge objects as part of the view
representation.
As mentioned before, any view object can only be added if its associated
model object has already been added to its corresponding model Graph.
Suppose, for example, that we have an instance of type VisualGraphView that was
created with the code provided in the previous example and stored in a
local variable called visualgraphview. Adding two nodes
and connecting them with an edge, in both the model and the view, would
require the following code:
Example 1.4. Adding VisualNodes and VisualEdges
void addObjects(VisualGraphView visualgraphview) throws StaticException
{
// set up factory references
GraphModelFactory modelfactory=
GraphModelFactory.newInstance();
GraphViewFactory viewfactory=
GraphViewFactory.newInstance();
// first we create the nodes and edges
Node node1=
GraphModelFactory.makeDefaultNode(modelfactory, "node1");
Node node2=
GraphModelFactory.makeDefaultNode(modelfactory, "node2");
VisualNode visualNode1= viewfactory.newVisualNode(node1,
GeometryPool.get("Rectangle"));
VisualNode visualNode2= viewfactory.newVisualNode(node2,
GeometryPool.get("Rectangle"));
Edge edge= modelfactory.newEdge(node1, node2);
VisualEdge visualEdge=
viewfactory.newVisualEdge(
edge, visualNode1, visualNode2);
// add first node
visualgraphview.getGraph().addNode(node1);
visualgraphview.addVisualNode(visualNode2);
// add second node
visualgraphview.getGraph().addNode(node2);
visualgraphview.addVisualNode(visualNode1);
// add edge
visualgraphview.getGraph().addEdge(edge);
visualgraphview.addVisualEdge(visualEdge);
}
Please note the order in which objects are added. First a model object is added, then the associated view object.
The following code illustrates how to remove the objects that were added in the previous example.
Example 1.5. Removing VisualNodes and VisualEdges
void removeObjects(VisualGraphView visualgraphview)
throws StaticException
{
// remove edge
VisualEdge visualEdge=
(VisualEdge) visualgraphview.getVisualEdges().next();
visualgraphview.removeVisualEdge(visualEdge);
visualgraphview.getGraph().removeEdge(visualEdge.getEdge());
// remove first node
VisualNode tmpNode=
(VisualNode) visualgraphview.getVisualNodes().next();
visualgraphview.removeVisualNode(tmpNode);
visualgraphview.getGraph().removeNode(tmpNode.getNode());
// remove another node
tmpNode=
(VisualNode) visualgraphview.getVisualNodes().next();
visualgraphview.removeVisualNode(tmpNode);
visualgraphview.getGraph().removeNode(tmpNode.getNode());
}
Please note the order when removing objects. First a view object is removed, then the associated model object.
© 2004, 2005 Tensegrity Software GmbH