#include "dynamicdebugmenu.h" // system includes #include #include #include // 3rdparty lib includes #include #include #include #include #include #include #include #include #include #include #include // local includes #include "displays/bobbychangevaluedisplay.h" #include "utils.h" #include "icons/lock.h" #include "bobbycheckbox.h" #include "bobbyerrorhandler.h" using namespace espgui; namespace { constexpr char TEXT_FONTTEST0[] = "Rich&1Text&2Renderer"; constexpr char TEXT_FONTTEST1[] = "Test&ssmall&mmedium"; constexpr char TEXT_FONTTEST2[] = "Test&ssmall&frestored"; constexpr char TEXT_FONTTEST3[] = "Test&s&3small&4with&6color&7grey"; constexpr char TEXT_DUMMYITEM[] = "Dummy item"; constexpr char TEXT_DYNAMICCOLOR[] = "Dynamic color"; constexpr char TEXT_DYNAMICFONT[] = "Dynamic font"; constexpr char TEXT_DYNAMICICON[] = "Dynamic icon"; constexpr char TEXT_STATICICON[] = "Static icon"; constexpr char TEXT_LOCKTOGGLE[] = "Lock toggle"; constexpr char TEXT_DEBUGTOGGLE[] = "Toggle"; constexpr char TEXT_DEBUGTOGGLEMENU[] = "Toggle (with menu)"; constexpr char TEXT_OPENPOPUP[] = "Open popup"; constexpr char TEXT_BACK[] = "Back"; bool toggleLocked{}; bool toggle{}; class RandomColor : public virtual ColorInterface { public: int color() const override; private: mutable std::optional m_nextUpdate; mutable int m_color; }; class RandomFont : public virtual FontInterface { public: int font() const override; private: mutable std::optional m_nextUpdate; mutable int m_font; }; class RandomIcon : public virtual MenuItemIconInterface { public: const MenuItemIcon *icon() const override; private: mutable std::optional m_nextUpdate; mutable const Icon<24, 24> *m_icon; }; struct ToggleLockedAccessor : public virtual RefAccessor { public: bool &getRef() const override { return toggleLocked; } }; struct ToggleAccessor : public virtual AccessorInterface { public: bool getValue() const override { return toggle; }; std::expected setValue(bool value) override; }; using ToggleChangeValueDisplay = espgui::makeComponent< BobbyChangeValueDisplay, espgui::StaticText, ToggleAccessor, espgui::ConfirmActionInterface, espgui::BackActionInterface >; class OpenPopupAction : public virtual espgui::ActionInterface { public: void triggered() override { BobbyErrorHandler{}.errorOccurred("Das\nist\nein sehr langer text, der nicht in eine zeile passt"); } }; } // namespace std::string RandomText::text() const { const auto now = espchrono::millis_clock::now(); if (!m_nextUpdate || now >= *m_nextUpdate) { m_title = fmt::format("Dynamic text: {}", cpputils::randomNumber(100, espcpputils::esp_random_device{})); m_nextUpdate = now + std::chrono::milliseconds{cpputils::randomNumber(100, 1000, espcpputils::esp_random_device{})}; } return m_title; } DynamicDebugMenu::DynamicDebugMenu() { // dummy items to allow for scrolling constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); // the interesting bits constructMenuItem, OpenPopupAction>>(); constructMenuItem>(); constructMenuItem, RandomColor, DummyAction>>(); constructMenuItem, RandomFont, DummyAction>>(); constructMenuItem, RandomIcon, DummyAction>>(); constructMenuItem, StaticMenuItemIcon<&bobbyicons::lock>, DummyAction>>(); constructMenuItem, BobbyCheckbox, ToggleLockedAccessor>>(); constructMenuItem, BobbyCheckbox, ToggleAccessor>>(); constructMenuItem, PushScreenAction>>(); constructMenuItem>(); // more scrolling constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, PopScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } void DynamicDebugMenu::back() { espgui::popScreen(); } namespace { int RandomColor::color() const { const auto now = espchrono::millis_clock::now(); if (!m_nextUpdate || now >= *m_nextUpdate) { const auto count = std::size(default_4bit_palette); m_color = default_4bit_palette[cpputils::randomNumber(count-1, espcpputils::esp_random_device{})]; m_nextUpdate = now + std::chrono::milliseconds{cpputils::randomNumber(100, 1000, espcpputils::esp_random_device{})}; } return m_color; } int RandomFont::font() const { const auto now = espchrono::millis_clock::now(); if (!m_nextUpdate || now >= *m_nextUpdate) { constexpr const int fonts[] = { 2, 4 }; m_font = fonts[cpputils::randomNumber(std::size(fonts)-1, espcpputils::esp_random_device{})]; m_nextUpdate = now + std::chrono::milliseconds{cpputils::randomNumber(100, 1000, espcpputils::esp_random_device{})}; } return m_font; } const MenuItemIcon *RandomIcon::icon() const { const auto now = espchrono::millis_clock::now(); if (!m_nextUpdate || now >= *m_nextUpdate) { if (m_icon) m_icon = nullptr; else m_icon = &bobbyicons::lock; m_nextUpdate = now + std::chrono::milliseconds{cpputils::randomNumber(100, 1000, espcpputils::esp_random_device{})}; } return m_icon; } std::expected ToggleAccessor::setValue(bool value) { if (toggleLocked) return tl::make_unexpected("cannot be changed while is locked!"); toggle = value; return {}; } } // namespace