Scrolling layout
This commit is contained in:
parent
03b2b5d038
commit
047d67c4fa
14 changed files with 288 additions and 35 deletions
|
|
@ -122,7 +122,7 @@ namespace tp {
|
||||||
pos.y += dy;
|
pos.y += dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect<Type>& scaleFromCenter(tp::halnf fac, bool add = false) {
|
Rect<Type>& shrinkFromCenter(tp::halnf fac, bool add = false) {
|
||||||
if (add) {
|
if (add) {
|
||||||
pos += fac;
|
pos += fac;
|
||||||
size -= fac * 2;
|
size -= fac * 2;
|
||||||
|
|
@ -260,20 +260,20 @@ namespace tp {
|
||||||
Vec2<Type> center() const { return pos + size / 2.f; }
|
Vec2<Type> center() const { return pos + size / 2.f; }
|
||||||
|
|
||||||
// splits by Factor Horizontally returning Left rect
|
// splits by Factor Horizontally returning Left rect
|
||||||
Rect<Type> splitByFactorHL(halnf factor) {
|
Rect<Type> splitByFactorHL(halnf factor) const {
|
||||||
return { x, y, size.x * factor, size.y };
|
return { x, y, size.x * factor, size.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect<Type> splitByFactorHR(halnf factor) {
|
Rect<Type> splitByFactorHR(halnf factor) const {
|
||||||
const auto abs = size.x * factor;
|
const auto abs = size.x * factor;
|
||||||
return { x + abs, y, size.x - abs, size.y };
|
return { x + abs, y, size.x - abs, size.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect<Type> splitByFactorVT(halnf factor) {
|
Rect<Type> splitByFactorVT(halnf factor) const {
|
||||||
return { x, y, size.x, size.y * factor };
|
return { x, y, size.x, size.y * factor };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect<Type> splitByFactorVB(halnf factor) {
|
Rect<Type> splitByFactorVB(halnf factor) const {
|
||||||
const auto abs = size.y * factor;
|
const auto abs = size.y * factor;
|
||||||
return { x, y + abs, size.x, size.y - abs };
|
return { x, y + abs, size.x, size.y - abs };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
TODO
7
TODO
|
|
@ -1,7 +1,10 @@
|
||||||
Widgets-New:
|
Widgets-New:
|
||||||
Lock-focus feature
|
Make visual parameters static
|
||||||
Collapsing menu
|
Make visual parameters configurable
|
||||||
|
Make get-areas fetch cache and not animation objects
|
||||||
|
|
||||||
Scrolling in basic layout
|
Scrolling in basic layout
|
||||||
|
Collapsing menu
|
||||||
|
|
||||||
Add Widgets:
|
Add Widgets:
|
||||||
popups, drop-downs, tool-tips
|
popups, drop-downs, tool-tips
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ScrollableWidget.hpp"
|
#include "ScrollableWidget.hpp"
|
||||||
|
#include "../../WidgetsNew/public/widgets/ScrollableWidget.hpp"
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@
|
||||||
#include "GraphicApplication.hpp"
|
#include "GraphicApplication.hpp"
|
||||||
|
|
||||||
#include "RootWidget.hpp"
|
#include "RootWidget.hpp"
|
||||||
#include "AnimationTestWidget.hpp"
|
|
||||||
#include "FloatingWidget.hpp"
|
#include "FloatingWidget.hpp"
|
||||||
#include "DockWidget.hpp"
|
#include "DockWidget.hpp"
|
||||||
|
#include "ScrollableWidget.hpp"
|
||||||
|
|
||||||
|
#include "ScrollableLayout.hpp"
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
|
|
@ -21,8 +23,27 @@ using namespace tp;
|
||||||
class WidgetApplication : public Application {
|
class WidgetApplication : public Application {
|
||||||
public:
|
public:
|
||||||
WidgetApplication() {
|
WidgetApplication() {
|
||||||
exampleNestedMenus();
|
exampleScrolling();
|
||||||
// examplePopup();
|
}
|
||||||
|
|
||||||
|
void exampleScrolling() {
|
||||||
|
static Widget widget;
|
||||||
|
static Widget content;
|
||||||
|
static ButtonWidget buttons[10];
|
||||||
|
static ScrollableBarWidget scrollBar;
|
||||||
|
|
||||||
|
mRootWidget.setRootWidget(&widget);
|
||||||
|
|
||||||
|
widget.addChild(&scrollBar);
|
||||||
|
widget.addChild(&content);
|
||||||
|
|
||||||
|
for (auto& button : buttons) {
|
||||||
|
content.addChild(&button);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.setLayout(new ScrollableLayout(&widget));
|
||||||
|
|
||||||
|
RootWidget::setWidgetArea(content, { 333, 333, 522, 522 });
|
||||||
}
|
}
|
||||||
|
|
||||||
void examplePopup() {
|
void examplePopup() {
|
||||||
|
|
@ -72,6 +93,22 @@ public:
|
||||||
|
|
||||||
menu2.addToMenu(&menu1);
|
menu2.addToMenu(&menu1);
|
||||||
|
|
||||||
|
// popup
|
||||||
|
{
|
||||||
|
buttons[0].setAction([&](){
|
||||||
|
buttons[10].setArea({ 30, 30, 100, 100 });
|
||||||
|
buttons[0].openPopup(&buttons[10]);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons[0].setText("open popup");
|
||||||
|
|
||||||
|
buttons[10].setAction([&](){
|
||||||
|
buttons[10].closePopup(&buttons[10]);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons[10].setText("close popup");
|
||||||
|
}
|
||||||
|
|
||||||
RootWidget::setWidgetArea(menu1, { 300, 100, 150, 500 });
|
RootWidget::setWidgetArea(menu1, { 300, 100, 150, 500 });
|
||||||
RootWidget::setWidgetArea(menu2, { 100, 100, 150, 300 });
|
RootWidget::setWidgetArea(menu2, { 100, 100, 150, 300 });
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +144,7 @@ public:
|
||||||
((BasicLayout*)widgets[1].getLayout())->setLayoutPolicy(LayoutPolicy::Horizontal);
|
((BasicLayout*)widgets[1].getLayout())->setLayoutPolicy(LayoutPolicy::Horizontal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup1() {
|
void exampleDock() {
|
||||||
static DockWidget dock;
|
static DockWidget dock;
|
||||||
static FloatingMenu menu1;
|
static FloatingMenu menu1;
|
||||||
static FloatingMenu menu2;
|
static FloatingMenu menu2;
|
||||||
|
|
@ -140,22 +177,8 @@ public:
|
||||||
buttons[5].setText("dock");
|
buttons[5].setText("dock");
|
||||||
buttons[6].setText("undock");
|
buttons[6].setText("undock");
|
||||||
|
|
||||||
// mLayoutWidget.addChild(&buttons[2]);
|
|
||||||
|
|
||||||
// mWidgetFloating.addChild(&buttons[0]);
|
|
||||||
|
|
||||||
// mRootWidget.setRootWidget(&mAnimationTestWidget);
|
|
||||||
|
|
||||||
// mAnimationTestWidget.addChild(&mWidgetFloating);
|
|
||||||
// mAnimationTestWidget.addChild(&mLayoutWidget);
|
|
||||||
|
|
||||||
RootWidget::setWidgetArea(menu2, { 300, 100, 150, 500 });
|
RootWidget::setWidgetArea(menu2, { 300, 100, 150, 500 });
|
||||||
RootWidget::setWidgetArea(menu1, { 100, 100, 150, 300 });
|
RootWidget::setWidgetArea(menu1, { 100, 100, 150, 300 });
|
||||||
|
|
||||||
// mWidgetFloating.addChild(&mLayoutWidget);
|
|
||||||
|
|
||||||
// mLayoutWidget.addChild(&buttons[0]);
|
|
||||||
// mLayoutWidget.addChild(&mLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler, halnf deltaTime) override {
|
void processFrame(EventHandler* eventHandler, halnf deltaTime) override {
|
||||||
|
|
@ -166,7 +189,7 @@ public:
|
||||||
void drawFrame(Canvas* canvas) override {
|
void drawFrame(Canvas* canvas) override {
|
||||||
mRootWidget.drawFrame(*canvas);
|
mRootWidget.drawFrame(*canvas);
|
||||||
|
|
||||||
drawDebug();
|
// drawDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool forceNewFrame() override {
|
bool forceNewFrame() override {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ void BasicLayout::pickRect(bool vertical) {
|
||||||
auto current = getArea();
|
auto current = getArea();
|
||||||
auto children = getChildrenEnclosure();
|
auto children = getChildrenEnclosure();
|
||||||
auto parent = getParentEnclosure();
|
auto parent = getParentEnclosure();
|
||||||
RectF newArea = current;
|
|
||||||
|
|
||||||
|
children.shrinkFromCenter(-mLayoutMargin, true);
|
||||||
|
|
||||||
|
RectF newArea;
|
||||||
if (vertical) {
|
if (vertical) {
|
||||||
auto rangeY = pickRange(current.getRangeY(), children.getRangeY(), parent.getRangeY(), true);
|
auto rangeY = pickRange(current.getRangeY(), children.getRangeY(), parent.getRangeY(), true);
|
||||||
newArea = RectF(current.getRangeX(), rangeY);
|
newArea = RectF(current.getRangeX(), rangeY);
|
||||||
|
|
@ -143,5 +145,5 @@ void BasicLayout::adjustLayout(bool vertical) {
|
||||||
|
|
||||||
RectF BasicLayout::getAvailableChildArea() const {
|
RectF BasicLayout::getAvailableChildArea() const {
|
||||||
auto out = WidgetLayout::getAvailableChildArea();
|
auto out = WidgetLayout::getAvailableChildArea();
|
||||||
return out.scaleFromCenter(mLayoutMargin, true);
|
return out.shrinkFromCenter(mLayoutMargin, true);
|
||||||
}
|
}
|
||||||
53
WidgetsNew/private/layouts/ScrollableLayout.cpp
Normal file
53
WidgetsNew/private/layouts/ScrollableLayout.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "ScrollableLayout.hpp"
|
||||||
|
|
||||||
|
// fixme : this dependency should be removed
|
||||||
|
#include "ScrollableWidget.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
void ScrollableLayout::updateLayout(bool vertical) {
|
||||||
|
if (vertical) return;
|
||||||
|
|
||||||
|
// TODO : make better interface to get scroller and content widget
|
||||||
|
if (children().size() != 2) return;
|
||||||
|
|
||||||
|
auto scroller = dynamic_cast<ScrollableBarWidget*>(children().front());
|
||||||
|
auto content = children().back();
|
||||||
|
|
||||||
|
if (!scroller || !content) return;
|
||||||
|
|
||||||
|
updateWidgetRects(getArea(), content, scroller);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableLayout::updateWidgetRects(const RectF& area, Widget* content, ScrollableBarWidget* scroller) const {
|
||||||
|
bool dir = scroller->getDirection();
|
||||||
|
|
||||||
|
// update content
|
||||||
|
// auto contentItems = content->getLayout()->getChildrenEnclosure();
|
||||||
|
// content->getLayout()->setArea(contentItems.shrinkFromCenter(-10, true));
|
||||||
|
content->getLayout()->pickRect(dir);
|
||||||
|
|
||||||
|
auto sizeFactor = (area.size[dir] / content->getLayout()->getArea().size[dir]);
|
||||||
|
auto splitFactor = 1 - ((sizeFactor > 1.f) ? 0 : mScrollerSize / area.size[!dir]);
|
||||||
|
|
||||||
|
auto holderArea = area.splitByFactorHL(splitFactor);
|
||||||
|
auto contentArea = content->getLayout()->getArea();
|
||||||
|
auto scrollerArea = area.splitByFactorHR(splitFactor);
|
||||||
|
|
||||||
|
scroller->updateSizeFactor(sizeFactor);
|
||||||
|
|
||||||
|
contentArea.pos[dir] = -scroller->getPosFactor() * contentArea.size[dir];
|
||||||
|
contentArea.size[!dir] = holderArea.size[!dir];
|
||||||
|
contentArea.pos[!dir] = 0;
|
||||||
|
|
||||||
|
scroller->getLayout()->setArea(scrollerArea);
|
||||||
|
content->getLayout()->setArea(contentArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
RectF ScrollableLayout::getAvailableChildArea() const {
|
||||||
|
auto out = getArea();
|
||||||
|
// dont constrain on scroll axis
|
||||||
|
out.pos = -FLT_MAX / 4;
|
||||||
|
out.size = FLT_MAX / 2;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,9 @@ DebugManager tp::gDebugWidget;
|
||||||
bool DebugManager::update(RootWidget* rootWidget, EventHandler& events) {
|
bool DebugManager::update(RootWidget* rootWidget, EventHandler& events) {
|
||||||
mRootWidget = rootWidget;
|
mRootWidget = rootWidget;
|
||||||
|
|
||||||
|
events.setEnableKeyEvents(true);
|
||||||
|
if (events.isPressed(InputID::D)) mDebug = !mDebug;
|
||||||
|
|
||||||
if (mDebug) {
|
if (mDebug) {
|
||||||
auto area = rootWidget->mRoot.getAreaT();
|
auto area = rootWidget->mRoot.getAreaT();
|
||||||
area.size -= { 400, 0 };
|
area.size -= { 400, 0 };
|
||||||
|
|
@ -53,12 +56,12 @@ bool DebugManager::update(RootWidget* rootWidget, EventHandler& events) {
|
||||||
void DebugManager::drawDebug(RootWidget* rootWidget, Canvas& canvas) {
|
void DebugManager::drawDebug(RootWidget* rootWidget, Canvas& canvas) {
|
||||||
mRootWidget = rootWidget;
|
mRootWidget = rootWidget;
|
||||||
|
|
||||||
ImGui::Checkbox("Draw debug", &mDebug);
|
|
||||||
|
|
||||||
if (!mDebug) {
|
if (!mDebug) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImGui::Checkbox("Draw debug", &mDebug);
|
||||||
|
|
||||||
ImGui::SameLine(); ImGui::Text("To Toggle processing press k");
|
ImGui::SameLine(); ImGui::Text("To Toggle processing press k");
|
||||||
|
|
||||||
auto& upd = rootWidget->mUpdateManager;
|
auto& upd = rootWidget->mUpdateManager;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "DebugManager.hpp"
|
#include "DebugManager.hpp"
|
||||||
|
|
||||||
#include "DockLayout.hpp"
|
#include "DockLayout.hpp"
|
||||||
|
#include "ScrollableLayout.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
@ -91,6 +92,7 @@ int LayoutManager::getLayoutOrder(WidgetLayout* parent, WidgetLayout* child) con
|
||||||
auto policyChild = parent->getSizePolicy()[mVertical];
|
auto policyChild = parent->getSizePolicy()[mVertical];
|
||||||
|
|
||||||
if (dynamic_cast<DockLayout*>(parent)) return -1;
|
if (dynamic_cast<DockLayout*>(parent)) return -1;
|
||||||
|
// if (dynamic_cast<ScrollableLayout*>(parent)) return -1;
|
||||||
|
|
||||||
return sizePolicyDep[int(policyParent)][int(policyChild)];
|
return sizePolicyDep[int(policyParent)][int(policyChild)];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,6 @@ void UpdateManager::lockFocus(tp::Widget* widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateManager::freeFocus(tp::Widget* widget) {
|
void UpdateManager::freeFocus(tp::Widget* widget) {
|
||||||
DEBUG_ASSERT(mFocusLockWidget == widget)
|
// DEBUG_ASSERT(mFocusLockWidget == widget)
|
||||||
mFocusLockWidget = nullptr;
|
mFocusLockWidget = nullptr;
|
||||||
}
|
}
|
||||||
87
WidgetsNew/private/widgets/ScrollableWidget.cpp
Normal file
87
WidgetsNew/private/widgets/ScrollableWidget.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#include "ScrollableWidget.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
void ScrollableBarWidget::process(const EventHandler& events) {
|
||||||
|
// all content is visible no need to process anything
|
||||||
|
if (mSizeFactor >= 1) {
|
||||||
|
mScrolling = false;
|
||||||
|
mPosFactor = mSizeFactor / 2.f;
|
||||||
|
freeFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHandleRect();
|
||||||
|
|
||||||
|
auto pointer = events.getPointer();
|
||||||
|
auto size = getArea().size;
|
||||||
|
|
||||||
|
mHandleHovered = getHandleRect().isInside(pointer);
|
||||||
|
|
||||||
|
if (getRelativeAreaT().isInside(pointer) && events.isPressed(InputID::MOUSE1)) {
|
||||||
|
if (!mHandleHovered) {
|
||||||
|
jumpTo((pointer / size)[mVertical]);
|
||||||
|
mStartPos = { 0, 0 };
|
||||||
|
} else {
|
||||||
|
mStartPos = pointer - getHandleRect().center();
|
||||||
|
}
|
||||||
|
mScrolling = true;
|
||||||
|
lockFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mScrolling && events.isReleased(InputID::MOUSE1)) {
|
||||||
|
mScrolling = false;
|
||||||
|
freeFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mScrolling) {
|
||||||
|
updateHandleRect();
|
||||||
|
auto dragDelta = (pointer - getHandleRect().center()) - mStartPos;
|
||||||
|
moveBy((dragDelta / size)[mVertical]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::jumpTo(halnf pos) {
|
||||||
|
mPosFactor = pos;
|
||||||
|
clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::moveBy(halnf delta) {
|
||||||
|
mPosFactor += delta;
|
||||||
|
clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::updateSizeFactor(halnf factor) {
|
||||||
|
mSizeFactor = factor;
|
||||||
|
clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::clamp() {
|
||||||
|
mSizeFactor = ::clamp(mSizeFactor, 0.f, 1.f);
|
||||||
|
mPosFactor = ::clamp(mPosFactor, mSizeFactor / 2, 1.f - mSizeFactor / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::draw(Canvas& canvas) {
|
||||||
|
updateHandleRect();
|
||||||
|
|
||||||
|
canvas.rect(getArea().relative(), mBGColor, mRounding);
|
||||||
|
|
||||||
|
auto& handleColor = mScrolling ? mHandleSlideColor : (mHandleHovered ? mHandleHoverColor : mHandleColor);
|
||||||
|
canvas.rect(getHandleRect(), handleColor, mRounding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableBarWidget::updateHandleRect() {
|
||||||
|
auto area = getArea().relative();
|
||||||
|
|
||||||
|
mHandleRect = area;
|
||||||
|
mHandleRect.size[mVertical] = area.size[mVertical] * mSizeFactor;
|
||||||
|
mHandleRect.pos[mVertical] = area.size[mVertical] * mPosFactor;
|
||||||
|
|
||||||
|
mHandleRect.pos[mVertical] -= mHandleRect.size[mVertical] / 2;
|
||||||
|
|
||||||
|
mHandleRect.shrinkFromCenter(mHandlePadding, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const RectF& ScrollableBarWidget::getHandleRect() const {
|
||||||
|
return mHandleRect;
|
||||||
|
}
|
||||||
|
|
@ -27,8 +27,8 @@ namespace tp {
|
||||||
|
|
||||||
virtual void updateLayout(bool vertical) {}
|
virtual void updateLayout(bool vertical) {}
|
||||||
|
|
||||||
virtual void pickRect(bool vertical) = 0;
|
virtual void pickRect(bool vertical) {}
|
||||||
virtual void clampRect() = 0;
|
virtual void clampRect() {}
|
||||||
[[nodiscard]] virtual RectF getAvailableChildArea() const;
|
[[nodiscard]] virtual RectF getAvailableChildArea() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -59,7 +59,7 @@ namespace tp {
|
||||||
Widget* mWidget = nullptr;
|
Widget* mWidget = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Vec2<SizePolicy> mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed };
|
Vec2<SizePolicy> mSizePolicy = { SizePolicy::Fixed, SizePolicy::Minimal };
|
||||||
Vec2F mMinSize = { 50, 50 };
|
Vec2F mMinSize = { 50, 50 };
|
||||||
Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 };
|
Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
22
WidgetsNew/public/layouts/ScrollableLayout.hpp
Normal file
22
WidgetsNew/public/layouts/ScrollableLayout.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Layout.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
class ScrollableBarWidget;
|
||||||
|
|
||||||
|
class ScrollableLayout : public WidgetLayout {
|
||||||
|
public:
|
||||||
|
explicit ScrollableLayout(Widget* widget) :
|
||||||
|
WidgetLayout(widget) {}
|
||||||
|
|
||||||
|
void updateLayout(bool vertical) override;
|
||||||
|
[[nodiscard]] RectF getAvailableChildArea() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateWidgetRects(const RectF& area, Widget* content, ScrollableBarWidget* scroller) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
halnf mScrollerSize = 15;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ namespace tp {
|
||||||
RootWidget* mRootWidget = nullptr;
|
RootWidget* mRootWidget = nullptr;
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
bool mDebug = true;
|
bool mDebug = false;
|
||||||
bool mDebugStopProcessing = false;
|
bool mDebugStopProcessing = false;
|
||||||
bool mDebugRedrawAlways = false;
|
bool mDebugRedrawAlways = false;
|
||||||
bool mSlowMotion = false;
|
bool mSlowMotion = false;
|
||||||
|
|
|
||||||
57
WidgetsNew/public/widgets/ScrollableWidget.hpp
Normal file
57
WidgetsNew/public/widgets/ScrollableWidget.hpp
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Widget.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
// just the scrolling bar
|
||||||
|
class ScrollableBarWidget : public Widget {
|
||||||
|
public:
|
||||||
|
ScrollableBarWidget() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool processesEvents() const override { return true; }
|
||||||
|
[[nodiscard]] bool propagateEventsToChildren() const override { return false; }
|
||||||
|
[[nodiscard]] bool needsNextFrame() const override { return mScrolling; }
|
||||||
|
|
||||||
|
void process(const EventHandler& events) override;
|
||||||
|
void draw(Canvas& canvas) override;
|
||||||
|
|
||||||
|
void updateSizeFactor(halnf factor); // holder-size divided by content-size
|
||||||
|
|
||||||
|
[[nodiscard]] bool getDirection() const { return mVertical; }
|
||||||
|
[[nodiscard]] halnf getPosFactor() const { return mPosFactor - mSizeFactor / 2; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] const RectF& getHandleRect() const;
|
||||||
|
void updateHandleRect();
|
||||||
|
void jumpTo(halnf);
|
||||||
|
void moveBy(halnf);
|
||||||
|
void clamp();
|
||||||
|
|
||||||
|
private: // state
|
||||||
|
bool mVertical = true;
|
||||||
|
bool mScrolling = false;
|
||||||
|
bool mHandleHovered = false;
|
||||||
|
|
||||||
|
Vec2F mStartPos = {};
|
||||||
|
|
||||||
|
halnf mPosFactor = 0.2f; // (center-of-holder - content-start) / content-size
|
||||||
|
halnf mSizeFactor = 0.3f;
|
||||||
|
|
||||||
|
private: // TODO : make params static
|
||||||
|
halnf mRounding = 5;
|
||||||
|
halnf mHandlePadding = 0;
|
||||||
|
|
||||||
|
RGBA mBGColor = { 0.1, 0.1, 0.1, 0.0 };
|
||||||
|
RGBA mHandleColor = { 0.2, 0.2, 0.2, 1 };
|
||||||
|
RGBA mHandleHoverColor = { 0.3, 0.3, 0.3, 1 };
|
||||||
|
RGBA mHandleSlideColor = { 0.5, 0.5, 0.5, 1 };
|
||||||
|
|
||||||
|
private: // cache
|
||||||
|
RectF mHandleRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScrollableWidget : public Widget {
|
||||||
|
public:
|
||||||
|
ScrollableWidget();
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue