Skip to content

Add annotations #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 56 additions & 40 deletions adafruit_button/button.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries
# SPDX-FileCopyrightText: 2024 Channing Ramos
#
# SPDX-License-Identifier: MIT

Expand All @@ -9,7 +10,7 @@
UI Buttons for displayio


* Author(s): Limor Fried
* Author(s): Limor Fried, Channing Ramos

Implementation Notes
--------------------
Expand All @@ -27,7 +28,7 @@
from adafruit_button.button_base import ButtonBase, _check_color

try:
from typing import Optional, Union
from typing import Optional, Union, Tuple
from fontio import FontProtocol
from displayio import Group
except ImportError:
Expand All @@ -39,30 +40,45 @@

class Button(ButtonBase):
# pylint: disable=too-many-instance-attributes, too-many-locals
"""Helper class for creating UI buttons for ``displayio``.

:param x: The x position of the button.
:param y: The y position of the button.
:param width: The width of the button in pixels.
:param height: The height of the button in pixels.
:param name: The name of the button.
"""Helper class for creating UI buttons for ``displayio``. Provides the following
buttons:
RECT: A rectangular button. SHAWDOWRECT adds a drop shadow.
ROUNDRECT: A rectangular button with rounded corners. SHADOWROUNDRECT adds
a drop shadow.

