From d6025bc4e0f688330d042bd7d9f47b896cee02c1 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Fri, 11 Oct 2024 17:30:38 +0300 Subject: [PATCH] Refactor idea done unstable --- WidgetsNew/private/LayoutPolicies.cpp | 96 ++++---- WidgetsNew/private/Widget.cpp | 320 +++++--------------------- WidgetsNew/public/LayoutPolicies.hpp | 43 ++-- WidgetsNew/public/Widget.hpp | 83 +++---- 4 files changed, 160 insertions(+), 382 deletions(-) diff --git a/WidgetsNew/private/LayoutPolicies.cpp b/WidgetsNew/private/LayoutPolicies.cpp index 5507117..521ec6e 100644 --- a/WidgetsNew/private/LayoutPolicies.cpp +++ b/WidgetsNew/private/LayoutPolicies.cpp @@ -1,10 +1,11 @@ +#include #include "LayoutPolicies.hpp" #include "Widget.hpp" using namespace tp; -const RectF& WidgetLayout::getArea() { +const RectF& WidgetLayout::getArea() const { return mWidget->getAreaCache(); } @@ -12,7 +13,15 @@ void WidgetLayout::setArea(const RectF& area) { mWidget->setAreaCache(area); } -void WidgetLayout::pickRect() { +Widget* WidgetLayout::parent() const { return mWidget->mParent; } + +const std::vector& WidgetLayout::children() const { return mWidget->mChildren; } + +const Vec2F& BasicLayout::getMinSize() { return mMinSize; } + +void BasicLayout::setMinSize(const Vec2F& size) { mMinSize = size; } + +void BasicLayout::pickRect() { auto current = getArea(); auto children = getChildrenEnclosure(); auto parent = getParentEnclosure(); @@ -25,7 +34,7 @@ void WidgetLayout::pickRect() { setArea(newArea); } -void WidgetLayout::clampRect() { +void BasicLayout::clampRect() { auto current = getArea(); auto children = getChildrenEnclosure(); auto parent = getParentEnclosure(); @@ -36,10 +45,10 @@ void WidgetLayout::clampRect() { setArea(RectF(rangeX, rangeY)); } -void WidgetLayout::adjustChildrenRect() { - if (mWidget->mChildren.empty()) return; +void BasicLayout::adjustChildrenRect() { + if (children().empty()) return; - switch (mWidget->mLayoutPolicy) { + switch (mLayoutPolicy) { case LayoutPolicy::Passive: break; case LayoutPolicy::Vertical: adjustLayout(true); break; case LayoutPolicy::Horizontal: adjustLayout(false); break; @@ -47,42 +56,45 @@ void WidgetLayout::adjustChildrenRect() { } -halnf WidgetLayout::changeChildSize(tp::Widget* widget, halnf diff, bool vertical) { +halnf BasicLayout::changeChildSize(tp::Widget* widget, halnf diff, bool vertical) { auto prevSize = widget->getAreaCache().size[vertical]; { auto area = widget->getAreaCache(); area.size[vertical] += diff; widget->setAreaCache(area); - widget->clampMinMaxSize(); + + // FIXME : widget->clampMinMaxSize(); } auto newSize = widget->getAreaCache().size[vertical]; return newSize - prevSize; } -void WidgetLayout::adjustLayout(bool vertical) { +void BasicLayout::adjustLayout(bool vertical) { std::vector> contributors; Vec2F contentSize = { 0, 0 }; - Vec2F availableSize = getRelativeAreaT().size; + Vec2F availableSize = getArea().size; - for (auto child : mChildren) { - if (child->mSizePolicy[!vertical] != SizePolicy::Minimal) { - child->pickRect(); - } + for (auto child : children()) { + // FIXME : - if (child->mSizePolicy[vertical] == SizePolicy::Expanding) { + // if (child->mSizePolicy[!vertical] != SizePolicy::Minimal) { + // child->pickRect(); + // } + + // if (child->mSizePolicy[vertical] == SizePolicy::Expanding) { contributors.emplace_back( child, true ); auto area = child->getAreaCache(); area.size[vertical] = 0; child->setAreaCache(area); - child->clampRect(); + // child->clampRect(); - } + //} contentSize += child->getAreaCache().size; } - availableSize -= mLayoutGap * ((halnf) mChildren.size() - 1) + mLayoutMargin * 2; + availableSize -= mLayoutGap * ((halnf) children().size() - 1) + mLayoutMargin * 2; auto diff = availableSize - contentSize; @@ -111,7 +123,7 @@ void WidgetLayout::adjustLayout(bool vertical) { // arrange halnf iterPos = mLayoutMargin; - for (auto child : mChildren) { + for (auto child : children()) { auto area = child->getAreaCache(); area.pos[vertical] = iterPos; iterPos += area.size[vertical] + mLayoutGap; @@ -123,7 +135,7 @@ void WidgetLayout::adjustLayout(bool vertical) { } } -RangeF WidgetLayout::pickRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical) { +RangeF BasicLayout::pickRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical) const { RangeF out; switch (mSizePolicy[vertical]) { @@ -136,17 +148,17 @@ RangeF WidgetLayout::pickRange(const RangeF& current, const RangeF& children, co return out; } -void WidgetLayout::clampMinMaxSize() { - auto current = getAreaCache(); +void BasicLayout::clampMinMaxSize() { + auto current = getArea(); current.size.clamp(mMinSize, mMaxSize); - setAreaCache(current); + setArea(current); } -RangeF WidgetLayout::clampRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical) { +RangeF BasicLayout::clampRange(const RangeF& current, const RangeF& child, const RangeF& parent, bool vertical) const { auto out = current; - if (!mChildren.empty()) { - auto clampedChild = children; + if (!children().empty()) { + auto clampedChild = child; clampedChild.clamp(parent); out.clamp(clampedChild, parent); } else { @@ -162,29 +174,33 @@ RangeF WidgetLayout::clampRange(const RangeF& current, const RangeF& children, c return out; } -RectF WidgetLayout::getChildrenEnclosure() const { +RectF BasicLayout::getChildrenEnclosure() const { RectF out; - if (mChildren.empty()) { - out = { getAreaCache().center(), { 0, 0 } }; + if (children().empty()) { + out = { getArea().center(), { 0, 0 } }; } else { - out = mChildren.front()->getAreaCache(); - for (auto child : mChildren) { + out = children().front()->getAreaCache(); + for (auto child : children()) { out.expand(child->getAreaCache()); } - out.pos += getAreaCache().pos; + out.pos += getArea().pos; } return out; } -RectF WidgetLayout::getParentEnclosure() { - DEBUG_ASSERT(mParent); - if (!mParent) return { { 0, 0 }, mMaxSize }; +RectF BasicLayout::getParentEnclosure() const { + DEBUG_ASSERT(parent()) + if (!parent()) return { { 0, 0 }, mMaxSize }; - auto out = mParent->getRelativeAreaT(); - if (mParent->mLayoutPolicy != LayoutPolicy::Passive) { - return out.scaleFromCenter(mParent->mLayoutMargin, true); - } - return out; + // FIXME : + // auto out = parent()->getRelativeAreaT(); + + // if (parent()->mLayoutPolicy != LayoutPolicy::Passive) { + // return out.scaleFromCenter(parent()->mLayoutMargin, true); + // } + + // return out; + return {}; } \ No newline at end of file diff --git a/WidgetsNew/private/Widget.cpp b/WidgetsNew/private/Widget.cpp index 4679b87..8407e92 100644 --- a/WidgetsNew/private/Widget.cpp +++ b/WidgetsNew/private/Widget.cpp @@ -4,104 +4,14 @@ using namespace tp; -WidgetManagerInterface* Widget::getRoot() { - Widget* iter = mParent; - while (iter && iter->mParent) { - iter = iter->mParent; - } - return dynamic_cast(iter); -} - -void Widget::triggerWidgetUpdate(const char* reason) { - if (auto root = getRoot()) { - root->updateWidget(this, reason); - } -} - Widget::Widget() { - mArea.setTargetRect({ 100, 100, 10, 10, }); + mArea.setTargetRect({ 100, 100, 10, 10 }); + setLayout(new BasicLayout(this)); mArea.endAnimation(); } -void Widget::setAreaCache(const tp::RectF& area) { - mAreaCache = area; -} - -void Widget::setArea(const RectF& area) { - if (mArea.getTargetRect() == area) return; - - mArea.setTargetRect(area); - triggerWidgetUpdate("new area"); -} - -RectF Widget::getArea() const { - return mArea.getCurrentRect(); -} - -RectF Widget::getAreaT() const { - return mArea.getTargetRect(); -} - -const RectF& Widget::getAreaCache() const { - return mAreaCache; -} - -RectF Widget::getRelativeArea() const { - return { {}, mArea.getCurrentRect().size }; -} - -RectF Widget::getRelativeAreaT() const { - return { {}, mArea.getTargetRect().size }; -} - -RectF Widget::getRelativeAreaCache() const { - return { {}, mAreaCache.size }; -} - -void Widget::endAnimations() { - mArea.endAnimation(); -} - -bool Widget::processesEvents() const { - return false; -} - -void Widget::updateAnimations() { - mArea.updateCurrentRect(); -} - -bool Widget::needsNextFrame() const { - return !mArea.shouldEndTransition(); // || mInFocus; -} - -void Widget::bringToFront() { - if (!mParent) return; - auto& order = mParent->mDepthOrder; - auto node = order.find(this); - DEBUG_ASSERT(node) - order.detach(node); - order.pushFront(node); -} - -void Widget::bringToBack() { - if (!mParent) return; - auto& order = mParent->mDepthOrder; - auto node = order.find(this); - DEBUG_ASSERT(node) - order.detach(node); - order.pushBack(node); -} - -void Widget::mouseEnter() { - mInFocus = true; -} - -void Widget::mouseLeave() { - mInFocus = false; -} - -bool Widget::propagateEventsToChildren() const { - return true; +Widget::~Widget() { + delete mLayout; } void Widget::addChild(Widget* child) { @@ -134,200 +44,76 @@ void Widget::removeChild(Widget* child) { child->triggerWidgetUpdate("parent changed"); } -void Widget::setSizePolicy(SizePolicy x, SizePolicy y) { - mSizePolicy = { x, y }; - triggerWidgetUpdate("chane size policy"); +void Widget::endAnimations() { mArea.endAnimation(); } +bool Widget::processesEvents() const { return false; } +void Widget::updateAnimations() { mArea.updateCurrentRect(); } +bool Widget::needsNextFrame() const { return !mArea.shouldEndTransition(); } + +void Widget::bringToFront() { + if (!mParent) return; + auto& order = mParent->mDepthOrder; + auto node = order.find(this); + DEBUG_ASSERT(node) + order.detach(node); + order.pushFront(node); } -void Widget::setLayoutPolicy(LayoutPolicy layoutPolicy) { - mLayoutPolicy = layoutPolicy; - triggerWidgetUpdate("new layout"); +void Widget::bringToBack() { + if (!mParent) return; + auto& order = mParent->mDepthOrder; + auto node = order.find(this); + DEBUG_ASSERT(node) + order.detach(node); + order.pushBack(node); } -const Vec2F& Widget::getMinSize() { return mMinSize; } +void Widget::mouseEnter() { mInFocus = true; } +void Widget::mouseLeave() { mInFocus = false; } +bool Widget::propagateEventsToChildren() const { return true; } -void Widget::setMinSize(const Vec2F& size) { - mMinSize = size; - triggerWidgetUpdate("new min size"); +void Widget::setLayout(tp::WidgetLayout* layout) { + mLayout = layout; + triggerWidgetUpdate("chane layout"); } -void Widget::pickRect() { - auto current = getAreaCache(); - auto children = getChildrenEnclosure(); - auto parent = getParentEnclosure(); +WidgetLayout* Widget::getLayout() { return mLayout; } - auto rangeX = pickRange(current.getRangeX(), children.getRangeX(), parent.getRangeX(), false); - auto rangeY = pickRange(current.getRangeY(), children.getRangeY(), parent.getRangeY(), true); - - auto newArea = RectF(rangeX, rangeY); - - for (auto child : mChildren) { - child->setAreaCache(RectF(child->getAreaCache()).move(current.pos - newArea.pos)); +WidgetManagerInterface* Widget::getRoot() { + Widget* iter = mParent; + while (iter && iter->mParent) { + iter = iter->mParent; } - - setAreaCache(newArea); + return dynamic_cast(iter); } -void Widget::clampRect() { - auto current = getAreaCache(); - auto children = getChildrenEnclosure(); - auto parent = getParentEnclosure(); - - auto rangeX = clampRange(current.getRangeX(), children.getRangeX(), parent.getRangeX(), false); - auto rangeY = clampRange(current.getRangeY(), children.getRangeY(), parent.getRangeY(), true); - - setAreaCache(RectF(rangeX, rangeY)); -} - -void Widget::adjustChildrenRect() { - if (mChildren.empty()) return; - - switch (mLayoutPolicy) { - case LayoutPolicy::Passive: break; - case LayoutPolicy::Vertical: adjustLayout(true); break; - case LayoutPolicy::Horizontal: adjustLayout(false); break; +void Widget::triggerWidgetUpdate(const char* reason) { + if (auto root = getRoot()) { + root->updateWidget(this, reason); } } +void Widget::setAreaCache(const tp::RectF& area) { mAreaCache = area; } -halnf Widget::changeChildSize(tp::Widget* widget, halnf diff, bool vertical) { - auto prevSize = widget->getAreaCache().size[vertical]; - { - auto area = widget->getAreaCache(); - area.size[vertical] += diff; - widget->setAreaCache(area); - widget->clampMinMaxSize(); - } - auto newSize = widget->getAreaCache().size[vertical]; +void Widget::setArea(const RectF& area) { + if (mArea.getTargetRect() == area) return; - return newSize - prevSize; + mArea.setTargetRect(area); + triggerWidgetUpdate("new area"); } -void Widget::adjustLayout(bool vertical) { - std::vector> contributors; - Vec2F contentSize = { 0, 0 }; - Vec2F availableSize = getRelativeAreaT().size; +RectF Widget::getArea() const { return mArea.getCurrentRect(); } - for (auto child : mChildren) { - if (child->mSizePolicy[!vertical] != SizePolicy::Minimal) { - child->pickRect(); - } +RectF Widget::getAreaT() const { return mArea.getTargetRect(); } - if (child->mSizePolicy[vertical] == SizePolicy::Expanding) { - contributors.emplace_back( child, true ); +const RectF& Widget::getAreaCache() const { return mAreaCache; } - auto area = child->getAreaCache(); - area.size[vertical] = 0; - child->setAreaCache(area); - child->clampRect(); +RectF Widget::getRelativeArea() const { return { {}, mArea.getCurrentRect().size }; } - } - contentSize += child->getAreaCache().size; - } +RectF Widget::getRelativeAreaT() const { return { {}, mArea.getTargetRect().size }; } - availableSize -= mLayoutGap * ((halnf) mChildren.size() - 1) + mLayoutMargin * 2; +RectF Widget::getRelativeAreaCache() const { return { {}, mAreaCache.size }; } - auto diff = availableSize - contentSize; - - // expand or contract as much as possible - while (!contributors.empty() && (diff[vertical] != 0)) { - auto quota = diff / (halnf) contributors.size(); - - for (auto& contributor : contributors) { - if (!contributor.second) continue; - - // contributor.first->endAnimations(); - auto contribution = changeChildSize(contributor.first, quota[vertical], vertical); - - if (contribution == 0) { - contributor.second = false; - } - - diff[vertical] -= contribution; - } - - contributors.erase( - std::remove_if(contributors.begin(), contributors.end(), [](auto node) { return !node.second; }), - contributors.end() - ); - } - - // arrange - halnf iterPos = mLayoutMargin; - for (auto child : mChildren) { - auto area = child->getAreaCache(); - area.pos[vertical] = iterPos; - iterPos += area.size[vertical] + mLayoutGap; - child->setAreaCache(area); - - - // child->updateAnimations(); - // child->triggerWidgetUpdate("layout changed"); - } -} - -RangeF Widget::pickRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical) { - RangeF out; - - switch (mSizePolicy[vertical]) { - case SizePolicy::Fixed: out = current; break; - case SizePolicy::Expanding: out = parent; break; - case SizePolicy::Minimal: out = children; break; - } - - out = clampRange(out, children, parent, vertical); - return out; -} - -void Widget::clampMinMaxSize() { - auto current = getAreaCache(); - current.size.clamp(mMinSize, mMaxSize); - setAreaCache(current); -} - -RangeF Widget::clampRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical) { - auto out = current; - - if (!mChildren.empty()) { - auto clampedChild = children; - clampedChild.clamp(parent); - out.clamp(clampedChild, parent); - } else { - out.clamp(parent); - } - - // clamp min max sizes - auto len = clamp(current.size(), mMinSize[vertical], mMaxSize[vertical]); - if (len != current.size()) { - out.resizeFromCenter(len); - } - - return out; -} - -RectF Widget::getChildrenEnclosure() const { - RectF out; - - if (mChildren.empty()) { - out = { getAreaCache().center(), { 0, 0 } }; - } else { - out = mChildren.front()->getAreaCache(); - for (auto child : mChildren) { - out.expand(child->getAreaCache()); - } - out.pos += getAreaCache().pos; - } - - return out; -} - -RectF Widget::getParentEnclosure() { - DEBUG_ASSERT(mParent); - if (!mParent) return { { 0, 0 }, mMaxSize }; - - auto out = mParent->getRelativeAreaT(); - if (mParent->mLayoutPolicy != LayoutPolicy::Passive) { - return out.scaleFromCenter(mParent->mLayoutMargin, true); - } - return out; -} +void Widget::setDebug(const char* name, RGBA col) { + mDebug.id = name; + mDebug.col = col; +} \ No newline at end of file diff --git a/WidgetsNew/public/LayoutPolicies.hpp b/WidgetsNew/public/LayoutPolicies.hpp index 4a66a57..14d9939 100644 --- a/WidgetsNew/public/LayoutPolicies.hpp +++ b/WidgetsNew/public/LayoutPolicies.hpp @@ -1,6 +1,7 @@ #pragma once #include "Rect.hpp" +#include namespace tp { class Widget; @@ -20,26 +21,17 @@ namespace tp { class WidgetLayout { public: explicit WidgetLayout(Widget* widget) { mWidget = widget; } + virtual ~WidgetLayout() = default; - virtual void adjustWidget() = 0; - - virtual void pickRect(); - virtual void clampRect(); - virtual void adjustChildrenRect(); - void adjustLayout(bool vertical); - halnf changeChildSize(Widget*, halnf diff, bool vertical); - - RangeF pickRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical); - RangeF clampRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical); - - void clampMinMaxSize(); - - RectF getChildrenEnclosure(); - RectF getParentEnclosure(); + virtual void pickRect() = 0; + virtual void clampRect() = 0; + virtual void adjustChildrenRect() = 0; protected: - const RectF& getArea(); + [[nodiscard]] const RectF& getArea() const; void setArea(const RectF& area); + [[nodiscard]] Widget* parent() const; + [[nodiscard]] const std::vector& children() const; private: Widget* mWidget = nullptr; @@ -47,12 +39,27 @@ namespace tp { class BasicLayout : public WidgetLayout { public: - BasicLayout() = default; + explicit BasicLayout(Widget* widget) : WidgetLayout(widget) {} - void adjustWidget() override; + void pickRect() override; + void clampRect() override; + void adjustChildrenRect() override; + + public: + const Vec2F& getMinSize(); + void setMinSize(const Vec2F& size); private: + void adjustLayout(bool vertical); + static halnf changeChildSize(Widget*, halnf diff, bool vertical); + [[nodiscard]] RangeF pickRange(const RangeF& current, const RangeF& child, const RangeF& parent, bool v) const; + [[nodiscard]] RangeF clampRange(const RangeF& current, const RangeF& child, const RangeF& parent, bool v) const; + + void clampMinMaxSize(); + + [[nodiscard]] RectF getChildrenEnclosure() const; + [[nodiscard]] RectF getParentEnclosure() const; private: LayoutPolicy mLayoutPolicy = LayoutPolicy::Vertical; diff --git a/WidgetsNew/public/Widget.hpp b/WidgetsNew/public/Widget.hpp index 07a1b60..db6c85a 100644 --- a/WidgetsNew/public/Widget.hpp +++ b/WidgetsNew/public/Widget.hpp @@ -10,66 +10,42 @@ namespace tp { class WidgetManagerInterface; + class WidgetLayout; class Widget { friend class RootWidget; public: Widget(); - virtual ~Widget() = default; - - void setDebug(const char* name, RGBA col) { - mName = name; - mDebugColor = col; - } + virtual ~Widget(); void addChild(Widget* child); void removeChild(Widget* child); - WidgetManagerInterface* getRoot(); - - void triggerWidgetUpdate(const char* reason = nullptr); - void bringToFront(); void bringToBack(); - void setSizePolicy(SizePolicy x, SizePolicy y); - void setLayoutPolicy(LayoutPolicy layoutPolicy); + void setLayout(WidgetLayout* layout); + WidgetLayout* getLayout(); - const Vec2F& getMinSize(); - void setMinSize(const Vec2F& size); - - public: + protected: virtual void process(const EventHandler& events) {} virtual void draw(Canvas& canvas) {} virtual void drawOverlay(Canvas& canvas) {} + virtual void endAnimations(); + virtual void updateAnimations(); + + [[nodiscard]] virtual bool processesEvents() const; + [[nodiscard]] virtual bool propagateEventsToChildren() const; + [[nodiscard]] virtual bool needsNextFrame() const; virtual void mouseEnter(); virtual void mouseLeave(); - // size policies - virtual void pickRect(); - virtual void clampRect(); - virtual void adjustChildrenRect(); - - // resizing - RangeF pickRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical); - RangeF clampRange(const RangeF& current, const RangeF& children, const RangeF& parent, bool vertical); - - void clampMinMaxSize(); - - RectF getChildrenEnclosure() const; - RectF getParentEnclosure(); - void adjustLayout(bool vertical); - halnf changeChildSize(Widget*, halnf diff, bool vertical); - - [[nodiscard]] virtual bool processesEvents() const; - [[nodiscard]] virtual bool propagateEventsToChildren() const; - - [[nodiscard]] virtual bool needsNextFrame() const; - - virtual void endAnimations(); - virtual void updateAnimations(); + protected: + void setDebug(const char* name, RGBA col); + WidgetManagerInterface* getRoot(); + void triggerWidgetUpdate(const char* reason = nullptr); public: [[nodiscard]] RectF getArea() const; @@ -84,7 +60,7 @@ namespace tp { void setAreaCache(const RectF& area); protected: - friend class WidgetLayout; + friend WidgetLayout; Widget* mParent = nullptr; @@ -93,30 +69,23 @@ namespace tp { // relative to the parent SpringRect mArea; + RectF mAreaCache; - // resizing - LayoutPolicy mLayoutPolicy = LayoutPolicy::Passive; - Vec2 mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed }; - Vec2F mMinSize = { 50, 50 }; - Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 }; + WidgetLayout* mLayout = nullptr; bool mInFocus = false; - halnf mLayoutGap = 5; - halnf mLayoutMargin = 10; - - // cache - RectF mAreaCache; - // debug - std::string mName = "widget base"; - Vec2F mLocalPoint; - Vec2F mGlobalPoint; - RGBA mDebugColor = { 1, 1, 1, 0.3 }; - std::string mTriggerReason = "none"; + struct { + std::string id = "widget base"; + RGBA col = { 1, 1, 1, 0.3 }; + std::string triggerReason = "none"; + Vec2F pLocal; + Vec2F pGlobal; + } mDebug; }; struct WidgetManagerInterface : public Widget { - virtual void updateWidget(Widget*, const char* reason = nullptr) = 0; + virtual void updateWidget(Widget*, const char* reason) = 0; }; } \ No newline at end of file