diff --git a/adafruit_cursorcontrol/cursorcontrol_cursormanager.py b/adafruit_cursorcontrol/cursorcontrol_cursormanager.py index dd46f9d..49cf53a 100755 --- a/adafruit_cursorcontrol/cursorcontrol_cursormanager.py +++ b/adafruit_cursorcontrol/cursorcontrol_cursormanager.py @@ -236,45 +236,103 @@ def _check_cursor_movement(self) -> None: class DebouncedCursorManager(CursorManager): - """Simple interaction user interface interaction for Adafruit_CursorControl. - This subclass provide a debounced version on the A button and provides queries for when - the button is just pressed, and just released, as well it's current state. "Just" in this - context means "since the previous call to update." + """Simple user interface interaction for Adafruit_CursorControl. + This subclass provide a debounced version on the A, B, Start or Select buttons + and provides queries for when the buttons are just pressed, and just released, + as well their current state. "Just" in this context means "since the previous call to update." :param Cursor cursor: The cursor object we are using. """ def __init__(self, cursor: Cursor, debounce_interval: float = 0.01) -> None: CursorManager.__init__(self, cursor) - self._debouncer = Debouncer( - lambda: bool(self._pad_states & (1 << self._pad_btns["btn_a"])), - interval=debounce_interval, - ) + self._debouncers = {} + for btn in self._pad_btns: + self._debouncers[btn] = Debouncer( + lambda btn=btn: bool((self._pad_states & (1 << self._pad_btns[btn]))), + interval=debounce_interval, + ) @property def is_clicked(self) -> bool: - """Returns True if the cursor button was pressed + """Returns True if the cursor A button was pressed + during previous call to update() + """ + return self._debouncers["btn_a"].rose + + @property + def is_alt_clicked(self) -> bool: + """Returns True if the cursor B button was pressed during previous call to update() """ - return self._debouncer.rose + return self._debouncers["btn_b"].rose - pressed = is_clicked + @property + def is_select_clicked(self) -> bool: + """Returns True if the Select button was pressed + during previous call to update() + """ + return self._debouncers["btn_select"].rose + + @property + def is_start_clicked(self) -> bool: + """Returns True if the Start button was pressed + during previous call to update() + """ + return self._debouncers["btn_start"].rose @property def released(self) -> bool: - """Returns True if the cursor button was released + """Returns True if the cursor A button was released + during previous call to update() + """ + return self._debouncers["btn_a"].fell + + @property + def alt_released(self) -> bool: + """Returns True if the cursor B button was released during previous call to update() """ - return self._debouncer.fell + return self._debouncers["btn_b"].fell + + @property + def start_released(self) -> bool: + """Returns True if the cursor Start button was released + during previous call to update() + """ + return self._debouncers["btn_start"].fell + + @property + def select_released(self) -> bool: + """Returns True if the cursor Select button was released + during previous call to update() + """ + return self._debouncers["btn_select"].fell @property def held(self) -> bool: - """Returns True if the cursor button is currently being held""" - return self._debouncer.value + """Returns True if the cursor A button is currently being held""" + return self._debouncers["btn_a"].value + + @property + def alt_held(self) -> bool: + """Returns True if the cursor B button is currently being held""" + return self._debouncers["btn_b"].value + + @property + def start_held(self) -> bool: + """Returns True if the cursor Start button is currently being held""" + return self._debouncers["btn_start"].value + + @property + def select_held(self) -> bool: + """Returns True if the cursor Select is currently being held""" + return self._debouncers["btn_select"].value def update(self) -> None: """Updates the cursor object.""" if self._pad.events.get_into(self._event): self._store_button_states() self._check_cursor_movement() - self._debouncer.update() + for debouncer in self._debouncers.values(): + debouncer.update() diff --git a/examples/cursorcontrol_buttons_debounced.py b/examples/cursorcontrol_buttons_debounced.py new file mode 100644 index 0000000..f1a9459 --- /dev/null +++ b/examples/cursorcontrol_buttons_debounced.py @@ -0,0 +1,158 @@ +# SPDX-FileCopyrightText: 2022 flom84 for Adafruit Industries +# SPDX-License-Identifier: MIT + +import time +import board +import displayio +import terminalio + +from adafruit_button import Button +from adafruit_cursorcontrol.cursorcontrol import Cursor +from adafruit_cursorcontrol.cursorcontrol_cursormanager import DebouncedCursorManager + +SELECT_BUTTON_X = 0 +SELECT_BUTTON_Y = 103 +SELECT_BUTTON_WIDTH = 60 +SELECT_BUTTON_HEIGHT = 25 +SELECT_BUTTON_STYLE = Button.ROUNDRECT +SELECT_BUTTON_OUTLINE_COLOR = 0xFFFFFF +SELECT_BUTTON_LABEL = "Select" +SELECT_BUTTON_LABEL_COLOR = 0xFFFFFF + +START_BUTTON_X = 100 +START_BUTTON_Y = 103 +START_BUTTON_WIDTH = 60 +START_BUTTON_HEIGHT = 25 +START_BUTTON_STYLE = Button.ROUNDRECT +START_BUTTON_OUTLINE_COLOR = 0xFFFFFF +START_BUTTON_LABEL = "Start" +START_BUTTON_LABEL_COLOR = 0xFFFFFF + +A_BUTTON_X = 120 +A_BUTTON_Y = 20 +A_BUTTON_WIDTH = 30 +A_BUTTON_HEIGHT = 30 +A_BUTTON_STYLE = Button.ROUNDRECT +A_BUTTON_OUTLINE_COLOR = 0xFFFFFF +A_BUTTON_LABEL = "A" +A_BUTTON_LABEL_COLOR = 0xFFFFFF + +B_BUTTON_X = 80 +B_BUTTON_Y = 30 +B_BUTTON_WIDTH = 30 +B_BUTTON_HEIGHT = 30 +B_BUTTON_STYLE = Button.ROUNDRECT +B_BUTTON_OUTLINE_COLOR = 0xFFFFFF +B_BUTTON_LABEL = "B" +B_BUTTON_LABEL_COLOR = 0xFFFFFF + +BUTTON_FILL_PURPLE = 0xB400FF +BUTTON_FILL_BLACK = 0x000000 + +start_button = Button( + x=START_BUTTON_X, + y=START_BUTTON_Y, + width=START_BUTTON_WIDTH, + height=START_BUTTON_HEIGHT, + style=START_BUTTON_STYLE, + fill_color=BUTTON_FILL_BLACK, + outline_color=START_BUTTON_OUTLINE_COLOR, + label=START_BUTTON_LABEL, + label_font=terminalio.FONT, + label_color=START_BUTTON_LABEL_COLOR, +) + +select_button = Button( + x=SELECT_BUTTON_X, + y=SELECT_BUTTON_Y, + width=SELECT_BUTTON_WIDTH, + height=SELECT_BUTTON_HEIGHT, + style=SELECT_BUTTON_STYLE, + fill_color=BUTTON_FILL_BLACK, + outline_color=SELECT_BUTTON_OUTLINE_COLOR, + label=SELECT_BUTTON_LABEL, + label_font=terminalio.FONT, + label_color=SELECT_BUTTON_LABEL_COLOR, +) + +a_button = Button( + x=A_BUTTON_X, + y=A_BUTTON_Y, + width=A_BUTTON_WIDTH, + height=A_BUTTON_HEIGHT, + style=A_BUTTON_STYLE, + fill_color=BUTTON_FILL_BLACK, + outline_color=A_BUTTON_OUTLINE_COLOR, + label=A_BUTTON_LABEL, + label_font=terminalio.FONT, + label_color=A_BUTTON_LABEL_COLOR, +) + +b_button = Button( + x=B_BUTTON_X, + y=B_BUTTON_Y, + width=B_BUTTON_WIDTH, + height=B_BUTTON_HEIGHT, + style=B_BUTTON_STYLE, + fill_color=BUTTON_FILL_BLACK, + outline_color=B_BUTTON_OUTLINE_COLOR, + label=B_BUTTON_LABEL, + label_font=terminalio.FONT, + label_color=B_BUTTON_LABEL_COLOR, +) + +# Create the display +display = board.DISPLAY + +# Create the display context +splash = displayio.Group() + +# initialize the mouse cursor object +mouse_cursor = Cursor(display, display_group=splash) + +# initialize the debounced cursor manager +debounced_cursor = DebouncedCursorManager(mouse_cursor) + +# create displayio group +splash.append(start_button) +splash.append(select_button) +splash.append(a_button) +splash.append(b_button) +display.show(splash) + +while True: + debounced_cursor.update() + + if debounced_cursor.is_clicked: + a_button.fill_color = BUTTON_FILL_PURPLE + print("A pressed: " + str(debounced_cursor.held)) + + if debounced_cursor.released: + a_button.fill_color = BUTTON_FILL_BLACK + print("A pressed: " + str(debounced_cursor.held)) + + if debounced_cursor.is_alt_clicked: + b_button.fill_color = BUTTON_FILL_PURPLE + print("B pressed: " + str(debounced_cursor.alt_held)) + + if debounced_cursor.alt_released: + b_button.fill_color = BUTTON_FILL_BLACK + print("B pressed: " + str(debounced_cursor.alt_held)) + + if debounced_cursor.is_start_clicked: + start_button.fill_color = BUTTON_FILL_PURPLE + print("Start pressed: " + str(debounced_cursor.start_held)) + + if debounced_cursor.start_released: + start_button.fill_color = BUTTON_FILL_BLACK + print("Start pressed: " + str(debounced_cursor.start_held)) + + if debounced_cursor.is_select_clicked: + select_button.fill_color = BUTTON_FILL_PURPLE + print("Select pressed: " + str(debounced_cursor.select_held)) + + if debounced_cursor.select_released: + select_button.fill_color = BUTTON_FILL_BLACK + print("Select pressed: " + str(debounced_cursor.select_held)) + + time.sleep(0.01)