-
Notifications
You must be signed in to change notification settings - Fork 0
/
graphviz.d
116 lines (91 loc) · 2.03 KB
/
graphviz.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/++
+ D interface to the Graphviz graph visualization library
+
+ Written by Vegard Sjonfjell <[email protected]>
+/
module graphviz;
import std.stdio;
import std.string;
import std.array;
import std.algorithm;
import std.conv;
import cgraphviz.graph;
import cgraphviz.gvc;
enum GraphType
{
graph = AGRAPH,
graphStrict = AGRAPHSTRICT,
digraph = AGDIGRAPH,
digraphStrict = AGDIGRAPHSTRICT
}
mixin template AttrAccess(alias gv_var)
{
void opDispatch(string attr)(string value) {
agsafeset(gv_var, attr.toStringz, value.toStringz, "");
}
string opDispatch(string attr)() {
return to!string(agget(gv_var, attr.toStringz));
}
}
class Graph
{
graph_t* gv_graph;
GVC_t* gv_context;
string layout = "dot";
static this() {
aginit();
}
this(GraphType type, string name)
{
gv_context = gvContext();
gv_graph = agopen(name.toStringz, type);
}
this(GraphType type) {
this(type, "");
}
~this()
{
gvFreeLayout(gv_context, gv_graph);
agclose(gv_graph);
}
Node addNode(string name) {
return new Node(agnode(gv_graph, name.toStringz));
}
Edge addEdge(Node pre, Node post) {
return new Edge(agedge(gv_graph, pre.gv_node, post.gv_node));
}
Edge addEdge(Node pre, Node post, string label)
{
auto edge = new Edge(agedge(gv_graph, pre.gv_node, post.gv_node));
agset(edge.gv_edge, "label", label.toStringz);
return edge;
}
void doLayout() {
gvLayout(gv_context, gv_graph, layout.toStringz);
}
void outputFile(string type, string filename) {
doLayout();
gvRenderFilename(gv_context, gv_graph, type.toStringz, filename.toStringz);
}
void outputFp(string type, File file) {
doLayout();
gvRender(gv_context, gv_graph, type.toStringz, file.getFP);
}
mixin AttrAccess!(gv_graph);
}
class Node
{
node_t* gv_node;
this(node_t* gv_node) {
this.gv_node = gv_node;
}
mixin AttrAccess!(gv_node);
}
class Edge
{
edge_t* gv_edge;
this(edge_t* gv_edge) {
this.gv_edge = gv_edge;
}
mixin AttrAccess!(gv_edge);
}