To specify graphs, a mechanism of identifiers (called labels
in former releases) and references is used in daVinci. For
example, if a child node has more than one parent node, then in the term
representation the corresponding subgraph of the child
appears in only one of the parents as a subterm. This subterm is marked with
an identifier (in fact, all nodes and edges need to be marked with a unique
identifier). All the other parents of the same child do not duplicate the
subterm. Instead, they point to the child by using a reference to the
identifier. Note that this way it is even possible to describe cyclic graphs.
When loading a term representation, daVinci will construct an
internal graph by resolving these references.
The linear order of a node's subterm (where the identifier is declared) and
a reference to this node (where the identifier is used) is arbitrary in a term
representation, so references can be used before the corresponding identifier
and subterm appears in the term representation.
Note: You have to make sure that each node and edge in a term
representation has its own unique identifier, i.e. do not use the same ID for
two objects. In multi-graph mode,
each context (graph) has its own scope, so there is no need to have unique
identifiers for the union of all current contexts.
Beside the identifier (a unique string) and the list of child nodes (which is
probably empty), each node also has a type and a list of
attributes which are responsible for the image of a node in the
visualization.
Types and
attributes
are discussed below. Between a parent
and the corresponding child node, there is an edge in the term representation
which also has its unique edge identifier, type and attributes. So, in fact
the children of a node are edges and each edge has one node or reference as
subterm.
Note: In previous V1.x releases of daVinci, identifiers
(labels) for nodes and edges were recommended, but optional. In
daVinci V2.x, identifiers are now mandatory to support several new
features. For example, identifiers will be sent back to a connected
application when the user selects nodes or edges.
The syntax of the term representation
(startsymbol is graphterm) can be found in the API definition.
When a graph is loaded from file, whitespace (blanks, tabs or returns)
may occur at any position in a term representation. Of course, in strings
whitespace is significant. When a graph is sent in term representations to the
API, whitespace should be avoided and returns are
forbidden.
The following figure illustrates a term representation of a small graph and
the corresponding visualization in daVinci. A
more complex example is demonstrated below.
Multi-Edges and Self-Edges
Multi-edges and self-edges are special kinds of edges
that are treated in a different way in the graph layout. Multi-edges are
present when there are two or more edges between the same parent and child
node. All these edges form one multi-edge. The single edges of a
multi-edge are spreaded in the middle between the parent and the child
(see figure below), whereby the used gap can be adjusted with the
Options/Layout Dimensions...
dialog window.
Self-edges are edges where the parent and child node are the same, i.e. a node that has an edge pointing to itself. Self-edges are visualized with a circular edge at the left resp. lower side of the node. The user can adjust the radius of self-edges with the Options/Layout Dimensions... dialog window. Multi self-edges are also possible when a node uses edges with a reference to itself many times in its list of children. These edges are visualized by writing the number of self-edges in the middle of the circle. The attributes of self-edges are considered for the graph visualization (only in daVinci V2.0.2 or higher), but it is undefined which self-edge of a multi self-edge is taken for the attributes. So for example, if you have a multi self-edge containing a red and a blue self-edge, then it is not defined whether the multi self-edge is drawn in red or blue.
The following figure illustrates the visualization of multi- and self-edges in daVinci.
Note: With the command-line option -init you can supply API commands at startup of daVinci. If you put your definitions into such an initial file, you will be able to use visualization defintions without the API. Unfortunately, you will not be able to change the definitions at runtime.
In one of the next daVinci releases, the user will be able to load
a file of rules (visualization definition) that defines the visual
appearance of a class.
Attributes
Attributes are used in the term representation to specify the
visualization of individual nodes and edges. Each node and edge has its own
attributes which is a list of string pairs with a constructor a
followed by an attribute name and attribute value in parentheses or a
constructor m followed by a list of menus. Here is an
example for the attributes of a node:
[a("OBJECT","hello"),a("COLOR","red"),a("FONTFAMILY","times"), m([menu_entry("MenuID","Menu Entry")]) ]If a particular attribute is specified for a node or edge, it will overwrite the default value for this attribute which is used otherwise. Please look at the paragraph visualization defintion of the concepts document to find out more about the evaluation order for attributes. Node and edge attributes are distinguished from eachother. For example, there are different attributes (more precisely: attribute names) to set the color of nodes ("COLOR") and edges ("EDGECOLOR"). Edge attributes cannot be used for nodes and vice versa. Unknown attribute names and values are simply ignored without any warning. This way, the term representation is both up- and backward compatible with previous and future releases of daVinci. Some attributes, starting with character '_', are needed for internal purposes, but can also be used in a term representation. The usage of attributes is demonstrated in the example below.
Graphical object "text" can be used to simulate edge labels which are currently not available in daVinci. "text" is very similar to object "box", in fact it is a box without the black border. An example graph with simulated edge labels is file example_graphs/edge_labels.daVinci of the daVinci distribution. The trick with simulated edge lables is to use a regular node with graphical object "text" to show an edge label.
With object "icon", a user can define to use a monochrome image for a node in the visualization. Unfortunately, "icon" is more complicated than the other graphical objects. The bitmap file with the image of the icon need to be specified with a second attribute "ICONFILE" (see below), so for icons you need two attributes: "_GO" and "ICONFILE".
Note: The geometrical object "scissors" is normally used to display
nodes with hidden subgraphs. So it is not recommended to use this object,
because the user may get confused.
Node Attribute "_CGO" (Graphical Object)
Same as attribute "_GO" but this geometrical object is used, if the subgraph of
the node is hidden. The default value for this attribute is "scissors".
You also need the attribute "CICONFILE", if you choose the geometrical object
"icon" as the attribute value, as described for "_GO".
Node Attribute "ICONFILE"
This is used as a supplement for attribute
"_GO"
when its value is set to "icon".
Attribute "ICONFILE" specifies the (relative) filename of the bitmap used
to draw the node as icon. The file must be in X-Window bitmap format
(.xbm). Absolute filenames are not allowed as a value for this
attribute. daVinci is looking for the file in all directories
given by environment variable $DAVINCI_ICONDIR. So for example,
when the bitmap of an icon is in file /home/me/images/my_image.xbm,
then add /home/me/images to the search path of environement variable
$DAVINCI_ICONDIR before starting daVinci, set attribute
"_GO" to "icon" and attribute "ICONFILE" to "my_image.xbm" for a particular
node. The default value for this attribute is "".
Notes about attribute "ICONFILE":
[ l("Node A",n("Module",[a("COLOR","#f31d8b"), a("OBJECT","Node A"), a("_GO","ellipse"), a("FONTFAMILY","helvetica")], [ l("Edge A->B",e("",[a("EDGECOLOR","red")], l("Node B",n("anything",[a("COLOR","light steel blue"), a("BORDER","double"), a("OBJECT","Node B\nThis node has two lines")], [ l("Edge B->D",e("",[a("EDGEPATTERN","dotted"), a("_DIR","inverse")], r("Node D"))) ])))), l("Edge A->C",e("",[a("EDGEPATTERN","dotted"), a("EDGECOLOR","#0054aa")], l("Node C",n("anything",[a("_GO","icon"), a("ICONFILE","bkb.xbm"), a("COLOR","gold"), a("OBJECT","Node C"), a("FONTSTYLE","italic")], [ l("Edge C->D",e("anything",[a("EDGECOLOR","#00aaaa"), a("_DIR","both")], l("Node D",n("Module",[a("OBJECT","Node D"), a("_GO","text"), a("FONTFAMILY","times"), a("FONTSTYLE","italic")],[])))), l("Edge C->F",e("anything",[a("EDGEPATTERN","double")], r("Node F"))) ])))), l("Edge A->E",e("",[a("EDGEPATTERN","dashed"), a("_DIR","none")], l("Node E",n("anything",[a("COLOR","LightGray"), a("FONTFAMILY","courier"), a("FONTSTYLE","normal"), a("BORDER","double"), a("OBJECT","Node E"), a("_GO","rhombus")], [ l("Edge E->F",e("anything",[a("EDGEPATTERN","thick")], l("Node F",n("anything",[a("COLOR","#00dddd"), a("OBJECT","Node F"), a("HIDDEN","true")], [ l("Edge F->G",e("anything",[], l("Node G",n("anything",[a("OBJECT","Node G")],[])))) ])))) ])))) ])) ]Here is the visualization of this term representation: