Implemented the execute_selection and the run method, along with a new loop method

The new loop method allows for more advanced usages (e.g. when you want to use the cpu core for more than just the stupid while True, listen for btn presses procedure but also invoke other commands from time to time - then you can implement your 'own' run procedure!)
This commit is contained in:
BlueFox 2024-11-01 16:30:41 +00:00
parent e120574784
commit 4ad714fa83

View File

@ -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 <https://www.gnu.org/licenses/>.
"""
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 <lcdMenuObject>.<attribute_name>, 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()