diff --git a/extra/DefaultTheme.oss b/extra/DefaultTheme.oss index 14a5b84..78a84f6 100644 --- a/extra/DefaultTheme.oss +++ b/extra/DefaultTheme.oss @@ -134,9 +134,16 @@ window.backgroundColor = rgba(160, 160, 160, 255) useBackgroundGradient = true padding = rect(15, 8, 15, 8) margin = rect(0, 0, 0, 0) - icon = file("img.png") - showIcon = true - iconANimation = anim( + (icon) { + show = true + image = file("img.png") + animation = anim(frameCount: 36, \ + fps: 60, \ + columns: 9, \ + rows: 4, \ + frameWidth: 256, \ + frameHeight: 256) + } } (button:hover) { borderColor = $accentColor @@ -148,3 +155,25 @@ window.backgroundColor = rgba(160, 160, 160, 255) backgroundGradient = gradientV(rgb(120, 120, 120) - rgb(160, 160, 160)) } % ==================== + + +(image) { + path = file("img.png") + animated = true + animation = anim(frameCount: 36, \ + fps: 60, \ + columns: 9, \ + rows: 4, \ + frameWidth: 256, \ + frameHeight: 256) + backgroundColor = #999999FF + backgroundGradient = gradientV(rgb(160, 160, 160) - rgb(120, 120, 120)) + borderColor = $accentColorDark + borderRadius = 0 + borderWidth = 1 + showBackground = true + showBorder = true + useBackgroundGradient = true + padding = rect(15, 8, 15, 8) + margin = rect(0, 0, 0, 0) +} diff --git a/src/ogfx/gui/WidgetManager.cpp b/src/ogfx/gui/WidgetManager.cpp index bba2d96..8d794fd 100644 --- a/src/ogfx/gui/WidgetManager.cpp +++ b/src/ogfx/gui/WidgetManager.cpp @@ -139,6 +139,7 @@ namespace ogfx { if (w == nullptr) continue; if (w->isInvalid()) continue; + if (!w->isThemingEnabled()) continue; w->__applyTheme(theme, true); w->reloadTheme(); } diff --git a/src/ogfx/gui/Window.cpp b/src/ogfx/gui/Window.cpp index ef88fa3..5054d3a 100644 --- a/src/ogfx/gui/Window.cpp +++ b/src/ogfx/gui/Window.cpp @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + along with OmniaFramewo6 If not, see . */ #include "Window.hpp" @@ -86,7 +86,7 @@ namespace ogfx m_window = SDL_CreateWindow("", m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE); m_renderer = SDL_CreateRenderer(m_window, nullptr); SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight); - SDL_SetWindowPosition(m_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + setPosition(WindowsPositionCenter); SDL_SetWindowTitle(m_window, m_title.c_str()); SDL_StartTextInput(m_window); @@ -260,6 +260,33 @@ namespace ogfx SDL_SetRenderScale(m_renderer, s, s); } + void WindowCore::setPosition(const IPoint& pos) + { + IPoint p = pos; + if (p.x < 0) + p.x = SDL_WINDOWPOS_CENTERED; + if (p.y < 0) + p.y = SDL_WINDOWPOS_CENTERED; + SDL_SetWindowPosition(m_window, p.x, p.y); + } + + void WindowCore::setWindowState(eWindowState state) + { + switch (state) + { + case eWindowState::Default: + SDL_RestoreWindow(m_window); + break; + case eWindowState::Maximized: + SDL_MaximizeWindow(m_window); + break; + case eWindowState::Minimized: + SDL_MinimizeWindow(m_window); + break; + default: break; + } + } + WindowCore::State WindowCore::getWindowState(void) const { SDL_WindowFlags flags = SDL_GetWindowFlags(m_window); diff --git a/src/ogfx/gui/Window.hpp b/src/ogfx/gui/Window.hpp index 0bedeec..d09d478 100644 --- a/src/ogfx/gui/Window.hpp +++ b/src/ogfx/gui/Window.hpp @@ -65,6 +65,11 @@ namespace ogfx Center, Left }; + public: enum class eWindowState : u8 { + Default = 0, + Maximized, + Minimized + }; public: struct State { bool fullscreen { false }; @@ -85,6 +90,8 @@ namespace ogfx void setTitle(const String& title); void setCursor(eCursor cursor); void setUserScale(f32 scale); + void setPosition(const IPoint& pos); + void setWindowState(eWindowState state); State getWindowState(void) const; eCursor getCurosr(void) const; void enableResizable(bool enable = true); @@ -186,6 +193,8 @@ namespace ogfx inline static constexpr i32 MaxBlockingEventsFPS { 240 }; inline static constexpr i32 DefaultBlockingEventsFPS { 30 }; + inline static const IPoint WindowsPositionCenter { -1, -1 }; + private: inline static ostd::Stylesheet DefaultTheme; stdumap> m_defaultStylesheetVariables; diff --git a/src/ogfx/gui/widgets/Button.cpp b/src/ogfx/gui/widgets/Button.cpp index 5c25c7c..f0ca9de 100644 --- a/src/ogfx/gui/widgets/Button.cpp +++ b/src/ogfx/gui/widgets/Button.cpp @@ -32,37 +32,17 @@ namespace ogfx setText(text); setPadding({ 5, 5, 5, 5 }); setTypeName("ogfx::gui::widgets::Button"); - disableDrawBox(); disableChildren(); enableBackground(false); + setStylesheetCategoryName("button"); validate(); return *this; } - void Button::applyTheme(const ostd::Stylesheet& theme) - { - setTextColor(getThemeValue(theme, "button.textColor", Colors::White)); - setBackGroundColor(getThemeValue(theme, "button.backgroundColor", Colors::Transparent)); - setFontSize(getThemeValue(theme, "button.fontSize", 20)); - setBorderRadius(getThemeValue(theme, "button.borderRadius", 10)); - setBorderWidth(getThemeValue(theme, "button.borderWidth", 2)); - enableBorder(getThemeValue(theme, "button.showBorder", false)); - setBorderColor(getThemeValue(theme, "button.borderColor", Colors::White)); - enableBackground(getThemeValue(theme, "button.showBackground", false)); - setPadding(getThemeValue(theme, "button.padding", { 5, 5, 5, 5 })); - setMargin(getThemeValue(theme, "button.margin", { 0, 0, 0, 0 })); - m_useBackgroundGradient = getThemeValue(theme, "button.useBackgroundGradient", false); - m_backgroundGradient = getThemeValue(theme, "button.backgroundGradient", m_backgroundGradient); - if (m_useBackgroundGradient && isBackgoundEnabled()) - enableBackground(false); - } - void Button::onDraw(ogfx::BasicRenderer2D& gfx) { if (m_textChanged) __update_size(gfx); - if (m_useBackgroundGradient) - gfx.fillGradientRect(getGlobalBounds(), m_backgroundGradient); gfx.drawString(getText(), getGlobalContentPosition(), getTextColor(), getFontSize()); } diff --git a/src/ogfx/gui/widgets/Button.hpp b/src/ogfx/gui/widgets/Button.hpp index 569a9ca..910fc81 100644 --- a/src/ogfx/gui/widgets/Button.hpp +++ b/src/ogfx/gui/widgets/Button.hpp @@ -34,14 +34,9 @@ namespace ogfx inline Button(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); } inline Button(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } Button& create(const String& text); - void applyTheme(const ostd::Stylesheet& theme) override; void onDraw(ogfx::BasicRenderer2D& gfx) override; void setText(const String& text); inline String getText(void) const { return m_text; } - inline Color getTextColor(void) const { return m_textColor; } - inline void setTextColor(const Color& color) { m_textColor = color; } - inline i32 getFontSize(void) const { return m_fontSize; } - inline void setFontSize(i32 fontSize) { m_fontSize = fontSize; } private: void __update_size(ogfx::BasicRenderer2D& gfx); @@ -49,13 +44,6 @@ namespace ogfx private: String m_text { "" }; bool m_textChanged { false }; - i32 m_fontSize { 20 }; - Color m_textColor { 255, 255, 255 }; - bool m_useBackgroundGradient { false }; - ColorGradient m_backgroundGradient { - { Color { 160, 160, 160 }, Color { 120, 120, 120 } }, - { 1.0f } - }; }; } } diff --git a/src/ogfx/gui/widgets/CheckBox.cpp b/src/ogfx/gui/widgets/CheckBox.cpp index fbd8ab8..a788c39 100644 --- a/src/ogfx/gui/widgets/CheckBox.cpp +++ b/src/ogfx/gui/widgets/CheckBox.cpp @@ -32,29 +32,19 @@ namespace ogfx setText(text); setPadding({ 5, 5, 5, 5 }); setTypeName("ogfx::gui::widgets::Label"); - disableDrawBox(); disableChildren(); enableBackground(false); + setStylesheetCategoryName("checkbox"); validate(); return *this; } void CheckBox::applyTheme(const ostd::Stylesheet& theme) { - setCheckBorderColor(getThemeValue(theme, "checkbox.checkBorderColor", Colors::White)); - setCheckBoxColor(getThemeValue(theme, "checkbox.checkBoxColor", Colors::White)); - setTextColor(getThemeValue(theme, "checkbox.textColor", Colors::Black)); - setBackGroundColor(getThemeValue(theme, "checkbox.backgroundColor", Colors::Transparent)); - setFontSize(getThemeValue(theme, "checkbox.fontSize", 28)); - setBorderRadius(getThemeValue(theme, "checkbox.borderRadius", 10)); - setBorderWidth(getThemeValue(theme, "checkbox.borderWidth", 2)); - enableBorder(getThemeValue(theme, "checkbox.showBorder", false)); - setBorderColor(getThemeValue(theme, "checkbox.borderColor", Colors::White)); - enableBackground(getThemeValue(theme, "checkbox.showBackground", false)); - setPadding(getThemeValue(theme, "checkbox.padding", { 5, 5, 5, 5 })); - setMargin(getThemeValue(theme, "checkbox.margin", { 0, 0, 0, 0 })); - m_checkBorderRadius = getThemeValue(theme, "checkbox.checkBorderRadius", 5); - m_checkBorderWidth = getThemeValue(theme, "checkbox.checkBorderWidth", 1); + setCheckBorderColor(getThemeValue(theme, "checkBorderColor", Colors::White)); + setCheckBoxColor(getThemeValue(theme, "checkBoxColor", Colors::White)); + m_checkBorderRadius = getThemeValue(theme, "checkBorderRadius", 5); + m_checkBorderWidth = getThemeValue(theme, "checkBorderWidth", 1); } void CheckBox::onDraw(ogfx::BasicRenderer2D& gfx) diff --git a/src/ogfx/gui/widgets/CheckBox.hpp b/src/ogfx/gui/widgets/CheckBox.hpp index 6d58522..1b05fe0 100644 --- a/src/ogfx/gui/widgets/CheckBox.hpp +++ b/src/ogfx/gui/widgets/CheckBox.hpp @@ -46,10 +46,6 @@ namespace ogfx inline void setCheckBorderColor(const Color& color) { m_checkBorderColor = color; } inline Color getCheckBoxColor(void) const { return m_checkBoxColor; } inline void setCheckBoxColor(const Color& color) { m_checkBoxColor = color; } - inline Color getTextColor(void) const { return m_textColor; } - inline void setTextColor(const Color& color) { m_textColor = color; } - inline i32 getFontSize(void) const { return m_fontSize; } - inline void setFontSize(i32 fontSize) { m_fontSize = fontSize; } inline bool isChecked(void) const { return m_checked; } inline void setStateChangedCallback(std::function callback) { callback_onStateChanged = callback; } @@ -60,8 +56,6 @@ namespace ogfx bool m_checked { false }; String m_text { "" }; bool m_textChanged { false }; - i32 m_fontSize { 20 }; - Color m_textColor { 255, 255, 255 }; f32 m_spacing { 10 }; Vec2 m_checkSize { 0, 0 }; i32 m_checkBorderRadius { 5 }; diff --git a/src/ogfx/gui/widgets/Containers.cpp b/src/ogfx/gui/widgets/Containers.cpp index acf38ac..69bc7f1 100644 --- a/src/ogfx/gui/widgets/Containers.cpp +++ b/src/ogfx/gui/widgets/Containers.cpp @@ -32,33 +32,25 @@ namespace ogfx { setPadding({ 5, 5, 5, 5 }); setTypeName("ogfx::gui::widgets::Panel"); - disableDrawBox(); disableFocus(); enableStopEvents(); + setStylesheetCategoryName("panel"); validate(); return *this; } void Panel::applyTheme(const ostd::Stylesheet& theme) { - setBackGroundColor(getThemeValue(theme, "panel.backgroundColor", Colors::Gray)); - setBorderRadius(getThemeValue(theme, "panel.borderRadius", 8)); - setBorderWidth(getThemeValue(theme, "panel.borderWidth", 2)); - enableBorder(getThemeValue(theme, "panel.showBorder", true)); - enableBackground(getThemeValue(theme, "panel.showBackground", true)); - setBorderColor(getThemeValue(theme, "panel.borderColor", Colors::Black)); - setPadding(getThemeValue(theme, "panel.padding", { 15, 15, 15, 15 })); - setMargin(getThemeValue(theme, "panel.margin", { 0, 0, 0, 0 })); - setScrollSpeed(getThemeValue(theme, "panel.scrollSpeed", 0.8f)); - setScrollSmoothFactor(getThemeValue(theme, "panel.scrollSmoothFactor", 0.7f)); - m_titleColor = getThemeValue(theme, "panel.titleColor", Colors::Black); - m_titlebarColor = getThemeValue(theme, "panel.titlebarColor", Colors::Transparent); - m_titlebarBorderColor = getThemeValue(theme, "panel.titlebarBorderColor", Colors::Black); - m_titlebarHeight = getThemeValue(theme, "panel.titlebarHeight", 30); - m_titlebarBorderWidth = getThemeValue(theme, "panel.titlebarBorderWidth", 1); - m_titlebarFontSize = getThemeValue(theme, "panel.titlebarFontSize", 26); - m_titleTextAlign = getThemeValue(theme, "panel.titlebarTextAlign", cast(WindowCore::eTextAlign::Left)); - setTitlebarType(getThemeValue(theme, "panel.titlebarType", TitleBarTypes::None)); + setScrollSpeed(getThemeValue(theme, "scrollSpeed", 0.8f)); + setScrollSmoothFactor(getThemeValue(theme, "scrollSmoothFactor", 0.7f)); + m_titleColor = getThemeValue(theme, "titleColor", Colors::Black); + m_titlebarColor = getThemeValue(theme, "titlebarColor", Colors::Transparent); + m_titlebarBorderColor = getThemeValue(theme, "titlebarBorderColor", Colors::Black); + m_titlebarHeight = getThemeValue(theme, "titlebarHeight", 30); + m_titlebarBorderWidth = getThemeValue(theme, "titlebarBorderWidth", 1); + m_titlebarFontSize = getThemeValue(theme, "titlebarFontSize", 26); + m_titleTextAlign = getThemeValue(theme, "titlebarTextAlign", cast(WindowCore::eTextAlign::Left)); + setTitlebarType(getThemeValue(theme, "titlebarType", TitleBarTypes::None)); } void Panel::afterDraw(ogfx::BasicRenderer2D& gfx) @@ -141,9 +133,9 @@ namespace ogfx { setPadding({ 0, 0, 0, 0 }); setTypeName("ogfx::gui::widgets::TabPanel"); - disableDrawBox(); disableFocus(); enableStopEvents(); + setStylesheetCategoryName("tabPanel"); validate(); return *this; } diff --git a/src/ogfx/gui/widgets/Containers.hpp b/src/ogfx/gui/widgets/Containers.hpp index 27e31d0..93b1909 100644 --- a/src/ogfx/gui/widgets/Containers.hpp +++ b/src/ogfx/gui/widgets/Containers.hpp @@ -49,8 +49,6 @@ namespace ogfx void afterDraw(ogfx::BasicRenderer2D& gfx) override; void setTitlebarType(const String& type); String getTitlebarType(void) const; - inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; } - inline Color getBackgroundColor(void) { return m_backgroundColor; } inline String getTitle(void) const { return m_title; } inline void setTitle(const String& title) { m_title = title; } inline f32 getTitlebarHeight(void) const { return m_titlebarHeight; } diff --git a/src/ogfx/gui/widgets/Label.cpp b/src/ogfx/gui/widgets/Label.cpp index 869571e..ee0dfcb 100644 --- a/src/ogfx/gui/widgets/Label.cpp +++ b/src/ogfx/gui/widgets/Label.cpp @@ -32,32 +32,18 @@ namespace ogfx setText(text); setPadding({ 5, 5, 5, 5 }); setTypeName("ogfx::gui::widgets::Label"); - disableDrawBox(); disableChildren(); enableBackground(false); + setStylesheetCategoryName("label"); validate(); return *this; } - void Label::applyTheme(const ostd::Stylesheet& theme) - { - setColor(getThemeValue(theme, "label.textColor", Colors::White)); - setBackGroundColor(getThemeValue(theme, "label.backgroundColor", Colors::Transparent)); - setFontSize(getThemeValue(theme, "label.fontSize", 20)); - setBorderRadius(getThemeValue(theme, "label.borderRadius", 10)); - setBorderWidth(getThemeValue(theme, "label.borderWidth", 2)); - enableBorder(getThemeValue(theme, "label.showBorder", false)); - setBorderColor(getThemeValue(theme, "label.borderColor", Colors::White)); - enableBackground(getThemeValue(theme, "label.showBackground", false)); - setPadding(getThemeValue(theme, "label.padding", { 5, 5, 5, 5 })); - setMargin(getThemeValue(theme, "label.margin", { 0, 0, 0, 0 })); - } - void Label::onDraw(ogfx::BasicRenderer2D& gfx) { if (m_textChanged) __update_size(gfx); - gfx.drawString(getText(), getGlobalContentPosition(), getColor(), getFontSize()); + gfx.drawString(getText(), getGlobalContentPosition(), getTextColor(), getFontSize()); } void Label::setText(const String& text) diff --git a/src/ogfx/gui/widgets/Label.hpp b/src/ogfx/gui/widgets/Label.hpp index 171d489..fb99cd7 100644 --- a/src/ogfx/gui/widgets/Label.hpp +++ b/src/ogfx/gui/widgets/Label.hpp @@ -34,14 +34,9 @@ namespace ogfx inline Label(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); } inline Label(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } Label& create(const String& text); - void applyTheme(const ostd::Stylesheet& theme) override; void onDraw(ogfx::BasicRenderer2D& gfx) override; void setText(const String& text); inline String getText(void) const { return m_text; } - inline Color getColor(void) const { return m_color; } - inline void setColor(const Color& color) { m_color = color; } - inline i32 getFontSize(void) const { return m_fontSize; } - inline void setFontSize(i32 fontSize) { m_fontSize = fontSize; } private: void __update_size(ogfx::BasicRenderer2D& gfx); @@ -49,8 +44,6 @@ namespace ogfx private: String m_text { "" }; bool m_textChanged { false }; - i32 m_fontSize { 20 }; - Color m_color { 255, 255, 255 }; }; } } diff --git a/src/ogfx/gui/widgets/RootWidget.cpp b/src/ogfx/gui/widgets/RootWidget.cpp index d668dc3..48ba104 100644 --- a/src/ogfx/gui/widgets/RootWidget.cpp +++ b/src/ogfx/gui/widgets/RootWidget.cpp @@ -30,9 +30,9 @@ namespace ogfx { RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { - disableDrawBox(); - m_rootChild = true; + setRootChild(); setSize(cast(window.getWindowWidth()), cast(window.getWindowHeight())); + setStylesheetCategoryName("window"); setTypeName("ogfx::gui::widgets::RootWidget"); } @@ -43,7 +43,7 @@ namespace ogfx void RootWidget::applyTheme(const ostd::Stylesheet& theme) { - m_color = getThemeValue(theme, "window.backgroundColor", getWindow().getClearColor()); + m_color = getThemeValue(theme, "backgroundColor", getWindow().getClearColor()); } void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx) diff --git a/src/ogfx/gui/widgets/Scrollbar.cpp b/src/ogfx/gui/widgets/Scrollbar.cpp index ed77725..971c9aa 100644 --- a/src/ogfx/gui/widgets/Scrollbar.cpp +++ b/src/ogfx/gui/widgets/Scrollbar.cpp @@ -32,24 +32,24 @@ namespace ogfx setPadding({ 0, 0, 0, 0 }); setMargin({ 0, 0, 0, 0 }); setTypeName("ogfx::gui::widgets::Label"); - disableDrawBox(); disableChildren(); enableBackground(true); enableBorder(false); enableTopMost(true); - allowIgnoreScroll(true); + enableIgnoreScroll(true); + setStylesheetCategoryName("scrollbar"); validate(); return *this; } void VerticalScrollBar::applyTheme(const ostd::Stylesheet& theme) { - w = getThemeValue(theme, "scrollbar.width", 15); - m_thumbColor = getThemeValue(theme, "scrollbar.thumb.color", { 120, 120, 120 }); - m_thumbBorderRadius = getThemeValue(theme, "scrollbar.thumb.borderRadius", 16); - m_thumbBorderColor = getThemeValue(theme, "scrollbar.thumb.borderColor", { 150, 150, 150 }); - m_thumbShowBorder = getThemeValue(theme, "scrollbar.thumb.showBorder", true); - m_trackColor = getThemeValue(theme, "scrollbar.track.color", { 70, 70, 70 }); + w = getThemeValue(theme, "width", 15); + m_thumbColor = getThemeValue(theme, "thumb.color", { 120, 120, 120 }); + m_thumbBorderRadius = getThemeValue(theme, "thumb.borderRadius", 16); + m_thumbBorderColor = getThemeValue(theme, "thumb.borderColor", { 150, 150, 150 }); + m_thumbShowBorder = getThemeValue(theme, "thumb.showBorder", true); + m_trackColor = getThemeValue(theme, "track.color", { 70, 70, 70 }); } void VerticalScrollBar::afterDraw(ogfx::BasicRenderer2D& gfx) @@ -155,24 +155,24 @@ namespace ogfx setPadding({ 0, 0, 0, 0 }); setMargin({ 0, 0, 0, 0 }); setTypeName("ogfx::gui::widgets::Label"); - disableDrawBox(); disableChildren(); enableBackground(true); enableBorder(false); enableTopMost(true); - allowIgnoreScroll(true); + enableIgnoreScroll(true); + setStylesheetCategoryName("scrollbar"); validate(); return *this; } void HorizontalScrollbar::applyTheme(const ostd::Stylesheet& theme) { - h = getThemeValue(theme, "scrollbar.width", 15); - m_thumbColor = getThemeValue(theme, "scrollbar.thumb.color", { 120, 120, 120 }); - m_thumbBorderRadius = getThemeValue(theme, "scrollbar.thumb.borderRadius", 16); - m_thumbBorderColor = getThemeValue(theme, "scrollbar.thumb.borderColor", { 150, 150, 150 }); - m_thumbShowBorder = getThemeValue(theme, "scrollbar.thumb.showBorder", true); - m_trackColor = getThemeValue(theme, "scrollbar.track.color", { 70, 70, 70 }); + h = getThemeValue(theme, "width", 15); + m_thumbColor = getThemeValue(theme, "thumb.color", { 120, 120, 120 }); + m_thumbBorderRadius = getThemeValue(theme, "thumb.borderRadius", 16); + m_thumbBorderColor = getThemeValue(theme, "thumb.borderColor", { 150, 150, 150 }); + m_thumbShowBorder = getThemeValue(theme, "thumb.showBorder", true); + m_trackColor = getThemeValue(theme, "track.color", { 70, 70, 70 }); } void HorizontalScrollbar::afterDraw(ogfx::BasicRenderer2D& gfx) @@ -277,8 +277,8 @@ namespace ogfx ScrollableWidget& ScrollableWidget::create(void) { setTypeName("ogfx::gui::widgets::ScrollableWidget"); - allowVScroll(true); - allowHScroll(true); + enableVScroll(true); + enableHScroll(true); m_vScrollbar.enableManualDraw(true); addWidget(m_vScrollbar); m_hScrollbar.setMargin({ 0, 0, 0, 0 }); @@ -321,7 +321,7 @@ namespace ogfx void ScrollableWidget::onMouseScrolled(const Event& event) { - if (isVScrollAllowed()) + if (isVScrollEnabled()) { bool mouseInsideHScrollbar = m_hScrollbar.isMouseInsideThumb({ event.mouse->position_x, event.mouse->position_y }) && needsHScroll(); if (std::abs(event.mouse->scrollAmount.y) > 0 && !mouseInsideHScrollbar) @@ -339,7 +339,7 @@ namespace ogfx event.handle(); } } - if (isHScrollAllowed()) + if (isHScrollEnabled()) { if (std::abs(event.mouse->scrollAmount.x) > 0) { @@ -383,12 +383,12 @@ namespace ogfx bool ScrollableWidget::needsVScroll(void) const { - return isVScrollAllowed() && getContentExtents().h > getContentBounds().h; + return isVScrollEnabled() && getContentExtents().h > getContentBounds().h; } bool ScrollableWidget::needsHScroll(void) const { - return isHScrollAllowed() && getContentExtents().w > getContentBounds().w; + return isHScrollEnabled() && getContentExtents().w > getContentBounds().w; } void ScrollableWidget::onWidgetAdded(Widget& child) @@ -401,7 +401,7 @@ namespace ogfx f32 ScrollableWidget::getVScrollbarSize(void) const { - if (!isVScrollAllowed()) + if (!isVScrollEnabled()) return 0; if (!needsVScroll()) return 0; @@ -410,7 +410,7 @@ namespace ogfx f32 ScrollableWidget::getHScrollbarSize(void) const { - if (!isHScrollAllowed()) + if (!isHScrollEnabled()) return 0; if (!needsHScroll()) return 0; diff --git a/src/ogfx/gui/widgets/Widget.cpp b/src/ogfx/gui/widgets/Widget.cpp index 5f65d94..ef50a4b 100644 --- a/src/ogfx/gui/widgets/Widget.cpp +++ b/src/ogfx/gui/widgets/Widget.cpp @@ -61,7 +61,7 @@ namespace ogfx if (!m_rootChild && m_parent != nullptr) { glob += m_parent->getGlobalPosition(); - if (!isIgnoreScrollAllowed()) + if (!isIgnoreScrollEnabled()) { glob += m_parent->getPadding().getPosition(); glob += m_parent->getContentOffset(); @@ -109,7 +109,7 @@ namespace ogfx for (auto* child : m_widgets.getWidgets()) { if (!child || child->isInvalid()) continue; - if (child->isIgnoreScrollAllowed()) continue; + if (child->isIgnoreScrollEnabled()) continue; if (!child->isVisible()) continue; Vec2 localPos = getPadding().getPosition() + child->getPosition() + child->getMargin().getPosition() + child->getContentBounds().getPosition(); maxX = std::max(maxX, localPos.x + child->getw() + child->getMargin().w); @@ -138,6 +138,8 @@ namespace ogfx { if (getWindow().theme() == nullptr) return; + if (!isThemingEnabled()) + return; auto& theme = *getWindow().theme(); applyTheme(theme); @@ -214,20 +216,38 @@ namespace ogfx m_visible = v; } + void Widget::setCallback(eCallback type, EventCallback callback) + { + switch (type) + { + case eCallback::MousePressed: callback_onMousePressed = std::move(callback); break; + case eCallback::MouseReleased: callback_onMouseReleased = std::move(callback); break; + case eCallback::MouseMoved: callback_onMouseMoved = std::move(callback); break; + case eCallback::MouseScrolled: callback_onMouseScrolled = std::move(callback); break; + case eCallback::DragAndDrop: callback_onDragAndDrop = std::move(callback); break; + case eCallback::MouseEntered: callback_onMouseEntered = std::move(callback); break; + case eCallback::MouseExited: callback_onMouseExited = std::move(callback); break; + case eCallback::MouseDragged: callback_onMouseDragged = std::move(callback); break; + case eCallback::KeyPressed: callback_onKeyPressed = std::move(callback); break; + case eCallback::KeyReleased: callback_onKeyReleased = std::move(callback); break; + case eCallback::TextEntered: callback_onTextEntered = std::move(callback); break; + case eCallback::WindowClosed: callback_onWindowClosed = std::move(callback); break; + case eCallback::WindowResized: callback_onWindowResized = std::move(callback); break; + case eCallback::WindowFocused: callback_onWindowFocused = std::move(callback); break; + case eCallback::WindowFocusLost: callback_onWindowFocusLost = std::move(callback); break; + default: break; + } + } + void Widget::__draw(ogfx::BasicRenderer2D& gfx) { if (!isVisible()) return; - if (isDrawBoxEnabled()) - gfx.fillRect({ getGlobalPosition(), getSize() }, getDrawBoxColor()); - else - { - beforeDraw(gfx); - if (m_showBackground && m_showBorder) - gfx.outlinedRoundRect({ getGlobalPosition(), getSize() }, m_backgroundColor, m_borderColor, m_borderRadius, m_borderWidth); - else if (m_showBackground) - gfx.fillRoundRect({ getGlobalPosition(), getSize() }, m_backgroundColor, m_borderRadius); - } + beforeDraw(gfx); + if (m_useBackgroundGradient && m_showBorder) + gfx.fillGradientRect({ getGlobalPosition(), getSize() }, m_backgroundGradient); + else if (m_showBackground) + gfx.fillRoundRect({ getGlobalPosition(), getSize() }, m_backgroundColor, m_borderRadius); onDraw(gfx); // gfx.fillRect(getGlobalPureContentBounds(), { 0, 255, 0, 120 }); @@ -431,7 +451,26 @@ namespace ogfx { if (propagate && hasChildren()) m_widgets.onThemeApplied(theme); + apply_common_theme_values(theme); applyTheme(theme); } + + void Widget::apply_common_theme_values(const ostd::Stylesheet& theme) + { + setTextColor(getThemeValue(theme, "textColor", m_textColor)); + setBackgroundColor(getThemeValue(theme, "backgroundColor", m_backgroundColor)); + setFontSize(getThemeValue(theme, "fontSize", m_fontSize)); + setBorderRadius(getThemeValue(theme, "borderRadius", m_borderRadius)); + setBorderWidth(getThemeValue(theme, "borderWidth", m_borderWidth)); + enableBorder(getThemeValue(theme, "showBorder", m_showBorder)); + setBorderColor(getThemeValue(theme, "borderColor", m_borderColor)); + enableBackground(getThemeValue(theme, "showBackground", m_showBackground)); + setPadding(getThemeValue(theme, "padding", m_padding)); + setMargin(getThemeValue(theme, "margin", m_margin)); + enableBackgroundGradient(getThemeValue(theme, "useBackgroundGradient", m_useBackgroundGradient)); + setBackgroundGradient(getThemeValue(theme, "backgroundGradient", m_backgroundGradient)); + if (isBackgroundGradientEnabled() && isBackgroundEnabled()) + enableBackground(false); + } } } diff --git a/src/ogfx/gui/widgets/Widget.hpp b/src/ogfx/gui/widgets/Widget.hpp index 556156e..d4b1f76 100644 --- a/src/ogfx/gui/widgets/Widget.hpp +++ b/src/ogfx/gui/widgets/Widget.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace ogfx @@ -38,30 +39,31 @@ namespace ogfx String fullKey; ostd::Stylesheet::TypeVariant value; }; + public: enum class eCallback + { + MousePressed = 0, + MouseReleased, + MouseMoved, + MouseScrolled, + DragAndDrop, + MouseEntered, + MouseExited, + MouseDragged, + KeyPressed, + KeyReleased, + TextEntered, + WindowClosed, + WindowResized, + WindowFocused, + WindowFocusLost + }; public: using EventCallback = std::function; public: + // ================================== MAIN ================================= Widget(const Rectangle& bounds, WindowCore& window); bool addWidget(Widget& child, const Vec2& position = { 0, 0 }, bool __skip_callback = false); bool removeWidget(Widget& child); - virtual Vec2 getGlobalPosition(void) const; - virtual Vec2 getGlobalContentPosition(void) const; - virtual Rectangle getGlobalBounds(void) const; - virtual Rectangle getContentBounds(void) const; - virtual Rectangle getPureContentBounds(void) const; - virtual Rectangle getGlobalContentBounds(void) const; - virtual Rectangle getGlobalPureContentBounds(void) const; - virtual Rectangle getContentExtents(void) const; - using Rectangle::contains; - bool contains(Vec2 p, bool includeBounds = false) const override; void enable(bool enable = true); - virtual void applyTheme(const ostd::Stylesheet& theme) = 0; - inline virtual Vec2 getScrollOffset(void) const { return { 0, 0 }; } - inline virtual void setScrollOffset(const Vec2& offset) { } - inline virtual void addScrollOffset(const Vec2& offset) { } - inline virtual bool needsVScroll(void) const { return false; } - inline virtual bool needsHScroll(void) const { return false; } - inline virtual f32 getVScrollbarSize(void) const { return 0; } - inline virtual f32 getHScrollbarSize(void) const { return 0; } void addThemeOverride(const String& fullKey, ostd::Stylesheet::TypeVariant value); void reloadTheme(bool propagate = false); void setThemeQualifier(const String& qualifier, bool value = true); @@ -69,32 +71,18 @@ namespace ogfx bool addThemeID(const String& id); bool removeThemeID(const String& id); void setVisible(bool v); - inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; } + void setCallback(eCallback type, EventCallback callback); + using Rectangle::contains; bool contains(Vec2 p, bool includeBounds = false) const override; + template + inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback) + { + return theme.get(property(key), fallback, getThemeIDList(), getThemeQualifierList()); + } + // ========================================================================== - inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { } - inline virtual void afterDraw(ogfx::BasicRenderer2D& gfx) { } - inline virtual void beforeDraw(ogfx::BasicRenderer2D& gfx) { } - inline virtual void onUpdate(void) { } - inline virtual void onWidgetAdded(Widget& child) { } - inline virtual void onMousePressed(const Event& event) { } - inline virtual void onMouseReleased(const Event& event) { } - inline virtual void onMouseMoved(const Event& event) { } - inline virtual void onMouseScrolled(const Event& event) { } - inline virtual void onDragAndDrop(const Event& event) { } - inline virtual void onMouseEntered(const Event& event) { } - inline virtual void onMouseExited(const Event& event) { } - inline virtual void onMouseDragged(const Event& event) { } - inline virtual void onKeyPressed(const Event& event) { } - inline virtual void onKeyReleased(const Event& event) { } - inline virtual void onTextEntered(const Event& event) { } - inline virtual void onFocusGained(const Event& event) { } - inline virtual void onFocusLost(const Event& event) { } - inline virtual void onWindowClosed(const Event& event) { } - inline virtual void onWindowResized(const Event& event) { } - inline virtual void onWindowFocused(const Event& event) { } - inline virtual void onWindowFocusLost(const Event& event) { } + // ================================== CORE ================================= void __draw(ogfx::BasicRenderer2D& gfx); void __update(void); void __onMousePressed(const Event& event); @@ -113,103 +101,155 @@ namespace ogfx void __onWindowFocused(const Event& event); void __onWindowFocusLost(const Event& event); void __applyTheme(const ostd::Stylesheet& theme, bool propagate); + // ========================================================================== - inline virtual void setMousePressedCallback(EventCallback callback) { callback_onMousePressed = callback; } - inline virtual void setMouseReleasedCallback(EventCallback callback) { callback_onMouseReleased = callback; } - inline virtual void setMouseMovedCallback(EventCallback callback) { callback_onMouseMoved = callback; } - inline virtual void setMouseScrolledCallback(EventCallback callback) { callback_onMouseScrolled = callback; } - inline virtual void setDragAndDropCallback(EventCallback callback) { callback_onDragAndDrop = callback; } - inline virtual void setMouseEnteredCallback(EventCallback callback) { callback_onMouseEntered = callback; } - inline virtual void setMouseExitedCallback(EventCallback callback) { callback_onMouseExited = callback; } - inline virtual void setMouseDraggedCallback(EventCallback callback) { callback_onMouseDragged = callback; } - inline virtual void setKeyPressedCallback(EventCallback callback) { callback_onKeyPressed = callback; } - inline virtual void setKeyReleasedCallback(EventCallback callback) { callback_onKeyReleased = callback; } - inline virtual void setTextEnteredCallback(EventCallback callback) { callback_onTextEntered = callback; } - inline virtual void setWindowClosedCallback(EventCallback callback) { callback_onWindowClosed = callback; } - inline virtual void setWindowResizedCallback(EventCallback callback) { callback_onWindowResized = callback; } - inline virtual void setWindowFocusedCallback(EventCallback callback) { callback_onWindowFocused = callback; } - inline virtual void setWindowFocusLostCallback(EventCallback callback) { callback_onWindowFocusLost = callback; } - inline bool hasChildren(void) const { return m_allowChildren && m_widgets.widgetCount() > 0; } - inline virtual bool isInvalid(void) const override { return ostd::BaseObject::isInvalid() || (m_parent == nullptr && !m_rootChild); } - inline void setTabIndex(i32 tabIndex) { m_tabIndex = tabIndex; } - inline i32 getTabIndex(void) const { return m_tabIndex; } - inline bool isFocused(void) const { return m_focused; } - inline WindowCore& getWindow(void) { return *m_window; } - inline Widget* getParent(void) { return m_parent; } - inline i32 getZIndex(void) const { return m_zIndex; } - inline bool isChildrenEnabled(void) const { return m_allowChildren; } - inline void setPadding(const Rectangle& pad) { m_padding = pad; } - inline void setMargin(const Rectangle& margin) { m_margin = margin; } - inline void setContentOffset(const Vec2& offset) { m_contentOffset = offset; } - inline Rectangle getPadding(void) const { return m_padding; } - inline Rectangle getMargin(void) const { return m_margin; } - inline Vec2 getContentOffset(void) const { return m_contentOffset; } - inline bool isMouseInside(void) const { return m_mouseInside; } - inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; } - inline const stdvec& 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 disable(void) { enable(false); } - inline void enableStopEvents(bool enable = true) { m_stopEvents = enable; } - inline bool isDragAndDropEnabled(void) const { return m_acceptDragAndDrop; } - inline void enableDragAndDrop(bool enable = true) { m_acceptDragAndDrop = enable; } - inline void disableDragAndDrop(void) { enableDragAndDrop(false); } - inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; } - inline Color getBackgroundColor(void) { return m_backgroundColor; } - inline void enableBackground(bool enable = true) { m_showBackground = enable; } - inline bool isBackgoundEnabled(void) const { return m_showBackground; } - inline void setBorderColor(const Color& color) { m_borderColor = color; } - inline Color getBorderColor(void) { return m_borderColor; } - inline void enableBorder(bool enable = true) { m_showBorder = enable; } - inline bool isBorderEnabled(void) const { return m_showBorder; } - inline void enableManualDraw(bool enable = true) { m_manualDraw = enable; } - inline bool isManualDrawEnabled(void) const { return m_manualDraw; } - inline void enableTopMost(bool enable = true) { m_topMost = enable; } - inline bool isTopMostEnabled(void) const { return m_topMost; } - inline void setBorderRadius(i32 br) { m_borderRadius = br; } - inline i32 getBorderRadius(void) const { return m_borderRadius; } - inline void setBorderWidth(i32 bw) { m_borderWidth = bw; } - inline i32 getBorderWidth(void) const { return m_borderWidth; } - inline bool isVisible(void) const { return m_visible; } - inline void show(void) { setVisible(true); } - inline void hide(void) { setVisible(false); } - inline void allowVScroll(bool allow = true) { m_vScrollEnabled = allow; } - inline bool isVScrollAllowed(void) const { return m_vScrollEnabled; } - inline void allowHScroll(bool allow = true) { m_hScrollEnabled = allow; } - inline bool isHScrollAllowed(void) const { return m_hScrollEnabled; } - inline void allowIgnoreScroll(bool allow = true) { m_ignoreScroll = allow; } - inline bool isIgnoreScrollAllowed(void) const { return m_ignoreScroll; } - template - inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback) - { - return theme.get(key, fallback, getThemeIDList(), getThemeQualifierList()); - } + // =============================== DIMENSIONS =============================== + virtual Vec2 getGlobalPosition(void) const; + virtual Vec2 getGlobalContentPosition(void) const; + virtual Rectangle getGlobalBounds(void) const; + virtual Rectangle getContentBounds(void) const; + virtual Rectangle getPureContentBounds(void) const; + virtual Rectangle getGlobalContentBounds(void) const; + virtual Rectangle getGlobalPureContentBounds(void) const; + virtual Rectangle getContentExtents(void) const; + // ========================================================================== + + + // ================================= GETSET ================================= inline static void setDragAndDropData(ostd::BaseObject& data) { s_dragAndDropData = &data; s_hasDragAndDropData = true; } inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; } inline static ostd::BaseObject* getDragAndDropData(void) { return s_dragAndDropData; } + inline WindowCore& getWindow(void) { return *m_window; } + inline Widget* getParent(void) { return m_parent; } + inline i32 getZIndex(void) const { return m_zIndex; } + inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; } + inline const stdvec& getThemeIDList(void) const { return m_themeIDList; } + inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; } + inline String getStylesheetCategoryName(void) const { return m_stylesheetCategoryName; } + OSTD_PARAM_GETSET(Color, TextColor, m_textColor); + OSTD_PARAM_GETSET(Color, BackgroundColor, m_backgroundColor); + OSTD_PARAM_GETSET(Color, BorderColor, m_borderColor); + OSTD_PARAM_GETSET(i32, BorderRadius, m_borderRadius); + OSTD_PARAM_GETSET(i32, BorderWidth, m_borderWidth); + OSTD_PARAM_GETSET(i32, FontSize, m_fontSize); + OSTD_PARAM_GETSET(ostd::ColorGradient, BackgroundGradient, m_backgroundGradient); + OSTD_PARAM_GETSET(Rectangle, Padding, m_padding); + OSTD_PARAM_GETSET(Rectangle, Margin, m_margin); + OSTD_PARAM_GETSET(i32, TabIndex, m_tabIndex); + OSTD_PARAM_GETSET(Vec2, ContentOffset, m_contentOffset); + + // BOOL PARAMETERS + inline bool isVisible(void) const { return m_visible; } + inline void show(void) { setVisible(true); } + inline void hide(void) { setVisible(false); } + inline bool isChildrenEnabled(void) const { return m_allowChildren; } + inline bool isEnabled(void) const { return m_enabled; } + inline void disable(void) { enable(false); } + inline bool isFocused(void) const { return m_focused; } + inline bool isMouseInside(void) const { return m_mouseInside; } + inline bool hasChildren(void) const { return m_allowChildren && m_widgets.widgetCount() > 0; } + inline bool isRootChild(void) const { return m_rootChild; } + inline void setRootChild(void) { m_rootChild = true; } + inline virtual bool isInvalid(void) const override { return ostd::BaseObject::isInvalid() || (m_parent == nullptr && !m_rootChild); } + OSTD_BOOL_PARAM_GETSET_E(Focus, m_allowFocus); + OSTD_BOOL_PARAM_GETSET_E(StopEvents, m_stopEvents); + OSTD_BOOL_PARAM_GETSET_E(DragAndDrop, m_acceptDragAndDrop); + OSTD_BOOL_PARAM_GETSET_E(Background, m_showBackground); + OSTD_BOOL_PARAM_GETSET_E(Border, m_showBorder); + OSTD_BOOL_PARAM_GETSET_E(ManualDraw, m_manualDraw); + OSTD_BOOL_PARAM_GETSET_E(TopMost, m_topMost); + OSTD_BOOL_PARAM_GETSET_E(IgnoreScroll, m_ignoreScroll); + OSTD_BOOL_PARAM_GETSET_E(VScroll, m_vScrollEnabled); + OSTD_BOOL_PARAM_GETSET_E(HScroll, m_vScrollEnabled); + OSTD_BOOL_PARAM_GETSET_E(BackgroundGradient, m_useBackgroundGradient); + OSTD_BOOL_PARAM_GETSET_E(Theming, m_enableTheming); + // ========================================================================== protected: + void apply_common_theme_values(const ostd::Stylesheet& theme); inline void disableChildren(void) { m_allowChildren = false; } - inline void disableDrawBox(void) { m_drawBox = false; } - inline void enableDrawBox(void) { m_drawBox = true; } - inline bool isDrawBoxEnabled(void) const { return m_drawBox; } - inline void setDrawBoxColor(const Color& color) { m_drawBoxColor = color; } - inline Color getDrawBoxColor(void) { return m_drawBoxColor; } + inline void setStylesheetCategoryName(const String& name) { m_stylesheetCategoryName = name; } + inline String property(const ostd::String& prop) const { return m_stylesheetCategoryName + "." + prop; } + + private: + // ======= CORE ======= + WindowCore* m_window { nullptr }; + Widget* m_parent { nullptr }; + WidgetManager m_widgets; - protected: bool m_rootChild { false }; + bool m_focused { false }; + i32 m_tabIndex { -1 }; + i32 m_zIndex { -1 }; + MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; + // ==================== + + + + // ======= BOOL ======= + bool m_allowChildren { true }; + bool m_mouseInside { false }; + bool m_allowFocus { true }; + bool m_enabled { true }; + bool m_stopEvents { true }; + bool m_clipContents { true }; + bool m_acceptDragAndDrop { false }; + bool m_visible { true }; + bool m_ignoreScroll { false}; + bool m_manualDraw { false }; + bool m_topMost { false }; + bool m_vScrollEnabled { false }; + bool m_hScrollEnabled { false }; + bool m_enableTheming { true }; + // ==================== + + + + // ====== THEMING ===== + String m_stylesheetCategoryName { "" }; + stdvec m_themeIDList; + ostd::Stylesheet::QualifierList m_qualifierList { + { "disabled", false }, + { "pressed", false }, + { "hover", false }, + { "focused", false }, + { "active", false } + }; + stdvec m_themeOverrides; + Rectangle m_padding { 0, 0, 0, 0 }; + Rectangle m_margin { 0, 0, 0, 0 }; + Vec2 m_contentOffset { 0, 0 }; i32 m_borderRadius { 10 }; i32 m_borderWidth { 2 }; Color m_borderColor { 255, 255, 255 }; bool m_showBorder { false }; Color m_backgroundColor { Colors::Transparent }; bool m_showBackground { false }; + i32 m_fontSize { 20 }; + Color m_textColor { 255, 255, 255 }; + bool m_useBackgroundGradient { false }; + ColorGradient m_backgroundGradient { + { Color { 160, 160, 160 }, Color { 120, 120, 120 } }, + { 1.0f } + }; + // ==================== + + + // ====== STATIC ====== + static ostd::BaseObject* s_dragAndDropData; + static bool s_hasDragAndDropData; + friend class WidgetManager; + // ==================== + + + + + // =============================== CALLBACKS/DUMMIES =============================== + protected: EventCallback callback_onMousePressed { nullptr }; EventCallback callback_onMouseReleased { nullptr }; EventCallback callback_onDragAndDrop { nullptr }; @@ -226,49 +266,40 @@ namespace ogfx EventCallback callback_onWindowFocused { nullptr }; EventCallback callback_onWindowFocusLost { nullptr }; - private: - WindowCore* m_window { nullptr }; - Widget* m_parent { nullptr }; - bool m_focused { false }; - i32 m_tabIndex { -1 }; - i32 m_zIndex { -1 }; - WidgetManager m_widgets; - bool m_allowChildren { true }; - bool m_mouseInside { false }; - bool m_allowFocus { true }; - bool m_enabled { true }; - bool m_stopEvents { true }; - bool m_clipContents { true }; - bool m_acceptDragAndDrop { false }; - bool m_visible { true }; - bool m_ignoreScroll { false}; - bool m_manualDraw { false }; - bool m_topMost { false }; - bool m_vScrollEnabled { false }; - bool m_hScrollEnabled { false }; - MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; + public: + // ====================== DUMMIES ====================== + inline virtual void applyTheme(const ostd::Stylesheet& theme) { } + inline virtual Vec2 getScrollOffset(void) const { return { 0, 0 }; } + inline virtual void setScrollOffset(const Vec2& offset) { } + inline virtual void addScrollOffset(const Vec2& offset) { } + inline virtual bool needsVScroll(void) const { return false; } + inline virtual bool needsHScroll(void) const { return false; } + inline virtual f32 getVScrollbarSize(void) const { return 0; } + inline virtual f32 getHScrollbarSize(void) const { return 0; } + // ===================================================== - stdvec m_themeIDList; - ostd::Stylesheet::QualifierList m_qualifierList { - { "disabled", false }, - { "pressed", false }, - { "hover", false }, - { "focused", false }, - { "active", false } - }; - stdvec m_themeOverrides; - - bool m_drawBox { true }; - Color m_drawBoxColor { 255, 0, 0 }; - - Rectangle m_padding { 0, 0, 0, 0 }; - Rectangle m_margin { 0, 0, 0, 0 }; - Vec2 m_contentOffset { 0, 0 }; - - static ostd::BaseObject* s_dragAndDropData; - static bool s_hasDragAndDropData; - - friend class WidgetManager; + inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { } + inline virtual void afterDraw(ogfx::BasicRenderer2D& gfx) { } + inline virtual void beforeDraw(ogfx::BasicRenderer2D& gfx) { } + inline virtual void onUpdate(void) { } + inline virtual void onWidgetAdded(Widget& child) { } + inline virtual void onMousePressed(const Event& event) { } + inline virtual void onMouseReleased(const Event& event) { } + inline virtual void onMouseMoved(const Event& event) { } + inline virtual void onMouseScrolled(const Event& event) { } + inline virtual void onDragAndDrop(const Event& event) { } + inline virtual void onMouseEntered(const Event& event) { } + inline virtual void onMouseExited(const Event& event) { } + inline virtual void onMouseDragged(const Event& event) { } + inline virtual void onKeyPressed(const Event& event) { } + inline virtual void onKeyReleased(const Event& event) { } + inline virtual void onTextEntered(const Event& event) { } + inline virtual void onFocusGained(const Event& event) { } + inline virtual void onFocusLost(const Event& event) { } + inline virtual void onWindowClosed(const Event& event) { } + inline virtual void onWindowResized(const Event& event) { } + inline virtual void onWindowFocused(const Event& event) { } + inline virtual void onWindowFocusLost(const Event& event) { } }; } } diff --git a/src/ogfx/utils/Animation.hpp b/src/ogfx/utils/Animation.hpp index 8ea31cd..c019dca 100644 --- a/src/ogfx/utils/Animation.hpp +++ b/src/ogfx/utils/Animation.hpp @@ -20,54 +20,16 @@ #pragma once -#include +#include #include #include #include namespace ogfx { + using AnimationData = ostd::AnimationData; class Animation { - public: struct AnimationData : public ostd::__i_stringeable { - i32 frameCount { 1 }; - i32 stillFrame { 0 }; - f64 fps { 60.0 }; - - i32 rowOffset { 0 }; - i32 columnOffset { 0 }; - f32 pixelOffsetX { 0.0f }; - f32 pixelOffsetY { 0.0f }; - i32 rows { 1 }; - i32 columns { 1 }; - f32 frameWidth{ 32 }; - f32 frameHeight { 32 }; - - bool still { false }; - bool turnBack { false }; - bool random { false }; - - inline String toString(void) const override - { - String str = ""; - str.add("AnimData {"); - str.add(" ").add("frameCount: ").add(frameCount).add(",\n"); - str.add(" ").add("stillFrame: ").add(stillFrame).add(",\n"); - str.add(" ").add("rowOffset: ").add(rowOffset).add(",\n"); - str.add(" ").add("columnOffset: ").add(columnOffset).add(",\n"); - str.add(" ").add("pixelOffsetX: ").add(pixelOffsetX, 2).add(",\n"); - str.add(" ").add("pixelOffsetY: ").add(pixelOffsetY, 2).add(",\n"); - str.add(" ").add("rows: ").add(rows).add(",\n"); - str.add(" ").add("columns: ").add(columns).add(",\n"); - str.add(" ").add("frameWidth: ").add(frameWidth, 2).add(",\n"); - str.add(" ").add("frameHeight: ").add(frameHeight, 2).add(",\n"); - str.add(" ").add("still: ").add(STR_BOOL(still)).add(",\n"); - str.add(" ").add("turnBack: ").add(STR_BOOL(turnBack)).add(",\n"); - str.add(" ").add("random: ").add(STR_BOOL(random)).add(",\n"); - str.add("}"); - return str; - } - }; public: inline Animation(void) { } inline Animation(const AnimationData& ad) { create(ad); }; diff --git a/src/ostd/data/AnimationData.hpp b/src/ostd/data/AnimationData.hpp new file mode 100644 index 0000000..a075d92 --- /dev/null +++ b/src/ostd/data/AnimationData.hpp @@ -0,0 +1,67 @@ +/* + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev + + This file is part of OmniaFramework. + + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . +*/ + +#pragma once + +#include +#include + +namespace ostd +{ + struct AnimationData : public ostd::__i_stringeable { + i32 frameCount { 1 }; + i32 stillFrame { 0 }; + f64 fps { 60.0 }; + + i32 rowOffset { 0 }; + i32 columnOffset { 0 }; + f32 pixelOffsetX { 0.0f }; + f32 pixelOffsetY { 0.0f }; + i32 rows { 1 }; + i32 columns { 1 }; + f32 frameWidth{ 32 }; + f32 frameHeight { 32 }; + + bool still { false }; + bool turnBack { false }; + bool random { false }; + + inline String toString(void) const override + { + String str = ""; + str.add("AnimData {"); + str.add(" ").add("frameCount: ").add(frameCount).add(",\n"); + str.add(" ").add("stillFrame: ").add(stillFrame).add(",\n"); + str.add(" ").add("rowOffset: ").add(rowOffset).add(",\n"); + str.add(" ").add("columnOffset: ").add(columnOffset).add(",\n"); + str.add(" ").add("pixelOffsetX: ").add(pixelOffsetX, 2).add(",\n"); + str.add(" ").add("pixelOffsetY: ").add(pixelOffsetY, 2).add(",\n"); + str.add(" ").add("rows: ").add(rows).add(",\n"); + str.add(" ").add("columns: ").add(columns).add(",\n"); + str.add(" ").add("frameWidth: ").add(frameWidth, 2).add(",\n"); + str.add(" ").add("frameHeight: ").add(frameHeight, 2).add(",\n"); + str.add(" ").add("still: ").add(STR_BOOL(still)).add(",\n"); + str.add(" ").add("turnBack: ").add(STR_BOOL(turnBack)).add(",\n"); + str.add(" ").add("random: ").add(STR_BOOL(random)).add(",\n"); + str.add("}"); + return str; + } +}; +} diff --git a/src/ostd/io/Stylesheet.cpp b/src/ostd/io/Stylesheet.cpp index 7262e7b..69d64ec 100644 --- a/src/ostd/io/Stylesheet.cpp +++ b/src/ostd/io/Stylesheet.cpp @@ -63,6 +63,8 @@ namespace ostd stdvec group; u32 groupSelectorCount = 0; bool debug_print = false; + bool brokenLine = false; + String brokenLineBuffer = ""; for (auto& line : lines) { lineNumber++; @@ -73,6 +75,18 @@ namespace ostd line.substr(0, line.indexOf("%")).trim(); if (line == "") continue; + if (brokenLine) + { + line = brokenLineBuffer + line; + brokenLine = false; + brokenLineBuffer = ""; + } + if (line.endsWith("\\")) + { + brokenLine = true; + brokenLineBuffer = line.new_trim().substr(0, line.len() - 1).trim(); + continue; + } if (line.startsWith("const ") || line.startsWith("$")) { bool is_const = false; @@ -283,6 +297,15 @@ namespace ostd } return false; }; + auto l_isAnim = [this](String& value) -> bool { + value.trim(); + if (value.startsWith("anim(") && value.endsWith(")")) + { + value.substr(5, value.len() - 1).trim(); + return true; + } + return false; + }; if (key.startsWith("@")) { @@ -313,6 +336,14 @@ namespace ostd return false; set(key, grad, themeID); } + else if (l_isAnim(value)) + { + bool outError = false; + AnimationData ad = parseAnim(value, outError); + if (outError) + return false; + set(key, ad, themeID); + } else if (l_isFile(value)) { bool exists = ostd::FileSystem::fileExists(value) || @@ -510,6 +541,113 @@ namespace ostd return grad; } + AnimationData Stylesheet::parseAnim(const String& _value, bool& outError) + { + String value = _value.new_toLower().trim(); + AnimationData ad; + auto tokens = value.tokenize(","); + auto l_error = [&](bool err) -> AnimationData { + outError = err; + return ad; + }; + for (auto& tok : tokens) + { + if (tok.count(":") != 1 || tok.startsWith(":") || tok.endsWith(":")) + return l_error(true); + String prop = tok.new_substr(0, tok.indexOf(":")).trim(); + String val = tok.new_substr(tok.indexOf(":") + 1).trim(); + if (prop == "framecount") + { + if (!val.isInt()) + return l_error(true); + ad.frameCount = val.toInt(); + } + else if (prop == "stillframe") + { + if (!val.isInt()) + return l_error(true); + ad.stillFrame = val.toInt(); + } + else if (prop == "fps") + { + if (!val.isNumeric(true)) + return l_error(true); + ad.fps = val.toFloat(); + } + else if (prop == "rowoffset") + { + if (!val.isInt()) + return l_error(true); + ad.rowOffset = val.toInt(); + } + else if (prop == "columnoffset") + { + if (!val.isInt()) + return l_error(true); + ad.columnOffset = val.toInt(); + } + else if (prop == "pixeloffsetx") + { + if (!val.isNumeric(true)) + return l_error(true); + ad.pixelOffsetX = val.toFloat(); + } + else if (prop == "pixeloffsety") + { + if (!val.isNumeric(true)) + return l_error(true); + ad.pixelOffsetY = val.toFloat(); + } + else if (prop == "rows") + { + if (!val.isInt()) + return l_error(true); + ad.rows = val.toInt(); + } + else if (prop == "columns") + { + if (!val.isInt()) + return l_error(true); + ad.columns = val.toInt(); + } + else if (prop == "framewidth") + { + if (!val.isNumeric(true)) + return l_error(true); + ad.frameWidth = val.toFloat(); + } + else if (prop == "frameheight") + { + if (!val.isNumeric(true)) + return l_error(true); + ad.frameHeight = val.toFloat(); + } + else if (prop == "still") + { + if (!val.isBool()) + return l_error(true); + ad.still = val.toBool(); + } + else if (prop == "turnback") + { + if (!val.isBool()) + return l_error(true); + ad.turnBack = val.toBool(); + } + else if (prop == "random") + { + if (!val.isBool()) + return l_error(true); + ad.random = val.toBool(); + } + else + { + return l_error(true); + } + } + return l_error(false); + } + void Stylesheet::debugPrint(void) { for (const auto&[key, value] : m_values) diff --git a/src/ostd/io/Stylesheet.hpp b/src/ostd/io/Stylesheet.hpp index 1e3207c..a12442f 100644 --- a/src/ostd/io/Stylesheet.hpp +++ b/src/ostd/io/Stylesheet.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -32,7 +33,7 @@ namespace ostd { public: using QualifierList = stdvec>; public: using VariableList = stdumap>; - public: using TypeVariant = std::variant; + public: using TypeVariant = std::variant; public: Stylesheet(void); Stylesheet& clear(void); @@ -63,6 +64,7 @@ namespace ostd String parseGroupSelector(const String& rawSelector) const; stdvec parseGroup(const String& selector, const stdvec& group); ColorGradient parseColorGradient(const String& _value); + AnimationData parseAnim(const String& _value, bool& outError); private: stdumap m_values; diff --git a/src/ostd/string/String.cpp b/src/ostd/string/String.cpp index 411eb29..88498ae 100644 --- a/src/ostd/string/String.cpp +++ b/src/ostd/string/String.cpp @@ -460,6 +460,18 @@ namespace ostd return std::stod(m_data); } + bool String::toBool(void) const + { + String str = new_toLower().trim(); + return str == "true"; + } + + bool String::isBool(void) const + { + String str = new_toLower().trim(); + return str == "true" || str == "false"; + } + bool String::isNumeric(bool decimal) const { if (decimal) diff --git a/src/ostd/string/String.hpp b/src/ostd/string/String.hpp index 1f26975..edbfadb 100644 --- a/src/ostd/string/String.hpp +++ b/src/ostd/string/String.hpp @@ -156,6 +156,8 @@ namespace ostd i64 toInt(void) const; f32 toFloat(void) const; f64 toDouble(void) const; + bool toBool(void) const; + bool isBool(void) const; bool isNumeric(bool decimal = false) const; bool isInt(void) const; bool isHex(void) const; diff --git a/src/ostd/utils/Defines.hpp b/src/ostd/utils/Defines.hpp index 5cb93a0..e366522 100755 --- a/src/ostd/utils/Defines.hpp +++ b/src/ostd/utils/Defines.hpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once @@ -57,3 +57,17 @@ #else #define _DEBUG(n) std::cout << (i32)n << "\n"; #endif + +#define OSTD_BOOL_PARAM_GETSET_E(name, member) \ + inline bool is##name##Enabled(void) const { return member; } \ + inline void enable##name(bool enable = true) { member = enable; } \ + inline void disable##name(void) { enable##name(false); } + +#define OSTD_BOOL_PARAM_GETSET_I(name, member) \ + inline bool is##name(void) const { return member; } \ + inline void enable##name(bool enable = true) { member = enable; } \ + inline void disable##name(void) { enable##name(false); } + +#define OSTD_PARAM_GETSET(type, name, member) \ + inline type get##name(void) const { return member; } \ + inline void set##name(const type& value) { member = value; } \ diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp index 15afd54..82c1356 100644 --- a/src/test/GuiTest.cpp +++ b/src/test/GuiTest.cpp @@ -33,7 +33,7 @@ class Window : public ogfx::gui::Window inline void onInitialize(void) override { m_img.loadFromFile("./img.png", m_gfx); - ogfx::Animation::AnimationData ad; + ogfx::AnimationData ad; ad.columns = 9; ad.rows = 4; ad.frameWidth = 256; @@ -45,10 +45,11 @@ class Window : public ogfx::gui::Window m_label1.setText("Show Panel2"); - m_label1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { + m_label1.setCallback(ogfx::gui::Widget::eCallback::MousePressed, [&](const ogfx::gui::Event& event) -> void { m_check1.setChecked(!m_check1.isChecked()); m_label1.addy(10); }); + m_label1.disableTheming(); m_label1.addThemeOverride("@.label.showBackground", true); m_label1.addThemeOverride("@.label.backgroundColor", Colors::Beige); m_label1.addThemeOverride("@.label.showBorder", true); @@ -56,6 +57,8 @@ class Window : public ogfx::gui::Window m_label1.addThemeOverride("@.label.borderColor", Colors::DarkMagenta); m_label1.addThemeOverride("@:pressed.label.backgroundColor", Colors::Crimson); m_label1.addThemeOverride("@:hover.label.backgroundColor", Colors::DarkRed); + m_label1.setBackgroundColor(Colors::Red); + m_label1.enableBackground(); m_label1.reloadTheme(); m_check1.setText("Check this out!"); @@ -65,7 +68,7 @@ class Window : public ogfx::gui::Window }); m_btn1.setText("BUTTON"); - m_btn1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { + m_btn1.setCallback(ogfx::gui::Widget::eCallback::MousePressed, [&](const ogfx::gui::Event& event) -> void { }); @@ -75,13 +78,13 @@ class Window : public ogfx::gui::Window m_label5.setText("Label5"); m_panel1.setSize(700, 300); - m_panel1.allowVScroll(false); - m_panel1.allowHScroll(false); + m_panel1.disableVScroll(); + m_panel1.disableHScroll(); m_panel1.setTitle("Panel 1"); m_panel3.setSize(150, 150); - m_panel3.allowVScroll(false); - m_panel3.allowHScroll(false); + m_panel3.disableVScroll(); + m_panel3.disableHScroll(); m_panel3.setTitle("Panel 3"); m_panel2.setSize(600, 400); @@ -148,8 +151,10 @@ i32 main(i32 argc, char** argv) { ostd::initialize(); Window window; - window.initialize(800, 600, "OmniaFramework - Test Window"); + window.initialize(1200, 800, "OmniaFramework - Test Window"); window.setClearColor({ 0, 0, 0 }); + window.setPosition({ 50, 50 }); + window.setWindowState(ogfx::WindowCore::eWindowState::Maximized); window.mainLoop(); return 0; }