mirror of
https://github.com/jhbruhn/eurorack.git
synced 2025-03-15 02:55:49 +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 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++;
|
||||
if (this->selectedVisibleItem < this->visibleItemCount - 1) {
|
||||
if (this->selectedVisibleItem - this->currentVisibleScrollStart == maxVisibleItems - 2 && this->visibleItemCount - this->currentVisibleScrollStart > maxVisibleItems) {
|
||||
this->currentVisibleScrollStart++;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue