Skip to content

Commit ac2aa1e

Browse files
feat: support for adding borders for multiple sides (#518)
* feat: support for adding borders for multiple sides * feat: add cases for multiple borders * feat: update Full border type string representation --------- Co-authored-by: John Fercher <4752636+johnfercher@users.noreply.github.com>
1 parent 3455352 commit ac2aa1e

File tree

11 files changed

+2949
-2759
lines changed

11 files changed

+2949
-2759
lines changed

docs/assets/examples/cellstyle/v2/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ func GetMaroto() core.Maroto {
8080
BorderType: border.Bottom,
8181
BorderColor: &props.Color{0, 0, 200},
8282
},
83+
{
84+
BackgroundColor: &props.Color{220, 220, 220},
85+
BorderType: border.Left | border.Top,
86+
BorderColor: &props.Color{0, 0, 200},
87+
},
88+
{
89+
BackgroundColor: &props.Color{220, 220, 220},
90+
BorderType: border.Left | border.Right,
91+
BorderColor: &props.Color{0, 0, 200},
92+
},
93+
{
94+
BackgroundColor: &props.Color{220, 220, 220},
95+
BorderType: border.Top | border.Bottom,
96+
BorderColor: &props.Color{0, 0, 200},
97+
},
98+
{
99+
BackgroundColor: &props.Color{220, 220, 220},
100+
BorderType: border.Left | border.Right | border.Top,
101+
BorderColor: &props.Color{0, 0, 200},
102+
},
83103
}
84104

85105
whiteText := props.Text{

internal/providers/gofpdf/cellwriter/cellwriter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (c *cellWriter) Apply(width, height float64, config *entity.Config, prop *p
3636
bd = border.Full
3737
}
3838

39-
c.fpdf.CellFormat(width, height, "", string(bd), 0, "C", false, 0, "")
39+
c.fpdf.CellFormat(width, height, "", bd.String(), 0, "C", false, 0, "")
4040
return
4141
}
4242

@@ -45,5 +45,5 @@ func (c *cellWriter) Apply(width, height float64, config *entity.Config, prop *p
4545
bd = border.Full
4646
}
4747

48-
c.fpdf.CellFormat(width, height, "", string(bd), 0, "C", prop.BackgroundColor != nil, 0, "")
48+
c.fpdf.CellFormat(width, height, "", bd.String(), 0, "C", prop.BackgroundColor != nil, 0, "")
4949
}

