Added scrollbar widget

This commit is contained in:
OmniaX-Dev 2026-04-16 21:01:15 +02:00
parent 777124579f
commit fde961c78e
13 changed files with 315 additions and 36 deletions

View file

@ -91,6 +91,7 @@ list(APPEND OGFX_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Label.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Label.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/RootWidget.cpp ${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/CheckBox.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Scrollbar.cpp
# render # render
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp

View file

@ -40,22 +40,29 @@ window.backgroundColor = rgba(160, 160, 160, 255)
% ====== Scrollbar ====== % ====== Scrollbar ======
(scrollbar) { (scrollbar) {
width = 20 (thumb) {
(handle) { color = rgb(140, 140, 140)
color = #333333FF borderRadius = 16
borderColor = rgb(150, 150, 150)
showBorder = true
} }
(track) { (track) {
color = #555555FF color = rgb(90, 90, 90)
borderRadii = Rect(0, 0, 10, 0)
}
width = 18.0
}
(scrollbar:hover) {
(thumb) {
color = #999999FF
} }
} }
(scrollbar:handle_hover) { (scrollbar:pressed) {
(handle) { (thumb) {
color = $accentColorDark color = #999999FF
} }
} (track) {
(scrollbar:handle_pressed) { color = rgb(70, 70, 70)
(handle) {
color = $accentColorDark
} }
} }
% ======================= % =======================

View file

@ -18,9 +18,9 @@
***Add triangle drawing functions to BasicRenderer2D ***Add triangle drawing functions to BasicRenderer2D
***Implement Panel title ***Implement Panel title
***Implement show/hide functionality for widgets ***Implement show/hide functionality for widgets
***Create reliable default stylesheet
Add theme caching Add theme caching
Implement global scale (probably query desktop scale and adjust accordingly) Implement global scale (probably query desktop scale and adjust accordingly)
Create reliable default stylesheet
Implement cursors in Stylesheet Implement cursors in Stylesheet
@ -30,6 +30,7 @@ Implement following widgets:
***Checkbox ***Checkbox
***Panel / Container ***Panel / Container
***Title Label ***Title Label
***ScrollView
Button Button
Image/Icon Image/Icon
Radio Button Radio Button
@ -38,7 +39,6 @@ Implement following widgets:
Horizontal Slider Horizontal Slider
Vertical Slider Vertical Slider
Image / Icon Image / Icon
ScrollView
ListBox ListBox
ComboBox ComboBox
TreeView TreeView

View file

@ -144,6 +144,7 @@ namespace ogfx
if (!w->isVisible()) continue; if (!w->isVisible()) continue;
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true)) if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
continue; continue;
event.mouse->mousePressedOnWidget = w;
w->__onMousePressed(event); w->__onMousePressed(event);
m_mousePressedOnWidget = w; m_mousePressedOnWidget = w;
if (event.isHandled() || w->m_stopEvents) if (event.isHandled() || w->m_stopEvents)
@ -178,6 +179,12 @@ namespace ogfx
void WidgetManager::onMouseMoved(const Event& event) void WidgetManager::onMouseMoved(const Event& event)
{ {
if (m_mousePressedOnWidget != nullptr &&
m_mousePressedOnWidget->m_pressedButton != MouseEventData::eButton::None &&
!m_mousePressedOnWidget->contains(event.mouse->position_x, event.mouse->position_y, true))
{
m_mousePressedOnWidget->__onMouseDragged(event);
}
for (i32 i = m_widgetList.size() - 1; i >= 0; i--) for (i32 i = m_widgetList.size() - 1; i >= 0; i--)
{ {
Widget* w = m_widgetList[i]; Widget* w = m_widgetList[i];
@ -200,7 +207,7 @@ namespace ogfx
} }
else else
{ {
if (w->m_pressedButton != ogfx::MouseEventData::eButton::None) if (w->m_pressedButton != MouseEventData::eButton::None)
w->__onMouseDragged(event); w->__onMouseDragged(event);
else else
w->__onMouseMoved(event); w->__onMouseMoved(event);
@ -246,8 +253,8 @@ namespace ogfx
if (w == nullptr) continue; if (w == nullptr) continue;
if (w->isInvalid()) continue; if (w->isInvalid()) continue;
if (!w->isVisible()) continue; if (!w->isVisible()) continue;
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true)) // if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
continue; // continue;
w->__onMouseDragged(event); w->__onMouseDragged(event);
if (event.isHandled()) if (event.isHandled())
break; break;

View file

@ -23,3 +23,4 @@
#include <ogfx/gui/widgets/Containers.hpp> #include <ogfx/gui/widgets/Containers.hpp>
#include <ogfx/gui/widgets/Label.hpp> #include <ogfx/gui/widgets/Label.hpp>
#include <ogfx/gui/widgets/CheckBox.hpp> #include <ogfx/gui/widgets/CheckBox.hpp>
#include <ogfx/gui/widgets/Scrollbar.hpp>

View file

@ -64,8 +64,8 @@ namespace ogfx
void Panel::onDraw(ogfx::BasicRenderer2D& gfx) void Panel::onDraw(ogfx::BasicRenderer2D& gfx)
{ {
if (isScrollAllowed()) // if (isScrollAllowed())
gfx.fillRect(getContentExtents() + Rectangle { getGlobalPosition(), 0, 0 }, { 80, 0, 0, 30 }); // gfx.fillRect(getContentExtents() + Rectangle { getGlobalPosition(), 0, 0 }, { 80, 0, 0, 30 });
} }
void Panel::afterDraw(ogfx::BasicRenderer2D& gfx) void Panel::afterDraw(ogfx::BasicRenderer2D& gfx)
@ -77,21 +77,12 @@ namespace ogfx
{ {
if (!isScrollAllowed()) if (!isScrollAllowed())
return; return;
auto ext = getContentExtents(); f32 offset_y = 0;
auto cont = getContentBounds(); if (event.mouse->scroll == MouseEventData::eScrollDirection::Down)
f32 maxScroll = -(ext.h - cont.h); offset_y = -(m_scrollSpeed.y * 15.0f);
if (event.mouse->scroll == MouseEventData::eScrollDirection::Down && m_scrollOffset.y > maxScroll) else if (event.mouse->scroll == MouseEventData::eScrollDirection::Up)
{ offset_y = (m_scrollSpeed.y * 15.0f);
m_scrollOffset.y -= (m_scrollSpeed.y * 15.0f); addScrollOffset({ 0, offset_y });
if (m_scrollOffset.y < maxScroll)
m_scrollOffset.y = maxScroll;
}
else if (event.mouse->scroll == MouseEventData::eScrollDirection::Up && m_scrollOffset.y < 0)
{
m_scrollOffset.y += (m_scrollSpeed.y * 15.0f);
if (m_scrollOffset.y > 0)
m_scrollOffset.y = 0;
}
event.handle(); event.handle();
} }
@ -126,6 +117,35 @@ namespace ogfx
} }
} }
void Panel::setScrollOffset(const Vec2& offset)
{
auto ext = getContentExtents();
auto cont = getContentBounds();
f32 maxScroll = -(ext.h - cont.h);
m_scrollOffset = offset;
if (m_scrollOffset.y < maxScroll)
m_scrollOffset.y = maxScroll;
if (m_scrollOffset.y > 0)
m_scrollOffset.y = 0;
}
void Panel::addScrollOffset(const Vec2& offset)
{
auto ext = getContentExtents();
auto cont = getContentBounds();
f32 maxScroll = -(ext.h - cont.h);
m_scrollOffset += offset;
if (m_scrollOffset.y < maxScroll)
m_scrollOffset.y = maxScroll;
if (m_scrollOffset.y > 0)
m_scrollOffset.y = 0;
}
bool Panel::needsScroll(void) const
{
return getContentExtents().h > getContentBounds().h;
}
void Panel::draw_titlebar(BasicRenderer2D& gfx) void Panel::draw_titlebar(BasicRenderer2D& gfx)
{ {
f32 br = cast<f32>(getBorderWidth()); f32 br = cast<f32>(getBorderWidth());

View file

@ -49,11 +49,15 @@ namespace ogfx
void onMouseScrolled(const Event& event) override; void onMouseScrolled(const Event& event) override;
void setTitlebarType(const String& type); void setTitlebarType(const String& type);
String getTitlebarType(void) const; String getTitlebarType(void) const;
void setScrollOffset(const Vec2& offset) override;
void addScrollOffset(const Vec2& offset) override;
bool needsScroll(void) const override;
inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; } inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; }
inline Color getBackgroundColor(void) { return m_backgroundColor; } inline Color getBackgroundColor(void) { return m_backgroundColor; }
inline String getTitle(void) const { return m_title; } inline String getTitle(void) const { return m_title; }
inline void setTitle(const String& title) { m_title = title; } inline void setTitle(const String& title) { m_title = title; }
inline Vec2 getScrollOffset(void) const override { return m_scrollOffset; } inline Vec2 getScrollOffset(void) const override { return m_scrollOffset; }
inline f32 getTitlebarHeight(void) const { return m_titlebarHeight; }
private: private:
void draw_titlebar(BasicRenderer2D& gfx); void draw_titlebar(BasicRenderer2D& gfx);

