-
Notifications
You must be signed in to change notification settings - Fork 6
/
grid_layout.go
121 lines (105 loc) · 2.88 KB
/
grid_layout.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
package control
import "github.com/goradd/html5tag"
// LayoutDirection controls whether items are layed out in rows or columns.
type LayoutDirection int
const (
// LayoutRow lays out items in rows
LayoutRow LayoutDirection = iota
// LayoutColumn lays out items in columns, computing the number of rows required to make the specified number of columns.
LayoutColumn
)
// GridLayoutBuilder is a helper that will allow a slice of items to be layed out in a table like
// pattern. It will compute the number of rows required, and then wrap the rows in
// row html, and the cells in cell html. You can have the items flow with the rows, or flow
// across the row axis. You can use this to build a table or a table-like structure.
//
// This is largely obsoleted by CSS Grid.
type GridLayoutBuilder struct {
items []string
columnCount int
direction LayoutDirection
rowTag string
rowAttributes html5tag.Attributes
}
// Items sets the html for each item to display.
func (g *GridLayoutBuilder) Items(items []string) *GridLayoutBuilder {
g.items = items
return g
}
// ColumnCount sets the number of columns.
func (g *GridLayoutBuilder) ColumnCount(count int) *GridLayoutBuilder {
g.columnCount = count
return g
}
// LayoutDirection indicates how items are placed, whether they should fill up rows first, or fill up columns.
func (g *GridLayoutBuilder) Direction(placement LayoutDirection) *GridLayoutBuilder {
g.direction = placement
return g
}
func (g *GridLayoutBuilder) RowTag(t string) *GridLayoutBuilder {
g.rowTag = t
return g
}
func (g *GridLayoutBuilder) RowClass(t string) *GridLayoutBuilder {
g.getRowAttributes().SetClass(t)
return g
}
func (g *GridLayoutBuilder) getRowAttributes() html5tag.Attributes {
if g.rowAttributes == nil {
g.rowAttributes = html5tag.NewAttributes()
}
return g.rowAttributes
}
func (g *GridLayoutBuilder) Build() string {
if len(g.items) == 0 {
return ""
}
if g.rowTag == "" {
g.rowTag = "div"
}
if g.columnCount == 0 {
g.columnCount = 1
}
if g.direction == LayoutRow {
return g.wrapRows()
} else {
return g.wrapColumns()
}
}
func (g *GridLayoutBuilder) wrapRows() string {
var rows string
var row string
for i := range g.items {
row += g.items[i]
if (i+1)%g.columnCount == 0 {
rows += html5tag.RenderTag(g.rowTag, g.rowAttributes, row)
row = ""
}
}
if row != "" {
// partial row
rows += html5tag.RenderTag(g.rowTag, g.rowAttributes, row)
}
return rows
}
func (g *GridLayoutBuilder) wrapColumns() string {
l := len(g.items)
rowCount := (l-1)/g.columnCount + 1
var row string
var rows string
for r := 0; r < rowCount; r++ {
for c := 0; c < g.columnCount; c++ {
i := c*rowCount + r
if i < l {
row += g.items[i]
}
}
rows += html5tag.RenderTag(g.rowTag, g.rowAttributes, row)
row = ""
}
if row != "" {
// partial row
rows += html5tag.RenderTag(g.rowTag, g.rowAttributes, row)
}
return rows
}