From 5d089bc557813a5624e6d3e6bac6c9e9777bd0ff Mon Sep 17 00:00:00 2001 From: Shubham Patel <165564832+shubham0x13@users.noreply.github.com> Date: Thu, 5 Jun 2025 10:49:05 +0530 Subject: [PATCH 1/3] Add anchor method --- adafruit_displayio_layout/layouts/__init__.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/adafruit_displayio_layout/layouts/__init__.py b/adafruit_displayio_layout/layouts/__init__.py index e69de29..7d9f684 100644 --- a/adafruit_displayio_layout/layouts/__init__.py +++ b/adafruit_displayio_layout/layouts/__init__.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2025 Shubham Patel +# +# SPDX-License-Identifier: MIT + +from micropython import const + +try: + from typing import Tuple +except ImportError: + pass + +# Anchor point constants for anchor method. +ANCHOR_TOP_LEFT = const((0.0, 0.0)) +ANCHOR_TOP_CENTER = const((0.5, 0.0)) +ANCHOR_TOP_RIGHT = const((1.0, 0.0)) +ANCHOR_CENTER_LEFT = const((0.0, 0.5)) +ANCHOR_CENTER = const((0.5, 0.5)) +ANCHOR_CENTER_RIGHT = const((1.0, 0.5)) +ANCHOR_BOTTOM_LEFT = const((0.0, 1.0)) +ANCHOR_BOTTOM_CENTER = const((0.5, 1.0)) +ANCHOR_BOTTOM_RIGHT = const((1.0, 1.0)) + + +def anchor(obj, anchor: Tuple[float, float], width: int, height: int) -> None: + """Helper to position a display object on screen using a defined anchor point. + + Sets `anchor_point` and `anchored_position` for display elements such as `Label`, + `Widget`, `AnchoredTileGrid`, or `AnchoredGroup`. + + :param obj: The object to be positioned. Must support `anchor_point` and `anchored_position`. + :param anchor: One of the predefined anchor constants (e.g. ANCHOR_TOP_LEFT, ANCHOR_CENTER) + :param width: Width of the display in pixels + :param height: Height of the display in pixels + """ + if not hasattr(obj, "anchor_point") or not hasattr(obj, "anchored_position"): + raise AttributeError( + "Object must have both `anchor_point` and `anchored_position` attributes." + ) + + if anchor not in { + ANCHOR_TOP_LEFT, + ANCHOR_TOP_CENTER, + ANCHOR_TOP_RIGHT, + ANCHOR_CENTER_LEFT, + ANCHOR_CENTER, + ANCHOR_CENTER_RIGHT, + ANCHOR_BOTTOM_LEFT, + ANCHOR_BOTTOM_CENTER, + ANCHOR_BOTTOM_RIGHT, + }: + raise ValueError( + "Anchor must be one of: ANCHOR_TOP_LEFT, ANCHOR_TOP_CENTER, ANCHOR_TOP_RIGHT,\n" + "ANCHOR_CENTER_LEFT, ANCHOR_CENTER, ANCHOR_CENTER_RIGHT,\n" + "ANCHOR_BOTTOM_LEFT, ANCHOR_BOTTOM_CENTER, ANCHOR_BOTTOM_RIGHT." + ) + + obj.anchor_point = anchor + obj.anchored_position = ( + int(anchor[0] * width), + int(anchor[1] * height), + ) From cfb3f13e9fffb3e2c28a04eb633f2f53608750f3 Mon Sep 17 00:00:00 2001 From: Shubham Patel <165564832+shubham0x13@users.noreply.github.com> Date: Thu, 5 Jun 2025 11:16:35 +0530 Subject: [PATCH 2/3] Add bounds check in add_content --- adafruit_displayio_layout/layouts/grid_layout.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index 957cb91..15cfd09 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -378,6 +378,15 @@ def add_content( then the cell_anchor_point from the GridLayout will be used. :return: None""" + grid_x = grid_position[0] + grid_y = grid_position[1] + max_grid_x = self.grid_size[0] + max_grid_y = self.grid_size[1] + if grid_x >= max_grid_x or grid_y >= max_grid_y: + raise ValueError( + f"Grid position {grid_position} is out of bounds for grid size {self.grid_size}" + ) + if cell_anchor_point: _this_cell_anchor_point = cell_anchor_point else: From 74411706db2f863ced498925409b4060a99492c2 Mon Sep 17 00:00:00 2001 From: Shubham Patel <165564832+shubham0x13@users.noreply.github.com> Date: Thu, 5 Jun 2025 11:23:46 +0530 Subject: [PATCH 3/3] Simplify grid bounds unpacking --- adafruit_displayio_layout/layouts/grid_layout.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index 15cfd09..b57bd16 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -378,10 +378,8 @@ def add_content( then the cell_anchor_point from the GridLayout will be used. :return: None""" - grid_x = grid_position[0] - grid_y = grid_position[1] - max_grid_x = self.grid_size[0] - max_grid_y = self.grid_size[1] + grid_x, grid_y = grid_position + max_grid_x, max_grid_y = self.grid_size if grid_x >= max_grid_x or grid_y >= max_grid_y: raise ValueError( f"Grid position {grid_position} is out of bounds for grid size {self.grid_size}"