Accessors now report result of setter, added error handler interface

This commit is contained in:
2021-12-29 21:53:23 +01:00
parent a29efa4e47
commit a279559e76
6 changed files with 187 additions and 9 deletions

View File

@ -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

View File

@ -1,11 +1,16 @@
#pragma once
// 3rdparty lib includes
#include <tl/expected.hpp>
namespace espgui {
template<typename T>
struct AccessorInterface
{
using setter_result_t = tl::expected<void, std::string>;
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<T>
virtual T& getRef() const = 0;
T getValue() const override { return getRef(); };
void setValue(T value) override { getRef() = value; };
tl::expected<void, std::string> setValue(T value) override { getRef() = value; return {}; };
};
} // namespace espgui

View File

@ -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<typename Tvalue>
class ChangeValueDisplay :
public ChangeValueDisplayInterface,
public virtual AccessorInterface<Tvalue>,
public virtual ChangeValueDisplaySettingsInterface<Tvalue>,
public virtual BackInterface
public virtual ChangeValueDisplaySettingsInterface<Tvalue>
{
using Base = ChangeValueDisplayInterface;
@ -95,8 +97,11 @@ void ChangeValueDisplay<Tvalue>::update()
}
else
{
static_cast<AccessorInterface<Tvalue>*>(this)->setValue(m_value);
triggered();
m_pressed = false;
if (auto result = static_cast<AccessorInterface<Tvalue>*>(this)->setValue(m_value); result)
confirm();
else
errorOccured(std::move(result).error());
}
}

View File

@ -0,0 +1,20 @@
#pragma once
// system includes
#include <string>
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

111
src/popupdisplay.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "popupdisplay.h"
// 3rdparty lib includes
#include <tftinstance.h>
#include <screenmanager.h>
#include <cppmacros.h>
namespace espgui {
PopupDisplay::PopupDisplay(std::string &&message, std::unique_ptr<Display> &&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

34
src/popupdisplay.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
// system includes
#include <memory>
// local includes
#include "display.h"
namespace espgui {
class PopupDisplay : public Display
{
using Base = Display;
public:
PopupDisplay(std::string &&message, std::unique_ptr<Display> &&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<Display> m_lastDisplay;
};
} // namespace espgui