Files
EasyMenu/src/MenuSystem.cpp
2025-05-06 15:15:17 +02:00

152 lines
4.5 KiB
C++

#include "MenuSystem.h"
#include "MenuGraphics.h"
MenuSystem::MenuSystem(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display) {
_display = display;
_itemCount = 0;
_selectedItem = 0;
_screen = 0;
_btnUp = false;
_btnSelect = false;
_btnDown = false;
_prevBtnUp = false;
_prevBtnSelect = false;
_prevBtnDown = false;
// Initialize arrays
for (int i = 0; i < MAX_ITEMS; i++) {
_itemNames[i][0] = '\0';
_itemIcons[i] = nullptr;
_itemScreens[i] = nullptr;
_itemCallbacks[i] = nullptr;
}
}
void MenuSystem::begin() {
// Ensure display is properly initialized
_display->begin();
_display->clearBuffer();
_display->sendBuffer();
delay(100); // Short delay to ensure display is ready
}
void MenuSystem::addMenuItem(const char* name, const uint8_t* icon) {
if (_itemCount < MAX_ITEMS) {
strncpy(_itemNames[_itemCount], name, MAX_NAME_LEN-1);
_itemNames[_itemCount][MAX_NAME_LEN-1] = '\0'; // Ensure null termination
_itemIcons[_itemCount] = icon;
_itemCount++;
}
}
void MenuSystem::setItemCallback(int index, void (*callback)()) {
if (index >= 0 && index < _itemCount) {
_itemCallbacks[index] = callback;
}
}
void MenuSystem::setButtons(bool up, bool select, bool down) {
// Save previous button states
_prevBtnUp = _btnUp;
_prevBtnSelect = _btnSelect;
_prevBtnDown = _btnDown;
// Set new button states
_btnUp = up;
_btnSelect = select;
_btnDown = down;
}
void MenuSystem::update() {
// Process button inputs before drawing
handleButtons();
// Simple drawing approach (not using page buffer mode)
_display->clearBuffer();
if (_screen == 0) {
// Draw the main menu screen
drawMenu();
} else if (_screen == 1 && _itemScreens[_selectedItem] != nullptr) {
// Draw the full-screen bitmap for the selected item
_display->drawXBM(0, 0, 128, 64, _itemScreens[_selectedItem]);
}
_display->sendBuffer();
}
void MenuSystem::drawMenu() {
if (_itemCount == 0) return; // Nothing to draw
// Calculate which items to show (previous, current, next)
int prevItem = (_selectedItem > 0) ? _selectedItem - 1 : _itemCount - 1;
int nextItem = (_selectedItem < _itemCount - 1) ? _selectedItem + 1 : 0;
// Draw the background with the item selector outline (if enabled)
// _display->drawXBM(0, 0, 128, 64, bitmap_item_sel_outline);
// Instead, draw a simple selection highlight
_display->drawFrame(0, 20, 128, 24); // Highlight the middle selection
// Draw previous item (top position)
_display->setFont(u8g2_font_6x10_tf); // Use a different, simpler font
_display->drawStr(25, 15, _itemNames[prevItem]);
if (_itemIcons[prevItem] != nullptr) {
_display->drawXBM(4, 2, 16, 16, _itemIcons[prevItem]);
}
// Draw selected item (middle position)
_display->setFont(u8g2_font_6x10_tf); // Use same font for consistency
_display->drawStr(25, 35, _itemNames[_selectedItem]);
if (_itemIcons[_selectedItem] != nullptr) {
_display->drawXBM(4, 24, 16, 16, _itemIcons[_selectedItem]);
}
// Draw next item (bottom position)
_display->setFont(u8g2_font_6x10_tf); // Use same font for consistency
_display->drawStr(25, 55, _itemNames[nextItem]);
if (_itemIcons[nextItem] != nullptr) {
_display->drawXBM(4, 46, 16, 16, _itemIcons[nextItem]);
}
// Draw a simple scrollbar instead of using bitmap
if (_itemCount > 1) {
_display->drawVLine(125, 0, 64); // Scrollbar background
int barHeight = 64 / _itemCount;
int barY = (_selectedItem * 64) / _itemCount;
_display->drawBox(123, barY, 4, barHeight); // Scrollbar handle
}
}
void MenuSystem::handleButtons() {
// Only respond to button press events (not holds)
// Button rising edge detection for up
if (_btnUp && !_prevBtnUp) {
_selectedItem = (_selectedItem > 0) ? _selectedItem - 1 : _itemCount - 1;
Serial.print("Selected item: ");
Serial.println(_selectedItem);
}
// Button rising edge detection for down
if (_btnDown && !_prevBtnDown) {
_selectedItem = (_selectedItem < _itemCount - 1) ? _selectedItem + 1 : 0;
Serial.print("Selected item: ");
Serial.println(_selectedItem);
}
// Button rising edge detection for select
if (_btnSelect && !_prevBtnSelect) {
// Execute callback if it exists
if (_itemCallbacks[_selectedItem] != nullptr) {
_itemCallbacks[_selectedItem]();
}
// Toggle between menu and item screen if screen exists
if (_itemScreens[_selectedItem] != nullptr) {
_screen = (_screen == 0) ? 1 : 0;
Serial.print("Screen changed to: ");
Serial.println(_screen);
}
}
}