diff --git a/CMakeLists.txt b/CMakeLists.txt
index 129e27f..4f80d52 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,6 +92,7 @@ list(APPEND OGFX_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/RootWidget.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/CheckBox.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Scrollbar.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Button.cpp
# render
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp
diff --git a/other/TODO.txt b/other/TODO.txt
index c4e692e..5319a81 100644
--- a/other/TODO.txt
+++ b/other/TODO.txt
@@ -19,8 +19,8 @@
***Implement Panel title
***Implement show/hide functionality for widgets
***Create reliable default stylesheet
+***Implement global scale (probably query desktop scale and adjust accordingly)
Add theme caching
-Implement global scale (probably query desktop scale and adjust accordingly)
Implement cursors in Stylesheet
diff --git a/src/ogfx/gui/WidgetManager.cpp b/src/ogfx/gui/WidgetManager.cpp
index 7599b63..bba2d96 100644
--- a/src/ogfx/gui/WidgetManager.cpp
+++ b/src/ogfx/gui/WidgetManager.cpp
@@ -22,6 +22,7 @@
#include "widgets/Widget.hpp"
#include "../render/BasicRenderer.hpp"
#include "../utils/Keycodes.hpp"
+#include "../../ostd/io/Memory.hpp"
namespace ogfx
{
@@ -68,12 +69,20 @@ namespace ogfx
if (hasWidget(widget)) return false;
widget.m_parent = &m_owner;
m_widgetList.push_back(&widget);
+ if (widget.m_topMost)
+ return true;
std::ranges::sort(m_widgetList, {}, [](Widget* w) {
return w->m_zIndex;
});
return true;
}
+ bool WidgetManager::removeWidget(Widget& widget)
+ {
+ STDVEC_REMOVE(m_widgetList, &widget);
+ return true;
+ }
+
Widget* WidgetManager::focusNext(void)
{
if (m_widgetList.empty())
@@ -107,6 +116,7 @@ namespace ogfx
if (w == nullptr) continue;
if (w->isInvalid()) continue;
if (!w->isVisible()) continue;
+ if (w->isManualDrawEnabled()) continue;
gfx.pushClippingRect({ w->getGlobalPosition(), w->getSize() }, true);
w->__draw(gfx);
gfx.popClippingRect();
diff --git a/src/ogfx/gui/WidgetManager.hpp b/src/ogfx/gui/WidgetManager.hpp
index 81429a9..465ba40 100644
--- a/src/ogfx/gui/WidgetManager.hpp
+++ b/src/ogfx/gui/WidgetManager.hpp
@@ -41,6 +41,7 @@ namespace ogfx
bool hasWidget(Widget& widget);
bool requestFocus(Widget& widget);
bool addWidget(Widget& widget);
+ bool removeWidget(Widget& widget);
Widget* focusNext(void);
void draw(ogfx::BasicRenderer2D& gfx);
diff --git a/src/ogfx/gui/widgets/Button.cpp b/src/ogfx/gui/widgets/Button.cpp
new file mode 100644
index 0000000..fea4188
--- /dev/null
+++ b/src/ogfx/gui/widgets/Button.cpp
@@ -0,0 +1,32 @@
+/*
+ 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 .
+*/
+
+#include "Button.hpp"
+#include "../../render/BasicRenderer.hpp"
+
+namespace ogfx
+{
+ namespace gui
+ {
+ namespace widgets
+ {
+ }
+ }
+}
diff --git a/src/ogfx/gui/widgets/Button.hpp b/src/ogfx/gui/widgets/Button.hpp
new file mode 100644
index 0000000..a29db42
--- /dev/null
+++ b/src/ogfx/gui/widgets/Button.hpp
@@ -0,0 +1,33 @@
+/*
+ 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
+
+namespace ogfx
+{
+ namespace gui
+ {
+ namespace widgets
+ {
+ }
+ }
+}
diff --git a/src/ogfx/gui/widgets/Containers.cpp b/src/ogfx/gui/widgets/Containers.cpp
index 69551a4..9f39d40 100644
--- a/src/ogfx/gui/widgets/Containers.cpp
+++ b/src/ogfx/gui/widgets/Containers.cpp
@@ -36,6 +36,9 @@ namespace ogfx
disableFocus();
enableStopEvents();
allowScroll(true);
+ m_scrollbar.setMargin({ 0, getTitlebarHeight(), 0, 0 });
+ m_scrollbar.enableManualDraw(true);
+ addWidget(m_scrollbar);
validate();
return *this;
}
@@ -71,6 +74,7 @@ namespace ogfx
void Panel::afterDraw(ogfx::BasicRenderer2D& gfx)
{
draw_titlebar(gfx);
+ m_scrollbar.__draw(gfx);
}
void Panel::onMouseScrolled(const Event& event)
@@ -143,7 +147,13 @@ namespace ogfx
bool Panel::needsScroll(void) const
{
- return getContentExtents().h > getContentBounds().h;
+ return isScrollAllowed() && getContentExtents().h > getContentBounds().h;
+ }
+
+ void Panel::onWidgetAdded(Widget& child)
+ {
+ removeWidget(m_scrollbar);
+ addWidget(m_scrollbar, { 0, 0 }, true);
}
void Panel::draw_titlebar(BasicRenderer2D& gfx)
diff --git a/src/ogfx/gui/widgets/Containers.hpp b/src/ogfx/gui/widgets/Containers.hpp
index 1cdf96a..3d5e6f5 100644
--- a/src/ogfx/gui/widgets/Containers.hpp
+++ b/src/ogfx/gui/widgets/Containers.hpp
@@ -21,6 +21,7 @@
#pragma once
#include
+#include
namespace ogfx
{
@@ -52,6 +53,7 @@ namespace ogfx
void setScrollOffset(const Vec2& offset) override;
void addScrollOffset(const Vec2& offset) override;
bool needsScroll(void) const override;
+ void onWidgetAdded(Widget& child) override;
inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; }
inline Color getBackgroundColor(void) { return m_backgroundColor; }
inline String getTitle(void) const { return m_title; }
@@ -65,6 +67,7 @@ namespace ogfx
private:
String m_title { "Panel" };
Vec2 m_scrollOffset { 0, 0 };
+ VerticalScrollBar m_scrollbar { getWindow() };
Color m_titleColor { Colors::Black };
i32 m_titlebarType = TitleBarTypes::NoneValue;
diff --git a/src/ogfx/gui/widgets/Label.hpp b/src/ogfx/gui/widgets/Label.hpp
index e51e71a..171d489 100644
--- a/src/ogfx/gui/widgets/Label.hpp
+++ b/src/ogfx/gui/widgets/Label.hpp
@@ -28,7 +28,6 @@ namespace ogfx
{
namespace widgets
{
-
class Label : public Widget
{
public:
diff --git a/src/ogfx/gui/widgets/Scrollbar.cpp b/src/ogfx/gui/widgets/Scrollbar.cpp
index b8c4eb5..7d22e53 100644
--- a/src/ogfx/gui/widgets/Scrollbar.cpp
+++ b/src/ogfx/gui/widgets/Scrollbar.cpp
@@ -36,6 +36,7 @@ namespace ogfx
disableChildren();
enableBackground(true);
enableBorder(false);
+ enableTopMost(true);
allowIgnoreScroll(true);
validate();
return *this;
diff --git a/src/ogfx/gui/widgets/Widget.cpp b/src/ogfx/gui/widgets/Widget.cpp
index 7ba7d9f..d460c71 100644
--- a/src/ogfx/gui/widgets/Widget.cpp
+++ b/src/ogfx/gui/widgets/Widget.cpp
@@ -36,14 +36,23 @@ namespace ogfx
m_window = &window;
}
- bool Widget::addWidget(Widget& child, const Vec2& position)
+ bool Widget::addWidget(Widget& child, const Vec2& position, bool __skip_callback)
{
if (!m_allowChildren)
return false;
if (position.x != 0 || position.y != 0)
child.setPosition(position);
child.reloadTheme();
- return m_widgets.addWidget(child);
+ bool result = m_widgets.addWidget(child);
+ if (!result) return false;
+ if (!__skip_callback)
+ onWidgetAdded(child);
+ return result;
+ }
+
+ bool Widget::removeWidget(Widget& child)
+ {
+ return m_widgets.removeWidget(child);
}
Vec2 Widget::getGlobalPosition(void) const
diff --git a/src/ogfx/gui/widgets/Widget.hpp b/src/ogfx/gui/widgets/Widget.hpp
index 82d855c..008ff3a 100644
--- a/src/ogfx/gui/widgets/Widget.hpp
+++ b/src/ogfx/gui/widgets/Widget.hpp
@@ -41,7 +41,8 @@ namespace ogfx
public: using EventCallback = std::function;
public:
Widget(const Rectangle& bounds, WindowCore& window);
- bool addWidget(Widget& child, const Vec2& position = { 0, 0 });
+ 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;
@@ -68,6 +69,7 @@ namespace ogfx
inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { }
inline virtual void afterDraw(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) { }
@@ -155,6 +157,10 @@ namespace ogfx
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; }
@@ -227,6 +233,8 @@ namespace ogfx
bool m_visible { true };
bool m_allowScroll { false };
bool m_ignoreScroll { false};
+ bool m_manualDraw { false };
+ bool m_topMost { false };
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
stdvec m_themeIDList;
diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp
index c3f5172..f476e18 100644
--- a/src/test/GuiTest.cpp
+++ b/src/test/GuiTest.cpp
@@ -75,14 +75,11 @@ class Window : public ogfx::gui::Window
m_panel2.setSize(600, 400);
- m_scroll.setMargin({ 0, m_panel2.getTitlebarHeight(), 0, 0 });
-
m_panel1.addWidget(m_label2);
m_panel2.addWidget(m_label3);
- m_panel2.addWidget(m_panel1, { 0, 50 });
+ m_panel2.addWidget(m_panel1, { 400, 50 });
m_panel2.addWidget(m_label1, { 0, 500 });
- m_panel2.addWidget(m_scroll);
addWidget(m_check1, { 30, 30 });
addWidget(m_panel2, { 30, 100 });
@@ -118,7 +115,6 @@ class Window : public ogfx::gui::Window
ogfx::gui::widgets::Panel m_panel1 { *this };
ogfx::gui::widgets::Panel m_panel2 { *this };
ogfx::gui::widgets::CheckBox m_check1 { *this };
- ogfx::gui::widgets::VerticalScrollBar m_scroll { *this };
ostd::Stylesheet m_theme;
ogfx::Animation m_anim;