View file

@ -0,0 +1,147 @@
/*
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/>.
*/
#include "Scrollbar.hpp"
#include "../../render/BasicRenderer.hpp"
namespace ogfx
{
namespace gui
{
namespace widgets
{
VerticalScrollBar& VerticalScrollBar::create(const String& text)
{
setPadding({ 0, 0, 0, 0 });
setMargin({ 0, 0, 0, 0 });
setTypeName("ogfx::gui::widgets::Label");
disableDrawBox();
disableChildren();
enableBackground(true);
enableBorder(false);
allowIgnoreScroll(true);
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 });
m_trackBorderRadii = getThemeValue<Rectangle>(theme, "scrollbar.track.borderRadii", { 0, 0, 10, 0 });
}
void VerticalScrollBar::afterDraw(ogfx::BasicRenderer2D& gfx)
{
if (!getParent()->needsScroll())
return;
gfx.fillRoundRect(getGlobalBounds() - m_correctionOffset, m_trackColor, m_trackBorderRadii);
gfx.outlinedRoundRect(m_thumbGlobalBounds, m_thumbColor, m_thumbBorderColor, m_thumbBorderRadius, 1);
}
void VerticalScrollBar::onMouseDragged(const Event& event)
{
if (!m_mousePressed)
return;
if (is_mouse_in_thumb({ event.mouse->position_x, event.mouse->position_y }))
m_mouseDragged = true;
if (m_mouseDragged)
{
auto bounds = getGlobalBounds() - m_correctionOffset;
f32 newThumbY = (event.mouse->position_y - bounds.y) - m_dragGrabOffset;
set_thumb_y(newThumbY);
}
}
void VerticalScrollBar::onMousePressed(const Event& event)
{
m_mousePressed = true;
m_dragGrabOffset = event.mouse->position_y - m_thumbGlobalBounds.y;
}
void VerticalScrollBar::onMouseReleased(const Event& event)
{
m_mousePressed = false;
if (event.mouse->mousePressedOnWidget != this)
return;
if (!m_mouseDragged)
{
auto bounds = getGlobalBounds() - m_correctionOffset;
f32 newThumbY = (event.mouse->position_y - bounds.y);
newThumbY -= m_thumbHeight / 2.0f;
set_thumb_y(newThumbY);
}
m_mouseDragged = false;
}
void VerticalScrollBar::onUpdate(void)
{
update_thumb();
}
void VerticalScrollBar::update_thumb(void)
{
x = getParent()->getSize().x - w;
y = 0;
h = getParent()->getGlobalContentBounds().h;
auto ext = getParent()->getContentExtents();
auto cont = getParent()->getContentBounds();
auto scrollOfset = getParent()->getScrollOffset();
// Thumb size is proportional to visible/total ratio
f32 visibleRatio = cont.h / ext.h; // e.g. 0.4 means 40% visible
m_thumbHeight = std::max(20.0f, geth() * visibleRatio); // min 20px for usability
// Thumb position is proportional to scroll progress
f32 scrollProgress = -scrollOfset.y / (ext.h - cont.h); // 0 to 1
m_thumbY = gety() + ((geth() - m_thumbHeight) * scrollProgress);
auto bounds = getGlobalBounds() - m_correctionOffset;
m_thumbGlobalBounds = { bounds.x + 2, bounds.y + gety() + m_thumbY, getw() - 4, m_thumbHeight };
}
void VerticalScrollBar::set_thumb_y(f32 thumby)
{
auto bounds = getGlobalBounds() - m_correctionOffset;
auto ext = getParent()->getContentExtents();
auto cont = getParent()->getContentBounds();
thumby = std::clamp(thumby, 0.0f, h - m_thumbHeight);
m_thumbY = thumby;
f32 scrollProgress = (bounds.y + gety() + m_thumbY - bounds.y) / (bounds.h - m_thumbHeight);
f32 maxScroll = -(ext.h - cont.h);
auto parentScrollOffset = getParent()->getScrollOffset();
parentScrollOffset.y = maxScroll * scrollProgress;
getParent()->setScrollOffset(parentScrollOffset);
}
bool VerticalScrollBar::is_mouse_in_thumb(const Vec2& mouse_pos)
{
return m_thumbGlobalBounds.contains(mouse_pos, true);
}
}
}
}

