Added scrollbar widget
This commit is contained in:
parent
777124579f
commit
fde961c78e
13 changed files with 315 additions and 36 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
% =======================
|
% =======================
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
147
src/ogfx/gui/widgets/Scrollbar.cpp
Normal file
147
src/ogfx/gui/widgets/Scrollbar.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/ogfx/gui/widgets/Scrollbar.hpp
Normal file
72
src/ogfx/gui/widgets/Scrollbar.hpp
Normal 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 };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue