Added ScrollableWidget class
This commit is contained in:
parent
510ce50684
commit
63d00adf96
5 changed files with 192 additions and 159 deletions
|
|
@ -43,7 +43,7 @@ window.backgroundColor = rgba(160, 160, 160, 255)
|
|||
(scrollbar) {
|
||||
(thumb) {
|
||||
color = rgb(140, 140, 140)
|
||||
borderRadius = 0.0
|
||||
borderRadius = 16.0
|
||||
borderColor = rgb(150, 150, 150)
|
||||
showBorder = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,28 +35,6 @@ namespace ogfx
|
|||
disableDrawBox();
|
||||
disableFocus();
|
||||
enableStopEvents();
|
||||
allowVScroll(true);
|
||||
allowHScroll(true);
|
||||
m_vScrollbar.setMargin({ 0, getTitlebarHeight(), 0, 0 });
|
||||
m_vScrollbar.enableManualDraw(true);
|
||||
addWidget(m_vScrollbar);
|
||||
m_hScrollbar.setMargin({ 0, 0, 0, 0 });
|
||||
m_hScrollbar.enableManualDraw(true);
|
||||
addWidget(m_hScrollbar);
|
||||
m_smoothScrollTimer.create(60.0f, [&](f64 dt) -> void {
|
||||
f32 stepX = m_scrollVelocity.x * (1.0f - m_scrollSmoothFactor);
|
||||
f32 stepY = m_scrollVelocity.y * (1.0f - m_scrollSmoothFactor);
|
||||
|
||||
addScrollOffset({ stepX, stepY });
|
||||
m_scrollVelocity -= { stepX, stepY };
|
||||
|
||||
if (std::abs(m_scrollVelocity.x) < 0.5f) m_scrollVelocity.x = 0;
|
||||
if (std::abs(m_scrollVelocity.y) < 0.5f) m_scrollVelocity.y = 0;
|
||||
}, true);
|
||||
|
||||
m_smoothScrollTimer.setStopCondition([&](void) -> bool {
|
||||
return m_scrollVelocity.x == 0 && m_scrollVelocity.y == 0;
|
||||
});
|
||||
validate();
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -71,8 +49,8 @@ namespace ogfx
|
|||
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 }));
|
||||
m_scrollSpeed = getThemeValue<f32>(theme, "panel.scrollSpeed", 0.8f);
|
||||
m_scrollSmoothFactor = std::clamp(getThemeValue<f32>(theme, "panel.scrollSmoothFactor", 0.7f), 0.0f, 1.0f);
|
||||
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);
|
||||
|
|
@ -83,54 +61,10 @@ namespace ogfx
|
|||
setTitlebarType(getThemeValue<String>(theme, "panel.titlebarType", TitleBarTypes::None));
|
||||
}
|
||||
|
||||
void Panel::onDraw(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
// if (isScrollAllowed())
|
||||
// gfx.fillRect(getContentExtents() + Rectangle { getGlobalPosition(), 0, 0 }, { 80, 0, 0, 30 });
|
||||
}
|
||||
|
||||
void Panel::onUpdate(void)
|
||||
{
|
||||
m_smoothScrollTimer.update();
|
||||
}
|
||||
|
||||
void Panel::afterDraw(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
draw_titlebar(gfx);
|
||||
m_vScrollbar.__draw(gfx);
|
||||
m_hScrollbar.__draw(gfx);
|
||||
}
|
||||
|
||||
void Panel::onMouseScrolled(const Event& event)
|
||||
{
|
||||
if (isVScrollAllowed())
|
||||
{
|
||||
bool mouseInsideHScrollbar = m_hScrollbar.isMouseInsideThumb({ event.mouse->position_x, event.mouse->position_y });
|
||||
if (std::abs(event.mouse->scrollAmount.y) > 0 && !mouseInsideHScrollbar)
|
||||
{
|
||||
m_scrollVelocity.y += m_scrollSpeed * event.mouse->scrollAmount.y * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
else if (std::abs(event.mouse->scrollAmount.y) > 0)
|
||||
{
|
||||
m_scrollVelocity.x += m_scrollSpeed * event.mouse->scrollAmount.y * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
}
|
||||
if (isHScrollAllowed())
|
||||
{
|
||||
if (std::abs(event.mouse->scrollAmount.x) > 0)
|
||||
{
|
||||
m_scrollVelocity.x += m_scrollSpeed * event.mouse->scrollAmount.x * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
}
|
||||
drawScrollbars(gfx);
|
||||
}
|
||||
|
||||
void Panel::setTitlebarType(const String& type)
|
||||
|
|
@ -139,16 +73,19 @@ namespace ogfx
|
|||
if (t == TitleBarTypes::None)
|
||||
{
|
||||
setContentOffset({ 0, 0 });
|
||||
updateScrollbarsSize();
|
||||
m_titlebarType = TitleBarTypes::NoneValue;
|
||||
}
|
||||
else if (t == TitleBarTypes::Minimal)
|
||||
{
|
||||
setContentOffset({ 0, m_titlebarHeight });
|
||||
updateScrollbarsSize();
|
||||
m_titlebarType = TitleBarTypes::MinimalValue;
|
||||
}
|
||||
else if (t == TitleBarTypes::Full)
|
||||
{
|
||||
setContentOffset({ 0, m_titlebarHeight });
|
||||
updateScrollbarsSize();
|
||||
m_titlebarType = TitleBarTypes::FullValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -164,72 +101,6 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::setScrollOffset(const Vec2& offset)
|
||||
{
|
||||
auto ext = getContentExtents();
|
||||
auto cont = getContentBounds();
|
||||
f32 maxScrollY = -(ext.h - cont.h);
|
||||
f32 maxScrollX = -(ext.w - cont.w);
|
||||
|
||||
m_scrollOffset = offset;
|
||||
|
||||
if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
|
||||
if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
|
||||
if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
|
||||
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
|
||||
}
|
||||
|
||||
void Panel::addScrollOffset(const Vec2& offset)
|
||||
{
|
||||
auto ext = getContentExtents();
|
||||
auto cont = getContentBounds();
|
||||
f32 maxScrollY = -(ext.h - cont.h);
|
||||
f32 maxScrollX = -(ext.w - cont.w);
|
||||
|
||||
m_scrollOffset += offset;
|
||||
|
||||
if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
|
||||
if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
|
||||
if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
|
||||
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
|
||||
}
|
||||
|
||||
bool Panel::needsVScroll(void) const
|
||||
{
|
||||
return isVScrollAllowed() && getContentExtents().h > getContentBounds().h;
|
||||
}
|
||||
|
||||
bool Panel::needsHScroll(void) const
|
||||
{
|
||||
return isHScrollAllowed() && getContentExtents().w > getContentBounds().w;
|
||||
}
|
||||
|
||||
void Panel::onWidgetAdded(Widget& child)
|
||||
{
|
||||
removeWidget(m_vScrollbar);
|
||||
removeWidget(m_hScrollbar);
|
||||
addWidget(m_vScrollbar, { 0, 0 }, true);
|
||||
addWidget(m_hScrollbar, { 0, 0 }, true);
|
||||
}
|
||||
|
||||
f32 Panel::getVScrollbarSize(void) const
|
||||
{
|
||||
if (!isVScrollAllowed())
|
||||
return 0;
|
||||
if (!needsVScroll())
|
||||
return 0;
|
||||
return m_vScrollbar.getw();
|
||||
}
|
||||
|
||||
f32 Panel::getHScrollbarSize(void) const
|
||||
{
|
||||
if (!isHScrollAllowed())
|
||||
return 0;
|
||||
if (!needsHScroll())
|
||||
return 0;
|
||||
return m_hScrollbar.geth();
|
||||
}
|
||||
|
||||
void Panel::draw_titlebar(BasicRenderer2D& gfx)
|
||||
{
|
||||
f32 br = cast<f32>(getBorderWidth());
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ogfx
|
|||
{
|
||||
namespace widgets
|
||||
{
|
||||
class Panel : public Widget
|
||||
class Panel : public ScrollableWidget
|
||||
{
|
||||
public: struct TitleBarTypes
|
||||
{
|
||||
|
|
@ -43,27 +43,16 @@ namespace ogfx
|
|||
inline static constexpr i32 MinimalValue = 2;
|
||||
};
|
||||
public:
|
||||
inline Panel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline Panel(WindowCore& window) : ScrollableWidget(window) { create(); }
|
||||
Panel& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
void onUpdate(void) override;
|
||||
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
void onMouseScrolled(const Event& event) override;
|
||||
void setTitlebarType(const String& type);
|
||||
String getTitlebarType(void) const;
|
||||
void setScrollOffset(const Vec2& offset) override;
|
||||
void addScrollOffset(const Vec2& offset) override;
|
||||
bool needsVScroll(void) const override;
|
||||
bool needsHScroll(void) const override;
|
||||
void onWidgetAdded(Widget& child) override;
|
||||
f32 getVScrollbarSize(void) const override;
|
||||
f32 getHScrollbarSize(void) const 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; }
|
||||
inline void setTitle(const String& title) { m_title = title; }
|
||||
inline Vec2 getScrollOffset(void) const override { return m_scrollOffset; }
|
||||
inline f32 getTitlebarHeight(void) const { return m_titlebarHeight; }
|
||||
|
||||
private:
|
||||
|
|
@ -71,10 +60,6 @@ namespace ogfx
|
|||
|
||||
private:
|
||||
String m_title { "Panel" };
|
||||
Vec2 m_scrollOffset { 0, 0 };
|
||||
VerticalScrollBar m_vScrollbar { getWindow() };
|
||||
HorizontalScrollbar m_hScrollbar { getWindow() };
|
||||
ostd::StepTimer m_smoothScrollTimer;
|
||||
|
||||
Color m_titleColor { Colors::Black };
|
||||
i32 m_titlebarType = TitleBarTypes::NoneValue;
|
||||
|
|
@ -84,11 +69,6 @@ namespace ogfx
|
|||
Color m_titlebarColor { Colors::Transparent };
|
||||
Color m_titlebarBorderColor { Colors::Black };
|
||||
i32 m_titleTextAlign { 0 };
|
||||
f32 m_scrollSpeed { 0.8f };
|
||||
|
||||
Vec2 m_scrollVelocity { 0.0f, 0.0f };
|
||||
f32 m_scrollSmoothFactor { 0.7f };
|
||||
f32 m_scrollSpeedMultiplier { 15.0f };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ namespace ogfx
|
|||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
void HorizontalScrollbar::afterDraw(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
|
|
@ -268,6 +268,154 @@ namespace ogfx
|
|||
parentScrollOffset.x = maxScroll * scrollProgress;
|
||||
getParent()->setScrollOffset(parentScrollOffset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ScrollableWidget& ScrollableWidget::create(void)
|
||||
{
|
||||
setTypeName("ogfx::gui::widgets::ScrollableWidget");
|
||||
allowVScroll(true);
|
||||
allowHScroll(true);
|
||||
m_vScrollbar.enableManualDraw(true);
|
||||
addWidget(m_vScrollbar);
|
||||
m_hScrollbar.setMargin({ 0, 0, 0, 0 });
|
||||
m_hScrollbar.enableManualDraw(true);
|
||||
addWidget(m_hScrollbar);
|
||||
m_smoothScrollTimer.create(60.0f, [&](f64 dt) -> void {
|
||||
f32 stepX = m_scrollVelocity.x * (1.0f - m_scrollSmoothFactor);
|
||||
f32 stepY = m_scrollVelocity.y * (1.0f - m_scrollSmoothFactor);
|
||||
|
||||
addScrollOffset({ stepX, stepY });
|
||||
m_scrollVelocity -= { stepX, stepY };
|
||||
|
||||
if (std::abs(m_scrollVelocity.x) < 0.5f) m_scrollVelocity.x = 0;
|
||||
if (std::abs(m_scrollVelocity.y) < 0.5f) m_scrollVelocity.y = 0;
|
||||
}, true);
|
||||
|
||||
m_smoothScrollTimer.setStopCondition([&](void) -> bool {
|
||||
return m_scrollVelocity.x == 0 && m_scrollVelocity.y == 0;
|
||||
});
|
||||
updateScrollbarsSize();
|
||||
validate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ScrollableWidget::onUpdate(void)
|
||||
{
|
||||
m_smoothScrollTimer.update();
|
||||
}
|
||||
|
||||
void ScrollableWidget::drawScrollbars(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
m_vScrollbar.__draw(gfx);
|
||||
m_hScrollbar.__draw(gfx);
|
||||
}
|
||||
|
||||
void ScrollableWidget::updateScrollbarsSize(void)
|
||||
{
|
||||
m_vScrollbar.setMargin({ 0, getPureContentBounds().y, 0, 0 });
|
||||
}
|
||||
|
||||
void ScrollableWidget::onMouseScrolled(const Event& event)
|
||||
{
|
||||
if (isVScrollAllowed())
|
||||
{
|
||||
bool mouseInsideHScrollbar = m_hScrollbar.isMouseInsideThumb({ event.mouse->position_x, event.mouse->position_y });
|
||||
if (std::abs(event.mouse->scrollAmount.y) > 0 && !mouseInsideHScrollbar)
|
||||
{
|
||||
m_scrollVelocity.y += m_scrollSpeed * event.mouse->scrollAmount.y * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
else if (std::abs(event.mouse->scrollAmount.y) > 0)
|
||||
{
|
||||
m_scrollVelocity.x += m_scrollSpeed * event.mouse->scrollAmount.y * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
}
|
||||
if (isHScrollAllowed())
|
||||
{
|
||||
if (std::abs(event.mouse->scrollAmount.x) > 0)
|
||||
{
|
||||
m_scrollVelocity.x += m_scrollSpeed * event.mouse->scrollAmount.x * m_scrollSpeedMultiplier;
|
||||
if (m_smoothScrollTimer.isStopped())
|
||||
m_smoothScrollTimer.restart();
|
||||
event.handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollableWidget::setScrollOffset(const Vec2& offset)
|
||||
{
|
||||
auto ext = getContentExtents();
|
||||
auto cont = getContentBounds();
|
||||
f32 maxScrollY = -(ext.h - cont.h);
|
||||
f32 maxScrollX = -(ext.w - cont.w);
|
||||
|
||||
m_scrollOffset = offset;
|
||||
|
||||
if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
|
||||
if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
|
||||
if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
|
||||
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
|
||||
}
|
||||
|
||||
void ScrollableWidget::addScrollOffset(const Vec2& offset)
|
||||
{
|
||||
auto ext = getContentExtents();
|
||||
auto cont = getContentBounds();
|
||||
f32 maxScrollY = -(ext.h - cont.h);
|
||||
f32 maxScrollX = -(ext.w - cont.w);
|
||||
|
||||
m_scrollOffset += offset;
|
||||
|
||||
if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
|
||||
if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
|
||||
if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
|
||||
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
|
||||
}
|
||||
|
||||
bool ScrollableWidget::needsVScroll(void) const
|
||||
{
|
||||
return isVScrollAllowed() && getContentExtents().h > getContentBounds().h;
|
||||
}
|
||||
|
||||
bool ScrollableWidget::needsHScroll(void) const
|
||||
{
|
||||
return isHScrollAllowed() && getContentExtents().w > getContentBounds().w;
|
||||
}
|
||||
|
||||
void ScrollableWidget::onWidgetAdded(Widget& child)
|
||||
{
|
||||
removeWidget(m_vScrollbar);
|
||||
removeWidget(m_hScrollbar);
|
||||
addWidget(m_vScrollbar, { 0, 0 }, true);
|
||||
addWidget(m_hScrollbar, { 0, 0 }, true);
|
||||
}
|
||||
|
||||
f32 ScrollableWidget::getVScrollbarSize(void) const
|
||||
{
|
||||
if (!isVScrollAllowed())
|
||||
return 0;
|
||||
if (!needsVScroll())
|
||||
return 0;
|
||||
return m_vScrollbar.getw();
|
||||
}
|
||||
|
||||
f32 ScrollableWidget::getHScrollbarSize(void) const
|
||||
{
|
||||
if (!isHScrollAllowed())
|
||||
return 0;
|
||||
if (!needsHScroll())
|
||||
return 0;
|
||||
return m_hScrollbar.geth();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <ogfx/gui/widgets/Widget.hpp>
|
||||
#include <ostd/utils/Time.hpp>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
|
|
@ -104,6 +105,39 @@ namespace ogfx
|
|||
Color m_thumbBorderColor { 150, 150, 150 };
|
||||
bool m_thumbShowBorder { true };
|
||||
};
|
||||
class ScrollableWidget : public Widget
|
||||
{
|
||||
public:
|
||||
inline ScrollableWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
ScrollableWidget& create(void);
|
||||
virtual void onUpdate(void) override;
|
||||
void drawScrollbars(ogfx::BasicRenderer2D& gfx);
|
||||
void updateScrollbarsSize(void);
|
||||
virtual void onMouseScrolled(const Event& event) override;
|
||||
virtual void setScrollOffset(const Vec2& offset) override;
|
||||
virtual void addScrollOffset(const Vec2& offset) override;
|
||||
virtual bool needsVScroll(void) const override;
|
||||
virtual bool needsHScroll(void) const override;
|
||||
virtual void onWidgetAdded(Widget& child) override;
|
||||
virtual f32 getVScrollbarSize(void) const override;
|
||||
virtual f32 getHScrollbarSize(void) const override;
|
||||
inline Vec2 getScrollOffset(void) const override { return m_scrollOffset; }
|
||||
inline void setScrollSpeed(f32 speed) { m_scrollSpeed = speed; }
|
||||
inline f32 getScrollSpeed(void) const { return m_scrollSpeed; }
|
||||
inline void setScrollSmoothFactor(f32 speed) { m_scrollSmoothFactor = std::clamp(speed, 0.0f, 1.0f); }
|
||||
inline f32 getScrollSmoothFactor(void) const { return m_scrollSmoothFactor; }
|
||||
|
||||
private:
|
||||
String m_title { "Panel" };
|
||||
Vec2 m_scrollOffset { 0, 0 };
|
||||
VerticalScrollBar m_vScrollbar { getWindow() };
|
||||
HorizontalScrollbar m_hScrollbar { getWindow() };
|
||||
ostd::StepTimer m_smoothScrollTimer;
|
||||
f32 m_scrollSpeed { 0.8f };
|
||||
Vec2 m_scrollVelocity { 0.0f, 0.0f };
|
||||
f32 m_scrollSmoothFactor { 0.7f };
|
||||
f32 m_scrollSpeedMultiplier { 15.0f };
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue