eurorack/midi2cv/menu/menu.cc

141 lines
4.2 KiB
C++
Raw Normal View History

2020-01-03 21:09:11 +00:00
#include "menu.h"
#include <algorithm>
#include <u8g2.h>
2020-02-22 23:15:01 +00:00
const int kMenuItemHeight = 12;
2020-01-03 21:09:11 +00:00
2020-02-23 10:15:27 +00:00
void Menu::render(U8G2* u8g2_, uint8_t xStart, uint8_t yStart, uint8_t width, uint8_t height)
{
if (this->visibility_dirty) {
this->update_visible_items();
this->visibility_dirty = false;
}
this->width = width;
this->height = height;
2020-02-22 23:15:01 +00:00
uint8_t maxVisibleItems = height / kMenuItemHeight;
2020-01-03 21:09:11 +00:00
2020-02-26 18:16:33 +00:00
uint8_t itemsToRender = std::min(maxVisibleItems, uint8_t(this->visibleItemCount - currentVisibleScrollStart));
2020-02-23 10:15:27 +00:00
u8g2_->setFont(u8g2_font_6x10_tf);
for (uint8_t i = 0; i < itemsToRender; i++) {
2020-02-22 23:15:01 +00:00
uint8_t yPosition = yStart + i * kMenuItemHeight;
2020-02-26 18:16:33 +00:00
uint8_t itemIndex = this->currentVisibleScrollStart + i;
2020-02-26 18:16:33 +00:00
AbstractMenuItem* item = this->visibleItems[itemIndex];
2020-02-26 18:16:33 +00:00
bool selected = this->selectedVisibleItem == itemIndex;
bool editing = this->currentEditingVisibleItem == itemIndex;
2020-02-23 10:15:27 +00:00
u8g2_->setDrawColor(selected ? 1 : 0);
if (editing) {
2020-02-23 10:15:27 +00:00
u8g2_->drawFrame(xStart, yPosition, width, kMenuItemHeight);
2020-02-21 00:39:20 +00:00
} else if (selected) {
2020-02-23 10:15:27 +00:00
u8g2_->drawBox(xStart, yPosition, width, kMenuItemHeight);
}
2020-02-23 10:15:27 +00:00
u8g2_->setDrawColor(editing || !selected ? 1 : 0);
u8g2_->drawStr(xStart + 2, yPosition + kMenuItemHeight - 3, item->get_label());
2020-02-23 10:15:27 +00:00
uint8_t valueStringWidth = u8g2_->getStrWidth(item->get_string_representation());
u8g2_->drawStr(xStart + width - valueStringWidth - 2, yPosition + kMenuItemHeight - 3, item->get_string_representation());
itemIndex++;
}
2020-01-03 21:09:11 +00:00
}
2020-02-26 18:16:33 +00:00
void Menu::update_visible_items()
{
AbstractMenuItem* currentlySelectedItem = this->visibleItems[this->selectedVisibleItem];
2020-02-26 18:16:33 +00:00
// set all visibleItems to null
this->visibleItemCount = 0;
for (size_t i = 0; i < MAXIMUM_MENU_ITEM_COUNT; i++) {
this->visibleItems[i] = NULL;
}
2020-02-26 19:03:41 +00:00
uint8_t newIndexSelectedItem = 0;
2020-02-26 18:16:33 +00:00
// 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()) {
if (currentlySelectedItem && this->items[i] == currentlySelectedItem) {
2020-02-26 19:03:41 +00:00
newIndexSelectedItem = this->visibleItemCount;
}
2020-02-26 18:16:33 +00:00
this->visibleItems[this->visibleItemCount++] = this->items[i];
}
}
// if our visibleitem changed, chances are that the index of the selected item has changed:
if (currentlySelectedItem && this->visibleItems[this->selectedVisibleItem] != currentlySelectedItem) {
2020-02-26 19:03:41 +00:00
int8_t delta = this->selectedVisibleItem - newIndexSelectedItem;
this->selectedVisibleItem = this->currentEditingVisibleItem = newIndexSelectedItem;
this->currentVisibleScrollStart -= delta;
CONSTRAIN(this->currentVisibleScrollStart, 0, this->visibleItemCount);
CONSTRAIN(this->currentEditingVisibleItem, 0, this->visibleItemCount);
}
2020-02-26 18:16:33 +00:00
}
void Menu::up()
{
2020-02-26 18:16:33 +00:00
if (this->currentEditingVisibleItem >= 0) {
2020-02-26 18:29:42 +00:00
AbstractMenuItem* item = this->visibleItems[this->selectedVisibleItem];
if (item)
item->decrease();
2020-02-26 18:16:33 +00:00
} else if (this->selectedVisibleItem > 0) {
uint8_t newItem = this->selectedVisibleItem - 1;
2020-02-26 18:16:33 +00:00
if (newItem - this->currentVisibleScrollStart == 0) { // keep scroll start one up
this->currentVisibleScrollStart--;
}
2020-02-26 18:16:33 +00:00
this->selectedVisibleItem = newItem;
2020-02-26 18:16:33 +00:00
if (this->selectedVisibleItem == 0) {
this->currentVisibleScrollStart = 0;
}
}
this->visibility_dirty = true;
}
void Menu::down()
{
2020-02-26 18:16:33 +00:00
if (this->currentEditingVisibleItem >= 0) {
2020-02-26 18:29:42 +00:00
AbstractMenuItem* item = this->visibleItems[this->selectedVisibleItem];
if (item)
item->increase();
2020-02-21 00:39:20 +00:00
} else {
2020-02-22 23:15:01 +00:00
uint8_t maxVisibleItems = height / kMenuItemHeight;
2020-02-26 18:16:33 +00:00
if (this->selectedVisibleItem < this->visibleItemCount - 1) {
if (this->selectedVisibleItem - this->currentVisibleScrollStart == maxVisibleItems - 2 && this->visibleItemCount - this->currentVisibleScrollStart > maxVisibleItems) {
this->currentVisibleScrollStart++;
2020-02-21 00:39:20 +00:00
}
2020-02-26 18:16:33 +00:00
this->selectedVisibleItem++;
}
2020-02-21 00:39:20 +00:00
}
this->visibility_dirty = true;
2020-02-21 00:39:20 +00:00
}
bool Menu::enter()
2020-02-21 00:39:20 +00:00
{
2020-02-26 18:16:33 +00:00
if (this->currentEditingVisibleItem >= 0) {
this->currentEditingVisibleItem = -1;
return true;
}
2020-02-26 18:16:33 +00:00
this->currentEditingVisibleItem = this->selectedVisibleItem;
return false;
}
bool Menu::back()
{
2020-02-26 18:16:33 +00:00
if (this->currentEditingVisibleItem >= 0) {
this->currentEditingVisibleItem = -1;
return false;
}
return true;
}