:param int x: The x position of the button.
:param int y: The y position of the button.
:param int width: The width of the button in pixels.
:param int height: The height of the button in pixels.
:param Optional[str] name: The name of the button.
:param style: The style of the button. Can be RECT, ROUNDRECT, SHADOWRECT, SHADOWROUNDRECT.
Defaults to RECT.
:param fill_color: The color to fill the button. Defaults to 0xFFFFFF.
:param outline_color: The color of the outline of the button.
:param label: The text that appears inside the button. Defaults to not displaying the label.
:param label_font: The button label font.
:param label_color: The color of the button label text. Defaults to 0x0.
:param selected_fill: Inverts the fill color.
:param selected_outline: Inverts the outline color.
:param selected_label: Inverts the label color.
:param Optional[Union[int, Tuple[int, int, int]]] fill_color: The color to fill the button.
Accepts an int or a tuple of 3 integers representing RGB values. Defaults to 0xFFFFFF.
:param Optional[Union[int, Tuple[int, int, int]]] outline_color: The color of the outline of
the button. Accepts an int or a tuple of 3 integers representing RGB values. Defaults to 0x0.
:param Optional[str] label: The text that appears inside the button.
:param Optional[FontProtocol] label_font: The button label font. Defaults to
''terminalio.FONT''
:param Optional[Union[int, Tuple[int, int, int]]] label_color: The color of the button label
text. Accepts an int or a tuple of 3 integers representing RGB values. Defaults to 0x0.
:param Optional[Union[int, Tuple[int, int, int]]] selected_fill: The fill color when the
button is selected. Accepts an int or a tuple of 3 integers representing RGB values.
Defaults to the inverse of the fill_color.
:param Optional[Union[int, Tuple[int, int, int]]] selected_outline: The outline color when the
button is selected. Accepts an int or a tuple of 3 integers representing RGB values.
Defaults to the inverse of outline_color.
:param Optional[Union[int, Tuple[int, int, int]]] selected_label: The label color when the
button is selected. Accepts an int or a tuple of 3 integers representing RGB values.
Defaults to inverting the label_color.
:param Optional[int] label_scale: The scale factor used for the label. Defaults to 1.
"""

def _empty_self_group(self):
def _empty_self_group(self) -> None:
while len(self) > 0:
self.pop()

def _create_body(self):
def _create_body(self) -> None:
if (self.outline_color is not None) or (self.fill_color is not None):
if self.style == Button.RECT:
self.body = Rect(
Expand Down Expand Up @@ -129,17 +145,17 @@ def __init__(
width: int,
height: int,
name: Optional[str] = None,
style: int = RECT,
fill_color: Optional[Union[int, tuple[int, int, int]]] = 0xFFFFFF,
outline_color: Optional[Union[int, tuple[int, int, int]]] = 0x0,
style=RECT,
fill_color: Optional[Union[int, Tuple[int, int, int]]] = 0xFFFFFF,
outline_color: Optional[Union[int, Tuple[int, int, int]]] = 0x0,
label: Optional[str] = None,
label_font: Optional[FontProtocol] = None,
label_color: Optional[Union[int, tuple[int, int, int]]] = 0x0,
selected_fill: Optional[Union[int, tuple[int, int, int]]] = None,
selected_outline: Optional[Union[int, tuple[int, int, int]]] = None,
selected_label: Optional[Union[int, tuple[int, int, int]]] = None,
label_scale: Optional[int] = None
) -> None:
label_color: Optional[Union[int, Tuple[int, int, int]]] = 0x0,
selected_fill: Optional[Union[int, Tuple[int, int, int]]] = None,
selected_outline: Optional[Union[int, Tuple[int, int, int]]] = None,
selected_label: Optional[Union[int, Tuple[int, int, int]]] = None,
label_scale: Optional[int] = 1
):
super().__init__(
x=x,
y=y,
Expand All @@ -164,9 +180,9 @@ def __init__(
self._selected_outline = _check_color(selected_outline)

if self.selected_fill is None and fill_color is not None:
self.selected_fill = (~self._fill_color) & 0xFFFFFF
self.selected_fill = (~_check_color(self._fill_color)) & 0xFFFFFF
if self.selected_outline is None and outline_color is not None:
self.selected_outline = (~self._outline_color) & 0xFFFFFF
self.selected_outline = (~_check_color(self._outline_color)) & 0xFFFFFF

self._create_body()
if self.body:
Expand Down Expand Up @@ -206,45 +222,45 @@ def contains(self, point: tuple[int, int]) -> bool:
)

@property
def fill_color(self) -> int:
def fill_color(self) -> Optional[int]:
"""The fill color of the button body"""
return self._fill_color

@fill_color.setter
def fill_color(self, new_color: int) -> None:
def fill_color(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._fill_color = _check_color(new_color)
if not self.selected:
self.body.fill = self._fill_color

@property
def outline_color(self) -> int:
def outline_color(self) -> Optional[int]:
"""The outline color of the button body"""
return self._outline_color

@outline_color.setter
def outline_color(self, new_color: int) -> None:
def outline_color(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._outline_color = _check_color(new_color)
if not self.selected:
self.body.outline = self._outline_color

@property
def selected_fill(self) -> int:
def selected_fill(self) -> Optional[int]:
"""The fill color of the button body when selected"""
return self._selected_fill

@selected_fill.setter
def selected_fill(self, new_color: int) -> None:
def selected_fill(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._selected_fill = _check_color(new_color)
if self.selected:
self.body.fill = self._selected_fill

@property
def selected_outline(self) -> int:
def selected_outline(self) -> Optional[int]:
"""The outline color of the button body when selected"""
return self._selected_outline

@selected_outline.setter
def selected_outline(self, new_color: int) -> None:
def selected_outline(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._selected_outline = _check_color(new_color)
if self.selected:
self.body.outline = self._selected_outline
Expand Down Expand Up @@ -279,8 +295,8 @@ def height(self, new_height: int) -> None:

def resize(self, new_width: int, new_height: int) -> None:
"""Resize the button to the new width and height given
:param new_width int the desired width
:param new_height int the desired height
:param int new_width: The desired width in pixels.
:param int new_height: he desired height in pixels.
"""
self._width = new_width
self._height = new_height
Expand Down
62 changes: 35 additions & 27 deletions adafruit_button/button_base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2022 Tim Cocks for Adafruit Industries
# SPDX-FileCopyrightText: 2024 Channing Ramos
#
# SPDX-License-Identifier: MIT

Expand All @@ -9,7 +10,7 @@
UI Buttons for displayio


* Author(s): Limor Fried
* Author(s): Limor Fried, Channing Ramos

Implementation Notes
--------------------
Expand All @@ -22,15 +23,16 @@
"""
from adafruit_display_text.bitmap_label import Label
from displayio import Group
import terminalio

try:
from typing import Optional, Union
from typing import Optional, Union, Tuple
from fontio import FontProtocol
except ImportError:
pass


