From 52a49363eb770fc61a21756f87bd85712ef6f291 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Sat, 14 Jun 2025 19:02:51 +0200 Subject: [PATCH] optimized and commented code Signed-off-by: Peter Siegmund --- components/insa/include/MenuOptions.h | 19 +- components/insa/include/common/Common.h | 18 +- components/insa/include/common/PSMenu.h | 102 ++++++++- components/insa/include/common/ScrollBar.h | 52 ++++- components/insa/include/common/Widget.h | 34 ++- components/insa/include/data/MenuItem.h | 88 +++++++- components/insa/include/ui/MainMenu.h | 17 ++ components/insa/include/ui/SplashScreen.h | 37 +++- components/insa/src/common/PSMenu.cpp | 243 +++++++++++++-------- components/insa/src/common/ScrollBar.cpp | 18 +- 10 files changed, 494 insertions(+), 134 deletions(-) diff --git a/components/insa/include/MenuOptions.h b/components/insa/include/MenuOptions.h index e5a683d..7f047db 100644 --- a/components/insa/include/MenuOptions.h +++ b/components/insa/include/MenuOptions.h @@ -1,20 +1,33 @@ +// Prevents multiple inclusions of this header file #pragma once +// Standard libraries for function objects and smart pointers #include #include +// Project-specific headers #include "common/Widget.h" #include "u8g2.h" -class Widget; - +// Structure for menu options and callback functions typedef struct { + // Pointer to u8g2 display object for graphics output u8g2_t *u8g2; + // Callback function to set the current screen + // Parameter: Smart pointer to a Widget object std::function)> setScreen; + + // Callback function to add a new screen to the stack + // Parameter: Smart pointer to a Widget object std::function)> pushScreen; + + // Callback function to remove the top screen from the stack + // No parameters required std::function popScreen; + // Callback function to handle button presses + // Parameter: 8-bit button ID/status std::function onButtonClicked; -} menu_options_t; +} menu_options_t; \ No newline at end of file diff --git a/components/insa/include/common/Common.h b/components/insa/include/common/Common.h index 2f7c2e6..dca7e60 100644 --- a/components/insa/include/common/Common.h +++ b/components/insa/include/common/Common.h @@ -2,6 +2,20 @@ #include -enum class ButtonType { NONE, UP, DOWN, LEFT, RIGHT, SELECT, BACK }; +// Enumeration defining the different types of buttons available in the system +// NONE represents no button pressed or an invalid button state +enum class ButtonType { + NONE, // No button or invalid state + UP, // Up directional button + DOWN, // Down directional button + LEFT, // Left directional button + RIGHT, // Right directional button + SELECT, // Select/confirm button + BACK // Back/cancel button +}; -typedef std::function ButtonCallback; +// Type alias for button event callback function +// Parameters: +// - uint8_t: Button identifier or additional data +// - ButtonType: The type of button that was pressed +typedef std::function ButtonCallback; \ No newline at end of file diff --git a/components/insa/include/common/PSMenu.h b/components/insa/include/common/PSMenu.h index f8d202a..052891b 100644 --- a/components/insa/include/common/PSMenu.h +++ b/components/insa/include/common/PSMenu.h @@ -7,35 +7,131 @@ #include "Widget.h" #include "data/MenuItem.h" +/** + * PSMenu - A menu widget class + * + * This class extends the Widget base class to provide a customizable menu system + * with various types of interactive menu items including text buttons, selections, + * number inputs, and toggles. + */ class PSMenu : public Widget { public: + /** + * Constructor - Creates a new PSMenu instance + * @param options Pointer to menu configuration options + */ explicit PSMenu(menu_options_t *options); + + /** + * Destructor - Cleans up resources when menu is destroyed + */ ~PSMenu() override; + /** + * Adds a text-based menu item (button) to the menu + * @param id Unique identifier for this menu item + * @param text Display text shown on the menu + * @param callback Function to call when this item is selected + */ void addText(uint8_t id, const std::string &text, const ButtonCallback &callback); + + /** + * Adds a selection menu item (dropdown/list selection) + * @param id Unique identifier for this menu item + * @param text Display text/label for the selection + * @param value Reference to current selected value (will be modified) + * @param values Vector of all available options to choose from + * @param callback Function to call when selection changes + */ void addSelection(uint8_t id, const std::string &text, std::string &value, const std::vector& values, const ButtonCallback &callback); + + /** + * Adds a numeric input menu item + * @param id Unique identifier for this menu item + * @param text Display text/label for the number input + * @param value Reference to current numeric value as string (will be modified) + * @param callback Function to call when value changes + */ void addNumber(uint8_t id, const std::string &text, std::string &value, const ButtonCallback &callback); + + /** + * Adds a toggle/checkbox menu item + * @param id Unique identifier for this menu item + * @param text Display text/label for the toggle + * @param selected Current state of the toggle (true = on, false = off) + * @param callback Function to call when toggle state changes + */ void addToggle(uint8_t id, const std::string &text, bool selected, const ButtonCallback &callback); private: + /** + * Renders the entire menu on screen + * Override from Widget base class + */ void render() override; + + /** + * Handles button press events from the controller/input system + * @param button The button that was pressed + * Override from Widget base class + */ void onButtonClicked(uint8_t button) override; + // Navigation event handlers + /** + * Handles down arrow/stick input - moves selection down + */ void onPressedDown(); + + /** + * Handles up arrow/stick input - moves selection up + */ void onPressedUp(); + + /** + * Handles left arrow/stick input - decreases value for current item + */ void onPressedLeft() const; + + /** + * Handles right arrow/stick input - increases value for current item + */ void onPressedRight() const; + + /** + * Handles select/confirm button (X on PlayStation controller) + */ void onPressedSelect() const; + + /** + * Handles back/cancel button (Circle on PlayStation controller) + */ void onPressedBack() const; + // Rendering helper methods + /** + * Draws the scroll bar indicating position in long menus + */ void drawScrollBar() const; + + /** + * Draws the selection highlight box around current menu item + */ void drawSelectionBox() const; + /** + * Renders an individual menu item widget + * @param item Pointer to the menu item to render + * @param font Font to use for rendering text + * @param x X coordinate for rendering position + * @param y Y coordinate for rendering position + */ void renderWidget(const MenuItem *item, const uint8_t *font, int x, int y) const; - size_t m_selected_item = 0; - std::vector m_items; - menu_options_t *m_options; + // Member variables + size_t m_selected_item = 0; ///< Index of currently selected menu item + std::vector m_items; ///< Collection of all menu items + menu_options_t *m_options; ///< Pointer to menu configuration options }; \ No newline at end of file diff --git a/components/insa/include/common/ScrollBar.h b/components/insa/include/common/ScrollBar.h index 9292d67..b6a91d3 100644 --- a/components/insa/include/common/ScrollBar.h +++ b/components/insa/include/common/ScrollBar.h @@ -3,22 +3,50 @@ #include "MenuOptions.h" #include "Widget.h" +/** + * ScrollBar class that represents a vertical scrollbar widget + * Inherits from Widget base class and provides scrolling functionality + */ class ScrollBar final : public Widget { - public: +public: + /** + * Constructor for ScrollBar + * @param options Pointer to menu options configuration + * @param x X coordinate position of the scrollbar + * @param y Y coordinate position of the scrollbar + * @param width Width of the scrollbar + * @param height Height of the scrollbar + */ ScrollBar(const menu_options_t *options, size_t x, size_t y, size_t width, size_t height); + + /** + * Renders the scrollbar to the screen + * Overrides the base Widget render method + */ void render() override; + + /** + * Updates the scrollbar state with new values + * @param value Current scroll position value + * @param max Maximum scroll value + * @param min Minimum scroll value (default: 0) + */ void refresh(size_t value, size_t max, size_t min = 0); - private: - size_t m_x; - size_t m_y; - size_t m_width; - size_t m_height; - size_t m_value; - size_t m_max; - size_t m_min; +private: + // Position and dimensions + size_t m_x; // X coordinate of the scrollbar + size_t m_y; // Y coordinate of the scrollbar + size_t m_width; // Width of the scrollbar + size_t m_height; // Height of the scrollbar - size_t m_thumbHeight; - size_t m_thumbY; -}; + // Scroll state values + size_t m_value; // Current scroll position + size_t m_max; // Maximum scroll value + size_t m_min; // Minimum scroll value + + // Calculated thumb properties + size_t m_thumbHeight; // Height of the scroll thumb + size_t m_thumbY; // Y position of the scroll thumb +}; \ No newline at end of file diff --git a/components/insa/include/common/Widget.h b/components/insa/include/common/Widget.h index 71c2edd..c010852 100644 --- a/components/insa/include/common/Widget.h +++ b/components/insa/include/common/Widget.h @@ -1,22 +1,52 @@ #pragma once -#include - #include "u8g2.h" +/** + * Base class for UI widgets that can be rendered and interact with user input. + * This class provides a common interface for all widgets in the system. + */ class Widget { public: + /** + * Constructs a widget with the given u8g2 display context. + * @param u8g2 Pointer to the u8g2 display context used for rendering + */ explicit Widget(u8g2_t *u8g2); + /** + * Virtual destructor to ensure proper cleanup of derived classes. + */ virtual ~Widget() = default; + /** + * Updates the widget's internal state based on elapsed time. + * This method is called once per frame to handle animations, + * timers, or other time-dependent behavior. + * @param dt Delta time in milliseconds since last update + */ virtual void update(uint64_t dt); + /** + * Renders the widget to the display. + * This method should be overridden by derived classes to implement + * their specific rendering logic using the u8g2 display context. + */ virtual void render(); + /** + * Handles button click events. + * This method is called when a button is pressed and allows + * the widget to respond to user input. + * @param button The identifier of the button that was clicked + */ virtual void onButtonClicked(uint8_t button); protected: + /** + * Pointer to the u8g2 display context used for rendering operations. + * This provides access to drawing functions for text, graphics, and other UI elements. + */ u8g2_t *u8g2; }; \ No newline at end of file diff --git a/components/insa/include/data/MenuItem.h b/components/insa/include/data/MenuItem.h index bf91d08..7fa21fc 100644 --- a/components/insa/include/data/MenuItem.h +++ b/components/insa/include/data/MenuItem.h @@ -5,27 +5,103 @@ #include "common/Common.h" +/** + * Represents a menu item that can be displayed in a user interface. + * Supports different types of menu items with various interaction capabilities. + */ class MenuItem { public: + /** + * Constructor for a simple menu item with text and callback. + * @param id Unique identifier for this menu item + * @param type Type of the menu item (defines behavior and appearance) + * @param text Display text for the menu item + * @param callback Function to call when the item is activated + */ MenuItem(uint8_t id, uint8_t type, std::string text, ButtonCallback callback); + + /** + * Constructor for a menu item with a value field. + * @param id Unique identifier for this menu item + * @param type Type of the menu item + * @param text Display text for the menu item + * @param value Current value associated with this item + * @param callback Function to call when the item is activated + */ MenuItem(uint8_t id, uint8_t type, std::string text, std::string value, ButtonCallback callback); + + /** + * Constructor for a menu item with multiple selectable values. + * @param id Unique identifier for this menu item + * @param type Type of the menu item + * @param text Display text for the menu item + * @param value Currently selected value + * @param values List of all available values for selection + * @param callback Function to call when the item is activated + */ MenuItem(uint8_t id, uint8_t type, std::string text, std::string value, std::vector values, ButtonCallback callback); + + /** + * Constructor for a boolean/toggle menu item. + * @param id Unique identifier for this menu item + * @param type Type of the menu item + * @param text Display text for the menu item + * @param selected Whether this item is currently selected/checked + * @param callback Function to call when the item is activated + */ MenuItem(uint8_t id, uint8_t type, std::string text, bool selected, ButtonCallback callback); + + /** + * Gets the unique identifier of this menu item. + * @return The menu item's ID + */ [[nodiscard]] uint8_t getId() const; + + /** + * Gets the type of this menu item. + * @return The menu item's type + */ [[nodiscard]] uint8_t getType() const; + + /** + * Gets the display text of this menu item. + * @return Reference to the menu item's text + */ [[nodiscard]] const std::string &getText() const; + + /** + * Gets the current value of this menu item. + * @return Reference to the menu item's current value + */ [[nodiscard]] const std::string &getValue() const; + + /** + * Sets a new value for this menu item. + * @param value The new value to set + */ void setValue(const std::string &value); + + /** + * Handles button press events for this menu item. + * Calls the associated callback function if one exists. + * @param id The ID of the item that was pressed + * @param button The type of button that was pressed + */ void onButtonPressed(uint8_t id, ButtonType button) const; + + /** + * Checks if this menu item has an associated callback function. + * @return true if a callback is set, false otherwise + */ [[nodiscard]] bool hasCallback() const; private: - uint8_t m_id; - uint8_t m_type; - std::string m_text; - std::string m_value; - std::vector m_values; - ButtonCallback m_callback; + uint8_t m_id; // Unique identifier for this menu item + uint8_t m_type; // Type defining the item's behavior + std::string m_text; // Display text shown to the user + std::string m_value; // Current value (for value-based items) + std::vector m_values; // Available values (for selection items) + ButtonCallback m_callback; // Function to call when activated }; \ No newline at end of file diff --git a/components/insa/include/ui/MainMenu.h b/components/insa/include/ui/MainMenu.h index 68c573d..7b962b6 100644 --- a/components/insa/include/ui/MainMenu.h +++ b/components/insa/include/ui/MainMenu.h @@ -2,13 +2,30 @@ #include "common/PSMenu.h" +/** + * MainMenu class - represents the main menu interface of the application + * Inherits from PSMenu to provide menu functionality + */ class MainMenu final : public PSMenu { public: + /** + * Constructor - initializes the main menu with given options + * @param options Pointer to menu options configuration + */ explicit MainMenu(menu_options_t *options); private: + /** + * Handles button press events from the menu interface + * @param id Button identifier that was pressed + * @param button Type of button that was pressed + */ void onButtonPressed(uint8_t id, ButtonType button) const; + /** + * Pointer to menu options configuration + * Stores the menu configuration passed during construction + */ menu_options_t *m_options; }; \ No newline at end of file diff --git a/components/insa/include/ui/SplashScreen.h b/components/insa/include/ui/SplashScreen.h index 672c424..f3c90bc 100644 --- a/components/insa/include/ui/SplashScreen.h +++ b/components/insa/include/ui/SplashScreen.h @@ -3,13 +3,48 @@ #include "MenuOptions.h" #include "common/Widget.h" +/** + * @brief SplashScreen class represents the initial screen shown when the application starts + * + * This class inherits from Widget and is responsible for displaying the splash screen + * that typically shows application branding, loading status, or initialization messages. + * It's marked as final to prevent further inheritance. + */ class SplashScreen final : public Widget { public: + /** + * @brief Constructs a new SplashScreen object + * + * @param options Pointer to menu options configuration that controls + * the behavior and appearance of the splash screen + */ explicit SplashScreen(menu_options_t *options); + + /** + * @brief Updates the splash screen state and animations + * + * This method is called every frame to update the splash screen's + * internal state, handle timing, animations, or transitions. + * + * @param dt Delta time in milliseconds since the last update + */ void update(uint64_t dt) override; + + /** + * @brief Renders the splash screen to the display + * + * This method handles all the drawing operations for the splash screen, + * including background, logos, text, and any visual effects. + */ void render() override; private: + /** + * @brief Pointer to menu options configuration + * + * Stores the configuration options that control various aspects + * of the splash screen's behavior and appearance. + */ menu_options_t *m_options; -}; +}; \ No newline at end of file diff --git a/components/insa/src/common/PSMenu.cpp b/components/insa/src/common/PSMenu.cpp index 0b7aed1..c35b2a6 100644 --- a/components/insa/src/common/PSMenu.cpp +++ b/components/insa/src/common/PSMenu.cpp @@ -4,8 +4,30 @@ #include "common/ScrollBar.h" #include "u8g2.h" +// Menu item type constants for better readability +namespace MenuItemTypes { + constexpr uint8_t TEXT = 0; + constexpr uint8_t SELECTION = 1; + constexpr uint8_t NUMBER = 2; + constexpr uint8_t TOGGLE = 3; +} + +// UI layout constants +namespace UIConstants { + constexpr int LEFT_MARGIN = 8; + constexpr int RIGHT_PADDING = 8; + constexpr int SCROLLBAR_WIDTH = 3; + constexpr int FRAME_BOX_SIZE = 14; + constexpr int FRAME_OFFSET = 11; + constexpr int SELECTION_MARGIN = 10; + constexpr int CORNER_RADIUS = 3; + constexpr int LINE_SPACING = 14; + constexpr int BOTTOM_OFFSET = 10; +} + PSMenu::PSMenu(menu_options_t *options) : Widget(options->u8g2), m_options(options) { + // Set up button callback using lambda to forward to member function m_options->onButtonClicked = [this](const uint8_t button) { onButtonClicked(button); }; @@ -13,195 +35,226 @@ PSMenu::PSMenu(menu_options_t *options) : Widget(options->u8g2), m_options(optio PSMenu::~PSMenu() { - m_options->onButtonClicked = nullptr; + // Clean up callback to prevent dangling pointer + if (m_options) { + m_options->onButtonClicked = nullptr; + } } void PSMenu::render() { - if (m_selected_item < 0) - { - onPressedDown(); + // Initialize selection if not set + if (m_selected_item >= m_items.size() && !m_items.empty()) { + m_selected_item = 0; + } + + // Early return if no items to render + if (m_items.empty()) { + return; } + // Clear screen with black background u8g2_SetDrawColor(u8g2, 0); u8g2_DrawBox(u8g2, 0, 0, u8g2->width, u8g2->height); + // Set white foreground color for drawing u8g2_SetDrawColor(u8g2, 1); + // Draw UI components drawScrollBar(); drawSelectionBox(); - int x = 8; // sure? - auto widget = m_items.at(m_selected_item); - renderWidget(&widget, u8g2_font_helvB08_tr, x, u8g2->height / 2 + 3); + // Calculate center position for main item + const int centerY = u8g2->height / 2 + 3; + + // Render the currently selected item (main/center item) + const auto& selectedItem = m_items[m_selected_item]; + renderWidget(&selectedItem, u8g2_font_helvB08_tr, UIConstants::LEFT_MARGIN, centerY); - if (m_selected_item > 0) - { - auto item = m_items.at(m_selected_item - 1); - renderWidget(&item, u8g2_font_haxrcorp4089_tr, x, 14); + // Render previous item (above) if available + if (m_selected_item > 0) { + const auto& prevItem = m_items[m_selected_item - 1]; + renderWidget(&prevItem, u8g2_font_haxrcorp4089_tr, UIConstants::LEFT_MARGIN, UIConstants::LINE_SPACING); } - if (m_selected_item < m_items.size() - 1) - { - auto item = m_items.at(m_selected_item + 1); - renderWidget(&item, u8g2_font_haxrcorp4089_tr, x, u8g2->height - 10); + + // Render next item (below) if available + if (m_selected_item < m_items.size() - 1) { + const auto& nextItem = m_items[m_selected_item + 1]; + renderWidget(&nextItem, u8g2_font_haxrcorp4089_tr, UIConstants::LEFT_MARGIN, u8g2->height - UIConstants::BOTTOM_OFFSET); } } void PSMenu::renderWidget(const MenuItem *item, const uint8_t *font, const int x, const int y) const { + // Set font and draw main text u8g2_SetFont(u8g2, font); u8g2_DrawStr(u8g2, x, y, item->getText().c_str()); - switch (item->getType()) - { - case 1: // Selection - { - std::string value = "< "; - value += item->getValue(); - value += " >"; - const u8g2_uint_t w = u8g2_GetStrWidth(u8g2, value.c_str()); - u8g2_DrawStr(u8g2, u8g2->width - w - 10, y, value.c_str()); - break; - } - - case 3: // toggle - { - u8g2_DrawFrame(u8g2, u8g2->width - 24, y - 11, 14, 14); - if (strcmp(item->getValue().c_str(), "true") == 0) - { - u8g2_DrawLine(u8g2, u8g2->width - 22, y - 9, u8g2->width - 13, y); - u8g2_DrawLine(u8g2, u8g2->width - 22, y, u8g2->width - 13, y - 9); + + // Render type-specific elements + switch (item->getType()) { + case MenuItemTypes::SELECTION: { + // Format selection value with angle brackets + const std::string formattedValue = "< " + item->getValue() + " >"; + const u8g2_uint_t textWidth = u8g2_GetStrWidth(u8g2, formattedValue.c_str()); + u8g2_DrawStr(u8g2, u8g2->width - textWidth - UIConstants::SELECTION_MARGIN, y, formattedValue.c_str()); + break; } - break; - } - - default: - - + + case MenuItemTypes::TOGGLE: { + // Draw checkbox frame + const int frameX = u8g2->width - UIConstants::FRAME_BOX_SIZE - UIConstants::SELECTION_MARGIN; + const int frameY = y - UIConstants::FRAME_OFFSET; + u8g2_DrawFrame(u8g2, frameX, frameY, UIConstants::FRAME_BOX_SIZE, UIConstants::FRAME_BOX_SIZE); + + // Draw checkmark (X) if toggle is true + if (item->getValue() == "true") { + const int checkX1 = frameX + 2; + const int checkY1 = frameY + 2; + const int checkX2 = frameX + UIConstants::FRAME_BOX_SIZE - 3; + const int checkY2 = frameY + UIConstants::FRAME_BOX_SIZE - 3; + + // Draw X pattern for checked state + u8g2_DrawLine(u8g2, checkX1, checkY1, checkX2, checkY2); + u8g2_DrawLine(u8g2, checkX1, checkY2, checkX2, checkY1); + } + break; + } + + case MenuItemTypes::TEXT: + case MenuItemTypes::NUMBER: + default: + // No additional rendering needed for text and number types + break; } } void PSMenu::onButtonClicked(const uint8_t button) { - switch (button) - { - case BUTTON_UP: - onPressedUp(); - break; + // Map button input to navigation functions + switch (button) { + case BUTTON_UP: + onPressedUp(); + break; - case BUTTON_DOWN: - onPressedDown(); - break; + case BUTTON_DOWN: + onPressedDown(); + break; - case BUTTON_LEFT: - onPressedLeft(); - break; + case BUTTON_LEFT: + onPressedLeft(); + break; - case BUTTON_RIGHT: - onPressedRight(); - break; + case BUTTON_RIGHT: + onPressedRight(); + break; - case BUTTON_SELECT: - onPressedSelect(); - break; + case BUTTON_SELECT: + onPressedSelect(); + break; - case BUTTON_BACK: - onPressedBack(); - break; + case BUTTON_BACK: + onPressedBack(); + break; - default: - break; + default: + // Ignore unknown button inputs + break; } } void PSMenu::onPressedDown() { - if (m_selected_item == m_items.size() - 1) - { - m_selected_item = 0; - } - else - { - m_selected_item++; - } + if (m_items.empty()) return; + + // Wrap around to first item when at the end + m_selected_item = (m_selected_item + 1) % m_items.size(); } void PSMenu::onPressedUp() { - if (m_selected_item == 0) - { - m_selected_item = m_items.size() - 1; - } - else - { - m_selected_item--; - } + if (m_items.empty()) return; + + // Wrap around to last item when at the beginning + m_selected_item = (m_selected_item == 0) ? m_items.size() - 1 : m_selected_item - 1; } void PSMenu::onPressedLeft() const { - const auto item = m_items.at(m_selected_item); - item.onButtonPressed(item.getId(), ButtonType::LEFT); + if (m_selected_item < m_items.size()) { + const auto& item = m_items[m_selected_item]; + item.onButtonPressed(item.getId(), ButtonType::LEFT); + } } void PSMenu::onPressedRight() const { - const auto item = m_items.at(m_selected_item); - item.onButtonPressed(item.getId(), ButtonType::RIGHT); + if (m_selected_item < m_items.size()) { + const auto& item = m_items[m_selected_item]; + item.onButtonPressed(item.getId(), ButtonType::RIGHT); + } } void PSMenu::onPressedSelect() const { - const auto item = m_items.at(m_selected_item); - item.onButtonPressed(item.getId(), ButtonType::SELECT); + if (m_selected_item < m_items.size()) { + const auto& item = m_items[m_selected_item]; + item.onButtonPressed(item.getId(), ButtonType::SELECT); + } } void PSMenu::onPressedBack() const { - if (m_options && m_options->popScreen) - { + // Navigate back to previous screen if callback is available + if (m_options && m_options->popScreen) { m_options->popScreen(); } } void PSMenu::addText(uint8_t id, const std::string &text, const ButtonCallback &callback) { - m_items.emplace_back(id, 0, text, callback); + m_items.emplace_back(id, MenuItemTypes::TEXT, text, callback); } void PSMenu::addSelection(uint8_t id, const std::string &text, std::string &value, const std::vector &values, const ButtonCallback &callback) { - m_items.emplace_back(id, 1, text, value, values, callback); + m_items.emplace_back(id, MenuItemTypes::SELECTION, text, value, values, callback); } void PSMenu::addNumber(uint8_t id, const std::string &text, std::string &value, const ButtonCallback &callback) { - m_items.emplace_back(id, 2, text, value, callback); + m_items.emplace_back(id, MenuItemTypes::NUMBER, text, value, callback); } void PSMenu::addToggle(uint8_t id, const std::string &text, bool selected, const ButtonCallback &callback) { - m_items.emplace_back(id, 3, text, selected, callback); + m_items.emplace_back(id, MenuItemTypes::TOGGLE, text, selected, callback); } void PSMenu::drawScrollBar() const { - ScrollBar scrollBar(m_options, u8g2->width - 3, 3, 1, u8g2->height - 6); + // Create scrollbar instance + ScrollBar scrollBar(m_options, u8g2->width - UIConstants::SCROLLBAR_WIDTH, 3, 1, u8g2->height - 6); scrollBar.refresh(m_selected_item, m_items.size()); scrollBar.render(); } void PSMenu::drawSelectionBox() const { + // Calculate dimensions for the selection box const auto displayHeight = u8g2->height; const auto displayWidth = u8g2->width; - constexpr auto rightPadding = 8; const auto boxHeight = displayHeight / 3; const auto y = boxHeight * 2 - 2; - const auto x = displayWidth - rightPadding; + const auto x = displayWidth - UIConstants::RIGHT_PADDING; - u8g2_DrawRFrame(u8g2, 2, boxHeight, displayWidth - rightPadding, boxHeight, 3); - u8g2_DrawLine(u8g2, 4, y, displayWidth - rightPadding, y); + // Draw the rounded frame for the selection box + u8g2_DrawRFrame(u8g2, 2, boxHeight, displayWidth - UIConstants::RIGHT_PADDING, boxHeight, UIConstants::CORNER_RADIUS); + + // Draw horizontal line separator + u8g2_DrawLine(u8g2, 4, y, displayWidth - UIConstants::RIGHT_PADDING, y); + + // Draw vertical line on the right side u8g2_DrawLine(u8g2, x, y - boxHeight + 3, x, y - 1); } \ No newline at end of file diff --git a/components/insa/src/common/ScrollBar.cpp b/components/insa/src/common/ScrollBar.cpp index 73b1681..44b7b40 100644 --- a/components/insa/src/common/ScrollBar.cpp +++ b/components/insa/src/common/ScrollBar.cpp @@ -9,19 +9,17 @@ ScrollBar::ScrollBar(const menu_options_t *options, const size_t x, const size_t void ScrollBar::render() { - if (1 == m_max) + // Early return if scrollbar is not needed (only one item) + if (m_max <= 1) { return; - - // draw dotted line - for (size_t y = m_y; y < m_y + m_height; y++) - { - if (y % 2 == 0) - { - u8g2_DrawPixel(u8g2, m_x, y); - } } - // draw thumb + // Draw dotted track line for visual reference + for (size_t y = m_y; y < m_y + m_height; y += 2) { + u8g2_DrawPixel(u8g2, m_x, y); + } + + // Draw scroll thumb to indicate current position u8g2_DrawBox(u8g2, u8g2->width - 4, m_thumbY, 3, m_thumbHeight); }