Skip to content

Commit 16cd97d

Browse files
committed
configurable divider lines on GridLayout
1 parent 813b843 commit 16cd97d

File tree

3 files changed

+236
-49
lines changed

3 files changed

+236
-49
lines changed

adafruit_displayio_layout/layouts/grid_layout.py

Lines changed: 140 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,27 @@ class GridLayout(displayio.Group):
3939
:param int height: Height of the layout in pixels.
4040
:param tuple grid_size: Size in cells as two ints in a tuple e.g. (2, 2)
4141
:param int cell_padding: Extra padding space inside each cell. In pixels.
42-
:param bool divider_lines: Whether or not to draw lines between the cells.
42+
:param bool divider_lines: Whether or not to draw lines between the cells. Defaults to False.
43+
:param tuple h_divider_line_rows: Row indexes to draw divider lines above.
44+
Row indexes are 0 based.
45+
:param tuple v_divider_line_cols: Column indexes to draw divider lines before.
46+
Column indexes are 0 based.
47+
4348
"""
4449

4550
# pylint: disable=too-many-arguments
46-
def __init__(self, x, y, width, height, grid_size, cell_padding, divider_lines):
51+
def __init__(
52+
self,
53+
x,
54+
y,
55+
width,
56+
height,
57+
grid_size,
58+
cell_padding,
59+
divider_lines=False,
60+
h_divider_line_rows=None,
61+
v_divider_line_cols=None,
62+
):
4763
super().__init__(x=x, y=y)
4864
self.x = x
4965
self.y = y
@@ -54,9 +70,11 @@ def __init__(self, x, y, width, height, grid_size, cell_padding, divider_lines):
5470
self._cell_content_list = []
5571
self._divider_lines_enabled = divider_lines
5672
self._divider_lines = []
73+
self.h_divider_line_rows = h_divider_line_rows
74+
self.v_divider_line_cols = v_divider_line_cols
5775

5876
def _layout_cells(self):
59-
77+
# pylint: disable=too-many-locals, too-many-branches, too-many-statements
6078
for cell in self._cell_content_list:
6179
if cell["content"] not in self:
6280
grid_size_x = self.grid_size[0]
@@ -69,13 +87,13 @@ def _layout_cells(self):
6987
button_size_y = cell["cell_size"][1]
7088

7189
_measured_width = (
72-
int(button_size_x * self._width / grid_size_x)
73-
- 2 * self.cell_padding
90+
int(button_size_x * self._width / grid_size_x)
91+
- 2 * self.cell_padding
7492
)
7593

7694
_measured_height = (
77-
int(button_size_y * self._height / grid_size_y)
78-
- 2 * self.cell_padding
95+
int(button_size_y * self._height / grid_size_y)
96+
- 2 * self.cell_padding
7997
)
8098
if hasattr(cell["content"], "resize"):
8199
# if it has resize function
@@ -99,20 +117,35 @@ def _layout_cells(self):
99117
if not hasattr(cell["content"], "anchor_point"):
100118

101119
cell["content"].x = (
102-
int(grid_position_x * self._width / grid_size_x) + self.cell_padding
120+
int(grid_position_x * self._width / grid_size_x)
121+
+ self.cell_padding
103122
)
104123
cell["content"].y = (
105-
int(grid_position_y * self._height / grid_size_y) + self.cell_padding
124+
int(grid_position_y * self._height / grid_size_y)
125+
+ self.cell_padding
106126
)
107127
else:
108-
print("int({} * {} / {}) + {}".format(grid_position_x, self._width, grid_size_x, self.cell_padding))
109128
print(
110-
"int({} * {} / {}) + {}".format(grid_position_y, self._height, grid_size_y, self.cell_padding))
129+
"int({} * {} / {}) + {}".format(
130+
grid_position_x, self._width, grid_size_x, self.cell_padding
131+
)
132+
)
133+
print(
134+
"int({} * {} / {}) + {}".format(
135+
grid_position_y,
136+
self._height,
137+
grid_size_y,
138+
self.cell_padding,
139+
)
140+
)
111141

112142
cell["content"].anchor_point = (0, 0)
113143
cell["content"].anchored_position = (
114-
int(grid_position_x * self._width / grid_size_x) + self.cell_padding,
115-
int(grid_position_y * self._height / grid_size_y) + self.cell_padding)
144+
int(grid_position_x * self._width / grid_size_x)
145+
+ self.cell_padding,
146+
int(grid_position_y * self._height / grid_size_y)
147+
+ self.cell_padding,
148+
)
116149
print(cell["content"].anchored_position)
117150
print("---")
118151

@@ -124,73 +157,131 @@ def _layout_cells(self):
124157
palette[1] = 0xFFFFFF
125158

126159
if not hasattr(cell["content"], "anchor_point"):
127-
_bottom_line_loc_y = cell["content"].y + _measured_height + self.cell_padding
160+
_bottom_line_loc_y = (
161+
cell["content"].y + _measured_height + self.cell_padding
162+
)
128163
_bottom_line_loc_x = cell["content"].x - self.cell_padding
129164

130165
_top_line_loc_y = cell["content"].y - self.cell_padding
131166
_top_line_loc_x = cell["content"].x - self.cell_padding
132167

133168
_right_line_loc_y = cell["content"].y - self.cell_padding
134-
_right_line_loc_x = cell["content"].x + _measured_width + self.cell_padding
169+
_right_line_loc_x = (
170+
cell["content"].x + _measured_width + self.cell_padding
171+
)
135172
else:
136-
_bottom_line_loc_y = cell["content"].anchored_position[1] + _measured_height + self.cell_padding
137-
_bottom_line_loc_x = cell["content"].anchored_position[0] - self.cell_padding
138-
139-
_top_line_loc_y = cell["content"].anchored_position[1] - self.cell_padding
140-
_top_line_loc_x = cell["content"].anchored_position[0] - self.cell_padding
141-
142-
_right_line_loc_y = cell["content"].anchored_position[1] - self.cell_padding
143-
_right_line_loc_x = cell["content"].anchored_position[0] + _measured_width + self.cell_padding
173+
_bottom_line_loc_y = (
174+
cell["content"].anchored_position[1]
175+
+ _measured_height
176+
+ self.cell_padding
177+
)
178+
_bottom_line_loc_x = (
179+
cell["content"].anchored_position[0] - self.cell_padding
180+
)
181+
182+
_top_line_loc_y = (
183+
cell["content"].anchored_position[1] - self.cell_padding
184+
)
185+
_top_line_loc_x = (
186+
cell["content"].anchored_position[0] - self.cell_padding
187+
)
188+
189+
_right_line_loc_y = (
190+
cell["content"].anchored_position[1] - self.cell_padding
191+
)
192+
_right_line_loc_x = (
193+
cell["content"].anchored_position[0]
194+
+ _measured_width
195+
+ self.cell_padding
196+
)
144197

145198
_horizontal_divider_line = displayio.Shape(
146199
_measured_width + (2 * self.cell_padding),
147200
1,
148-
mirror_x=False, mirror_y=False)
201+
mirror_x=False,
202+
mirror_y=False,
203+
)
149204

150205
_bottom_divider_tilegrid = displayio.TileGrid(
151-
_horizontal_divider_line, pixel_shader=palette,
206+
_horizontal_divider_line,
207+
pixel_shader=palette,
152208
y=_bottom_line_loc_y,
153-
x=_bottom_line_loc_x)
209+
x=_bottom_line_loc_x,
210+
)
154211

155212
_top_divider_tilegrid = displayio.TileGrid(
156-
_horizontal_divider_line, pixel_shader=palette,
213+
_horizontal_divider_line,
214+
pixel_shader=palette,
157215
y=_top_line_loc_y,
158-
x=_top_line_loc_x)
216+
x=_top_line_loc_x,
217+
)
159218

160219
_vertical_divider_line = displayio.Shape(
161220
1,
162221
_measured_height + (2 * self.cell_padding),
163-
mirror_x=False, mirror_y=False)
222+
mirror_x=False,
223+
mirror_y=False,
224+
)
164225

165226
_left_divider_tilegrid = displayio.TileGrid(
166-
_vertical_divider_line, pixel_shader=palette,
227+
_vertical_divider_line,
228+
pixel_shader=palette,
167229
y=_top_line_loc_y,
168-
x=_top_line_loc_x)
230+
x=_top_line_loc_x,
231+
)
169232

170233
_right_divider_tilegrid = displayio.TileGrid(
171-
_vertical_divider_line, pixel_shader=palette,
234+
_vertical_divider_line,
235+
pixel_shader=palette,
172236
y=_right_line_loc_y,
173-
x=_right_line_loc_x)
237+
x=_right_line_loc_x,
238+
)
174239

175240
for line_obj in self._divider_lines:
176241
self.remove(line_obj["tilegrid"])
177242

178-
self._divider_lines.append({
179-
"shape": _horizontal_divider_line,
180-
"tilegrid": _bottom_divider_tilegrid
181-
})
182-
self._divider_lines.append({
183-
"shape": _horizontal_divider_line,
184-
"tilegrid": _top_divider_tilegrid
185-
})
186-
self._divider_lines.append({
187-
"shape": _horizontal_divider_line,
188-
"tilegrid": _left_divider_tilegrid
189-
})
190-
self._divider_lines.append({
191-
"shape": _vertical_divider_line,
192-
"tilegrid": _right_divider_tilegrid
193-
})
243+
print("pos_y: {} - size_y: {}".format(grid_position_y, grid_size_y))
244+
print(grid_position_y == grid_size_y)
245+
if grid_position_y == grid_size_y - 1 and (
246+
self.h_divider_line_rows is None
247+
or grid_position_y + 1 in self.h_divider_line_rows
248+
):
249+
self._divider_lines.append(
250+
{
251+
"shape": _horizontal_divider_line,
252+
"tilegrid": _bottom_divider_tilegrid,
253+
}
254+
)
255+
if (
256+
self.h_divider_line_rows is None
257+
or grid_position_y in self.h_divider_line_rows
258+
):
259+
self._divider_lines.append(
260+
{
261+
"shape": _horizontal_divider_line,
262+
"tilegrid": _top_divider_tilegrid,
263+
}
264+
)
265+
if (
266+
self.v_divider_line_cols is None
267+
or grid_position_x in self.v_divider_line_cols
268+
):
269+
self._divider_lines.append(
270+
{
271+
"shape": _horizontal_divider_line,
272+
"tilegrid": _left_divider_tilegrid,
273+
}
274+
)
275+
if grid_position_x == grid_size_x - 1 and (
276+
self.v_divider_line_cols is None
277+
or grid_position_x + 1 in self.v_divider_line_cols
278+
):
279+
self._divider_lines.append(
280+
{
281+
"shape": _vertical_divider_line,
282+
"tilegrid": _right_divider_tilegrid,
283+
}
284+
)
194285

195286
for line_obj in self._divider_lines:
196287
self.append(line_obj["tilegrid"])

docs/examples.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ Ensure your device works with this simple test.
77
:caption: examples/displayio_layout_simpletest.py
88
:linenos:
99

10+
GridLayout divider lines example
11+
--------------------------------
12+
13+
Create GridLayouts with divider lines.
14+
15+
.. literalinclude:: ../examples/displayio_layout_gridlayout_dividers.py
16+
:caption: examples/displayio_layout_gridlayout_dividers.py
17+
:linenos:
18+
1019
Pygame simple test
1120
------------------
1221

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# SPDX-FileCopyrightText: 2021 Tim C, written for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
Illustrate how to use divider lines with GridLayout
6+
"""
7+
import board
8+
import displayio
9+
import terminalio
10+
from adafruit_display_text import label
11+
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
12+
13+
# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
14+
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
15+
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
16+
display = board.DISPLAY
17+
18+
# Make the display context
19+
main_group = displayio.Group()
20+
display.show(main_group)
21+
22+
layout = GridLayout(
23+
x=10,
24+
y=10,
25+
width=200,
26+
height=100,
27+
grid_size=(2, 2),
28+
cell_padding=8,
29+
divider_lines=True, # divider lines around every cell
30+
)
31+
_labels = []
32+
33+
_labels.append(
34+
label.Label(
35+
terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077
36+
)
37+
)
38+
layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1))
39+
_labels.append(
40+
label.Label(
41+
terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700
42+
)
43+
)
44+
layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1))
45+
_labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello"))
46+
layout.add_content(_labels[2], grid_position=(0, 1), cell_size=(1, 1))
47+
_labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Grid"))
48+
layout.add_content(_labels[3], grid_position=(1, 1), cell_size=(1, 1))
49+
50+
main_group.append(layout)
51+
52+
other_layout = GridLayout(
53+
x=10,
54+
y=120,
55+
width=140,
56+
height=80,
57+
grid_size=(2, 3),
58+
cell_padding=4,
59+
divider_lines=True,
60+
h_divider_line_rows=(1, 2), # Lines before rows 1 and 2
61+
v_divider_line_cols=(), # No vertical divider lines
62+
)
63+
64+
other_layout.add_content(
65+
label.Label(terminalio.FONT, text="0x0"), grid_position=(0, 0), cell_size=(1, 1)
66+
)
67+
other_layout.add_content(
68+
label.Label(terminalio.FONT, text="0x1"), grid_position=(0, 1), cell_size=(1, 1)
69+
)
70+
other_layout.add_content(
71+
label.Label(terminalio.FONT, text="0x2"), grid_position=(0, 2), cell_size=(1, 1)
72+
)
73+
74+
other_layout.add_content(
75+
label.Label(terminalio.FONT, text="1x0"), grid_position=(1, 0), cell_size=(1, 1)
76+
)
77+
other_layout.add_content(
78+
label.Label(terminalio.FONT, text="1x1"), grid_position=(1, 1), cell_size=(1, 1)
79+
)
80+
other_layout.add_content(
81+
label.Label(terminalio.FONT, text="1x2"), grid_position=(1, 2), cell_size=(1, 1)
82+
)
83+
84+
main_group.append(other_layout)
85+
86+
while True:
87+
pass

0 commit comments

Comments
 (0)