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 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);
uint8_t itemIndex = this->currentScrollStart;
for (uint8_t i = 0; i < itemsToRender; i++) {
uint8_t yPosition = yStart + i * kMenuItemHeight;
AbstractMenuItem* item;
uint8_t itemIndex = this->currentVisibleScrollStart + i;
while (!(item = this->items[itemIndex])->visible()) {
itemIndex++;
if (itemIndex >= this->itemCount)
break;
}
AbstractMenuItem* item = this->visibleItems[itemIndex];
if (itemIndex >= this->itemCount)
break;
bool selected = this->selectedItem == itemIndex;
bool editing = this->currentEditingItem == itemIndex;
bool selected = this->selectedVisibleItem == itemIndex;
bool editing = this->currentEditingVisibleItem == itemIndex;
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()
{
if (this->currentEditingItem >= 0) {
this->update_visible_items();
if (this->currentEditingVisibleItem >= 0) {
// we store the amount of visible items before the counter before
// changing and then compare afterwards to move the cursor back to
// 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();
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->currentVisibleScrollStart == 0) { // keep scroll start one up
this->currentVisibleScrollStart--;
}
if (newItem - this->currentScrollStart == i) { // keep scroll start one up
this->currentScrollStart--;
}
this->selectedVisibleItem = newItem;
this->selectedItem = newItem;
if (this->selectedItem == 0) {
this->currentScrollStart = 0;
if (this->selectedVisibleItem == 0) {
this->currentVisibleScrollStart = 0;
}
}
this->update_visible_items();
}
void Menu::down()
{
if (this->currentEditingItem >= 0) {
uint8_t visible_count_before = this->visible_item_count_before_selection();
this->items[this->selectedItem]->increase();
uint8_t visible_count_after = this->visible_item_count_before_selection();
this->selectedItem += visible_count_after - visible_count_before;
this->update_visible_items();
if (this->currentEditingVisibleItem >= 0) {
this->visibleItems[this->selectedVisibleItem]->increase();
} else {
uint8_t maxVisibleItems = height / kMenuItemHeight;
if (this->selectedItem < this->itemCount - 1) {
if (this->items[this->selectedItem + 1]->visible()) {
if (this->selectedItem - this->currentScrollStart == maxVisibleItems - 2 && this->itemCount - this->currentScrollStart > maxVisibleItems) {
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;
}
}
if (this->selectedVisibleItem < this->visibleItemCount - 1) {
if (this->selectedVisibleItem - this->currentVisibleScrollStart == maxVisibleItems - 2 && this->visibleItemCount - this->currentVisibleScrollStart > maxVisibleItems) {
this->currentVisibleScrollStart++;
}
this->selectedVisibleItem++;
}
}
this->update_visible_items();
}
bool Menu::enter()
{
if (this->currentEditingItem >= 0) {
this->currentEditingItem = -1;
if (this->currentEditingVisibleItem >= 0) {
this->currentEditingVisibleItem = -1;
return true;
}
this->currentEditingItem = this->selectedItem;
this->currentEditingVisibleItem = this->selectedVisibleItem;
return false;
}
bool Menu::back()
{
if (this->currentEditingItem >= 0) {
this->currentEditingItem = -1;
if (this->currentEditingVisibleItem >= 0) {
this->currentEditingVisibleItem = -1;
return false;
}
return true;

View file

@ -9,17 +9,22 @@
class Menu {
private:
AbstractMenuItem* items[MAXIMUM_MENU_ITEM_COUNT];
AbstractMenuItem* visibleItems[MAXIMUM_MENU_ITEM_COUNT];
uint8_t itemCount;
uint8_t selectedItem;
uint8_t currentScrollStart; // index we start rendering the menu from (for scrolling)
int8_t currentEditingItem;
uint8_t visibleItemCount;
uint8_t selectedVisibleItem;
uint8_t currentVisibleScrollStart; // index we start rendering the menu from (for scrolling)
int8_t currentEditingVisibleItem;
uint8_t width, height;
void update_visible_items();
public:
Menu()
: selectedItem(0)
, currentScrollStart(0)
, currentEditingItem(-1)
: selectedVisibleItem(0)
, currentVisibleScrollStart(0)
, currentEditingVisibleItem(-1)
, width(10)
, height(10) {};
@ -27,36 +32,12 @@ class Menu {
void down();
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
void add_item(AbstractMenuItem* item)
{
if (itemCount < MAXIMUM_MENU_ITEM_COUNT) {
items[itemCount++] = item;
}
}
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;
this->update_visible_items();
}
void render(U8G2* u8g2_, uint8_t x, uint8_t y, uint8_t width, uint8_t height);