Fix visible item implementation

This commit is contained in:
Jan-Henrik 2020-02-26 19:16:33 +01:00
parent 600b139b8e
commit 677898f9f9
2 changed files with 58 additions and 93 deletions

View file

@ -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;

View file

@ -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);