...
1 package drawing
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7 "os"
8 )
9
10 type Digraph struct {
11 Title string
12 Subgraphs []Subgraph
13 }
14
15 type Subgraph interface {
16 Print()
17 Fprint(w io.Writer)
18 }
19
20 type DotNode struct {
21 Data string
22 Children []*DotNode
23 Attributes map[string]string
24 }
25
26 type DotTree struct {
27 Root *DotNode
28 Nodes map[string]*DotNode
29 Attributes map[string]string
30 }
31
32 func (d *Digraph) String() string {
33 buf := &bytes.Buffer{}
34 d.Fprint(buf)
35 return buf.String()
36 }
37
38 func (d *Digraph) Print() {
39 d.Fprint(os.Stdout)
40 }
41
42 func (d *Digraph) Fprint(w io.Writer) {
43 fmt.Fprintf(w, "strict digraph \"%v\" {\n", d.Title)
44
45 for _, sub := range d.Subgraphs {
46 sub.Fprint(w)
47 }
48
49 fmt.Fprintln(w, "}")
50 }
51
52 func (t *DotTree) Print() {
53 t.Fprint(os.Stdout)
54 }
55
56 func (t *DotTree) Fprint(w io.Writer) {
57 fmt.Fprintf(w, "subgraph \"cluster_%v\" {\n", t.Root.Data)
58 for attr, val := range t.Attributes {
59 fmt.Fprintf(w, `%s%s=%s%s`, "\t", attr, val, "\n")
60 }
61 t.Root.print(w)
62 fmt.Fprintln(w, "}")
63 }
64
65 func (node *DotNode) print(w io.Writer) {
66
67 for _, child := range node.Children {
68
69 nodeAttrs := ""
70 if len(node.Attributes) > 0 {
71 nodeAttrs += " ["
72 for attr, val := range node.Attributes {
73 nodeAttrs += fmt.Sprintf(`%s=%s `, attr, val)
74 }
75 nodeAttrs += "]"
76 }
77 fmt.Fprintf(w, `"%s"%s%s`, node.Data, nodeAttrs, "\n")
78
79
80 childAttrs := ""
81 if len(child.Attributes) > 0 {
82 childAttrs += " ["
83 for attr, val := range child.Attributes {
84 childAttrs += fmt.Sprintf(`%s=%s `, attr, val)
85 }
86 childAttrs += "]"
87 }
88 fmt.Fprintf(w, `"%s"%s%s`, child.Data, childAttrs, "\n")
89
90
91 fmt.Fprintf(w, `"%s" -> "%s"%s`, node.Data, child.Data, "\n")
92
93
94 child.print(w)
95 }
96 }
97
View as plain text