Added anim() to stylesheet + refactored Widget.hpp

This commit is contained in:
OmniaX-Dev 2026-04-20 06:49:00 +02:00
parent 0cf7478c24
commit 67a2b5f10e
24 changed files with 625 additions and 366 deletions

View file

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

View file

@ -139,6 +139,7 @@ namespace ogfx
{
if (w == nullptr) continue;
if (w->isInvalid()) continue;
if (!w->isThemingEnabled()) continue;
w->__applyTheme(theme, true);
w->reloadTheme();
}

View file

@ -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 <https://www.gnu.org/licenses/>.
along with OmniaFramewo6 If not, see <https://www.gnu.org/licenses/>.
*/
#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);

View file

@ -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<String, std::pair<String, bool>> m_defaultStylesheetVariables;

View file

@ -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<Color>(theme, "button.textColor", Colors::White));
setBackGroundColor(getThemeValue<Color>(theme, "button.backgroundColor", Colors::Transparent));
setFontSize(getThemeValue<i32>(theme, "button.fontSize", 20));
setBorderRadius(getThemeValue<i32>(theme, "button.borderRadius", 10));
setBorderWidth(getThemeValue<i32>(theme, "button.borderWidth", 2));
enableBorder(getThemeValue<bool>(theme, "button.showBorder", false));
setBorderColor(getThemeValue<Color>(theme, "button.borderColor", Colors::White));
enableBackground(getThemeValue<bool>(theme, "button.showBackground", false));
setPadding(getThemeValue<Rectangle>(theme, "button.padding", { 5, 5, 5, 5 }));
setMargin(getThemeValue<Rectangle>(theme, "button.margin", { 0, 0, 0, 0 }));
m_useBackgroundGradient = getThemeValue<bool>(theme, "button.useBackgroundGradient", false);
m_backgroundGradient = getThemeValue<ColorGradient>(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());
}

View file

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

View file

@ -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<Color>(theme, "checkbox.checkBorderColor", Colors::White));
setCheckBoxColor(getThemeValue<Color>(theme, "checkbox.checkBoxColor", Colors::White));
setTextColor(getThemeValue<Color>(theme, "checkbox.textColor", Colors::Black));
setBackGroundColor(getThemeValue<Color>(theme, "checkbox.backgroundColor", Colors::Transparent));
setFontSize(getThemeValue<i32>(theme, "checkbox.fontSize", 28));
setBorderRadius(getThemeValue<i32>(theme, "checkbox.borderRadius", 10));
setBorderWidth(getThemeValue<i32>(theme, "checkbox.borderWidth", 2));
enableBorder(getThemeValue<bool>(theme, "checkbox.showBorder", false));
setBorderColor(getThemeValue<Color>(theme, "checkbox.borderColor", Colors::White));
enableBackground(getThemeValue<bool>(theme, "checkbox.showBackground", false));
setPadding(getThemeValue<Rectangle>(theme, "checkbox.padding", { 5, 5, 5, 5 }));
setMargin(getThemeValue<Rectangle>(theme, "checkbox.margin", { 0, 0, 0, 0 }));
m_checkBorderRadius = getThemeValue<i32>(theme, "checkbox.checkBorderRadius", 5);
m_checkBorderWidth = getThemeValue<i32>(theme, "checkbox.checkBorderWidth", 1);
setCheckBorderColor(getThemeValue<Color>(theme, "checkBorderColor", Colors::White));
setCheckBoxColor(getThemeValue<Color>(theme, "checkBoxColor", Colors::White));
m_checkBorderRadius = getThemeValue<i32>(theme, "checkBorderRadius", 5);
m_checkBorderWidth = getThemeValue<i32>(theme, "checkBorderWidth", 1);
}
void CheckBox::onDraw(ogfx::BasicRenderer2D& gfx)

View file

@ -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<void(CheckBox&, bool)> 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 };

View file

