diff --git a/__init__.py b/__init__.py index 5b26d34..2fe8546 100644 --- a/__init__.py +++ b/__init__.py @@ -9,6 +9,8 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY You should have received a copy of the GNU General Public License along with this program. If not, see . """ +from time import sleep + class lcdMenu: # lcd: I2C_LCD - an object of the I2C_LCD class (https://git.privacynerd.de/BlueFox/micropython-libraries/src/branch/main/PCF8574T) @@ -22,7 +24,9 @@ class lcdMenu: # hide_menu_name: bool - OPTIONAL - if true, hide the menu's name (won't work in combination with a vertical scrolling direction) # name: str - OPTIONAL - a string with the name of the menu (can be hidden under certain circumstances) # default_selection: int - OPTIONAL - the index of the item selected by default (starting with 0) - DON'T USE NEGATIVE INDEXES - def __init__(self, lcd, buttons: dict, menu_items: list, scroll_direction: bool, cycle: bool, hide_menu_name: bool = False, name: str = "CHOOSE", default_selection: int = 0): + # debounce_time: float - OPTIONAL - the debounce time used by the library to debounce button presses + def __init__(self, lcd, buttons: dict, menu_items: list, scroll_direction: bool, cycle: bool, hide_menu_name: bool = False, name: str = "CHOOSE", default_selection: int = 0, debounce_time: float = 0.15): + # save the argument variables self.lcd = lcd if "prev_btn" in buttons.keys(): self.prev_btn = buttons["prev_btn"] @@ -36,6 +40,14 @@ class lcdMenu: self.hide_menu_name = hide_menu_name self.name = name self.current_selection = default_selection + self.debounce_time = debounce_time + + # variables that are very unlikely the user want's to set them (but can be set via ., of course) + self.start_execution_msg = "Selected..." # the string displayed when an menu item is selected + self.end_execution_msg = "Closing..." # the string displayed when the callback function of a selected menu item returns self.end_execution_wait = 1 # the time (in seconds) to wait after the callback function of a selected menu item returns + self.start_execution_wait = 0.5 # the time (in seconds) to wait before the callback function of a selected menu item is called + self.end_execution_wait = 1 # the time (in seconds) to wait after the callback function of a selected menu item returns + self.fill_char = '-' # the character used to fill up space (used only on 4x20 displays); MUST BE 1 character long def show_selection(self): @@ -48,6 +60,7 @@ class lcdMenu: pass else: # if vertical scrolling is activated pass + print(self.current_selection) def previous_selection(self): @@ -69,10 +82,51 @@ class lcdMenu: def execute_selection(self): - self.menu_items[self.current_selection][1]() + selection = self.menu_items[self.current_selection] + lw = self.lcd.num_columns + + # if the program executed had no display (so the user notices something happens!) + self.lcd.move_to(0,0) + if self.lcd.num_lines == 4: + self.lcd.putstr(f"{self.fill_char*lw}{' '*lw*2}{self.fill_char*lw}") # fill the first and last line with 'fill_char's + self.lcd.move_to(0,1) # move to the second line for the starting message below (takes two lines) + self.lcd.putstr(f"[{selection[0][0:lw].center(lw-2)}]{self.start_execution_msg[0:lw].center(lw)}") + sleep(self.start_execution_wait) # wait some time before execution (so that the text can be read) + + # run the program + return_value = selection[1]() + + # show a exit when there's no specific return value + if not return_value: # if the return value is None / nothing was returned + while self.ok_btn.value() == 1: time.sleep(self.debounce_time) # wait till ok_btn release (e.g. if the "program" is a simple send action) + self.lcd.move_to(0,0) + if self.lcd.num_lines == 4: + self.lcd.putstr(f"{self.fill_char*lw}{' '*lw*2}{self.fill_char*lw}") # fill the first and last line with 'fill_char's + self.lcd.move_to(0,1) # move to the second line for the starting message below (takes two lines) + self.lcd.putstr(f"[{selection[0][0:lw].center(lw-2)}]{self.end_execution_msg[0:lw].center(lw)}") + sleep(self.end_execution_wait) + # listen for button presses (this method should be called in an endless loop, see method run) + def loop(self): + if self.prev_btn: + if self.prev_btn.value() == 1: + self.previous_selection() + self.show_selection() + while self.prev_btn.value() == 1: sleep(self.debounce_time) # wait till release + if self.next_btn.value() == 1: + self.next_selection() + self.show_selection() + while self.next_btn.value() == 1: sleep(self.debounce_time) # wait till release + if self.ok_btn.value() == 1: + while self.ok_btn.value() == 1: sleep(self.debounce_time) # wait till release + self.execute_selection() + + def run(self): - # TODO: add btn handlers and the actual process - pass - + # show the selection first + self.show_selection() + + # then listen on button presses in a loop... + while True: + self.loop()