def _check_color(color):
def _check_color(color: Optional[Union[int, tuple[int, int, int]]]) -> int:
# if a tuple is supplied, convert it to a RGB number
if isinstance(color, tuple):
r, g, b = color
Expand All @@ -42,15 +44,20 @@ class ButtonBase(Group):
# pylint: disable=too-many-instance-attributes
"""Superclass for creating UI buttons for ``displayio``.

:param x: The x position of the button.
:param y: The y position of the button.
:param width: The width of the button in tiles.
:param height: The height of the button in tiles.
:param name: A name, or miscellaneous string that is stored on the button.
:param label: The text that appears inside the button. Defaults to not displaying the label.
:param label_font: The button label font.
:param label_color: The color of the button label text. Defaults to 0x0.
:param selected_label: Text that appears when selected
:param int x: The x position of the button.
:param int y: The y position of the button.
:param int width: The width of the button in tiles.
:param int height: The height of the button in tiles.
:param Optional[str] name: A name, or miscellaneous string that is stored on the button.
:param Optional[str] label: The text that appears inside the button.
:param Optional[FontProtocol] label_font: The button label font.
Defaults to ''terminalio.FONT''
:param Optional[Union[int, Tuple[int, int, int]]] label_color: The color of the label text.
Defaults to 0x0. Accepts an int or a tuple of 3 integers representing RGB values.
:param Optional[Union[int, Tuple[int, int, int]]] selected_label: The color of the label text
when the button is selected. Accepts an int or a tuple of 3 integers representing RGB values.
Defaults to an inverse of label_color.
:param Optional[int] label_scale: The scale factor used for the label. Defaults to 1.
"""

def __init__(
Expand All @@ -63,10 +70,10 @@ def __init__(
name: Optional[str] = None,
label: Optional[str] = None,
label_font: Optional[FontProtocol] = None,
label_color: Optional[Union[int, tuple[int, int, int]]] = 0x0,
selected_label: Optional[Union[int, tuple[int, int, int]]] = None,
label_scale: Optional[int] = None
):
label_color: Optional[Union[int, Tuple[int, int, int]]] = 0x0,
selected_label: Optional[Union[int, Tuple[int, int, int]]] = None,
label_scale: Optional[int] = 1,
) -> None:
super().__init__(x=x, y=y)
self.x = x
self.y = y
Expand All @@ -76,13 +83,13 @@ def __init__(
self._selected = False
self.name = name
self._label = label
self._label_color = label_color
self._label_color = _check_color(label_color)
self._label_font = label_font
self._selected_label = _check_color(selected_label)
self._label_scale = label_scale or 1
self._label_scale = label_scale

@property
def label(self) -> str:
def label(self) -> Optional[str]:
"""The text label of the button"""
return getattr(self._label, "text", None)

Expand All @@ -96,7 +103,7 @@ def label(self, newtext: str) -> None:
return # nothing to do!

if not self._label_font:
raise RuntimeError("Please provide label font")
self._label_font = terminalio.FONT
self._label = Label(self._label_font, text=newtext, scale=self._label_scale)
dims = list(self._label.bounding_box)
dims[2] *= self._label.scale
Expand All @@ -119,15 +126,15 @@ def label(self, newtext: str) -> None:
self.append(self._label)

if (self.selected_label is None) and (self._label_color is not None):
self.selected_label = (~self._label_color) & 0xFFFFFF
self.selected_label = (~_check_color(self._label_color)) & 0xFFFFFF

def _subclass_selected_behavior(self, value):
# Subclasses should overide this!
def _subclass_selected_behavior(self, value: bool):
# Subclasses should override this!
pass

@property
def selected(self) -> bool:
"""Selected inverts the colors."""
"""Returns whether the button is selected."""
return self._selected

@selected.setter
Expand All @@ -147,11 +154,12 @@ def selected(self, value: bool) -> None:

@property
def selected_label(self) -> int:
"""The font color of the button when selected"""
"""The font color of the button when selected.
If no color is specified it defaults to the inverse of the label_color"""
return self._selected_label

@selected_label.setter
def selected_label(self, new_color: int) -> None:
def selected_label(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._selected_label = _check_color(new_color)

@property
Expand All @@ -160,6 +168,6 @@ def label_color(self) -> int:
return self._label_color

@label_color.setter
def label_color(self, new_color: int):
def label_color(self, new_color: Union[int, Tuple[int, int, int]]) -> None:
self._label_color = _check_color(new_color)
self._label.color = self._label_color
Loading
Loading