diff --git a/src/ItemWidget.h b/src/ItemWidget.h index 655cc685..21d23d01 100644 --- a/src/ItemWidget.h +++ b/src/ItemWidget.h @@ -26,7 +26,6 @@ struct make_index_sequence<0, Is...> { using type = index_sequence; }; -// Updated ItemWidget class supporting zero or more widgets template class ItemWidget : public BaseItemManyWidgets { public: diff --git a/src/widget/WidgetCharset.h b/src/widget/WidgetCharset.h new file mode 100644 index 00000000..6d82bcb7 --- /dev/null +++ b/src/widget/WidgetCharset.h @@ -0,0 +1,106 @@ +// Creator: @ShishkinDmitriy +#pragma once + +#include "BaseWidgetValue.h" + +/** + * @class WidgetCharset + * @brief Widget that allows user to select a character from a charset. + * Manages a character value within a specified charset, allowing cycling through characters. + */ +class WidgetCharset : public BaseWidgetValue { + friend class ItemCharsetWidgets; + + protected: + const char*& charset; + const bool cycle; + uint8_t charsetPosition = 0; + + public: + WidgetCharset( + const char value, + const char*& charset, + const char* format, + const uint8_t cursorOffset, + const bool cycle, + void (*callback)(char)) + : BaseWidgetValue(value, 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()) { + value = charset[charsetPosition]; + BaseWidgetValue::handleChange(); + printLog(F("WidgetCharset::nextChar"), value); + } + return true; + case DOWN: + if (previousChar()) { + value = charset[charsetPosition]; + BaseWidgetValue::handleChange(); + printLog(F("WidgetCharset::previousChar"), value); + } + return true; + case BACKSPACE: + if (backspace()) { + printLog(F("WidgetCharset::backspace")); + BaseWidgetValue::handleChange(); + } + return true; + default: + return false; + } + } + return false; + } + + bool backspace() { + if (value != '\0') { + value = '\0'; + charsetPosition = 0; + 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; + } +}; \ No newline at end of file