22
22
https://github.com/adafruit/circuitpython/releases
23
23
24
24
"""
25
-
25
+ import math
26
26
import displayio
27
27
28
28
__version__ = "0.0.0-auto.0"
29
29
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git"
30
30
31
31
32
32
class GridLayout (displayio .Group ):
33
-
34
33
"""
35
34
A layout that organizes children into a grid table structure.
36
35
@@ -40,10 +39,27 @@ class GridLayout(displayio.Group):
40
39
:param int height: Height of the layout in pixels.
41
40
:param tuple grid_size: Size in cells as two ints in a tuple e.g. (2, 2)
42
41
: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.
43
+ :param Union[tuple, list] h_divider_line_rows: Row indexes to draw divider
44
+ lines above. Row indexes are 0 based.
45
+ :param Union[tuple, list] v_divider_line_cols: Column indexes to draw divider
46
+ lines before. Column indexes are 0 based.
47
+
43
48
"""
44
49
45
50
# pylint: disable=too-many-arguments
46
- def __init__ (self , x , y , width , height , grid_size , cell_padding ):
51
+ def __init__ (
52
+ self ,
53
+ x ,
54
+ y ,
55
+ width ,
56
+ height ,
57
+ grid_size ,
58
+ cell_padding = 0 ,
59
+ divider_lines = False ,
60
+ h_divider_line_rows = None ,
61
+ v_divider_line_cols = None ,
62
+ ):
47
63
super ().__init__ (x = x , y = y )
48
64
self .x = x
49
65
self .y = y
@@ -53,8 +69,39 @@ def __init__(self, x, y, width, height, grid_size, cell_padding):
53
69
self .cell_padding = cell_padding
54
70
self ._cell_content_list = []
55
71
56
- def _layout_cells (self ):
72
+ self ._divider_lines = []
73
+ self .h_divider_line_rows = h_divider_line_rows
74
+ self .v_divider_line_cols = v_divider_line_cols
75
+
76
+ self ._divider_lines_enabled = (
77
+ (divider_lines is True )
78
+ or (h_divider_line_rows is not None )
79
+ or (v_divider_line_cols is not None )
80
+ )
81
+
82
+ if divider_lines :
83
+ if self .h_divider_line_rows is None :
84
+ self .h_divider_line_rows = []
85
+ for _y in range (self .grid_size [1 ] + 1 ):
86
+ self .h_divider_line_rows .append (_y )
87
+ if self .v_divider_line_cols is None :
88
+ self .v_divider_line_cols = []
89
+ for _x in range (self .grid_size [0 ] + 1 ):
90
+ self .v_divider_line_cols .append (_x )
91
+ else :
92
+ if not h_divider_line_rows :
93
+ self .h_divider_line_rows = tuple ()
94
+ if not v_divider_line_cols :
95
+ self .v_divider_line_cols = tuple ()
57
96
97
+ # use at least 1 padding so that content is inside the divider lines
98
+ if cell_padding == 0 and (
99
+ divider_lines or h_divider_line_rows or v_divider_line_cols
100
+ ):
101
+ self .cell_padding = 1
102
+
103
+ def _layout_cells (self ):
104
+ # pylint: disable=too-many-locals, too-many-branches, too-many-statements
58
105
for cell in self ._cell_content_list :
59
106
if cell ["content" ] not in self :
60
107
grid_size_x = self .grid_size [0 ]
@@ -66,44 +113,180 @@ def _layout_cells(self):
66
113
button_size_x = cell ["cell_size" ][0 ]
67
114
button_size_y = cell ["cell_size" ][1 ]
68
115
116
+ _measured_width = (
117
+ math .ceil (button_size_x * self ._width / grid_size_x )
118
+ - 2 * self .cell_padding
119
+ )
120
+
121
+ _measured_height = (
122
+ math .ceil (button_size_y * self ._height / grid_size_y )
123
+ - 2 * self .cell_padding
124
+ )
69
125
if hasattr (cell ["content" ], "resize" ):
70
126
# if it has resize function
71
127
cell ["content" ].resize (
72
- (
73
- int (button_size_x * self ._width / grid_size_x )
74
- - 2 * self .cell_padding
75
- ),
76
- (
77
- int (button_size_y * self ._height / grid_size_y )
78
- - 2 * self .cell_padding
79
- ),
128
+ _measured_width ,
129
+ _measured_height ,
80
130
)
81
131
else :
82
132
try :
83
133
# try width and height properties.
84
- cell ["content" ].width = (
85
- int (button_size_x * self ._width / grid_size_x )
86
- - 2 * self .cell_padding
87
- )
88
- cell ["content" ].height = (
89
- int (button_size_y * self ._height / grid_size_y )
90
- - 2 * self .cell_padding
91
- )
134
+ cell ["content" ].width = _measured_width
135
+ cell ["content" ].height = _measured_height
92
136
except AttributeError :
93
137
# This element does not allow setting width and height.
94
138
# No problem, we'll use whatever size it already is.
139
+ # _measured_width = cell["content"].width
140
+ # _measured_height = cell["content"].height
141
+
95
142
pass
96
143
97
- cell ["content" ].x = (
98
- int (grid_position_x * self ._width / grid_size_x ) + self .cell_padding
99
- )
100
- cell ["content" ].y = (
101
- int (grid_position_y * self ._height / grid_size_y )
102
- + self .cell_padding
103
- )
144
+ if not hasattr (cell ["content" ], "anchor_point" ):
145
+
146
+ cell ["content" ].x = (
147
+ int (grid_position_x * self ._width / grid_size_x )
148
+ + self .cell_padding
149
+ )
150
+ cell ["content" ].y = (
151
+ int (grid_position_y * self ._height / grid_size_y )
152
+ + self .cell_padding
153
+ )
154
+ else :
155
+ cell ["content" ].anchor_point = (0 , 0 )
156
+ cell ["content" ].anchored_position = (
157
+ int (grid_position_x * self ._width / grid_size_x )
158
+ + self .cell_padding ,
159
+ int (grid_position_y * self ._height / grid_size_y )
160
+ + self .cell_padding ,
161
+ )
104
162
105
163
self .append (cell ["content" ])
106
164
165
+ if self ._divider_lines_enabled :
166
+ palette = displayio .Palette (2 )
167
+ palette [0 ] = 0xFFFFFF
168
+ palette [1 ] = 0xFFFFFF
169
+
170
+ if not hasattr (cell ["content" ], "anchor_point" ):
171
+ _bottom_line_loc_y = (
172
+ cell ["content" ].y + _measured_height + self .cell_padding
173
+ ) - 1
174
+ _bottom_line_loc_x = cell ["content" ].x - self .cell_padding
175
+
176
+ _top_line_loc_y = cell ["content" ].y - self .cell_padding
177
+ _top_line_loc_x = cell ["content" ].x - self .cell_padding
178
+
179
+ _right_line_loc_y = cell ["content" ].y - self .cell_padding
180
+ _right_line_loc_x = (
181
+ cell ["content" ].x + _measured_width + self .cell_padding
182
+ ) - 1
183
+ else :
184
+ _bottom_line_loc_y = (
185
+ cell ["content" ].anchored_position [1 ]
186
+ + _measured_height
187
+ + self .cell_padding
188
+ ) - 1
189
+ _bottom_line_loc_x = (
190
+ cell ["content" ].anchored_position [0 ] - self .cell_padding
191
+ )
192
+
193
+ _top_line_loc_y = (
194
+ cell ["content" ].anchored_position [1 ] - self .cell_padding
195
+ )
196
+ _top_line_loc_x = (
197
+ cell ["content" ].anchored_position [0 ] - self .cell_padding
198
+ )
199
+
200
+ _right_line_loc_y = (
201
+ cell ["content" ].anchored_position [1 ] - self .cell_padding
202
+ )
203
+ _right_line_loc_x = (
204
+ cell ["content" ].anchored_position [0 ]
205
+ + _measured_width
206
+ + self .cell_padding
207
+ ) - 1
208
+
209
+ _horizontal_divider_line = displayio .Shape (
210
+ _measured_width + (2 * self .cell_padding ),
211
+ 1 ,
212
+ mirror_x = False ,
213
+ mirror_y = False ,
214
+ )
215
+
216
+ _bottom_divider_tilegrid = displayio .TileGrid (
217
+ _horizontal_divider_line ,
218
+ pixel_shader = palette ,
219
+ y = _bottom_line_loc_y ,
220
+ x = _bottom_line_loc_x ,
221
+ )
222
+
223
+ _top_divider_tilegrid = displayio .TileGrid (
224
+ _horizontal_divider_line ,
225
+ pixel_shader = palette ,
226
+ y = _top_line_loc_y ,
227
+ x = _top_line_loc_x ,
228
+ )
229
+
230
+ _vertical_divider_line = displayio .Shape (
231
+ 1 ,
232
+ _measured_height + (2 * self .cell_padding ),
233
+ mirror_x = False ,
234
+ mirror_y = False ,
235
+ )
236
+
237
+ _left_divider_tilegrid = displayio .TileGrid (
238
+ _vertical_divider_line ,
239
+ pixel_shader = palette ,
240
+ y = _top_line_loc_y ,
241
+ x = _top_line_loc_x ,
242
+ )
243
+
244
+ _right_divider_tilegrid = displayio .TileGrid (
245
+ _vertical_divider_line ,
246
+ pixel_shader = palette ,
247
+ y = _right_line_loc_y ,
248
+ x = _right_line_loc_x ,
249
+ )
250
+
251
+ for line_obj in self ._divider_lines :
252
+ self .remove (line_obj ["tilegrid" ])
253
+
254
+ if grid_position_y == grid_size_y - 1 and (
255
+ grid_position_y + 1 in self .h_divider_line_rows
256
+ ):
257
+ self ._divider_lines .append (
258
+ {
259
+ "shape" : _horizontal_divider_line ,
260
+ "tilegrid" : _bottom_divider_tilegrid ,
261
+ }
262
+ )
263
+ if grid_position_y in self .h_divider_line_rows :
264
+ self ._divider_lines .append (
265
+ {
266
+ "shape" : _horizontal_divider_line ,
267
+ "tilegrid" : _top_divider_tilegrid ,
268
+ }
269
+ )
270
+ if grid_position_x in self .v_divider_line_cols :
271
+ self ._divider_lines .append (
272
+ {
273
+ "shape" : _horizontal_divider_line ,
274
+ "tilegrid" : _left_divider_tilegrid ,
275
+ }
276
+ )
277
+ if grid_position_x == grid_size_x - 1 and (
278
+ grid_position_x + 1 in self .v_divider_line_cols
279
+ ):
280
+ self ._divider_lines .append (
281
+ {
282
+ "shape" : _vertical_divider_line ,
283
+ "tilegrid" : _right_divider_tilegrid ,
284
+ }
285
+ )
286
+
287
+ for line_obj in self ._divider_lines :
288
+ self .append (line_obj ["tilegrid" ])
289
+
107
290
def add_content (self , cell_content , grid_position , cell_size ):
108
291
"""Add a child to the grid.
109
292
0 commit comments