Finally fully implemented the vertical scrolling; also, added more comments to the program for better understandability
This commit is contained in:
		| @@ -8,10 +8,10 @@ This project is the completely rewritten successor of my old (and now archived) | ||||
| ## Roadmap | ||||
|  | ||||
| - [x] forward, backward and select button | ||||
| - [ ] support for horizontal and vertical scrolling | ||||
| - [x] support for horizontal and vertical scrolling | ||||
| - [x] support for both 2x16 and 4x20 LCDs | ||||
| - [x] a reliable order of the menu items | ||||
| - [ ] good documentation for all of this (maybe through examples) | ||||
| - [x] good documentation for all of this (maybe through examples) | ||||
| - [x] show an exit screen when a specific exit code is returned by a callback function | ||||
| - [ ] make the menu itself exitable (to enable stuff like submenus, etc.) | ||||
| - [x] make the project a valid python package  | ||||
|   | ||||
							
								
								
									
										63
									
								
								__init__.py
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								__init__.py
									
									
									
									
									
								
							| @@ -63,10 +63,10 @@ class lcdMenu: | ||||
|         # fill the custom character fields in the displays memory | ||||
|         self.lcd.custom_char(0, bytearray([0x04,0x0A,0x11,0x00,0x00,0x00,0x00,0x00]))  # arrow up | ||||
|         self.lcd.custom_char(1, bytearray([0x00,0x00,0x00,0x00,0x00,0x11,0x0A,0x04]))  # arrow down | ||||
|         self.lcd.custom_char(2, bytearray([0x04,0x0A,0x11,0x00,0x00,0x11,0x0A,0x04]))  # arrow up and down (variant 5 from above) | ||||
|         self.lcd.custom_char(3, bytearray([0x11,0x0A,0x04,0x00,0x00,0x04,0x0A,0x11]))  # no options (variant 3 from above) | ||||
|         self.lcd.custom_char(4, bytearray([0x08,0x08,0x08,0x0F,0x08,0x08,0x08,0x08]))  # line with a fork (to show the current selection - h scrolling) | ||||
|         self.lcd.custom_char(5, bytearray([0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08]))  # line without a fork (to show unselected items - h scrolling) | ||||
|         self.lcd.custom_char(2, bytearray([0x04,0x0A,0x11,0x00,0x00,0x11,0x0A,0x04]))  # arrow up and down | ||||
|         self.lcd.custom_char(3, bytearray([0x11,0x0A,0x04,0x00,0x00,0x04,0x0A,0x11]))  # no options | ||||
|         self.lcd.custom_char(4, bytearray([0x08,0x08,0x08,0x0F,0x08,0x08,0x08,0x08]))  # line with a fork (to show the current selection - v scrolling) | ||||
|         self.lcd.custom_char(5, bytearray([0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08]))  # line without a fork (to show unselected items - v scrolling) | ||||
|         self.lcd.custom_char(6, bytearray([0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00]))  # three dots in a row | ||||
|          | ||||
|         # now show it off! | ||||
| @@ -97,31 +97,28 @@ class lcdMenu: | ||||
|                 # maybe the following could be done with a crazy math formula - but I want to keep it simpler! | ||||
|                 # as there aren't enough menu items after the current selection to fill the display, we have to... | ||||
|                 # ... calculate where to place the current selection, how many items there are before it and how many after it | ||||
|                 """ | ||||
|                 if lines_for_display > len(self.menu_items):  # if it is because of an overall small number of menu items (less than we can display) | ||||
|                     for i in range(len(self.menu_items)): | ||||
|                         if i < self.current_selection: | ||||
|                             self.lcd.putstr(chr(5)+" "+self.menu_items[i][0][0:lw-4]) | ||||
|                             self.lcd.putstr(" "*(lw-4-len(self.menu_items[i][0][0:lw-4]))) | ||||
|                             if len(self.menu_items) <= 1: | ||||
|                                 self.lcd.putstr(" " + chr(3))  # no options icon (as there's only one menu item!) | ||||
|                             elif self.current_selection == 0 and not self.cycle: | ||||
|                                 self.lcd.putstr(" "+chr(1)) | ||||
|                             elif self.current_selection == (len(self.menu_items)-1) and not self.cycle: | ||||
|                                 self.lcd.putstr(" "+chr(0)) | ||||
|                             else: | ||||
|                                 self.lcd.putstr(" "+chr(2)) | ||||
|                         elif i == self.current_selection: | ||||
|                             self.lcd.putstr(chr(5)+" "+self.menu_items[i][0][0:lw-4]) | ||||
|                             self.lcd.putstr(" "*(lw-4-len(self.menu_items[i][0][0:lw-4]))) | ||||
|                         elif i > self.current_selection: | ||||
|                 menu_items_cut = self.menu_items[:lines_for_display:-1][::-1]  # cut the menu_items list to the relevant last n ones maintaining order (n = number of lines for display) | ||||
|                 current_pos_in_cut = -len(self.menu_items) + self.current_selection + lines_for_display  # calculate the current index of the selection in the new cut | ||||
|                 # draw all the lines | ||||
|                 for i in range(lines_for_display): | ||||
|                     if i == current_pos_in_cut:  # if drawing the currently selected item | ||||
|                         self.lcd.putstr(f"{chr(4)} {menu_items_cut[i][0][0:lw-4]}") | ||||
|                         self.lcd.putstr(" " * ((lw-4)-len(menu_items_cut[i][0][0:lw-4])))  # fit the line | ||||
|                     else: | ||||
|                         self.lcd.putstr(f"{chr(5)} {menu_items_cut[i][0][0:lw-4]}") | ||||
|                         self.lcd.putstr(" " * ((lw-4)-len(menu_items_cut[i][0][0:lw-4])))  # fit the line | ||||
|                     # now the arrow | ||||
|                     if i == 0:  # if the first element is drawn, think about printing or not printing the up arrow | ||||
|                         if self.current_selection == 0 and not self.cycle:  # first item selected and no cycling | ||||
|                             self.lcd.putstr("  ")  # leave the line with spaces | ||||
|                         else: | ||||
|                             self.lcd.putstr(" " + chr(0)) | ||||
|                     elif i == lines_for_display-1:  # if the last element is drawn, print a down arrow? | ||||
|                         if self.current_selection == (len(self.menu_items)-1) and not self.cycle:  # first item selected and no cycling | ||||
|                             self.lcd.putstr("  ")  # leave the line with spaces | ||||
|                         else: | ||||
|                             self.lcd.putstr(" " + chr(1))  # arrow down | ||||
|                          | ||||
|                          | ||||
|                     print("Im here!") | ||||
|                 else:  # if it is because we reached the end of a (possibly) long menu list -> we have enough items to fill all the available lines | ||||
|                     print("Else here!") | ||||
|                 """ | ||||
|                 print("ToDo!") | ||||
|             else:  # there are enough items to fill the display after the current selection | ||||
|                 # the first line | ||||
|                 self.lcd.putstr(f"{chr(4)} {selection_name[0:lw-4]}") | ||||
| @@ -129,12 +126,12 @@ class lcdMenu: | ||||
|                  | ||||
|                 if len(self.menu_items) <= 1: | ||||
|                     self.lcd.putstr(" " + chr(3))  # no options icon (as there's only one menu item!) | ||||
|                 elif lines_for_display == 1:  # if there is exactly one line to display the menu entries | ||||
|                     if self.current_selection == 0 and not self.cycle: | ||||
|                 elif lines_for_display == 1:  # if there is exactly one line to display the menu entries... | ||||
|                     if self.current_selection == 0 and not self.cycle:  # ...and the first element is selected and cycling is disabled so you can't go back | ||||
|                         self.lcd.putstr(" "+chr(1)) | ||||
|                     elif self.current_selection == (len(self.menu_items)-1) and not self.cycle: | ||||
|                     elif self.current_selection == (len(self.menu_items)-1) and not self.cycle:  # ...as before but with the last element -> you can't go further | ||||
|                         self.lcd.putstr(" "+chr(0)) | ||||
|                     else: | ||||
|                     else:  # ...or anything else (cycling or in the middle -> you can go in both directions | ||||
|                         self.lcd.putstr(" "+chr(2)) | ||||
|                 elif self.current_selection == 0 and not self.cycle:  # first item selected and no cycling | ||||
|                     self.lcd.putstr("  ")  # leave the line with spaces | ||||
| @@ -190,7 +187,7 @@ class lcdMenu: | ||||
|         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 | ||||
|         if not return_value:  # if the return value is None / nothing was returned -> show a closing message | ||||
|             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: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user