From 03b2b5d03821bd252b93c8aa10f85ab961e6e25f Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Thu, 17 Oct 2024 15:10:58 +0300 Subject: [PATCH] Focus locking and popups --- WidgetsNew/examples/Example.cpp | 208 +++++++++--------- WidgetsNew/private/RootWidget.cpp | 72 ++++-- WidgetsNew/private/Widget.cpp | 29 ++- WidgetsNew/private/layouts/OverlayLayout.cpp | 29 +++ WidgetsNew/private/managers/DebugManager.cpp | 16 +- WidgetsNew/private/managers/UpdateManager.cpp | 27 ++- WidgetsNew/private/widgets/DockWidget.cpp | 2 +- WidgetsNew/private/widgets/FloatingWidget.cpp | 8 + WidgetsNew/public/RootWidget.hpp | 12 +- WidgetsNew/public/Widget.hpp | 13 ++ WidgetsNew/public/layouts/OverlayLayout.hpp | 18 ++ WidgetsNew/public/mangers/UpdateManager.hpp | 5 + WidgetsNew/public/widgets/FloatingWidget.hpp | 2 +- 13 files changed, 296 insertions(+), 145 deletions(-) create mode 100644 WidgetsNew/private/layouts/OverlayLayout.cpp create mode 100644 WidgetsNew/public/layouts/OverlayLayout.hpp diff --git a/WidgetsNew/examples/Example.cpp b/WidgetsNew/examples/Example.cpp index a3661f5..58422f7 100644 --- a/WidgetsNew/examples/Example.cpp +++ b/WidgetsNew/examples/Example.cpp @@ -21,119 +21,143 @@ using namespace tp; class WidgetApplication : public Application { public: WidgetApplication() { - setup1(); + exampleNestedMenus(); + // examplePopup(); } - void setupLay() { - mRootWidget.setRootWidget(&mWidget); + void examplePopup() { + static Widget root; + static ButtonWidget closeButton; + static ButtonWidget openButton; - mWidget.addChild(&mWidgets[1]); + root.addChild(&openButton); + ((BasicLayout*)root.getLayout())->setLayoutPolicy(LayoutPolicy::Passive); - mWidgets[1].addChild(&mButtons[1]); - mWidgets[1].addChild(&mButtons[2]); - mWidgets[1].addChild(&mWidgets[2]); + openButton.setAction([&](){ + closeButton.setArea({ 50, 50, 100, 100 }); + openButton.openPopup(&closeButton); + }); - RootWidget::setWidgetArea(mWidgets[1], { 300, 100, 350, 800 }); - RootWidget::setWidgetArea(mButtons[2], { 100, 100, 150, 300 }); + closeButton.setAction([&](){ + closeButton.closePopup(&closeButton); + }); - mWidgets[2].addChild(&mButtons[3]); - mWidgets[2].addChild(&mButtons[4]); - mWidgets[2].addChild(&mButtons[5]); - mWidgets[2].addChild(&mButtons[6]); + openButton.setText("open"); + closeButton.setText("close"); - mButtons[1].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - mButtons[2].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - mButtons[3].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - mButtons[4].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - mButtons[5].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - mButtons[6].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + RootWidget::setWidgetArea(openButton, { 333, 333, 222, 222 }); - mWidgets[2].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - ((BasicLayout*)mWidgets[1].getLayout())->setLayoutPolicy(LayoutPolicy::Horizontal); + mRootWidget.setRootWidget(&root); + } + + void exampleNestedMenus() { + static DockWidget dock; + static FloatingMenu menu1; + static FloatingMenu menu2; + static ButtonWidget buttons[15]; + + mRootWidget.setRootWidget(&dock); + + dock.addChild(&menu1); + dock.addChild(&menu2); + + dock.setCenterWidget(&buttons[5]); + dock.dockWidget(&buttons[6], DockLayout::RIGHT); + + menu1.addToMenu(&buttons[0]); + + menu2.addToMenu(&buttons[2]); + menu2.addToMenu(&buttons[3]); + menu2.addToMenu(&buttons[4]); + + menu2.addToMenu(&menu1); + + RootWidget::setWidgetArea(menu1, { 300, 100, 150, 500 }); + RootWidget::setWidgetArea(menu2, { 100, 100, 150, 300 }); + } + + void exampleLayouts() { + static Widget widgets[15]; + static ButtonWidget buttons[15]; + + mRootWidget.setRootWidget(&widgets[0]); + + widgets[0].addChild(&widgets[1]); + + widgets[1].addChild(&buttons[1]); + widgets[1].addChild(&buttons[2]); + widgets[1].addChild(&widgets[2]); + + RootWidget::setWidgetArea(buttons[1], { 300, 100, 350, 800 }); + RootWidget::setWidgetArea(buttons[2], { 100, 100, 150, 300 }); + + widgets[2].addChild(&buttons[3]); + widgets[2].addChild(&buttons[4]); + widgets[2].addChild(&buttons[5]); + widgets[2].addChild(&buttons[6]); + + buttons[1].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + buttons[2].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + buttons[3].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + buttons[4].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + buttons[5].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + buttons[6].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + + widgets[2].setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); + ((BasicLayout*)widgets[1].getLayout())->setLayoutPolicy(LayoutPolicy::Horizontal); } void setup1() { - mRootWidget.setRootWidget(&mDockLayout); + static DockWidget dock; + static FloatingMenu menu1; + static FloatingMenu menu2; + static ButtonWidget buttons[15]; + + mRootWidget.setRootWidget(&dock); - mDockLayout.addChild(&mFloatingMenu2); - mDockLayout.addChild(&mFloatingMenu); + dock.addChild(&menu2); + dock.addChild(&menu1); - mDockLayout.setCenterWidget(&mButton5); - mDockLayout.dockWidget(&mButton6, DockLayout::RIGHT); + dock.setCenterWidget(&buttons[5]); + dock.dockWidget(&buttons[6], DockLayout::RIGHT); - mFloatingMenu.addToMenu(&mButton); - mFloatingMenu2.addToMenu(&mButton2); - //mFloatingMenu2.addToMenu(&mFloatingMenu); - mFloatingMenu2.addToMenu(&mButton3); - mFloatingMenu2.addToMenu(&mButton4); + menu1.addToMenu(&buttons[0]); + menu2.addToMenu(&buttons[2]); + //menu2.addToMenu(&menu1); + menu2.addToMenu(&buttons[3]); + menu2.addToMenu(&buttons[4]); - mButton.setAction([this]() { mButton2.setColor(RGBA::random()); }); - mButton2.setAction([this]() { mButton.setColor(RGBA::random()); }); + buttons[0].setAction([&]() { buttons[2].setColor(RGBA::random()); }); + buttons[2].setAction([&]() { buttons[0].setColor(RGBA::random()); }); - mButton5.setAction([this]() { mDockLayout.dockWidget(&mFloatingMenu, DockLayout::LEFT); }); - mButton6.setAction([this]() { mDockLayout.undockWidget(DockLayout::LEFT); }); + buttons[5].setAction([&]() { dock.dockWidget(&menu1, DockLayout::LEFT); }); + buttons[6].setAction([&]() { dock.undockWidget(DockLayout::LEFT); }); - mButton3.setAction([this]() { mDockLayout.toggleWidgetVisibility(DockLayout::LEFT); }); - // mButton4.setAction([this]() { mDockLayout.undockWidget(DockLayout::LEFT); }); + buttons[3].setAction([&]() { dock.toggleWidgetVisibility(DockLayout::LEFT); }); + // buttons[4].setAction([this]() { mDockLayout.undockWidget(DockLayout::LEFT); }); - mButton3.setText("toggle"); - mButton5.setText("dock"); - mButton6.setText("undock"); + buttons[3].setText("toggle"); + buttons[5].setText("dock"); + buttons[6].setText("undock"); - // mLayoutWidget.addChild(&mButton2); + // mLayoutWidget.addChild(&buttons[2]); - // mWidgetFloating.addChild(&mButton); + // mWidgetFloating.addChild(&buttons[0]); // mRootWidget.setRootWidget(&mAnimationTestWidget); // mAnimationTestWidget.addChild(&mWidgetFloating); // mAnimationTestWidget.addChild(&mLayoutWidget); - RootWidget::setWidgetArea(mFloatingMenu2, { 300, 100, 150, 500 }); - RootWidget::setWidgetArea(mFloatingMenu, { 100, 100, 150, 300 }); + RootWidget::setWidgetArea(menu2, { 300, 100, 150, 500 }); + RootWidget::setWidgetArea(menu1, { 100, 100, 150, 300 }); // mWidgetFloating.addChild(&mLayoutWidget); - // mLayoutWidget.addChild(&mButton); + // mLayoutWidget.addChild(&buttons[0]); // mLayoutWidget.addChild(&mLabel); } - void setup3() { - mRootWidget.setRootWidget(&mWidget); - mWidget.addChild(&mFloatingWidget); - - mFloatingWidget.addChild(&mButton); - mFloatingWidget.addChild(&mButton2); - mFloatingWidget.addChild(&mButton3); - - mButton.setSizePolicy(SizePolicy::Minimal, SizePolicy::Expanding); - mButton2.setSizePolicy(SizePolicy::Minimal, SizePolicy::Expanding); - mButton3.setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding); - - RootWidget::setWidgetArea(mFloatingWidget, { 100, 100, 400, 400 }); - } - - void setup2() { - mRootWidget.setRootWidget(&mWidget); - // mDesktopLayout.addChild(&mWidget); - - mWidget.addChild(&mButton); - mWidget.addChild(&mButton2); - mWidget.addChild(&mButton3); - - mButton.setSizePolicy(SizePolicy::Expanding, SizePolicy::Minimal); - mButton2.setSizePolicy(SizePolicy::Expanding, SizePolicy::Minimal); - mButton3.setSizePolicy(SizePolicy::Expanding, SizePolicy::Minimal); - - mWidget.setSizePolicy(SizePolicy::Minimal, SizePolicy::Minimal); - // mWidget.setLayoutPolicy(LayoutPolicy::Horizontal); - - // mButton.setAction([this]() { mButton2.setMinSize(mButton2.getMinSize() + 10); }); - // mButton2.setAction([this]() { mButton.setMinSize(mButton.getMinSize() + 10); } ); - - RootWidget::setWidgetArea(mWidget, { 400, 100, 150, 200 }); - } - void processFrame(EventHandler* eventHandler, halnf deltaTime) override { const auto rec = RectF({ 0, 0 }, mWindow->getSize()); mRootWidget.processFrame(eventHandler, rec); @@ -150,28 +174,6 @@ public: } private: - Widget mWidgets[15]; - ButtonWidget mButtons[15]; - - Widget mWidget; - - ButtonWidget mButton; - ButtonWidget mButton2; - ButtonWidget mButton3; - ButtonWidget mButton4; - ButtonWidget mButton5; - ButtonWidget mButton6; - - FloatingWidget mFloatingWidget; - FloatingMenu mFloatingMenu; - FloatingMenu mFloatingMenu2; - - LabelWidget mLabel; - FloatingWidget mWidgetFloating; - AnimationTestWidget mAnimationTestWidget; - - DockWidget mDockLayout; - RootWidget mRootWidget; }; diff --git a/WidgetsNew/private/RootWidget.cpp b/WidgetsNew/private/RootWidget.cpp index 9178e95..bdb232c 100644 --- a/WidgetsNew/private/RootWidget.cpp +++ b/WidgetsNew/private/RootWidget.cpp @@ -1,7 +1,8 @@ #include "RootWidget.hpp" -#include "BasicLayout.hpp" +#include "BasicLayout.hpp" +#include "OverlayLayout.hpp" #include @@ -13,36 +14,47 @@ WidgetLayout* WidgetManagerInterface::defaultLayout(Widget* widget) { RootWidget::RootWidget() { setDebug("root", RGBA(1)); + + addChild(&mRoot); + + mRoot.addChild(&mPopups); + mRoot.setLayout(new OverlayLayout(&mRoot)); + + dynamic_cast(mPopups.getLayout())->setLayoutPolicy(LayoutPolicy::Passive); } void RootWidget::setRootWidget(Widget* widget) { - mRoot = widget; - widget->mParent = this; + mRoot.removeChild(mUserRoot); + mRoot.addChild(widget); + + widget->bringToBack(); + + mUserRoot = widget; } void RootWidget::processFrame(EventHandler* events, const RectF& screenArea) { - mRoot->setArea(screenArea); + mRoot.setArea(screenArea); if (!gDebugWidget.update(this, *events)) return; // construct hierarchy tree of widgets to process - mUpdateManager.updateTreeToProcess(mRoot); + mUpdateManager.updateTreeToProcess(&mRoot); updateAnimations(); - updateAreaCache(mRoot, true); + updateAreaCache(&mRoot, true); // update all events and call all event processing callbacks - mUpdateManager.processWidgets(mRoot, *events); + mUpdateManager.processWidgets(&mRoot, *events); - updateAreaCache(mRoot, true); + updateAreaCache(&mRoot, true); // update widget sizes base on individual size policies - mLayoutManager.adjust(mRoot); + mLayoutManager.adjust(&mRoot); - updateAreaCache(mRoot, false); + updateAreaCache(&mRoot, false); // trigger some widgets by moise pointer - mUpdateManager.handleFocusChanges(mRoot, *events); + mUpdateManager.handleFocusChanges(&mRoot, *events); // check triggered widgets for removal mUpdateManager.clean(); @@ -54,9 +66,9 @@ bool RootWidget::needsUpdate() const { } void RootWidget::drawFrame(Canvas& canvas) { - canvas.rect(mRoot->getAreaT(), RGBA(0, 0, 0, 1)); + canvas.rect(mRoot.getAreaT(), RGBA(0, 0, 0, 1)); - drawRecursion(canvas, mRoot, { 0, 0 }); + drawRecursion(canvas, &mRoot, { 0, 0 }); gDebugWidget.drawDebug(this, canvas); } @@ -86,17 +98,11 @@ void RootWidget::setWidgetArea(Widget& widget, const RectF& rect) { } void RootWidget::updateAnimations() { - dfs(mRoot, [](Widget* widget) { + dfs(&mRoot, [](Widget* widget) { widget->updateAnimations(); }); } - -void RootWidget::updateWidget(Widget* widget, const char* reason) { - DEBUG_ASSERT(reason) - mUpdateManager.scheduleUpdate(widget, reason); -} - void RootWidget::updateAreaCache(Widget* iter, bool read) { if (!iter || !iter->isUpdate()) return; @@ -119,4 +125,28 @@ void RootWidget::updateAreaCache(Widget* iter, bool read) { for (auto child : iter->mDepthOrder) { updateAreaCache(child.data(), read); } -} \ No newline at end of file +} + +void RootWidget::updateWidget(Widget* widget, const char* reason) { + DEBUG_ASSERT(reason) + mUpdateManager.scheduleUpdate(widget, reason); +} + +void RootWidget::openPopup(Widget* widget) { + auto relativeArea = widget->getAreaT(); + for (auto iter = widget->mParent; iter && iter->mParent; iter = iter->mParent) { + relativeArea.pos += iter->getAreaT().pos; + } + setWidgetArea(*widget, relativeArea); + + mPopups.addChild(widget); + mUpdateManager.lockFocus(widget); +} + +void RootWidget::closePopup(Widget* widget) { + mPopups.removeChild(widget); + mUpdateManager.freeFocus(widget); +} + +void RootWidget::lockFocus(Widget* widget) { mUpdateManager.lockFocus(widget); } +void RootWidget::freeFocus(Widget* widget) { mUpdateManager.freeFocus(widget); } diff --git a/WidgetsNew/private/Widget.cpp b/WidgetsNew/private/Widget.cpp index 7a15368..5f74899 100644 --- a/WidgetsNew/private/Widget.cpp +++ b/WidgetsNew/private/Widget.cpp @@ -97,12 +97,6 @@ WidgetManagerInterface* Widget::getRoot() { return dynamic_cast(iter); } -void Widget::triggerWidgetUpdate(const char* reason) { - if (auto root = getRoot()) { - root->updateWidget(this, reason); - } -} - void Widget::setAreaCache(const tp::RectF& area) { mAreaCache = area; } void Widget::setArea(const RectF& area) { @@ -128,3 +122,26 @@ void Widget::setDebug(const char* name, RGBA col) { void Widget::setSizePolicy(SizePolicy x, SizePolicy y) { getLayout()->setSizePolicy(x, y); } + +void Widget::triggerWidgetUpdate(const char* reason) { + if (auto root = getRoot()) { + root->updateWidget(this, reason); + } +} + +void Widget::openPopup(Widget* widget) { + addChild(widget); + getRoot()->openPopup(widget); +} + +void Widget::closePopup(Widget* widget) { + getRoot()->closePopup(widget); +} + +void Widget::lockFocus() { + getRoot()->lockFocus(this); +} + +void Widget::freeFocus() { + getRoot()->freeFocus(this); +} \ No newline at end of file diff --git a/WidgetsNew/private/layouts/OverlayLayout.cpp b/WidgetsNew/private/layouts/OverlayLayout.cpp new file mode 100644 index 0000000..e30ce16 --- /dev/null +++ b/WidgetsNew/private/layouts/OverlayLayout.cpp @@ -0,0 +1,29 @@ + +#include "OverlayLayout.hpp" +#include "Widget.hpp" + + +using namespace tp; + +void OverlayLayout::updateLayout(bool vertical) { + if (vertical) return; + + if (children().empty()) return; + + for (auto child : children()) { + child->getLayout()->setArea(getArea().relative()); + } + + /* +if (children().empty()) return; + +auto first = children().front(); + +first->getLayout()->setArea(getArea().relative()); + +for (auto child : children()) { + if (child == first) continue; + child->getLayout()->setArea(getArea().relative()); +} + */ +} \ No newline at end of file diff --git a/WidgetsNew/private/managers/DebugManager.cpp b/WidgetsNew/private/managers/DebugManager.cpp index de77067..66ddc18 100644 --- a/WidgetsNew/private/managers/DebugManager.cpp +++ b/WidgetsNew/private/managers/DebugManager.cpp @@ -15,9 +15,9 @@ bool DebugManager::update(RootWidget* rootWidget, EventHandler& events) { mRootWidget = rootWidget; if (mDebug) { - auto area = rootWidget->mRoot->getAreaT(); + auto area = rootWidget->mRoot.getAreaT(); area.size -= { 400, 0 }; - rootWidget->mRoot->setArea(area); + rootWidget->mRoot.setArea(area); events.setEnableKeyEvents(true); if (events.isPressed(InputID::K)) mDebugStopProcessing = !mDebugStopProcessing; @@ -63,7 +63,7 @@ void DebugManager::drawDebug(RootWidget* rootWidget, Canvas& canvas) { auto& upd = rootWidget->mUpdateManager; - recursiveDraw(canvas, rootWidget->mRoot, { 0, 0 }, 0); + recursiveDraw(canvas, &rootWidget->mRoot, { 0, 0 }, 0); ImGui::Text("Triggered: %i", (int) upd.mTriggeredWidgets.size()); ImGui::SameLine(); ImGui::Text("Processing: %i", upd.mDebugWidgetsToProcess); @@ -140,10 +140,9 @@ void DebugManager::widgetMenu(Widget* widget) { ImGui::InputFloat2("min size", &layout->mMinSize.x); ImGui::InputFloat2("max size", &layout->mMaxSize.x); - if (auto pBasicLayout = dynamic_cast(widget->getLayout())) { - int sizePolicyX = int(pBasicLayout->mSizePolicy.x); - int sizePolicyY = int(pBasicLayout->mSizePolicy.y); - int policy = int(pBasicLayout->mLayoutPolicy); + { + int sizePolicyX = int(widget->getLayout()->getSizePolicy().x); + int sizePolicyY = int(widget->getLayout()->getSizePolicy().y); if (ImGui::Combo("Size Policy X", &sizePolicyX, "Fixed\0Expanding\0Minimal\0")) { widget->setSizePolicy(SizePolicy(sizePolicyX), SizePolicy(sizePolicyY)); @@ -152,7 +151,10 @@ void DebugManager::widgetMenu(Widget* widget) { if (ImGui::Combo("Size Policy Y", &sizePolicyY, "Fixed\0Expanding\0Minimal\0")) { widget->setSizePolicy(SizePolicy(sizePolicyX), SizePolicy(sizePolicyY)); } + } + if (auto pBasicLayout = dynamic_cast(widget->getLayout())) { + int policy = int(pBasicLayout->mLayoutPolicy); if (ImGui::Combo("Layout", &policy, "Passive\0Vertical\0Horizontal\0")) { pBasicLayout->mLayoutPolicy = LayoutPolicy(policy); } diff --git a/WidgetsNew/private/managers/UpdateManager.cpp b/WidgetsNew/private/managers/UpdateManager.cpp index b03bb76..6b38ac2 100644 --- a/WidgetsNew/private/managers/UpdateManager.cpp +++ b/WidgetsNew/private/managers/UpdateManager.cpp @@ -74,11 +74,19 @@ void UpdateManager::handleFocusChanges(Widget* root, EventHandler& events) { events.setCursorOrigin({ 0, 0 }); - findFocusWidget(root, &mInFocusWidget, events.getPointer()); + mInFocusWidget = nullptr; + + if (!mFocusLockWidget) { + findFocusWidget(root, &mInFocusWidget, events.getPointer()); + } else { + mInFocusWidget = mFocusLockWidget; + } // if (mInFocusWidget == prevFocus) return; if (mInFocusWidget) scheduleUpdate(mInFocusWidget, "focus entered"); + if (!mInFocusWidget && !prevFocus) return; + std::vector path2; getWidgetPath(mInFocusWidget, path2); size_t propLen2 = path2.size(); @@ -99,7 +107,7 @@ void UpdateManager::handleFocusChanges(Widget* root, EventHandler& events) { } } - size_t mostCommonIdx = 0; + int mostCommonIdx = 0; if (!(path1.empty() || path2.empty())) { while (path1[mostCommonIdx] == path2[mostCommonIdx] && mostCommonIdx < min(path1.size(), path2.size())) { mostCommonIdx++; @@ -121,7 +129,9 @@ void UpdateManager::handleFocusChanges(Widget* root, EventHandler& events) { void UpdateManager::findFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer) { if (!iter->mArea.getTargetRect().isInside(pointer) || !iter->mFlags.get(Widget::ENABLED)) return; - *focus = iter; + if (iter->processesEvents()) { + *focus = iter; + } for (auto child = iter->mDepthOrder.lastNode(); child; child = child->prev) { findFocusWidget(child->data, focus, pointer - iter->mArea.getTargetRect().pos); @@ -148,8 +158,6 @@ void UpdateManager::processActiveTree(Widget* iter, EventHandler& events, Vec2F void UpdateManager::processFocusItems(EventHandler& events) { if (!mInFocusWidget) return; - // FIXME : cringe - std::vector path; getWidgetPath(mInFocusWidget, path); @@ -191,4 +199,13 @@ void UpdateManager::procWidget(Widget* widget, EventHandler& events, bool withEv events.setEnableKeyEvents(withEvents); gDebugWidget.checkProcBreakPoints(widget); widget->process(events); +} + +void UpdateManager::lockFocus(tp::Widget* widget) { + mFocusLockWidget = widget; +} + +void UpdateManager::freeFocus(tp::Widget* widget) { + DEBUG_ASSERT(mFocusLockWidget == widget) + mFocusLockWidget = nullptr; } \ No newline at end of file diff --git a/WidgetsNew/private/widgets/DockWidget.cpp b/WidgetsNew/private/widgets/DockWidget.cpp index 1d9c0a6..565d087 100644 --- a/WidgetsNew/private/widgets/DockWidget.cpp +++ b/WidgetsNew/private/widgets/DockWidget.cpp @@ -4,7 +4,7 @@ using namespace tp; DockWidget::DockWidget() : Widget() { - setDebug("dock", {}); + setDebug("dock", { 1, 1, 1, 1 }); setLayout(new DockLayout(this)); } diff --git a/WidgetsNew/private/widgets/FloatingWidget.cpp b/WidgetsNew/private/widgets/FloatingWidget.cpp index cb88bac..4687ab7 100644 --- a/WidgetsNew/private/widgets/FloatingWidget.cpp +++ b/WidgetsNew/private/widgets/FloatingWidget.cpp @@ -7,11 +7,14 @@ void FloatingWidget::process(const EventHandler& events) { if (getRelativeAreaT().isInside(pointer) && events.isPressed(InputID::MOUSE1)) { layout()->startAction(pointer); + bringToFront(); + lockFocus(); } if (layout()->isFloating() && events.isReleased(InputID::MOUSE1)) { layout()->endAction(); + freeFocus(); } layout()->updateAction(pointer); @@ -22,6 +25,10 @@ void FloatingWidget::draw(Canvas& canvas) { canvas.rect(getRelativeArea(), RGBA(0.5f), 10); } +bool FloatingWidget::processesEvents() const { + return true; +} + bool FloatingWidget::propagateEventsToChildren() const { return !layout()->isFloating(); } @@ -39,3 +46,4 @@ FloatingLayout* FloatingWidget::layout() { return dynamic_cast( const FloatingLayout* FloatingWidget::layout() const { return dynamic_cast(Widget::getLayout()); } + diff --git a/WidgetsNew/public/RootWidget.hpp b/WidgetsNew/public/RootWidget.hpp index c2375f4..d66b1b0 100644 --- a/WidgetsNew/public/RootWidget.hpp +++ b/WidgetsNew/public/RootWidget.hpp @@ -29,11 +29,21 @@ namespace tp { void drawRecursion(Canvas& canvas, Widget* active, const Vec2F& pos); void updateWidget(Widget*, const char* reason = nullptr) override; + + void openPopup(Widget*) override; + void closePopup(Widget*) override; + + void lockFocus(Widget*) override; + void freeFocus(Widget*) override; + void updateAnimations(); void updateAreaCache(Widget* iter, bool read); private: - Widget* mRoot = nullptr; + Widget mRoot; + Widget mPopups; + + Widget* mUserRoot = nullptr; LayoutManager mLayoutManager; UpdateManager mUpdateManager; diff --git a/WidgetsNew/public/Widget.hpp b/WidgetsNew/public/Widget.hpp index a0b2cc1..1cf44f9 100644 --- a/WidgetsNew/public/Widget.hpp +++ b/WidgetsNew/public/Widget.hpp @@ -58,6 +58,12 @@ namespace tp { void triggerWidgetUpdate(const char* reason = nullptr); + void openPopup(Widget*); + void closePopup(Widget*); + + void lockFocus(); + void freeFocus(); + protected: virtual void process(const EventHandler& events) {} virtual void draw(Canvas& canvas) {} @@ -130,6 +136,13 @@ namespace tp { struct WidgetManagerInterface : public Widget { virtual void updateWidget(Widget*, const char* reason) = 0; + + virtual void openPopup(Widget*) = 0; + virtual void closePopup(Widget*) = 0; + + virtual void lockFocus(Widget*) = 0; + virtual void freeFocus(Widget*) = 0; + static WidgetLayout* defaultLayout(Widget* widget); }; } \ No newline at end of file diff --git a/WidgetsNew/public/layouts/OverlayLayout.hpp b/WidgetsNew/public/layouts/OverlayLayout.hpp new file mode 100644 index 0000000..e674327 --- /dev/null +++ b/WidgetsNew/public/layouts/OverlayLayout.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Layout.hpp" + +namespace tp { + + class OverlayLayout : public WidgetLayout { + friend class DebugManager; + + public: + explicit OverlayLayout(Widget* widget) : WidgetLayout(widget) {} + + void updateLayout(bool vertical) override; + + void pickRect(bool vertical) override {} + void clampRect() override {} + }; +} \ No newline at end of file diff --git a/WidgetsNew/public/mangers/UpdateManager.hpp b/WidgetsNew/public/mangers/UpdateManager.hpp index 5a52038..33c5ecf 100644 --- a/WidgetsNew/public/mangers/UpdateManager.hpp +++ b/WidgetsNew/public/mangers/UpdateManager.hpp @@ -5,6 +5,7 @@ #include namespace tp { + // FIXME : desperately needs refactor class UpdateManager { friend DebugManager; @@ -13,6 +14,9 @@ namespace tp { void scheduleUpdate(Widget* widget, const char* reason); + void lockFocus(Widget* widget); + void freeFocus(Widget* widget); + [[nodiscard]] bool isPendingUpdates() const { return !mTriggeredWidgets.empty(); } @@ -34,6 +38,7 @@ namespace tp { private: std::map mTriggeredWidgets; Widget* mInFocusWidget = nullptr; + Widget* mFocusLockWidget = nullptr; private: int mDebugWidgetsToProcess = 0; diff --git a/WidgetsNew/public/widgets/FloatingWidget.hpp b/WidgetsNew/public/widgets/FloatingWidget.hpp index decba02..c32dd2e 100644 --- a/WidgetsNew/public/widgets/FloatingWidget.hpp +++ b/WidgetsNew/public/widgets/FloatingWidget.hpp @@ -19,7 +19,7 @@ namespace tp { [[nodiscard]] bool needsNextFrame() const override; [[nodiscard]] bool propagateEventsToChildren() const override; - [[nodiscard]] bool processesEvents() const override { return true; } + [[nodiscard]] bool processesEvents() const override; [[nodiscard]] bool isFloating() const;