View file

@ -0,0 +1,72 @@
/*
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 <ogfx/gui/widgets/Widget.hpp>
namespace ogfx
{
namespace gui
{
namespace widgets
{
class VerticalScrollBar : public Widget
{
public:
inline VerticalScrollBar(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline VerticalScrollBar(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
VerticalScrollBar& create(const String& text);
void applyTheme(const ostd::Stylesheet& theme) override;
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
void onMouseDragged(const Event& event) override;
void onMousePressed(const Event& event) override;
void onMouseReleased(const Event& event) override;
void onUpdate(void) override;
inline void setx(f32 xx) override { }
inline void sety(f32 yy) override { }
inline void setw(f32 ww) override { }
inline void seth(f32 hh) override { }
private:
void update_thumb(void);
void set_thumb_y(f32 thumby);
bool is_mouse_in_thumb(const Vec2& mouse_pos);
private:
f32 m_thumbHeight { 0 };
f32 m_thumbY { 0 };
Rectangle m_thumbGlobalBounds { 0, 0, 0, 0 };
bool m_mousePressed { false };
bool m_mouseDragged { false };
f32 m_dragGrabOffset { 0 };
Rectangle m_correctionOffset { 1, 1, 0, 0 };
Rectangle m_trackBorderRadii { 0, 0, 10, 0 };
f32 m_thumbBorderRadius { 16 };
Color m_trackColor { 70, 70, 70 };
Color m_thumbColor { 120, 120, 120 };
Color m_thumbBorderColor { 150, 150, 150 };
bool m_thumbShowBorder { true };
};
}
}
}

View file

@ -50,7 +50,14 @@ namespace ogfx
{ {
Vec2 glob = getPosition(); Vec2 glob = getPosition();
if (!m_rootChild && m_parent != nullptr) if (!m_rootChild && m_parent != nullptr)
glob += m_parent->getGlobalPosition() + m_parent->getPadding().getPosition() + m_parent->getScrollOffset(); {
glob += m_parent->getGlobalPosition();
if (!isIgnoreScrollAllowed())
{
glob += m_parent->getPadding().getPosition();
glob += m_parent->getScrollOffset();
}
}
glob += m_margin.getPosition(); glob += m_margin.getPosition();
return glob; return glob;
} }
@ -83,6 +90,7 @@ namespace ogfx
for (auto* child : m_widgets.getWidgets()) for (auto* child : m_widgets.getWidgets())
{ {
if (!child || child->isInvalid()) continue; if (!child || child->isInvalid()) continue;
if (child->isIgnoreScrollAllowed()) continue;
Vec2 localPos = getPadding().getPosition() + child->getPosition() + child->getMargin().getPosition() + child->getContentBounds().getPosition(); Vec2 localPos = getPadding().getPosition() + child->getPosition() + child->getMargin().getPosition() + child->getContentBounds().getPosition();
maxX = std::max(maxX, localPos.x + child->getw() + child->getMargin().w); maxX = std::max(maxX, localPos.x + child->getw() + child->getMargin().w);
maxY = std::max(maxY, localPos.y + child->geth() + child->getMargin().h); maxY = std::max(maxY, localPos.y + child->geth() + child->getMargin().h);

View file

@ -53,6 +53,9 @@ namespace ogfx
void enable(bool enable = true); void enable(bool enable = true);
virtual void applyTheme(const ostd::Stylesheet& theme) = 0; virtual void applyTheme(const ostd::Stylesheet& theme) = 0;
inline virtual Vec2 getScrollOffset(void) const { return { 0, 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 needsScroll(void) const { return false; }
void addThemeOverride(const String& fullKey, ostd::Stylesheet::TypeVariant value); void addThemeOverride(const String& fullKey, ostd::Stylesheet::TypeVariant value);
void reloadTheme(bool propagate = false); void reloadTheme(bool propagate = false);
void setThemeQualifier(const String& qualifier, bool value = true); void setThemeQualifier(const String& qualifier, bool value = true);
@ -161,6 +164,8 @@ namespace ogfx
inline void hide(void) { setVisible(false); } inline void hide(void) { setVisible(false); }
inline void allowScroll(bool allow = true) { m_allowScroll = allow; } inline void allowScroll(bool allow = true) { m_allowScroll = allow; }
inline bool isScrollAllowed(void) const { return m_allowScroll; } inline bool isScrollAllowed(void) const { return m_allowScroll; }
inline void allowIgnoreScroll(bool allow = true) { m_ignoreScroll = allow; }
inline bool isIgnoreScrollAllowed(void) const { return m_ignoreScroll; }
template<typename T> template<typename T>
inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback) inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback)
@ -221,6 +226,7 @@ namespace ogfx
bool m_acceptDragAndDrop { false }; bool m_acceptDragAndDrop { false };
bool m_visible { true }; bool m_visible { true };
bool m_allowScroll { false }; bool m_allowScroll { false };
bool m_ignoreScroll { false};
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
stdvec<String> m_themeIDList; stdvec<String> m_themeIDList;

View file

@ -323,7 +323,7 @@ namespace ostd
inline virtual Vec2 getSize(void) const { return Vec2(getw(), geth()); } inline virtual Vec2 getSize(void) const { return Vec2(getw(), geth()); }
inline virtual Vec2 getCenter(void) const { return Vec2(getx() + getw() / 2, gety() + geth() / 2); } inline virtual Vec2 getCenter(void) const { return Vec2(getx() + getw() / 2, gety() + geth() / 2); }
inline virtual void setPosition(Vec2 pos) { setx(pos.x); sety(pos.y); } inline virtual void setPosition(const Vec2& pos) { setx(pos.x); sety(pos.y); }
inline virtual void setPosition(f32 xx, f32 yy) { setx(xx); sety(yy); } inline virtual void setPosition(f32 xx, f32 yy) { setx(xx); sety(yy); }
inline virtual void setSize(Vec2 size) { setw(size.x); seth(size.y); } inline virtual void setSize(Vec2 size) { setw(size.x); seth(size.y); }
inline virtual void setSize(f32 ww, f32 hh) { setw(ww); seth(hh); } inline virtual void setSize(f32 ww, f32 hh) { setw(ww); seth(hh); }

View file

@ -50,6 +50,7 @@ class Window : public ogfx::gui::Window
m_label1.setText("Show Panel2"); m_label1.setText("Show Panel2");
m_label1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { m_label1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void {
m_check1.setChecked(!m_check1.isChecked()); m_check1.setChecked(!m_check1.isChecked());
m_label1.addy(10);
}); });
m_label1.addThemeOverride("@.label.showBackground", true); m_label1.addThemeOverride("@.label.showBackground", true);
m_label1.addThemeOverride("@.label.backgroundColor", Colors::Beige); m_label1.addThemeOverride("@.label.backgroundColor", Colors::Beige);
@ -75,11 +76,14 @@ class Window : public ogfx::gui::Window
m_panel2.setSize(600, 400); m_panel2.setSize(600, 400);
m_scroll.setMargin({ 0, m_panel2.getTitlebarHeight(), 0, 0 });
m_panel1.addWidget(m_label2); m_panel1.addWidget(m_label2);
m_panel2.addWidget(m_label3); m_panel2.addWidget(m_label3);
m_panel2.addWidget(m_panel1, { 0, 50 }); m_panel2.addWidget(m_panel1, { 0, 50 });
m_panel2.addWidget(m_label1, { 0, 340 }); m_panel2.addWidget(m_label1, { 0, 500 });
m_panel2.addWidget(m_scroll);
addWidget(m_check1, { 30, 30 }); addWidget(m_check1, { 30, 30 });
addWidget(m_panel2, { 30, 100 }); addWidget(m_panel2, { 30, 100 });
@ -115,6 +119,8 @@ class Window : public ogfx::gui::Window
ogfx::gui::widgets::Panel m_panel1 { *this }; ogfx::gui::widgets::Panel m_panel1 { *this };
ogfx::gui::widgets::Panel m_panel2 { *this }; ogfx::gui::widgets::Panel m_panel2 { *this };
ogfx::gui::widgets::CheckBox m_check1 { *this }; ogfx::gui::widgets::CheckBox m_check1 { *this };
ogfx::gui::widgets::VerticalScrollBar m_scroll { *this };
ostd::Stylesheet m_theme; ostd::Stylesheet m_theme;
ogfx::Animation m_anim; ogfx::Animation m_anim;
ogfx::Image m_img; ogfx::Image m_img;