mirror of
				https://github.com/jhbruhn/eurorack.git
				synced 2025-10-30 02:46:01 +00:00 
			
		
		
		
	Fix visible item implementation
This commit is contained in:
		
							parent
							
								
									600b139b8e
								
							
						
					
					
						commit
						677898f9f9
					
				
					 2 changed files with 58 additions and 93 deletions
				
			
		|  | @ -10,27 +10,18 @@ void Menu::render(U8G2* u8g2_, uint8_t xStart, uint8_t yStart, uint8_t width, ui | ||||||
| 
 | 
 | ||||||
|   uint8_t maxVisibleItems = height / kMenuItemHeight; |   uint8_t maxVisibleItems = height / kMenuItemHeight; | ||||||
| 
 | 
 | ||||||
|   uint8_t itemsToRender = std::min(maxVisibleItems, uint8_t(this->itemCount - currentScrollStart)); |   uint8_t itemsToRender = std::min(maxVisibleItems, uint8_t(this->visibleItemCount - currentVisibleScrollStart)); | ||||||
|   u8g2_->setFont(u8g2_font_6x10_tf); |   u8g2_->setFont(u8g2_font_6x10_tf); | ||||||
| 
 | 
 | ||||||
|   uint8_t itemIndex = this->currentScrollStart; |  | ||||||
| 
 |  | ||||||
|   for (uint8_t i = 0; i < itemsToRender; i++) { |   for (uint8_t i = 0; i < itemsToRender; i++) { | ||||||
|     uint8_t yPosition = yStart + i * kMenuItemHeight; |     uint8_t yPosition = yStart + i * kMenuItemHeight; | ||||||
| 
 | 
 | ||||||
|     AbstractMenuItem* item; |     uint8_t itemIndex = this->currentVisibleScrollStart + i; | ||||||
| 
 | 
 | ||||||
|     while (!(item = this->items[itemIndex])->visible()) { |     AbstractMenuItem* item = this->visibleItems[itemIndex]; | ||||||
|       itemIndex++; |  | ||||||
|       if (itemIndex >= this->itemCount) |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (itemIndex >= this->itemCount) |     bool selected = this->selectedVisibleItem == itemIndex; | ||||||
|       break; |     bool editing = this->currentEditingVisibleItem == itemIndex; | ||||||
| 
 |  | ||||||
|     bool selected = this->selectedItem == itemIndex; |  | ||||||
|     bool editing = this->currentEditingItem == itemIndex; |  | ||||||
| 
 | 
 | ||||||
|     u8g2_->setDrawColor(selected ? 1 : 0); |     u8g2_->setDrawColor(selected ? 1 : 0); | ||||||
| 
 | 
 | ||||||
|  | @ -50,86 +41,79 @@ void Menu::render(U8G2* u8g2_, uint8_t xStart, uint8_t yStart, uint8_t width, ui | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Menu::update_visible_items() | ||||||
|  | { | ||||||
|  |   // set all visibleItems to null
 | ||||||
|  |   this->visibleItemCount = 0; | ||||||
|  |   for (size_t i = 0; i < MAXIMUM_MENU_ITEM_COUNT; i++) { | ||||||
|  |     this->visibleItems[i] = NULL; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // find out which items are visible and only add these to the list.
 | ||||||
|  |   for (size_t i = 0; i < itemCount; i++) { | ||||||
|  |     if (this->items[i]->visible()) { | ||||||
|  |       this->visibleItems[this->visibleItemCount++] = this->items[i]; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Menu::up() | void Menu::up() | ||||||
| { | { | ||||||
|   if (this->currentEditingItem >= 0) { |   this->update_visible_items(); | ||||||
|  |   if (this->currentEditingVisibleItem >= 0) { | ||||||
|     // we store the amount of visible items before the counter before
 |     // we store the amount of visible items before the counter before
 | ||||||
|     // changing and then compare afterwards to move the cursor back to
 |     // changing and then compare afterwards to move the cursor back to
 | ||||||
|     // its intended position if necessary
 |     // its intended position if necessary
 | ||||||
|     uint8_t visible_count_before = this->visible_item_count_before_selection(); |     this->visibleItems[this->selectedVisibleItem]->decrease(); | ||||||
| 
 | 
 | ||||||
|     this->items[this->selectedItem]->decrease(); |   } else if (this->selectedVisibleItem > 0) { | ||||||
|  |     uint8_t newItem = this->selectedVisibleItem - 1; | ||||||
| 
 | 
 | ||||||
|     uint8_t visible_count_after = this->visible_item_count_before_selection(); |     if (newItem - this->currentVisibleScrollStart == 0) { // keep scroll start one up
 | ||||||
| 
 |       this->currentVisibleScrollStart--; | ||||||
|     this->selectedItem += visible_count_after - visible_count_before; |  | ||||||
|   } else if (this->selectedItem > 0) { |  | ||||||
|     uint8_t newItem = this->selectedItem; |  | ||||||
|     int8_t i; |  | ||||||
|     for (i = this->selectedItem - 1; i >= 0; i--) { |  | ||||||
|       if (this->items[i]->visible()) { |  | ||||||
|         newItem = i; |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (newItem - this->currentScrollStart == i) { // keep scroll start one up
 |     this->selectedVisibleItem = newItem; | ||||||
|       this->currentScrollStart--; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     this->selectedItem = newItem; |     if (this->selectedVisibleItem == 0) { | ||||||
| 
 |       this->currentVisibleScrollStart = 0; | ||||||
|     if (this->selectedItem == 0) { |  | ||||||
|       this->currentScrollStart = 0; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   this->update_visible_items(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Menu::down() | void Menu::down() | ||||||
| { | { | ||||||
|   if (this->currentEditingItem >= 0) { |   this->update_visible_items(); | ||||||
|     uint8_t visible_count_before = this->visible_item_count_before_selection(); |   if (this->currentEditingVisibleItem >= 0) { | ||||||
| 
 |     this->visibleItems[this->selectedVisibleItem]->increase(); | ||||||
|     this->items[this->selectedItem]->increase(); |  | ||||||
| 
 |  | ||||||
|     uint8_t visible_count_after = this->visible_item_count_before_selection(); |  | ||||||
| 
 |  | ||||||
|     this->selectedItem += visible_count_after - visible_count_before; |  | ||||||
|   } else { |   } else { | ||||||
|     uint8_t maxVisibleItems = height / kMenuItemHeight; |     uint8_t maxVisibleItems = height / kMenuItemHeight; | ||||||
|     if (this->selectedItem < this->itemCount - 1) { |     if (this->selectedVisibleItem < this->visibleItemCount - 1) { | ||||||
|       if (this->items[this->selectedItem + 1]->visible()) { |       if (this->selectedVisibleItem - this->currentVisibleScrollStart == maxVisibleItems - 2 && this->visibleItemCount - this->currentVisibleScrollStart > maxVisibleItems) { | ||||||
|         if (this->selectedItem - this->currentScrollStart == maxVisibleItems - 2 && this->itemCount - this->currentScrollStart > maxVisibleItems) { |         this->currentVisibleScrollStart++; | ||||||
|           this->currentScrollStart++; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         this->selectedItem++; |  | ||||||
|       } else { |  | ||||||
|         for (size_t i = this->selectedItem + 1; i < this->itemCount; i++) { |  | ||||||
|           if (this->items[i]->visible()) { |  | ||||||
|             this->selectedItem = i; |  | ||||||
|             break; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       this->selectedVisibleItem++; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   this->update_visible_items(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Menu::enter() | bool Menu::enter() | ||||||
| { | { | ||||||
|   if (this->currentEditingItem >= 0) { |   if (this->currentEditingVisibleItem >= 0) { | ||||||
|     this->currentEditingItem = -1; |     this->currentEditingVisibleItem = -1; | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|   this->currentEditingItem = this->selectedItem; |   this->currentEditingVisibleItem = this->selectedVisibleItem; | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Menu::back() | bool Menu::back() | ||||||
| { | { | ||||||
|   if (this->currentEditingItem >= 0) { |   if (this->currentEditingVisibleItem >= 0) { | ||||||
|     this->currentEditingItem = -1; |     this->currentEditingVisibleItem = -1; | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   return true; |   return true; | ||||||
|  |  | ||||||
|  | @ -9,17 +9,22 @@ | ||||||
| class Menu { | class Menu { | ||||||
|   private: |   private: | ||||||
|   AbstractMenuItem* items[MAXIMUM_MENU_ITEM_COUNT]; |   AbstractMenuItem* items[MAXIMUM_MENU_ITEM_COUNT]; | ||||||
|  |   AbstractMenuItem* visibleItems[MAXIMUM_MENU_ITEM_COUNT]; | ||||||
|   uint8_t itemCount; |   uint8_t itemCount; | ||||||
|   uint8_t selectedItem; |   uint8_t visibleItemCount; | ||||||
|   uint8_t currentScrollStart; // index we start rendering the menu from (for scrolling)
 |   uint8_t selectedVisibleItem; | ||||||
|   int8_t currentEditingItem; |   uint8_t currentVisibleScrollStart; // index we start rendering the menu from (for scrolling)
 | ||||||
|  |   int8_t currentEditingVisibleItem; | ||||||
|  | 
 | ||||||
|   uint8_t width, height; |   uint8_t width, height; | ||||||
| 
 | 
 | ||||||
|  |   void update_visible_items(); | ||||||
|  | 
 | ||||||
|   public: |   public: | ||||||
|   Menu() |   Menu() | ||||||
|       : selectedItem(0) |       : selectedVisibleItem(0) | ||||||
|       , currentScrollStart(0) |       , currentVisibleScrollStart(0) | ||||||
|       , currentEditingItem(-1) |       , currentEditingVisibleItem(-1) | ||||||
|       , width(10) |       , width(10) | ||||||
|       , height(10) {}; |       , height(10) {}; | ||||||
| 
 | 
 | ||||||
|  | @ -27,36 +32,12 @@ class Menu { | ||||||
|   void down(); |   void down(); | ||||||
|   bool back();  // returns true true if nothing happened here and the action can be delegated to up
 |   bool back();  // returns true true if nothing happened here and the action can be delegated to up
 | ||||||
|   bool enter(); // returns true if it wants to give up control
 |   bool enter(); // returns true if it wants to give up control
 | ||||||
| 
 |  | ||||||
|   void add_item(AbstractMenuItem* item) |   void add_item(AbstractMenuItem* item) | ||||||
|   { |   { | ||||||
|     if (itemCount < MAXIMUM_MENU_ITEM_COUNT) { |     if (itemCount < MAXIMUM_MENU_ITEM_COUNT) { | ||||||
|       items[itemCount++] = item; |       items[itemCount++] = item; | ||||||
|     } |     } | ||||||
|   } |     this->update_visible_items(); | ||||||
| 
 |  | ||||||
|   uint8_t visible_item_count() |  | ||||||
|   { |  | ||||||
|     uint8_t count = 0; |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 0; i < itemCount; i++) { |  | ||||||
|       if (items[i]->visible()) |  | ||||||
|         count++; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return count; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   uint8_t visible_item_count_before_selection() |  | ||||||
|   { |  | ||||||
|     uint8_t count = 0; |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 0; i <= selectedItem; i++) { |  | ||||||
|       if (items[i]->visible()) |  | ||||||
|         count++; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return count; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void render(U8G2* u8g2_, uint8_t x, uint8_t y, uint8_t width, uint8_t height); |   void render(U8G2* u8g2_, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue