-
Notifications
You must be signed in to change notification settings - Fork 400
/
table.go
136 lines (119 loc) · 3.7 KB
/
table.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package d2svg
import (
"fmt"
"io"
"math"
"strings"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label"
)
func tableHeader(box *geo.Box, text string, textWidth, textHeight, fontSize float64) string {
str := fmt.Sprintf(`<rect class="class_header" x="%f" y="%f" width="%f" height="%f" fill="%s" />`,
box.TopLeft.X, box.TopLeft.Y, box.Width, box.Height, "#0a0f25")
if text != "" {
tl := label.InsideMiddleLeft.GetPointOnBox(
box,
20,
textWidth,
textHeight,
)
str += fmt.Sprintf(`<text class="%s" x="%f" y="%f" style="%s">%s</text>`,
"text",
tl.X,
tl.Y+textHeight*3/4,
fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s",
"start",
4+fontSize,
"white",
),
escapeText(text),
)
}
return str
}
func tableRow(box *geo.Box, nameText, typeText, constraintText string, fontSize, longestNameWidth float64) string {
// Row is made up of name, type, and constraint
// e.g. | diagram int FK |
nameTL := label.InsideMiddleLeft.GetPointOnBox(
box,
prefixPadding,
box.Width,
fontSize,
)
constraintTR := label.InsideMiddleRight.GetPointOnBox(
box,
typePadding,
0,
fontSize,
)
// TODO theme based
primaryColor := "rgb(13, 50, 178)"
accentColor := "rgb(74, 111, 243)"
neutralColor := "rgb(103, 108, 126)"
return strings.Join([]string{
fmt.Sprintf(`<text class="text" x="%f" y="%f" style="%s">%s</text>`,
nameTL.X,
nameTL.Y+fontSize*3/4,
fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "start", fontSize, primaryColor),
escapeText(nameText),
),
// TODO light font
fmt.Sprintf(`<text class="text" x="%f" y="%f" style="%s">%s</text>`,
nameTL.X+longestNameWidth,
nameTL.Y+fontSize*3/4,
fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "start", fontSize, neutralColor),
escapeText(typeText),
),
fmt.Sprintf(`<text class="text" x="%f" y="%f" style="%s">%s</text>`,
constraintTR.X,
constraintTR.Y+fontSize*3/4,
fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s;letter-spacing:2px;", "end", fontSize, accentColor),
constraintText,
),
}, "\n")
}
func constraintAbbr(constraint string) string {
switch constraint {
case "primary_key":
return "PK"
case "foreign_key":
return "FK"
case "unique":
return "UNQ"
default:
return ""
}
}
func drawTable(writer io.Writer, targetShape d2target.Shape) {
fmt.Fprintf(writer, `<rect class="shape" x="%d" y="%d" width="%d" height="%d" style="%s"/>`,
targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, shapeStyle(targetShape))
box := geo.NewBox(
geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y)),
float64(targetShape.Width),
float64(targetShape.Height),
)
rowHeight := box.Height / float64(1+len(targetShape.SQLTable.Columns))
headerBox := geo.NewBox(box.TopLeft, box.Width, rowHeight)
fmt.Fprint(writer,
tableHeader(headerBox, targetShape.Label, float64(targetShape.LabelWidth), float64(targetShape.LabelHeight), float64(targetShape.FontSize)),
)
fontSize := float64(targetShape.FontSize)
var longestNameWidth float64
for _, f := range targetShape.SQLTable.Columns {
// TODO measure text
longestNameWidth = math.Max(longestNameWidth, float64(len(f.Name))*fontSize*5/9)
}
rowBox := geo.NewBox(box.TopLeft.Copy(), box.Width, rowHeight)
rowBox.TopLeft.Y += headerBox.Height
for _, f := range targetShape.SQLTable.Columns {
fmt.Fprint(writer,
tableRow(rowBox, f.Name, f.Type, constraintAbbr(f.Constraint), fontSize, longestNameWidth),
)
rowBox.TopLeft.Y += rowHeight
fmt.Fprintf(writer, `<line x1="%f" y1="%f" x2="%f" y2="%f" style="stroke-width:2;stroke:#0a0f25" />`,
rowBox.TopLeft.X, rowBox.TopLeft.Y,
rowBox.TopLeft.X+rowBox.Width, rowBox.TopLeft.Y,
)
}
}