Scrolling layout
This commit is contained in:
parent
03b2b5d038
commit
047d67c4fa
14 changed files with 288 additions and 35 deletions
|
|
@ -11,8 +11,10 @@ void BasicLayout::pickRect(bool vertical) {
|
|||
auto current = getArea();
|
||||
auto children = getChildrenEnclosure();
|
||||
auto parent = getParentEnclosure();
|
||||
RectF newArea = current;
|
||||
|
||||
children.shrinkFromCenter(-mLayoutMargin, true);
|
||||
|
||||
RectF newArea;
|
||||
if (vertical) {
|
||||
auto rangeY = pickRange(current.getRangeY(), children.getRangeY(), parent.getRangeY(), true);
|
||||
newArea = RectF(current.getRangeX(), rangeY);
|
||||
|
|
@ -143,5 +145,5 @@ void BasicLayout::adjustLayout(bool vertical) {
|
|||
|
||||
RectF BasicLayout::getAvailableChildArea() const {
|
||||
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) {
|
||||
mRootWidget = rootWidget;
|
||||
|
||||
events.setEnableKeyEvents(true);
|
||||
if (events.isPressed(InputID::D)) mDebug = !mDebug;
|
||||
|
||||
if (mDebug) {
|
||||
auto area = rootWidget->mRoot.getAreaT();
|
||||
area.size -= { 400, 0 };
|
||||
|
|
@ -53,12 +56,12 @@ bool DebugManager::update(RootWidget* rootWidget, EventHandler& events) {
|
|||
void DebugManager::drawDebug(RootWidget* rootWidget, Canvas& canvas) {
|
||||
mRootWidget = rootWidget;
|
||||
|
||||
ImGui::Checkbox("Draw debug", &mDebug);
|
||||
|
||||
if (!mDebug) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ImGui::Checkbox("Draw debug", &mDebug);
|
||||
|
||||
ImGui::SameLine(); ImGui::Text("To Toggle processing press k");
|
||||
|
||||
auto& upd = rootWidget->mUpdateManager;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "DebugManager.hpp"
|
||||
|
||||
#include "DockLayout.hpp"
|
||||
#include "ScrollableLayout.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -91,6 +92,7 @@ int LayoutManager::getLayoutOrder(WidgetLayout* parent, WidgetLayout* child) con
|
|||
auto policyChild = parent->getSizePolicy()[mVertical];
|
||||
|
||||
if (dynamic_cast<DockLayout*>(parent)) return -1;
|
||||
// if (dynamic_cast<ScrollableLayout*>(parent)) return -1;
|
||||
|
||||
return sizePolicyDep[int(policyParent)][int(policyChild)];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,6 +206,6 @@ void UpdateManager::lockFocus(tp::Widget* widget) {
|
|||
}
|
||||
|
||||
void UpdateManager::freeFocus(tp::Widget* widget) {
|
||||
DEBUG_ASSERT(mFocusLockWidget == widget)
|
||||
// DEBUG_ASSERT(mFocusLockWidget == widget)
|
||||
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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue