Skip to content

Commit

Permalink
Add ItemValue class for dynamic value display
Browse files Browse the repository at this point in the history
- Introduced a new template class to create menu items that display values.
- Added polling functionality to update the menu at regular intervals.
- Updated LcdMenu and MenuScreen classes to support polling.
- Defined ITEM_VALUE macro for easy item creation with formatting options.
  • Loading branch information
forntoh committed Jan 4, 2025
1 parent 40b3a1b commit 44d8e09
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 2 deletions.
55 changes: 55 additions & 0 deletions src/ItemValue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#include "BaseItemZeroWidget.h"

/**
* @class ItemValue
* @brief A menu item that displays a value.
*
* This class extends the BaseItemZeroWidget class and provides a menu item
* that displays a value. The value is provided as a reference during construction
* and is displayed using the provided format string.
*/
template <typename T>
class ItemValue : public BaseItemZeroWidget {
private:
T& value;
const char* format;

public:
ItemValue(const char* text, T& value, const char* format) : BaseItemZeroWidget(text), value(value), format(format) {
this->polling = true;
}

protected:
void handleCommit(LcdMenu* menu) override {}

void draw(MenuRenderer* renderer) override {
char buffer[ITEM_DRAW_BUFFER_SIZE];
snprintf(buffer, ITEM_DRAW_BUFFER_SIZE, format, value);
renderer->drawItem(text, buffer);
}
};

/**
* @brief Create a new item that displays a value.
* @note If you want to display a value that changes over time, use this item and
* call `LcdMenu::poll` in the loop function.
*
* @tparam T the type of the value to display
* @param text the text to display for the item
* @param value the value to display
* @param format the format string to use when displaying the value
* @return MenuItem* the created item
*
* @example
* int temp = 25;
* auto item = ITEM_VALUE("Temperature", temp, "%d°C");
*/
template <typename T>
inline MenuItem* ITEM_VALUE(
const char* text,
T& value,
const char* format = "%s") {
return new ItemValue<T>(text, value, format);
}
7 changes: 7 additions & 0 deletions src/LcdMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,10 @@ void LcdMenu::refresh() {
}
screen->draw(&renderer);
}

void LcdMenu::poll(uint16_t pollInterval) {
if (!enabled || pollInterval == 0) {
return;
}
screen->poll(&renderer, pollInterval < 100 ? 100 : pollInterval);
}
9 changes: 9 additions & 0 deletions src/LcdMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,13 @@ class LcdMenu {
* @brief Refresh the current screen.
*/
void refresh();
/**
* @brief Poll the menu for changes.
* This method is used to update the menu at regular intervals,
* for example, when a value bound to an item changes, the menu needs to be updated.
* This method should be called in the `loop` function of the sketch.
*
* @param pollInterval the interval to update the menu in milliseconds (default is 1000)
*/
void poll(uint16_t pollInterval = 1000);
};
3 changes: 3 additions & 0 deletions src/MenuItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#ifndef MenuItem_H
#define MenuItem_H

#define ITEM_DRAW_BUFFER_SIZE 25

#include "renderer/MenuRenderer.h"
#include "utils/constants.h"
#include <utils/utils.h>
Expand All @@ -49,6 +51,7 @@ class MenuItem {

protected:
const char* text = NULL;
bool polling = false;

public:
MenuItem(const char* text) : text(text) {}
Expand Down
13 changes: 13 additions & 0 deletions src/MenuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,17 @@ MenuScreen::MenuScreen(MenuItem** items) : items(items) {
while (items[itemCount] != nullptr) {
itemCount++;
}
}

void MenuScreen::poll(MenuRenderer* renderer, uint16_t pollInterval) {
static unsigned long lastPollTime = 0;
if (millis() - lastPollTime >= pollInterval) {
for (uint8_t i = 0; i < renderer->maxRows; i++) {
MenuItem* item = this->items[view + i];
if (item == nullptr || !item->polling) break;
syncIndicators(i, renderer);
item->draw(renderer);
}
lastPollTime = millis();
}
}
6 changes: 6 additions & 0 deletions src/MenuScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ class MenuScreen {
* @brief Reset the screen to initial state.
*/
void reset(MenuRenderer* renderer);
/**
* @brief Poll the screen for changes.
* @param renderer The renderer to use for drawing.
* @param pollInterval The interval to poll the screen.
*/
void poll(MenuRenderer* renderer, uint16_t pollInterval);
};

#define MENU_SCREEN(screen, items, ...) \
Expand Down
2 changes: 0 additions & 2 deletions src/widget/BaseWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#endif
#endif

#define ITEM_DRAW_BUFFER_SIZE 25

class LcdMenu;

/**
Expand Down

0 comments on commit 44d8e09

Please sign in to comment.