internal/providers/gofpdf/cellwriter/cellwriter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestCellWriter_Apply(t *testing.T) {
4747
width := 100.0
4848
height := 200.0
4949
fpdf := mocks.NewFpdf(t)
50-
fpdf.EXPECT().CellFormat(width, height, "", "1", 0, "C", false, 0, "")
50+
fpdf.EXPECT().CellFormat(width, height, "", "LTRB", 0, "C", false, 0, "")
5151

5252
sut := cellwriter.NewCellWriter(fpdf)
5353

@@ -83,7 +83,7 @@ func TestCellWriter_Apply(t *testing.T) {
8383
width := 100.0
8484
height := 200.0
8585
fpdf := mocks.NewFpdf(t)
86-
fpdf.EXPECT().CellFormat(width, height, "", "1", 0, "C", true, 0, "")
86+
fpdf.EXPECT().CellFormat(width, height, "", "LTRB", 0, "C", true, 0, "")
8787

8888
sut := cellwriter.NewCellWriter(fpdf)
8989

pkg/consts/border/border.go

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,64 @@
22
package border
33

44
// Type represents a border type.
5-
type Type string
5+
type Type int
6+
7+
// None is the default border type.
8+
const None Type = 0
69

710
const (
8-
// None is the default border type.
9-
None Type = ""
10-
// Full is a border type that borders all sides.
11-
Full Type = "1"
1211
// Left is a border type that borders the left side.
13-
Left Type = "L"
12+
Left Type = 1 << iota
1413
// Top is a border type that borders the top side.
15-
Top Type = "T"
14+
Top
1615
// Right is a border type that borders the right side.
17-
Right Type = "R"
16+
Right
1817
// Bottom is a border type that borders the bottom side.
19-
Bottom Type = "B"
18+
Bottom
19+
// Full is a border type that borders all sides.
20+
Full = Left | Top | Right | Bottom
2021
)
2122

2223
// IsValid checks if the border type is valid.
2324
func (t Type) IsValid() bool {
24-
return t == Full || t == Left || t == Top || t == Right || t == Bottom
25+
return t > None && t <= Full
26+
}
27+
28+
// HasLeft checks if the border type includes left border.
29+
func (t Type) HasLeft() bool {
30+
return t&Left != 0
31+
}
32+
33+
// HasTop checks if the border type includes top border.
34+
func (t Type) HasTop() bool {
35+
return t&Top != 0
36+
}
37+
38+
// HasRight checks if the border type includes right border.
39+
func (t Type) HasRight() bool {
40+
return t&Right != 0
41+
}
42+
43+
// HasBottom checks if the border type includes bottom border.
44+
func (t Type) HasBottom() bool {
45+
return t&Bottom != 0
46+
}
47+
48+
// String returns the string representation of the border type.
49+
func (t Type) String() string {
50+
result := ""
51+
if t.HasLeft() {
52+
result += "L"
53+
}
54+
if t.HasTop() {
55+
result += "T"
56+
}
57+
if t.HasRight() {
58+
result += "R"
59+
}
60+
if t.HasBottom() {
61+
result += "B"
62+
}
63+
64+
return result
2565
}

pkg/consts/border/border_test.go

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import (
99
)
1010

1111
func TestType_IsValid(t *testing.T) {
12-
t.Run("When type is empty, should not be valid", func(t *testing.T) {
12+
t.Run("When type is None, should not be valid", func(t *testing.T) {
1313
// Arrange
14-
borderType := border.Type("")
14+
borderType := border.None
1515

1616
// Act & Assert
1717
assert.False(t, borderType.IsValid())
@@ -52,3 +52,132 @@ func TestType_IsValid(t *testing.T) {
5252
assert.True(t, borderType.IsValid())
5353
})
5454
}
55+
56+
func TestType_HasBorders(t *testing.T) {
57+
t.Run("When type is None, should not have any border", func(t *testing.T) {
58+
// Arrange
59+
borderType := border.None
60+
61+
// Act & Assert
62+
assert.False(t, borderType.HasLeft())
63+
assert.False(t, borderType.HasTop())
64+
assert.False(t, borderType.HasRight())
65+
assert.False(t, borderType.HasBottom())
66+
})
67+
68+
t.Run("When type is Full, should have all borders", func(t *testing.T) {
69+
// Arrange
70+
borderType := border.Full
71+
72+
// Act & Assert
73+
assert.True(t, borderType.HasLeft())
74+
assert.True(t, borderType.HasTop())
75+
assert.True(t, borderType.HasRight())
76+
assert.True(t, borderType.HasBottom())
77+
})
78+
79+
t.Run("When type is Left, should have only left border", func(t *testing.T) {
80+
// Arrange
81+
borderType := border.Left
82+
83+
// Act & Assert
84+
assert.True(t, borderType.HasLeft())
85+
assert.False(t, borderType.HasTop())
86+
assert.False(t, borderType.HasRight())
87+
assert.False(t, borderType.HasBottom())
88+
})
89+
90+
t.Run("When type is combined (Left|Top), should have left and top borders", func(t *testing.T) {
91+
// Arrange
92+
borderType := border.Left | border.Top
93+
94+
// Act & Assert
95+
assert.True(t, borderType.HasLeft())
96+
assert.True(t, borderType.HasTop())
97+
assert.False(t, borderType.HasRight())
98+
assert.False(t, borderType.HasBottom())
99+
})
100+
101+
t.Run("When type is combined (Left|Right), should have left and right borders", func(t *testing.T) {
102+
// Arrange
103+
borderType := border.Left | border.Right
104+
105+
// Act & Assert
106+
assert.True(t, borderType.HasLeft())
107+
assert.False(t, borderType.HasTop())
108+
assert.True(t, borderType.HasRight())
109+
assert.False(t, borderType.HasBottom())
110+
})
111+
112+
t.Run("When type is combined (Top|Bottom), should have top and bottom borders", func(t *testing.T) {
113+
// Arrange
114+
borderType := border.Top | border.Bottom
115+
116+
// Act & Assert
117+
assert.False(t, borderType.HasLeft())
118+
assert.True(t, borderType.HasTop())
119+
assert.False(t, borderType.HasRight())
120+
assert.True(t, borderType.HasBottom())
121+
})
122+
123+
t.Run("When type is combined (Left|Top|Right), should have left, top and right borders", func(t *testing.T) {
124+
// Arrange
125+
borderType := border.Left | border.Top | border.Right
126+
127+
// Act & Assert
128+
assert.True(t, borderType.HasLeft())
129+
assert.True(t, borderType.HasTop())
130+
assert.True(t, borderType.HasRight())
131+
assert.False(t, borderType.HasBottom())
132+
})
133+
}
134+
135+
func TestType_String(t *testing.T) {
136+
t.Run("When type is None, should return empty string", func(t *testing.T) {
137+
// Arrange
138+
borderType := border.None
139+
140+
// Act & Assert
141+
assert.Equal(t, "", borderType.String())
142+
})
143+
144+
t.Run("When type is Full, should return 'LTRB'", func(t *testing.T) {
145+
// Arrange
146+
borderType := border.Full
147+
148+
// Act & Assert
149+
assert.Equal(t, "LTRB", borderType.String())
150+
})
151+
152+
t.Run("When type is Left, should return 'L'", func(t *testing.T) {
153+
// Arrange
154+
borderType := border.Left
155+
156+
// Act & Assert
157+
assert.Equal(t, "L", borderType.String())
158+
})
159+
160+
t.Run("When type is combined (Left|Top), should return 'LT'", func(t *testing.T) {
161+
// Arrange
162+
borderType := border.Left | border.Top
163+
164+
// Act & Assert
165+
assert.Equal(t, "LT", borderType.String())
166+
})
167+
168+
t.Run("When type is combined (Left|Right), should return 'LR'", func(t *testing.T) {
169+
// Arrange
170+
borderType := border.Left | border.Right
171+
172+
// Act & Assert
173+
assert.Equal(t, "LR", borderType.String())
174+
})
175+
176+
t.Run("When type is combined (Left|Top|Right), should return 'LTR'", func(t *testing.T) {
177+
// Arrange
178+
borderType := border.Left | border.Top | border.Right
179+
180+
// Act & Assert
181+
assert.Equal(t, "LTR", borderType.String())
182+
})
183+
}

pkg/props/cell.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (c *Cell) ToMap() map[string]interface{} {
3333

3434
m := make(map[string]interface{})
3535

36-
if c.BorderType != "" {
36+
if c.BorderType != border.None {
3737
m["prop_border_type"] = c.BorderType
3838
}
3939

test/maroto/components/cols/new_with_props.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"prop_border_color": "RGB(200, 80, 60)",
77
"prop_border_line_style": "dashed",
88
"prop_border_thickness": 0.6,
9-
"prop_border_type": "L"
9+
"prop_border_type": 1
1010
}
1111
}

test/maroto/components/list/build.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"prop_border_color": "RGB(200, 80, 60)",
3636
"prop_border_line_style": "dashed",
3737
"prop_border_thickness": 0.6,
38-
"prop_border_type": "L"
38+
"prop_border_type": 1
3939
},
4040
"nodes": [
4141
{
@@ -94,7 +94,7 @@
9494
"prop_border_color": "RGB(200, 80, 60)",
9595
"prop_border_line_style": "dashed",
9696
"prop_border_thickness": 0.6,
97-
"prop_border_type": "L"
97+
"prop_border_type": 1
9898
},
9999
"nodes": [
100100
{
@@ -153,7 +153,7 @@
153153
"prop_border_color": "RGB(200, 80, 60)",
154154
"prop_border_line_style": "dashed",
155155
"prop_border_thickness": 0.6,
156-
"prop_border_type": "L"
156+
"prop_border_type": 1
157157
},
158158
"nodes": [
159159
{
@@ -212,7 +212,7 @@
212212
"prop_border_color": "RGB(200, 80, 60)",
213213
"prop_border_line_style": "dashed",
214214
"prop_border_thickness": 0.6,
215-
"prop_border_type": "L"
215+
"prop_border_type": 1
216216
},
217217
"nodes": [
218218
{
@@ -271,7 +271,7 @@
271271
"prop_border_color": "RGB(200, 80, 60)",
272272
"prop_border_line_style": "dashed",
273273
"prop_border_thickness": 0.6,
274-
"prop_border_type": "L"
274+
"prop_border_type": 1
275275
},
276276
"nodes": [
277277
{

test/maroto/components/list/build_from_pointer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"prop_border_color": "RGB(200, 80, 60)",
3636
"prop_border_line_style": "dashed",
3737
"prop_border_thickness": 0.6,
38-
"prop_border_type": "L"
38+
"prop_border_type": 1
3939
},
4040
"nodes": [
4141
{
@@ -94,7 +94,7 @@
9494
"prop_border_color": "RGB(200, 80, 60)",
9595
"prop_border_line_style": "dashed",
9696
"prop_border_thickness": 0.6,
97-
"prop_border_type": "L"
97+
"prop_border_type": 1
9898
},
9999
"nodes": [
100100
{
@@ -153,7 +153,7 @@
153153
"prop_border_color": "RGB(200, 80, 60)",
154154
"prop_border_line_style": "dashed",
155155
"prop_border_thickness": 0.6,
156-
"prop_border_type": "L"
156+
"prop_border_type": 1
157157
},
158158
"nodes": [
159159
{
@@ -212,7 +212,7 @@
212212
"prop_border_color": "RGB(200, 80, 60)",
213213
"prop_border_line_style": "dashed",
214214
"prop_border_thickness": 0.6,
215-
"prop_border_type": "L"
215+
"prop_border_type": 1
216216
},
217217
"nodes": [
218218
{
@@ -271,7 +271,7 @@
271271
"prop_border_color": "RGB(200, 80, 60)",
272272
"prop_border_line_style": "dashed",
273273
"prop_border_thickness": 0.6,
274-
"prop_border_type": "L"
274+
"prop_border_type": 1
275275
},
276276
"nodes": [
277277
{

test/maroto/components/rows/new_col_with_prop.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"prop_border_color": "RGB(200, 80, 60)",
77
"prop_border_line_style": "dashed",
88
"prop_border_thickness": 0.6,
9-
"prop_border_type": "L"
9+
"prop_border_type": 1
1010
}
1111
}

0 commit comments

Comments
 (0)