From aed389f3b21292bf9ecc5492252427c581372ed4 Mon Sep 17 00:00:00 2001 From: Thomas Hooge Date: Fri, 1 Aug 2025 17:08:01 +0200 Subject: [PATCH] Added code for configuration menu handling --- lib/obp60task/ConfigMenu.cpp | 194 +++++++++++++++++++++++++++++++++++ lib/obp60task/ConfigMenu.h | 63 ++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 lib/obp60task/ConfigMenu.cpp create mode 100644 lib/obp60task/ConfigMenu.h diff --git a/lib/obp60task/ConfigMenu.cpp b/lib/obp60task/ConfigMenu.cpp new file mode 100644 index 0000000..1627531 --- /dev/null +++ b/lib/obp60task/ConfigMenu.cpp @@ -0,0 +1,194 @@ +/* + Menu system for online configuration +*/ +#include "ConfigMenu.h" + +ConfigMenuItem::ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit) { + if (! (itemtype == "int" or itemtype == "bool")) { + valtype = "int"; + } else { + valtype = itemtype; + } + label = itemlabel; + min = 0; + max = std::numeric_limits::max(); + value = itemval; + unit = itemunit; +} + +void ConfigMenuItem::setRange(uint16_t valmin, uint16_t valmax, std::vector valsteps) { + min = valmin; + max = valmax; + steps = valsteps; +}; + +bool ConfigMenuItem::checkRange(uint16_t checkval) { + return (checkval >= min) and (checkval <= max); +} + +String ConfigMenuItem::getLabel() { + return label; +}; + +uint16_t ConfigMenuItem::getValue() { + return value; +} + +bool ConfigMenuItem::setValue(uint16_t newval) { + if (valtype == "int") { + if (newval >= min and newval <= max) { + value = newval; + return true; + } + return false; // out of range + } else if (valtype == "bool") { + value = (newval != 0) ? 1 : 0; + return true; + } + return false; // invalid type +}; + +void ConfigMenuItem::incValue() { + // increase value by step + if (valtype == "int") { + if (value + step < max) { + value += step; + } else { + value = max; + } + } else if (valtype == "bool") { + value = !value; + } +}; + +void ConfigMenuItem::decValue() { + // decrease value by step + if (valtype == "int") { + if (value - step > min) { + value -= step; + } else { + value = min; + } + } else if (valtype == "bool") { + value = !value; + } +}; + +String ConfigMenuItem::getUnit() { + return unit; +} + +uint16_t ConfigMenuItem::getStep() { + return step; +} + +void ConfigMenuItem::setStep(uint16_t newstep) { + if (std::find(steps.begin(), steps.end(), newstep) == steps.end()) { + return; // invalid step: not in list of possible steps + } + step = newstep; +} + +int8_t ConfigMenuItem::getPos() { + return position; +}; + +void ConfigMenuItem::setPos(int8_t newpos) { + position = newpos; +}; + +String ConfigMenuItem::getType() { + return valtype; +} + +ConfigMenu::ConfigMenu(String menutitle, uint16_t menu_x, uint16_t menu_y) { + title = menutitle; + x = menu_x; + y = menu_y; +}; + +ConfigMenuItem* ConfigMenu::addItem(String key, String label, String valtype, uint16_t val, String valunit) { + if (items.find(key) != items.end()) { + // duplicate keys not allowed + return nullptr; + } + ConfigMenuItem *itm = new ConfigMenuItem(valtype, label, val, valunit); + items.insert(std::pair(key, itm)); + // Append key to index, index starting with 0 + int8_t ix = items.size() - 1; + index[ix] = key; + itm->setPos(ix); + return itm; +}; + +void ConfigMenu::setItemDimension(uint16_t itemwidth, uint16_t itemheight) { + w = itemwidth; + h = itemheight; +}; + +void ConfigMenu::setItemActive(String key) { + if (items.find(key) != items.end()) { + activeitem = items[key]->getPos(); + } else { + activeitem = -1; + } +}; + +int8_t ConfigMenu::getActiveIndex() { + return activeitem; +} + +ConfigMenuItem* ConfigMenu::getActiveItem() { + if (activeitem < 0) { + return nullptr; + } + return items[index[activeitem]]; +}; + +ConfigMenuItem* ConfigMenu::getItemByIndex(uint8_t ix) { + if (ix > index.size() - 1) { + return nullptr; + } + return items[index[ix]]; +}; + +ConfigMenuItem* ConfigMenu::getItemByKey(String key) { + if (items.find(key) == items.end()) { + return nullptr; + } + return items[key]; +}; + +uint8_t ConfigMenu::getItemCount() { + return items.size(); +}; + +void ConfigMenu::goPrev() { + if (activeitem == 0) { + activeitem = items.size() - 1; + } else { + activeitem--; + } +} + +void ConfigMenu::goNext() { + if (activeitem == items.size() - 1) { + activeitem = 0; + } else { + activeitem++; + } +} + +Point ConfigMenu::getXY() { + return {static_cast(x), static_cast(y)}; +} + +Rect ConfigMenu::getRect() { + return {static_cast(x), static_cast(y), + static_cast(w), static_cast(h)}; +} + +Rect ConfigMenu::getItemRect(int8_t index) { + return {static_cast(x), static_cast(y + index * h), + static_cast(w), static_cast(h)}; +} diff --git a/lib/obp60task/ConfigMenu.h b/lib/obp60task/ConfigMenu.h new file mode 100644 index 0000000..439097d --- /dev/null +++ b/lib/obp60task/ConfigMenu.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include "Graphics.h" // for Point and Rect + +class ConfigMenuItem { +private: + String label; + uint16_t value; + String unit; + String valtype; // "int" | "bool" + uint16_t min; + uint16_t max; + std::vector steps; + uint16_t step; + int8_t position; // counted fom 0 + +public: + ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit); + void setRange(uint16_t valmin, uint16_t valmax, std::vector steps); + bool checkRange(uint16_t checkval); + String getLabel(); + uint16_t getValue(); + bool setValue(uint16_t newval); + void incValue(); + void decValue(); + String getUnit(); + uint16_t getStep(); + void setStep(uint16_t newstep); + int8_t getPos(); + void setPos(int8_t newpos); + String getType(); +}; + +class ConfigMenu { +private: + String title; + std::map items; + std::map index; + int8_t activeitem = -1; // refers to position of item + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; + +public: + ConfigMenu(String title, uint16_t menu_x, uint16_t menu_y); + ConfigMenuItem* addItem(String key, String label, String valtype, uint16_t val, String valunit); + void setItemDimension(uint16_t itemwidth, uint16_t itemheight); + int8_t getActiveIndex(); + void setItemActive(String key); + ConfigMenuItem* getActiveItem(); + ConfigMenuItem* getItemByIndex(uint8_t index); + ConfigMenuItem* getItemByKey(String key); + uint8_t getItemCount(); + void goPrev(); + void goNext(); + Point getXY(); + Rect getRect(); + Rect getItemRect(int8_t index); +};