diff --git a/CMakeLists.txt b/CMakeLists.txt index f1bc6b0..44f2476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,12 +14,14 @@ set(headers src/confirminterface.h src/display.h src/displaywithtitle.h + src/errorhandlerinterface.h src/fontinterface.h src/graphdisplay.h src/icon.h src/iconinterface.h src/menudisplay.h src/menuitem.h + src/popupdisplay.h src/richtextrenderer.h src/screenmanager.h src/splitgraphdisplay.h @@ -56,6 +58,7 @@ set(sources src/menudisplay.cpp src/screenmanager.cpp src/splitgraphdisplay.cpp + src/popupdisplay.cpp src/richtextrenderer.cpp src/tftinstance.cpp src/icons/back.cpp diff --git a/src/accessorinterface.h b/src/accessorinterface.h index e6f38f6..8cc8165 100644 --- a/src/accessorinterface.h +++ b/src/accessorinterface.h @@ -1,11 +1,16 @@ #pragma once +// 3rdparty lib includes +#include + namespace espgui { template struct AccessorInterface { + using setter_result_t = tl::expected; + virtual T getValue() const = 0; - virtual void setValue(T value) = 0; + virtual setter_result_t setValue(T value) = 0; }; //! A special type of AccessorInterface that allows for simple variable read/write operations @@ -16,6 +21,6 @@ struct RefAccessor : public virtual AccessorInterface virtual T& getRef() const = 0; T getValue() const override { return getRef(); }; - void setValue(T value) override { getRef() = value; }; + tl::expected setValue(T value) override { getRef() = value; return {}; }; }; } // namespace espgui diff --git a/src/changevaluedisplay.h b/src/changevaluedisplay.h index 2304d24..133d144 100644 --- a/src/changevaluedisplay.h +++ b/src/changevaluedisplay.h @@ -3,17 +3,20 @@ // local includes #include "displaywithtitle.h" #include "textinterface.h" -#include "actioninterface.h" +#include "confirminterface.h" +#include "backinterface.h" +#include "errorhandlerinterface.h" #include "accessorinterface.h" #include "widgets/label.h" #include "tftinstance.h" -#include "backinterface.h" namespace espgui { class ChangeValueDisplayInterface : public DisplayWithTitle, - public virtual ActionInterface + public virtual ConfirmInterface, + public virtual BackInterface, + public virtual ErrorHandlerInterface { using Base = DisplayWithTitle; @@ -48,8 +51,7 @@ template class ChangeValueDisplay : public ChangeValueDisplayInterface, public virtual AccessorInterface, - public virtual ChangeValueDisplaySettingsInterface, - public virtual BackInterface + public virtual ChangeValueDisplaySettingsInterface { using Base = ChangeValueDisplayInterface; @@ -95,8 +97,11 @@ void ChangeValueDisplay::update() } else { - static_cast*>(this)->setValue(m_value); - triggered(); + m_pressed = false; + if (auto result = static_cast*>(this)->setValue(m_value); result) + confirm(); + else + errorOccured(std::move(result).error()); } } diff --git a/src/errorhandlerinterface.h b/src/errorhandlerinterface.h new file mode 100644 index 0000000..1957e93 --- /dev/null +++ b/src/errorhandlerinterface.h @@ -0,0 +1,20 @@ +#pragma once + +// system includes +#include + +namespace espgui { + +class ErrorHandlerInterface +{ +public: + virtual void errorOccured(std::string &&error) = 0; +}; + +class DummyErrorHandler : public virtual ErrorHandlerInterface +{ +public: + void errorOccured(std::string &&error) override {} +}; + +} // namespace espgui diff --git a/src/popupdisplay.cpp b/src/popupdisplay.cpp new file mode 100644 index 0000000..deb04a4 --- /dev/null +++ b/src/popupdisplay.cpp @@ -0,0 +1,111 @@ +#include "popupdisplay.h" + +// 3rdparty lib includes +#include +#include +#include + +namespace espgui { + +PopupDisplay::PopupDisplay(std::string &&message, std::unique_ptr &&lastDisplay) : + m_message{std::move(message)}, m_lastDisplay{std::move(lastDisplay)} +{ +} + +void PopupDisplay::initScreen() +{ + Base::initScreen(); + + m_lastDisplay->initScreen(); + + initOverlay(); +} + +void PopupDisplay::buttonPressed(espgui::Button button) +{ + //Base::buttonPressed(button); + + switch (button) + { + using espgui::Button; + case Button::Left: + case Button::Right: + closeOverlay(); + break; + default:; + } +} + +void PopupDisplay::initOverlay() +{ + constexpr auto leftMargin = 20; + constexpr auto rightMargin = leftMargin; + constexpr auto topMargin = 50; + constexpr auto bottomMargin = topMargin; + + const auto width = espgui::tft.width() - leftMargin - rightMargin; + const auto height = espgui::tft.height() - topMargin - bottomMargin; + const auto right = espgui::tft.width() - rightMargin; + const auto bottom = espgui::tft.height() - bottomMargin; + + CPP_UNUSED(right) + + espgui::tft.drawSunkenRect(leftMargin, topMargin, width, height, + color565(240, 240, 240), + color565(100, 100, 100), + color565(30, 30, 30)); + + espgui::tft.setTextColor(TFT_WHITE, color565(30, 30, 30)); + + int x = leftMargin + 5; + int y = topMargin + 5; + for (char c : m_message) + { + if (c == '\n' || x > espgui::tft.width() - rightMargin - 10) + { + x = leftMargin + 5; + y += espgui::tft.fontHeight(4); + } + + if (c != '\n') + { + const auto addedWidth = espgui::tft.drawChar(espgui::tft.decodeUTF8(c), x, y, 4); + x += addedWidth; + } + + if (y >= espgui::tft.height() - bottomMargin) + break; + } + + espgui::tft.setTextColor(TFT_BLACK, color565(170, 170, 170)); + + if constexpr (false) + { + espgui::tft.drawSunkenRect(leftMargin + 15, bottom - 40, + (width - 15 - 10 - 15) / 2, + 30, + color565(240, 240, 240), + color565(100, 100, 100), + color565(170, 170, 170)); + + espgui::tft.drawString("Retry", leftMargin + 18, bottom - 37); + } + + espgui::tft.drawSunkenRect(leftMargin + 15 + ((width - 15 - 30 - 15) / 2) + 15, bottom - 40, + (width - 15 - 10 - 15) / 2, + 30, + color565(240, 240, 240), + color565(100, 100, 100), + color565(170, 170, 170)); + + espgui::tft.drawString("Ok", leftMargin + 18 + ((width - 15 - 30 - 15) / 2) + 15 + 1, bottom - 37); +} + +void PopupDisplay::closeOverlay() +{ + auto guard = std::move(espgui::currentDisplay); + espgui::currentDisplay = std::move(m_lastDisplay); + espgui::currentDisplay->initScreen(); +} + +} // namespace espgui diff --git a/src/popupdisplay.h b/src/popupdisplay.h new file mode 100644 index 0000000..055cc0d --- /dev/null +++ b/src/popupdisplay.h @@ -0,0 +1,34 @@ +#pragma once + +// system includes +#include + +// local includes +#include "display.h" + +namespace espgui { + +class PopupDisplay : public Display +{ + using Base = Display; + +public: + PopupDisplay(std::string &&message, std::unique_ptr &&lastDisplay); + + //void start() override; + void initScreen() override; + //void update() override; + //void redraw() override; + //void stop() override; + + void buttonPressed(espgui::Button button) override; + + virtual void initOverlay(); + virtual void closeOverlay(); + +private: + std::string m_message; + std::unique_ptr m_lastDisplay; +}; + +} // namespace espgui