#ifndef UI_ELEMENT_H #define UI_ELEMENT_H #include "UIStructs.h" #include "UIPainter.h" #undef min #undef max #include class UIElement { protected: UIRect rect; bool _visible = true; bool _needsRedraw = true; bool opaque = true; bool focus = false; std::vector children; static constexpr const char* TAG = "UIElement"; public: void setOpaque(bool opaque) { this->opaque = opaque; } void setRect(const UIRect r) { this->rect = r; setNeedsRedraw(); reLayout(); } void setRect(const uint16_t x, const uint16_t y, const uint16_t w, const uint16_t h) { this->rect = UIRect(x,y,w,h); setNeedsRedraw(); reLayout(); } const UIRect& getRect() const { return rect; } void setVisible(bool visible) { this->_visible = visible; setNeedsRedraw(); } bool isVisible() const { return this->_visible; } void setFocus(bool focus) { this->focus = focus; setNeedsRedraw(); } void setNeedsRedraw() { this->_needsRedraw = true; } bool needsRedraw() const { return this->_needsRedraw; } void addChild(UIElement* e) { children.push_back(e); } protected: friend class UI; virtual void draw(UIPainter& p) {;} /** layout needs updating */ virtual void reLayout() {;} virtual void onTouchDown(uint16_t, uint16_t) {;} // relative (x,y) coordinate virtual void onTouch(uint16_t, uint16_t) {;} // relative (x,y) coordinate virtual void onTouchUp() {;} protected: UIElement* _onTouch(const uint16_t x, const uint16_t y) { // if i'm invisible, ignore for me and children if (!isVisible()) {return nullptr;} // touch outside of me, ignore for me and children if (!getRect().contains(x,y)) {return nullptr;} // find first child that takes the event for (UIElement* e : children) { UIElement* taken = e->_onTouch(x, y); if (taken) {return taken;} } // take the event myself const uint16_t x1 = x - getRect().x; // (x,y) relative to elements top-left const uint16_t y1 = y - getRect().y; debugMod2(TAG, "onTouchDown(%d,%d)", x1, y1); onTouchDown(x1, y1); return this; } void _draw(UIPainter& p) { // if hiden, ignore for me and children if (!_visible) {return;} // draw myself (if needed) if (_needsRedraw) { draw(p); _needsRedraw = false; } // call for children as well for (UIElement* child : children) { child->_draw(p); } } }; #endif // UI_ELEMENT_H