@ -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<Color>(theme, "panel.backgroundColor", Colors::Gray));
setBorderRadius(getThemeValue<i32>(theme, "panel.borderRadius", 8));
setBorderWidth(getThemeValue<i32>(theme, "panel.borderWidth", 2));
enableBorder(getThemeValue<bool>(theme, "panel.showBorder", true));
enableBackground(getThemeValue<bool>(theme, "panel.showBackground", true));
setBorderColor(getThemeValue<Color>(theme, "panel.borderColor", Colors::Black));
setPadding(getThemeValue<Rectangle>(theme, "panel.padding", { 15, 15, 15, 15 }));
setMargin(getThemeValue<Rectangle>(theme, "panel.margin", { 0, 0, 0, 0 }));
setScrollSpeed(getThemeValue<f32>(theme, "panel.scrollSpeed", 0.8f));
setScrollSmoothFactor(getThemeValue<f32>(theme, "panel.scrollSmoothFactor", 0.7f));
m_titleColor = getThemeValue<Color>(theme, "panel.titleColor", Colors::Black);
m_titlebarColor = getThemeValue<Color>(theme, "panel.titlebarColor", Colors::Transparent);
m_titlebarBorderColor = getThemeValue<Color>(theme, "panel.titlebarBorderColor", Colors::Black);
m_titlebarHeight = getThemeValue<f32>(theme, "panel.titlebarHeight", 30);
m_titlebarBorderWidth = getThemeValue<i32>(theme, "panel.titlebarBorderWidth", 1);
m_titlebarFontSize = getThemeValue<i32>(theme, "panel.titlebarFontSize", 26);
m_titleTextAlign = getThemeValue<i32>(theme, "panel.titlebarTextAlign", cast<i32>(WindowCore::eTextAlign::Left));
setTitlebarType(getThemeValue<String>(theme, "panel.titlebarType", TitleBarTypes::None));
setScrollSpeed(getThemeValue<f32>(theme, "scrollSpeed", 0.8f));
setScrollSmoothFactor(getThemeValue<f32>(theme, "scrollSmoothFactor", 0.7f));
m_titleColor = getThemeValue<Color>(theme, "titleColor", Colors::Black);
m_titlebarColor = getThemeValue<Color>(theme, "titlebarColor", Colors::Transparent);
m_titlebarBorderColor = getThemeValue<Color>(theme, "titlebarBorderColor", Colors::Black);
m_titlebarHeight = getThemeValue<f32>(theme, "titlebarHeight", 30);
m_titlebarBorderWidth = getThemeValue<i32>(theme, "titlebarBorderWidth", 1);
m_titlebarFontSize = getThemeValue<i32>(theme, "titlebarFontSize", 26);
m_titleTextAlign = getThemeValue<i32>(theme, "titlebarTextAlign", cast<i32>(WindowCore::eTextAlign::Left));
setTitlebarType(getThemeValue<String>(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;
}

View file

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

View file

@ -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<Color>(theme, "label.textColor", Colors::White));
setBackGroundColor(getThemeValue<Color>(theme, "label.backgroundColor", Colors::Transparent));
setFontSize(getThemeValue<i32>(theme, "label.fontSize", 20));
setBorderRadius(getThemeValue<i32>(theme, "label.borderRadius", 10));
setBorderWidth(getThemeValue<i32>(theme, "label.borderWidth", 2));
enableBorder(getThemeValue<bool>(theme, "label.showBorder", false));
setBorderColor(getThemeValue<Color>(theme, "label.borderColor", Colors::White));
enableBackground(getThemeValue<bool>(theme, "label.showBackground", false));
setPadding(getThemeValue<Rectangle>(theme, "label.padding", { 5, 5, 5, 5 }));
setMargin(getThemeValue<Rectangle>(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)

View file

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

View file

@ -30,9 +30,9 @@ namespace ogfx
{
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
{
disableDrawBox();
m_rootChild = true;
setRootChild();
setSize(cast<f32>(window.getWindowWidth()), cast<f32>(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<Color>(theme, "window.backgroundColor", getWindow().getClearColor());
m_color = getThemeValue<Color>(theme, "backgroundColor", getWindow().getClearColor());
}
void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx)

View file

@ -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<f32>(theme, "scrollbar.width", 15);
m_thumbColor = getThemeValue<Color>(theme, "scrollbar.thumb.color", { 120, 120, 120 });
m_thumbBorderRadius = getThemeValue<f32>(theme, "scrollbar.thumb.borderRadius", 16);
m_thumbBorderColor = getThemeValue<Color>(theme, "scrollbar.thumb.borderColor", { 150, 150, 150 });
m_thumbShowBorder = getThemeValue<bool>(theme, "scrollbar.thumb.showBorder", true);
m_trackColor = getThemeValue<Color>(theme, "scrollbar.track.color", { 70, 70, 70 });
w = getThemeValue<f32>(theme, "width", 15);
m_thumbColor = getThemeValue<Color>(theme, "thumb.color", { 120, 120, 120 });
m_thumbBorderRadius = getThemeValue<f32>(theme, "thumb.borderRadius", 16);
m_thumbBorderColor = getThemeValue<Color>(theme, "thumb.borderColor", { 150, 150, 150 });
m_thumbShowBorder = getThemeValue<bool>(theme, "thumb.showBorder", true);
m_trackColor = getThemeValue<Color>(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<f32>(theme, "scrollbar.width", 15);
m_thumbColor = getThemeValue<Color>(theme, "scrollbar.thumb.color", { 120, 120, 120 });
m_thumbBorderRadius = getThemeValue<f32>(theme, "scrollbar.thumb.borderRadius", 16);
m_thumbBorderColor = getThemeValue<Color>(theme, "scrollbar.thumb.borderColor", { 150, 150, 150 });
m_thumbShowBorder = getThemeValue<bool>(theme, "scrollbar.thumb.showBorder", true);
m_trackColor = getThemeValue<Color>(theme, "scrollbar.track.color", { 70, 70, 70 });
h = getThemeValue<f32>(theme, "width", 15);
m_thumbColor = getThemeValue<Color>(theme, "thumb.color", { 120, 120, 120 });
m_thumbBorderRadius = getThemeValue<f32>(theme, "thumb.borderRadius", 16);
m_thumbBorderColor = getThemeValue<Color>(theme, "thumb.borderColor", { 150, 150, 150 });
m_thumbShowBorder = getThemeValue<bool>(theme, "thumb.showBorder", true);
m_trackColor = getThemeValue<Color>(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;

View file

@ -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<Color>(theme, "textColor", m_textColor));
setBackgroundColor(getThemeValue<Color>(theme, "backgroundColor", m_backgroundColor));
setFontSize(getThemeValue<i32>(theme, "fontSize", m_fontSize));
setBorderRadius(getThemeValue<i32>(theme, "borderRadius", m_borderRadius));
setBorderWidth(getThemeValue<i32>(theme, "borderWidth", m_borderWidth));
enableBorder(getThemeValue<bool>(theme, "showBorder", m_showBorder));
setBorderColor(getThemeValue<Color>(theme, "borderColor", m_borderColor));
enableBackground(getThemeValue<bool>(theme, "showBackground", m_showBackground));
setPadding(getThemeValue<Rectangle>(theme, "padding", m_padding));
setMargin(getThemeValue<Rectangle>(theme, "margin", m_margin));
enableBackgroundGradient(getThemeValue<bool>(theme, "useBackgroundGradient", m_useBackgroundGradient));
setBackgroundGradient(getThemeValue<ColorGradient>(theme, "backgroundGradient", m_backgroundGradient));
if (isBackgroundGradientEnabled() && isBackgroundEnabled())
enableBackground(false);
}
}
}

View file

@ -25,6 +25,7 @@
#include <ostd/data/BaseObject.hpp>
#include <ostd/math/Geometry.hpp>
#include <ostd/io/Stylesheet.hpp>
#include <ostd/utils/Defines.hpp>
#include <functional>
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<void(const Event&)>;
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<typename T>
inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback)
{
return theme.get<T>(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<String>& 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<typename T>
inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback)
{
return theme.get<T>(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<String>& 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<String> m_themeIDList;
ostd::Stylesheet::QualifierList m_qualifierList {
{ "disabled", false },
{ "pressed", false },
{ "hover", false },
{ "focused", false },
{ "active", false }
};
stdvec<ThemeOverride> 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<String> m_themeIDList;
ostd::Stylesheet::QualifierList m_qualifierList {
{ "disabled", false },
{ "pressed", false },
{ "hover", false },
{ "focused", false },
{ "active", false }
};
stdvec<ThemeOverride> 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) { }
};
}
}

