diff --git a/CMakeLists.txt b/CMakeLists.txt index 4da994a..f87a0c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ set(headers src/visibleinterface.h src/widgets/centeredlabel.h src/widgets/graph.h + src/widgets/iconwidget.h src/widgets/label.h src/widgets/progressbar.h src/widgets/reverseprogressbar.h @@ -88,6 +89,7 @@ set(sources src/icons/checked_grey.cpp src/icons/unchecked_grey.cpp src/widgets/centeredlabel.cpp + src/widgets/iconwidget.cpp src/widgets/label.cpp src/widgets/progressbar.cpp src/widgets/reverseprogressbar.cpp diff --git a/src/menuitem.h b/src/menuitem.h index e0f0fed..49f502e 100644 --- a/src/menuitem.h +++ b/src/menuitem.h @@ -41,6 +41,38 @@ public: virtual const Icon *selectedIcon() const override { return T; } }; +template +class ChangeableSelectableIcon : public virtual SelectableIconInterface +{ +public: + virtual const Icon *icon(bool selected) const override { return selected ? m_selectedIcon : m_icon; } + + void setIcon(const Icon *icon, const Icon *selectedIcon) + { + m_icon = icon; + m_selectedIcon = selectedIcon; + } + + void setIcon(const Icon *icon) { m_icon = icon; } + void setSelectedIcon(const Icon *selectedIcon) { m_selectedIcon = selectedIcon; } + +private: + const Icon *m_icon = nullptr; + const Icon *m_selectedIcon = nullptr; +}; + +template +class ChangeableSelectedIcon : public virtual SelectedIconInterface +{ +public: + virtual const Icon *selectedIcon() const override { return m_selectedIcon; } + + void setSelectedIcon(const Icon *selectedIcon) { m_selectedIcon = selectedIcon; } + +private: + const Icon *m_selectedIcon = nullptr; +}; + using MenuItemIconInterface = SelectableIconInterface<24, 24>; using MenuItemSelectedIconInterface = SelectedIconInterface<24, 24>; @@ -51,6 +83,10 @@ using StaticMenuItemIcon = StaticSelectableIcon<24, 24, T, Tselected>; template using StaticMenuItemSelectedIcon = StaticSelectedIcon<24, 24, T>; +using ChangeableMenuItemIcon = ChangeableSelectableIcon<24, 24>; + +using ChangeableMenuItemSelectedIcon = ChangeableSelectedIcon<24, 24>; + class MenuItem : public virtual ActionInterface, public virtual TextInterface, diff --git a/src/widgets/centeredlabel.cpp b/src/widgets/centeredlabel.cpp index b11b792..bb5f5be 100644 --- a/src/widgets/centeredlabel.cpp +++ b/src/widgets/centeredlabel.cpp @@ -5,7 +5,6 @@ // local includes #include "tftinterface.h" -#include "richtextrenderer.h" namespace espgui { CenteredLabel::CenteredLabel(int x, int y) : @@ -76,7 +75,7 @@ void CenteredLabel::redraw(TftInterface &tft, FontRenderer &fontRenderer, std::s void CenteredLabel::clear(TftInterface &tft, uint16_t bgcolor) { if (m_lastWidth || m_lastHeight) - tft.fillRect(m_x, m_y, m_lastWidth, m_lastHeight, bgcolor); + tft.fillRect(m_x - (m_lastWidth / 2), m_y, m_lastWidth, m_lastHeight, bgcolor); start(tft); } diff --git a/src/widgets/iconwidget.cpp b/src/widgets/iconwidget.cpp new file mode 100644 index 0000000..1c7020f --- /dev/null +++ b/src/widgets/iconwidget.cpp @@ -0,0 +1,68 @@ +#include "iconwidget.h" + +namespace espgui { +void IconWidget::start(TftInterface &tft) +{ + m_lastIcon = nullptr; +} + +void IconWidget::start(TftInterface &tft, const int32_t iconWidth, const int32_t iconHeight, const uint16_t *icon) +{ + if (m_iconWidth != iconWidth || m_iconHeight != iconHeight) + { + ESP_LOGE(TAG, "Icon size mismatch: %dx%d vs %ldx%ld", m_iconWidth, m_iconHeight, iconWidth, iconHeight); + return; + } + + m_lastIcon = icon; + + if (icon) + tft.pushImage(m_x, m_y, m_iconWidth, m_iconHeight, icon); +} + +void IconWidget::redraw(TftInterface &tft, const int32_t iconWidth, const int32_t iconHeight, const uint16_t *icon, uint16_t bgcolor, bool forceRedraw) +{ + if (m_iconWidth != iconWidth || m_iconHeight != iconHeight) + { + ESP_LOGE(TAG, "Icon size mismatch: %dx%d vs %ldx%ld", m_iconWidth, m_iconHeight, iconWidth, iconHeight); + return; + } + + if (forceRedraw || m_lastIcon != icon) + { + if (icon) + tft.pushImage(m_x, m_y, m_iconWidth, m_iconHeight, icon); + else if (m_lastIcon) + tft.fillRect(m_x, m_y, m_iconWidth, m_iconHeight, bgcolor); + + m_lastIcon = icon; + } +} + +void IconWidget::redraw(TftInterface &tft, const int32_t iconWidth, const int32_t iconHeight, const uint16_t *icon, bool forceRedraw) +{ + redraw(tft, iconWidth, iconHeight, icon, m_bgcolor, forceRedraw); +} + +void IconWidget::clear(TftInterface &tft, uint16_t bgcolor) +{ + if (m_lastIcon) + tft.fillRect(m_x, m_y, m_iconWidth, m_iconHeight, bgcolor); + + m_lastIcon = nullptr; +} + +void IconWidget::clear(TftInterface &tft) +{ + clear(tft, m_bgcolor); +} + +IconWidget::IconWidget(int x, int y, int iconWidth, int iconHeight, uint16_t bgcolor): + m_x{x}, + m_y{y}, + m_iconWidth{iconWidth}, + m_iconHeight{iconHeight}, + m_bgcolor{bgcolor}, + m_lastIcon{nullptr} +{} +} // namespace espgui diff --git a/src/widgets/iconwidget.h b/src/widgets/iconwidget.h new file mode 100644 index 0000000..5017003 --- /dev/null +++ b/src/widgets/iconwidget.h @@ -0,0 +1,46 @@ +#pragma once + +// esp-idf includes +#include + +// local includes +#include "icon.h" +#include "tftcolors.h" +#include "tftinterface.h" + +namespace espgui { + +class IconWidget +{ + static constexpr const char * const TAG = "IconWidget"; +public: + IconWidget(int x, int y, int iconWidth, int iconHeight, uint16_t bgcolor = espgui::TFT_BLACK); + + void start(TftInterface &tft); + + void start(TftInterface &tft, int32_t iconWidth, int32_t iconHeight, const uint16_t *icon); + + void redraw(TftInterface &tft, int32_t iconWidth, int32_t iconHeight, const uint16_t *icon, uint16_t bgcolor, bool forceRedraw = false); + + void redraw(TftInterface &tft, int32_t iconWidth, int32_t iconHeight, const uint16_t *icon, bool forceRedraw = false); + + void clear(espgui::TftInterface &tft, uint16_t bgcolor); + + void clear(espgui::TftInterface &tft); + + int x() const { return m_x; } + + int y() const { return m_y; } + +private: + const int m_x; + const int m_y; + const int m_iconWidth; + const int m_iconHeight; + + uint16_t m_bgcolor; + + const uint16_t *m_lastIcon; +}; + +} // namespace espgui