From c695c0ad8521c3fd587020d666cd16ba2cb1042c Mon Sep 17 00:00:00 2001 From: OmniaX-Dev Date: Sun, 5 Apr 2026 14:12:16 +0200 Subject: [PATCH] Started work on Panel Widget --- extra/testTheme.txt | 13 ++++++-- src/ogfx/gui/Widgets.cpp | 63 +++++++++++++++++++++++++++++++++++--- src/ogfx/gui/Widgets.hpp | 30 +++++++++++++++++- src/ostd/io/Stylesheet.cpp | 37 ++++++++++++---------- src/ostd/io/Stylesheet.hpp | 1 + src/test/GuiTest.cpp | 40 +++++++++++++++--------- 6 files changed, 146 insertions(+), 38 deletions(-) diff --git a/extra/testTheme.txt b/extra/testTheme.txt index 4748451..a2d78c1 100644 --- a/extra/testTheme.txt +++ b/extra/testTheme.txt @@ -5,20 +5,29 @@ $accentColor = Color(rgba(255, 0, 255, 255)) $color2 = Color(#0000FFFF) % ------------------- -window.backgroundColor = Color(rgba(40, 0, 0, 255)) +window.backgroundColor = Color(rgba(120, 120, 120, 255)) (label) { textColor = $accentColor backgroundColor = Color(#000000FF) borderColor = $accentColor fontSize = 50 - borderRadius = 20 + borderRadius = 0 borderWidth = 2 showBackground = true showBorder = true padding = Rect(15, 15, 15, 15) } +(panel) { + backgroundColor = Color(#AAAAAAFF) + borderColor = Color(#000000FF) + borderRadius = 8 + borderWidth = 2 + showBorder = true + padding = Rect(15, 15, 15, 15) +} + (@testLabel label) { textColor = $color2 backgroundColor = Color(#000000FF) diff --git a/src/ogfx/gui/Widgets.cpp b/src/ogfx/gui/Widgets.cpp index 878c71b..a2e12df 100644 --- a/src/ogfx/gui/Widgets.cpp +++ b/src/ogfx/gui/Widgets.cpp @@ -52,12 +52,14 @@ namespace ogfx { w->m_focused = false; w->onFocusLost(Event(m_window)); + w->setThemeQualifier("focused", true); } else w->m_focused = false; } widget.m_focused = true; widget.onFocusGained(Event(m_window)); + widget.setThemeQualifier("focused", true); m_focused = &widget; return true; } @@ -305,6 +307,12 @@ namespace ogfx return ostd::Rectangle(getGlobalPosition(), getSize()).contains(p, includeBounds); } + void Widget::enable(bool enable) + { + m_enabled = enable; + setThemeQualifier("disabled", !enable); + } + void Widget::addThemeOverride(const ostd::String& fullKey, ostd::Stylesheet::TypeVariant value, bool propagate) { m_themeOverrides.push_back({ fullKey, value, propagate }); @@ -319,14 +327,29 @@ namespace ogfx applyTheme(theme); ostd::Stylesheet& const_cast_theme = const_cast(theme); + struct tBackup { + const ostd::Stylesheet::TypeVariant* ptr; + ostd::Stylesheet::TypeVariant val; + ostd::String key; + }; + + std::vector backup; for (auto& rule : m_themeOverrides) { - auto currentValue = theme.getFull(rule.fullKey); - if (currentValue == nullptr) - return; + auto currentValuePtr = theme.getFull(rule.fullKey); + ostd::Stylesheet::TypeVariant currentValue; + if (currentValuePtr) + currentValue = *currentValuePtr; + backup.push_back({ currentValuePtr, currentValue, rule.fullKey }); const_cast_theme.setFull(rule.fullKey, rule.value); __applyTheme(const_cast_theme, rule.propagate); - const_cast_theme.setFull(rule.fullKey, *currentValue); + } + for (auto&[ptr, val, key] : backup) + { + if (ptr == nullptr) + const_cast_theme.removeRule(key); + else + const_cast_theme.setFull(key, val); } } @@ -581,6 +604,7 @@ namespace ogfx setPadding({ 5, 5, 5, 5 }); setTypeName("ogfx::gui::widgets::Label"); disableDrawBox(); + disableChildren(); enableBackground(false); validate(); return *this; @@ -627,6 +651,37 @@ namespace ogfx m_textChanged = false; } + + + + Panel& Panel::create(void) + { + setPadding({ 5, 5, 5, 5 }); + setTypeName("ogfx::gui::widgets::Panel"); + disableDrawBox(); + disableFocus(); + enableStopEvents(); + validate(); + return *this; + } + + void Panel::applyTheme(const ostd::Stylesheet& theme) + { + setBackGroundColor(getThemeValue(theme, "panel.backgroundColor", ostd::Colors::Gray)); + m_borderRadius = getThemeValue(theme, "panel.borderRadius", 8); + m_borderWidth = getThemeValue(theme, "panel.borderWidth", 2); + m_showBorder = getThemeValue(theme, "panel.showBorder", true); + m_borderColor = getThemeValue(theme, "panel.borderColor", ostd::Colors::Black); + setPadding(getThemeValue(theme, "panel.padding", { 15, 15, 15, 15 })); + } + + void Panel::onDraw(ogfx::BasicRenderer2D& gfx) + { + if (m_showBorder) + gfx.outlinedRoundRect({ getGlobalPosition(), getSize() }, getBackgroundColor(), m_borderColor, m_borderRadius, m_borderWidth); + else + gfx.fillRoundRect({ getGlobalPosition(), getSize() }, getBackgroundColor(), m_borderRadius); + } } } } diff --git a/src/ogfx/gui/Widgets.hpp b/src/ogfx/gui/Widgets.hpp index d4926ae..bf10646 100644 --- a/src/ogfx/gui/Widgets.hpp +++ b/src/ogfx/gui/Widgets.hpp @@ -86,6 +86,7 @@ namespace ogfx ostd::Vec2 getGlobalPosition(void) const; using ostd::Rectangle::contains; bool contains(ostd::Vec2 p, bool includeBounds = false) const override; + void enable(bool enable = true); virtual void applyTheme(const ostd::Stylesheet& theme) = 0; void addThemeOverride(const ostd::String& fullKey, ostd::Stylesheet::TypeVariant value, bool propagate = true); void reloadTheme(void); @@ -159,6 +160,12 @@ namespace ogfx inline bool isMouseInside(void) const { return m_mouseInside; } inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; } inline const std::vector& getThemeIDList(void) const { return m_themeIDList; } + inline bool isEnabled(void) const { return m_enabled; } + inline bool isFocusEnabled(void) const { return m_allowFocus; } + inline void enableFocus(bool enable = true) { m_allowFocus = enable; } + inline void disableFocus(void) { enableFocus(false); } + inline void disabble(void) { enable(false); } + inline void enableStopEvents(bool enable = true) { m_stopEvents = enable; } template inline T getThemeValue(const ostd::Stylesheet &theme, const ostd::String& key, const T& fallback) @@ -200,6 +207,9 @@ namespace ogfx WidgetManager m_widgets; bool m_allowChildren { true }; bool m_mouseInside { false }; + bool m_allowFocus { true }; + bool m_enabled { true }; + bool m_stopEvents { false }; MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; std::vector m_themeIDList; @@ -247,7 +257,7 @@ namespace ogfx inline int32_t getFontSize(void) const { return m_fontSize; } inline void setFontSize(int32_t fontSize) { m_fontSize = fontSize; } inline void setBackGroundColor(const ostd::Color& color) { m_backgroundColor = color; } - inline ostd::Color getBackgroundColor(const ostd::Color& color) { return m_backgroundColor; } + inline ostd::Color getBackgroundColor(void) { return m_backgroundColor; } inline void enableBackground(bool enable = true) { m_showBackground = enable; } inline bool isBackgoundEnabled(void) const { return m_showBackground; } @@ -268,6 +278,24 @@ namespace ogfx private: }; + class Panel : public Widget + { + public: + inline Panel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); } + Panel& create(void); + void applyTheme(const ostd::Stylesheet& theme) override; + void onDraw(ogfx::BasicRenderer2D& gfx) override; + inline void setBackGroundColor(const ostd::Color& color) { m_backgroundColor = color; } + inline ostd::Color getBackgroundColor(void) { return m_backgroundColor; } + + private: + ostd::Color m_backgroundColor { 150, 150, 150 }; + ostd::Color m_borderColor { 0, 0, 0 }; + int32_t m_borderRadius { 10 }; + int32_t m_borderWidth { 2 }; + bool m_showBorder { false }; + + }; } } } diff --git a/src/ostd/io/Stylesheet.cpp b/src/ostd/io/Stylesheet.cpp index 3b00585..f98fa77 100644 --- a/src/ostd/io/Stylesheet.cpp +++ b/src/ostd/io/Stylesheet.cpp @@ -146,6 +146,11 @@ namespace ostd setFull(fullKey, value); } + void Stylesheet::removeRule(const ostd::String& fullKey) + { + m_values.erase(fullKey); + } + void Stylesheet::setFull(const ostd::String& fullKey, TypeVariant value) { m_values[fullKey] = std::move(value); @@ -305,25 +310,25 @@ namespace ostd { std::cout << key << " = " << typeVariantToString(value) << "\n"; } + std::cout << "\n"; } ostd::String Stylesheet::typeVariantToString(const TypeVariant& v) { - ostd::String str = ""; - // if (auto p = std::get_if(&v)) - // str.add(*p); - // else if (auto p = std::get_if(&v)) - // str.add(*p); - // else if (auto p = std::get_if(&v)) - // str.add(STR_BOOL(*p)); - // else if (auto p = std::get_if(&v)) - // str.add(*p); - // else if (auto p = std::get_if(&v)) - // str.add(*p); - // else if (auto p = std::get_if(&v)) - // std::cout << std::format("{{ {}, {}, {}, {} }}", (*p).x, (*p).y, (*p).w, (*p).h); - // else if (auto p = std::get_if(&v)) - // std::cout << *p; - return str; + if (auto p = std::get_if(&v)) + return String("").add(*p); + else if (auto p = std::get_if(&v)) + return String("").add(*p); + else if (auto p = std::get_if(&v)) + return STR_BOOL(*p); + else if (auto p = std::get_if(&v)) + return *p; + else if (auto p = std::get_if(&v)) + return *p; + else if (auto p = std::get_if(&v)) + return *p; + else if (auto p = std::get_if(&v)) + return *p; + return ""; } } diff --git a/src/ostd/io/Stylesheet.hpp b/src/ostd/io/Stylesheet.hpp index 266f7f4..c909339 100644 --- a/src/ostd/io/Stylesheet.hpp +++ b/src/ostd/io/Stylesheet.hpp @@ -37,6 +37,7 @@ namespace ostd Stylesheet& loadFromFile(const ostd::String& filePath, bool clearCurrentRules = true); Stylesheet& loadFromString(const ostd::String& content, const ostd::String& filePath = "memory://", bool clearCurrentRules = true); void set(const std::string& key, TypeVariant value, const ostd::String& themeID); + void removeRule(const ostd::String& fullKey); void setFull(const ostd::String& fullKey, TypeVariant value); const TypeVariant* getVariant(const ostd::String& key, const std::vector& themeIDList, const QualifierList& qualifierList) const; const TypeVariant* getFull(const ostd::String& fullKey) const; diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp index 78493cc..0f529de 100644 --- a/src/test/GuiTest.cpp +++ b/src/test/GuiTest.cpp @@ -22,7 +22,7 @@ /* - * Label + * --- Label * Button * Panel / Container * Checkbox @@ -49,32 +49,40 @@ class Window : public ogfx::gui::Window inline Window(void) { } inline void onInitialize(void) override { + m_panel1.setSize(300, 140); + m_panel1.setPosition(200, 150); + m_panel1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { + pos = { event.mouse->position_x, event.mouse->position_y }; + }); + m_panel1.setMouseDraggedCallback([&](const ogfx::gui::Event& event) -> void { + ostd::Vec2 pos2 { event.mouse->position_x, event.mouse->position_y }; + m_panel1.addPos(pos2 - pos); + pos = pos2; + }); + m_label1.setPosition(100, 200); m_label1.setText("Hello World!"); - // m_label1.setMouseEnteredCallback([&](const ogfx::gui::Event& event) -> void { - // m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkBlue, false); - // this->setCursor(eCursor::Move); - // }); - // m_label1.setMouseExitedCallback([&](const ogfx::gui::Event& event) -> void { - // m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkRed, false); - // this->setCursor(eCursor::Default); - // }); - // m_label1.setMouseDraggedCallback([&](const ogfx::gui::Event& event) -> void { - // m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkGreen, false); - // }); + m_label1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { + std::cout << "PRESS!\n"; + }); addWidget(m_label1); + addWidget(m_panel1); // m_label1.setThemeQualifier("disabled"); - m_label2.setPosition(100, 400); + m_label2.setPosition(10, 10); m_label2.setText("Ciccia Bella!"); m_label2.addThemeID("testLabel"); m_label2.addThemeID("testLabel2"); - addWidget(m_label2); + m_panel1.addChild(m_label2); + + m_label1.addThemeOverride("@:pressed.label.textColor", ostd::Colors::Crimson); m_theme.loadFromFile("./testTheme.txt"); setTheme(m_theme); - m_label2.addThemeOverride("@:hover.label.fontSize", 10); + m_label2.addThemeOverride("@:hover.label.showBackground", true); + m_label2.addThemeOverride("@:hover.label.backgroundColor", ostd::Colors::DarkGreen); + m_theme.debugPrint(); m_label2.reloadTheme(); m_theme.debugPrint(); @@ -98,7 +106,9 @@ class Window : public ogfx::gui::Window private: ogfx::gui::widgets::Label m_label1 { *this }; ogfx::gui::widgets::Label m_label2 { *this }; + ogfx::gui::widgets::Panel m_panel1 { *this }; ostd::Stylesheet m_theme; + ostd::Vec2 pos { 0, 0 }; }; int main(int argc, char** argv)