View file

@ -20,54 +20,16 @@
#pragma once
#include <ostd/data/Types.hpp>
#include <ostd/data/AnimationData.hpp>
#include <ostd/math/Geometry.hpp>
#include <ostd/utils/Time.hpp>
#include <ogfx/resources/Image.hpp>
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); };

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <ostd/data/Types.hpp>
#include <ostd/string/String.hpp>
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;
}
};
}

View file

@ -63,6 +63,8 @@ namespace ostd
stdvec<String> 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)

View file

@ -23,6 +23,7 @@
#include <ostd/string/TextStyleParser.hpp>
#include <ostd/data/Color.hpp>
#include <ostd/math/Geometry.hpp>
#include <ostd/data/AnimationData.hpp>
#include <variant>
@ -32,7 +33,7 @@ namespace ostd
{
public: using QualifierList = stdvec<std::pair<const String, bool>>;
public: using VariableList = stdumap<String, std::pair<String, bool>>;
public: using TypeVariant = std::variant<i32, f32, bool, String, Color, Rectangle, Vec2, ColorGradient>;
public: using TypeVariant = std::variant<i32, f32, bool, String, Color, Rectangle, Vec2, ColorGradient, AnimationData>;
public:
Stylesheet(void);
Stylesheet& clear(void);
@ -63,6 +64,7 @@ namespace ostd
String parseGroupSelector(const String& rawSelector) const;
stdvec<String> parseGroup(const String& selector, const stdvec<String>& group);
ColorGradient parseColorGradient(const String& _value);
AnimationData parseAnim(const String& _value, bool& outError);
private:
stdumap<String, TypeVariant> m_values;

View file

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

View file

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

View file

@ -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 <https://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
#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; } \

View file

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