diff --git a/src/widget/WidgetCharset.h b/src/widget/WidgetCharset.h deleted file mode 100644 index b38ae88a..00000000 --- a/src/widget/WidgetCharset.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include "BaseWidgetValue.h" - -/** - * @class WidgetCharset - * @brief Widget that allows a user to select a character from a charset. - * Manages a character value within a specified charset, allowing cycling through characters. - */ -class WidgetCharset : public BaseWidgetValue { - - protected: - const char*& charset; - const bool cycle; - int8_t charsetPosition = 0; - - public: - WidgetCharset( - int8_t charsetPosition, - const char*& charset, - const char* format, - const uint8_t cursorOffset, - const bool cycle, - void (*callback)(const char&)) - : BaseWidgetValue( - charsetPosition == -1 ? '\0' : charset[charsetPosition], - format, - cursorOffset, - callback), - charset(charset), cycle(cycle) {} - - protected: - uint8_t draw(char* buffer, const uint8_t start) override { - if (start >= ITEM_DRAW_BUFFER_SIZE) return 0; - return snprintf(buffer + start, ITEM_DRAW_BUFFER_SIZE - start, format, value == '\0' ? ' ' : value); - } - - /** - * @brief Process command. - * - * Handle commands: - * - `UP` - go to the next character in the charset and trigger callback - * - `DOWN` - go to the previous character in the charset and trigger callback - * - `BACKSPACE` - clear the value - */ - bool process(LcdMenu* menu, const unsigned char command) override { - MenuRenderer* renderer = menu->getRenderer(); - if (renderer->isInEditMode()) { - switch (command) { - case UP: - if (nextChar()) { - updateValue(F("WidgetCharset::nextChar")); - } - return true; - case DOWN: - if (previousChar()) { - updateValue(F("WidgetCharset::previousChar")); - } - return true; - case BACKSPACE: - if (backspace()) { - updateValue(F("WidgetCharset::backspace")); - } - return true; - default: - return false; - } - } - return false; - } - - void updateValue(const __FlashStringHelper* action) { - value = charset[charsetPosition]; - BaseWidgetValue::handleChange(); - LOG(action, value); - } - - bool backspace() { - if (value != '\0') { - value = '\0'; - charsetPosition = -1; - return true; - } - return false; - } - - bool nextChar() { - if (charset[charsetPosition + 1] != '\0') { - charsetPosition++; - return true; - } - if (cycle) { - charsetPosition = 0; - return true; - } - return false; - } - - bool previousChar() { - if (charsetPosition > 0) { - charsetPosition--; - return true; - } - if (cycle) { - charsetPosition = strlen(charset) - 1; - return true; - } - return false; - } -}; - -/** - * @brief Function to create a new WidgetCharset object. - * - * @param charset The charset to use for the widget. - * @param charsetPosition The initial position in the charset (default is -1 for no initial value). - * @param format The format to display the value (default is "%c"). - * @param cursorOffset The offset for the cursor (default is 0). - * @param cycle Whether the value should cycle when out of range (default is false). - * @param callback The callback function to execute when value changes (default is nullptr). - */ -inline BaseWidgetValue* WIDGET_CHARSET( - const char*& charset, - int8_t charsetPosition = -1, - const char* format = "%c", - uint8_t cursorOffset = 0, - bool cycle = false, - void (*callback)(const char&) = nullptr) { - return new WidgetCharset(charsetPosition, charset, format, cursorOffset, cycle, callback); -} \ No newline at end of file diff --git a/src/widget/WidgetList.h b/src/widget/WidgetList.h new file mode 100644 index 00000000..10e634a7 --- /dev/null +++ b/src/widget/WidgetList.h @@ -0,0 +1,112 @@ +#pragma once + +#include "BaseWidgetValue.h" + +/** + * @class WidgetList + * @brief Widget that allows a user to select a value from a list. + * Manages a value within a specified list, allowing cycling through values. + */ +template +class WidgetList : public BaseWidgetValue { + protected: + const uint8_t size; + uint8_t activePosition; + const bool cycle; + const T* values; + + public: + WidgetList( + const T values[], + const uint8_t size, + const int8_t activePosition, + const char* format, + const uint8_t cursorOffset, + const bool cycle, + void (*callback)(const T&)) + : BaseWidgetValue(values[activePosition], format, cursorOffset, callback), + size(size), + activePosition(activePosition), + cycle(cycle), + values(values) {} + + protected: + /** + * @brief Process command. + * + * Handle commands: + * - `UP` - increment value and trigger callback; + * - `DOWN` - decrement value and trigger callback; + */ + bool process(LcdMenu* menu, const unsigned char command) override { + MenuRenderer* renderer = menu->getRenderer(); + if (renderer->isInEditMode()) { + switch (command) { + case UP: + if (nextValue()) { + updateValue(F("WidgetList::nextValue")); + } + return true; + case DOWN: + if (previousValue()) { + updateValue(F("WidgetList::previousValue")); + } + return true; + default: + return false; + } + } + return false; + } + void updateValue(const __FlashStringHelper* action) { + this->value = values[activePosition]; + BaseWidgetValue::handleChange(); + LOG(action, this->value); + } + bool nextValue() { + if (activePosition + 1 < size) { + activePosition++; + return true; + } + if (cycle) { + activePosition = 0; + return true; + } + return false; + } + bool previousValue() { + if (activePosition > 0) { + activePosition--; + return true; + } + if (cycle) { + activePosition = size - 1; + return true; + } + return false; + } +}; + +/** + * @brief Function to create a new WidgetList instance. + * @tparam T The type of the value. + * + * @param values The list of values to choose from. + * @param size The size of the list. + * @param activePosition The initial active position in the list (default: 0). + * @param format The format of the value (default: "%s"). + * @param cursorOffset The cursor offset (default: 0). + * @param cycle Whether to cycle through the list (default: false). + * @param callback The callback function to call when the value changes (default: nullptr). + */ +template +inline BaseWidgetValue* WIDGET_LIST( + const T values[], + const uint8_t size, + const uint8_t activePosition = 0, + const char* format = "%s", + const uint8_t cursorOffset = 0, + const bool cycle = false, + void (*callback)(const T&) = nullptr) { + return new WidgetList(values, size, activePosition, format, cursorOffset, cycle, callback); +} \ No newline at end of file