@@ -111,8 +111,14 @@ def __init__(
111111 ):
112112 self .cell_padding = 1
113113
114+ def layout_cells (self ):
115+ """render the grid with all cell content and dividers"""
116+ self ._layout_cells ()
117+
114118 def _layout_cells (self ) -> None :
115119 # pylint: disable=too-many-locals, too-many-branches, too-many-statements
120+ for line_obj in self ._divider_lines :
121+ self .remove (line_obj ["rect" ])
116122 for cell in self ._cell_content_list :
117123 if cell ["content" ] not in self :
118124 grid_size_x = self .grid_size [0 ]
@@ -297,9 +303,6 @@ def _layout_cells(self) -> None:
297303 x = _right_line_loc_x ,
298304 )
299305
300- for line_obj in self ._divider_lines :
301- self .remove (line_obj ["rect" ])
302-
303306 """
304307 Only use bottom divider lines on the bottom row. All
305308 other rows rely on top divder lines of the row beneath them.
@@ -359,15 +362,16 @@ def _layout_cells(self) -> None:
359362 }
360363 )
361364
362- for line_obj in self ._divider_lines :
363- self .append (line_obj ["rect" ])
365+ for line_obj in self ._divider_lines :
366+ self .append (line_obj ["rect" ])
364367
365368 def add_content (
366369 self ,
367370 cell_content : displayio .Group ,
368371 grid_position : Tuple [int , int ],
369372 cell_size : Tuple [int , int ],
370373 cell_anchor_point : Optional [Tuple [float , ...]] = None ,
374+ layout_cells = True ,
371375 ) -> None :
372376 """Add a child to the grid.
373377
@@ -395,7 +399,8 @@ def add_content(
395399 "cell_size" : cell_size ,
396400 }
397401 self ._cell_content_list .append (sub_view_obj )
398- self ._layout_cells ()
402+ if layout_cells :
403+ self ._layout_cells ()
399404
400405 def get_cell (self , cell_coordinates : Tuple [int , int ]) -> displayio .Group :
401406 """
@@ -406,9 +411,21 @@ def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group:
406411 :return: the displayio content object at those coordinates
407412 """
408413 for index , cell in enumerate (self ._cell_content_list ):
414+ # exact location 1x1 cell
409415 if cell ["grid_position" ] == cell_coordinates :
410416 return self ._cell_content_list [index ]["content" ]
411417
418+ # multi-spanning cell, any size bigger than 1x1
419+ if (
420+ cell ["grid_position" ][0 ]
421+ <= cell_coordinates [0 ]
422+ < cell ["grid_position" ][0 ] + cell ["cell_size" ][0 ]
423+ and cell ["grid_position" ][1 ]
424+ <= cell_coordinates [1 ]
425+ < cell ["grid_position" ][1 ] + cell ["cell_size" ][1 ]
426+ ):
427+ return self ._cell_content_list [index ]["content" ]
428+
412429 raise KeyError (
413430 "GridLayout does not contain cell at coordinates {}" .format (
414431 cell_coordinates
@@ -425,3 +442,40 @@ def cell_size_pixels(self) -> Tuple[int, int]:
425442 pixels of a 1x1 cell in the GridLayout
426443 """
427444 return (self ._width // self .grid_size [0 ], self ._height // self .grid_size [1 ])
445+
446+ @property
447+ def width (self ) -> int :
448+ """
449+ The width in pixels of the GridLayout.
450+ """
451+ return self ._width
452+
453+ @property
454+ def height (self ) -> int :
455+ """
456+ The height in pixels of the GridLayout.
457+ """
458+ return self ._height
459+
460+ def which_cell_contains (
461+ self , pixel_location : Union [Tuple [int , int ], List [int ]]
462+ ) -> Optional [tuple ]:
463+ """
464+ Given a pixel x,y coordinate returns the location of the cell
465+ that contains the coordinate.
466+
467+ :param pixel_location: x,y pixel coordinate as a tuple or list
468+ :returns: cell coordinates x,y tuple or None if the pixel coordinates are
469+ outside the bounds of the GridLayout
470+ """
471+ cell_size = self .cell_size_pixels
472+ if (
473+ not self .x <= pixel_location [0 ] < self .x + self .width
474+ or not self .y <= pixel_location [1 ] < self .y + self .height
475+ ):
476+ return None
477+
478+ cell_x_coord = (pixel_location [0 ] - self .x ) // cell_size [0 ]
479+ cell_y_coord = (pixel_location [1 ] - self .y ) // cell_size [1 ]
480+
481+ return cell_x_coord , cell_y_coord
0 commit comments