This package provides a simple, flexible, and powerful interface to the graph drawing tool DaVinci. DaVinci is a professional graph drawing tool developped by Michael Fröhlich and Mattias Werner from the Group of Prof. Dr. Bernd Krieg-Brückner at University of Bremen in Germany.
To draw a graph, it is sufficient to specify its nodes and edges, and how to draw them (but not where to). The required graph specifiations can be defined on high level through Oz data-structures. These are automatically converted to strings in DaVinci's API-format and then send to an Oz-external DaVinci process that is created.
The interface also permits to define graph actions that are envoked by clicking on nodes or edges of the drawn graph. Specifications of actions can be defined through arbitrary Oz procedures. They may refer to the actual graph structure which is always memoized by the interface.
So far, the interface is available for Linux but soon, it will also be made available for Windows.
DaVinci displays a graph in its window after a term representation of the graph has been loaded from file. It is as well possible to communicate with daVinci directly via the shell by sending strings in the requisite syntax.
DaVinci was built with respect to the facility of connecting an extern application program that serves as a graph editor. The interface operates as the connector between daVinci and Oz datastructures that edit and modify graphs.
DaVinci visualizes graphs in a hierarchical manner, i.e. reflects the hierarchical relationships of a graph by arranging the nodes on horizontal levels in a way that all parent nodes are above their children nodes and edges point downwards (though it is possible to switch to the inverse bottom-up layout as well as to left-right or right-left layout). Cyclic graphs are handled with a trick.
Here is an example:
Nodes can be labelled with text (edges as well in version 3.x) Nodes and edges can have other layout attributes (color, pattern, for more examples see below). The graph can be edited (move, remove and add edges and nodes, change attributes). Menus can be placed at nodes, edges and the graph displaying window.
Graphs can be modified at run time. Nodes and edges can be added and removed, and attributes can be changed. Every nodes always knows its ingoing and outgoing edges.
For all of the documentation below we recommand to consult one of the examples for illustration.
A graph consists of a list of nodes and a list of edges.
A node is specified by a record of node features
that define the node's type Graph= unit(nodes:list(Node)
edges:list(Edge)
id
, kinds
,
and attributes. For conveniance, an optional feature
edges
is offered by node specifications
where some of
the outgoing edges of the node can be specified.
type Node = unit(id : Atom
edges : list(Edge)
kind : Atom
kinds : list(Atom)
'OBJECT' : VirtualString
menu : list(MenuEntry)
... )
This is only a small collection of possible node features. There may be many more useful node attributes. These are defined by actual DaVinci tool used. A set of such node attributes is also explained in Node Attributes
An edge is a record with features for specifying the edge's id
,
kinds
, end-node and attributes.
type Edge <= unit(id : Atom
'from' : Atom
to : Atom
kind : Atom
kinds : list(Atom)
'OBJECT' : VirtualString
menu : list(MenuEntry)
... )
The edge feature 'from'
can be ommited in edge
specifications that are embedded into the specification of that
node where the edge starts. The above types lists only a small
collection of possible edge features. For additional features,
we refer to Edge attributes
type Parameters = unit(layout : Layout
actions : Actions
configuration : Configuration
debugging : Bool)
type Layout = unit(node : Layouts
edge : Layouts
window: WindowProperties)
type Layouts = unit(default: Kind
atom : Kind
. .
. .
. .
atom : Kind)
A kind specifies values for a set of node resp. edge
attributes.
type Kind = unit(attribute : Value
. .
. .
. .
attribute: Value)
A node or edge inherits the values of all attributes of
its kinds. The complete list of kinds of a node or edge
is defined by the values of the two features kind
and kinds
. If both values are available, the
overall list is obtained by prepending the value
of kind
to the values of kinds
.
The attributes of the kinds of a node are inherited in that order in which the kinds occur in the overall list of kinds. Note that multiple inheritance may overwrite values inherited earlier.
The types of attributes of nodes and edges where already discussed
in the subsection on nodes and edges. The features id
,
edges
, kind
, and kinds
have
special meanings, i.e., the are not attributes in the sense of
DaVinci's specification.
Node and edge attributes that are left unspecified will be
given default values. The defaults can be definded by the user,
as it is given by the value of the default
feature of Layouts
.
type WindowProperties = unit(menu : list(MenuEntry)
icons: list(Icon))
MenuEntries
represents the entries of the edit menu in the daVinci window, while Icons
represents the icons to be found at the left side of the daVinci window.
type MenuEntry = menu_entry(MenuAction VirtualString)
+ submenu_entry(MenuLabel list(MenuEntry))
+ blank
type MenuAction = NodeMenuAction + EdgeMenuAction + WindowMenuAction
type NodeMenuAction = Node x DaVinci ->
type EdgeMenuAction = Edge x DaVinci ->
type WindowMenuAction = DaVinci ->
MenuAction
identifys the action to be executed
when choosing the correspinding menu entry. A VirtualString
represents the label of this entry (i.e. what is shown at the menu bar).
For specification of VirtualString cf. The Oz Base Environment .
A MenuAction
receives one or two arguments. The last
argument is always the actual DaVinci
. The first
of two arguments specifies either the node or edge to which
the menu belongs. WindowMenuActions only have one argument.
The blank
serves as a seperator of
menu entries.
type Icons = list(IconEntry)
type IconEntry = icon_entry(IconAction URI IconLabel)
type IconAction = Node x DaVinci ->
type IconLabel = VirtualString
IconAction
specifies the desired action, which receives two arguments:
the actual node and the actual DaVinci.
URI
adresses the bitmap of the icon in X-Window Bitmap format (.xbm format) of size 18x18 pixel. The URI is resolved to a filename by the Mozart resolver.
IconLabel
should be a short description of the semantic of the icon which will be displayed in the footer area of the daVinci window as soon as the mouse-pointer is over the icon.
type Actions = unit(nodeDoubleClick: Node x DaVinci ->
edgeDoubleClick: Edge x DaVinci ->
nodeSingleClick: Node x DaVinci ->
edgeSingleClick: Edge x DaVinci ->
ok: DaVinci ->
communication_error: Value x DaVinci ->
)
Please confer example2.oz.
DaVinci.state
can provide you with that information.
type DaVinci.graph = unit(inEdges : Node -> list(Edge)
outEdges : Node -> list(Edge)
reachable: list(Node) -> list(Node)
%% conversion of the graph
toNodes : -> list(Node)
toEdges : -> list(Edge)
%% implementation
nodes : dictionary
edges : dictionary
toNode : atom -> Node
toEdge : atom -> Edge
handle : ( -> ) ->
...)
The function DaVinci.graph.inEdges
maps a node to the list
of ingoing edges, and the function DaVinci.graph.outEdges
to the list of outgoing edges. These function are implemented via
dictionaries DaVinci.graph.nodes
and
DaVinci.graph.edges
that hash nodes and edges
via their ids. The type of dictionaries used are defined in
the package mogul:/niehren/base. These dictionaries
can be converted into the actual list of nodes and edges by applying
the functions DaVinci.graph.toNodes
and
DaVinci.graph.toEdges
.
It is also possible at each time point
to retrieve the actually selected edge or
the set of actually selected nodes of the graph:
returns a list containing of all nodes that are currently selected
in the graph window
type DaVinci.getSelectedNodes = -> list(Node)
returns the currently selected edge in the graph window
type DaVinci.getSelectedEdge = -> Edge + NoEdge
type NoEdge = Name
type Configuration = [DVCommand1 ... DVCommandN]
DVCommand is a daVinci command of category 'set'
(cf. DV-Documentation http://www.tzi.de/daVinci/docs/reference/api/api_set_cmd.html).
A possible configuration could be:
configuration: ['set(font_size(12))'
'set(gap_width(6))'
'set(gap_height(18))']
type Debugging = Bool
If Debugging
is set to true,
a large set of debugging information will be
displayed by the Oz Inspector. These values may
also be of interest if you want to understand more
about what this interface is doing internally.
By default, the value of this feature is false
.
manager.ozf
.
[Interface] = {Link ['manager.ozf']}
DaVinci = {Interface.new Parameters}
This functor exports a procedure Interface.new
;
it needs Parameters
(as defined above) and returns a
record with features stated below. Suppose you invoke
manager.ozf
as follows:
DaVinci.newGraph
draws a newly
specified graph.
{DaVinci.newGraph Graph}
Graph
is a graph specification in the form described above. A graph with the given parameters will be drawn into a daVinci window.
Next, we can add a subgraph that my be connected to the actual
graph.
First of all you can add nodes, edges, or graphs:
Second, you can remove nodes, edges or the subgraph
below some node:
{DaVinci.add.nodes list(Node)}
{DaVinci.add.edges list(Edge)}
{DaVinci.add.graph Graph}
Third, you can change the attributes of nodes and
edges:
{DaVinci.remove.subgraph Node}
{DaVinci.remove.nodes [Node1 ... NodeN]}
{DaVinci.remove.edges [Edge1 ... EdgeN]}
The Kinds specify new values for some node or
edge attributes.
{DaVinci.change AttribChanges}
type AttribChanges = list(AttribChange)
type AttribChange = node(Node Kind) + edge(Edge Kind)
DaVinci.newGraph
and of the menu
independent actions.
{DaVinci.configure NewParameters}
NewParameters = unit(parameter: Parameters
actions : Actions)
The procedure DaVinci.configure
receives
a record of parameters to be changed. The record has two
features: at the first you can give the whole parameters; the
second provides the possibility to only change the actions.
If no parameters or actions are given, the old ones are taken.
For types of Parameters
and Actions
see specification above.
{DaVinci.improveAll}
is a functionality provided by daVinci which reduces edge crossings. (cf. DV documentation).
{DaVinci.setTitle 'Desired title'}
setTitle
allows you to entitle the daVinci window
{DaVinci.setSize Int#Int}
setSize
allows you to determine the size of the daVinci window. The first integer is the new window width (in pixel) and the second is the new height. Do not use negative values or values larger than the screen.
{DaVinci.execute 'DV-Command'}
enables you to send daVinci commands in daVinci syntax directly to daVinci
API. The DV-Command must be set into single quotes. Using
DaVinci.execute
is dangerous since the actual state
of DaVinci may get inconsistent with respect to its image memoized
on the Oz-side. Even more libarally,
DaVinci.gi
makes the whole implementation of the
graphic interface available.
Download the file daVinci.pkg
, invoke ozmake and execute in a shell
ozmake --freshen --package=niehren-davinci-x.x.x.pkg
ozmake --extract --package=niehren-davinci-x.x.x.pkg
The second command will provide the necessary file in the current directory.
Then you can open the example files and feed them to the compiler.
In case that did not already install ozmake
on your
machine, note that it is also available in the Mogul archive.