Refactor done
This commit is contained in:
parent
3e37f0cd3d
commit
1508a51cde
25 changed files with 797 additions and 610 deletions
108
WidgetsNew/public/DockLayout.hpp
Normal file
108
WidgetsNew/public/DockLayout.hpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#include "Widget.hpp"
|
||||
|
||||
namespace tp {
|
||||
class DockLayout : public WidgetLayout {
|
||||
public:
|
||||
enum Side { LEFT, TOP, RIGHT, BOTTOM, NONE };
|
||||
|
||||
private:
|
||||
struct ResizeHandle {
|
||||
RectF area{ 0, 0, 0, 0 };
|
||||
halnf start{ 0 };
|
||||
halnf end{ 0 };
|
||||
bool active = false;
|
||||
bool hover = false;
|
||||
};
|
||||
|
||||
struct SideWidgetData {
|
||||
Widget* widget = nullptr;
|
||||
bool hidden = false;
|
||||
halnf absoluteSize = 200;
|
||||
alni order = -1;
|
||||
|
||||
Side side = { TOP };
|
||||
|
||||
RectF area = {};
|
||||
RectF headerArea = {};
|
||||
RectF previewHandleArea = {};
|
||||
|
||||
ResizeHandle resizeHandle;
|
||||
|
||||
RectF areaBeforeDocking = {};
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DockLayout(Widget* widget);
|
||||
|
||||
void updateResizeHover(const Vec2F& pointer);
|
||||
bool startResize(const Vec2F& pointer);
|
||||
void updateResize(const Vec2F& pointerDelta);
|
||||
void endResize();
|
||||
|
||||
void updatePreviewSide(const Vec2F& pointer);
|
||||
|
||||
public:
|
||||
void pickRect() override {}
|
||||
void adjustChildrenRect() override;
|
||||
void clampRect() override {};
|
||||
|
||||
public:
|
||||
bool setCenterWidget(Widget* widget);
|
||||
|
||||
bool dockWidget(Widget* widget, Side side);
|
||||
bool undockWidget(Side side);
|
||||
void toggleWidgetVisibility(Side side);
|
||||
|
||||
public:
|
||||
[[nodiscard]] bool isSideVisible(Side side) const;
|
||||
[[nodiscard]] bool sideExists(Side side) const;
|
||||
|
||||
[[nodiscard]] bool isResizing() const { return mResizing; }
|
||||
[[nodiscard]] bool isResizing(Side side) const { return mSideWidgets[side].resizeHandle.active; }
|
||||
[[nodiscard]] bool isResizeHandleHover(Side side) const { return mSideWidgets[side].resizeHandle.hover; }
|
||||
|
||||
Side getSideFromWidget(Widget*);
|
||||
Side getPreviewSide();
|
||||
|
||||
[[nodiscard]] RectF getRectBeforeDocked(Side side) const { return mSideWidgets[side].areaBeforeDocking; }
|
||||
[[nodiscard]] RectF getResizeHandleArea(Side side) const { return mSideWidgets[side].resizeHandle.area; }
|
||||
[[nodiscard]] RectF getHeaderArea(Side side) const { return mSideWidgets[side].headerArea; }
|
||||
[[nodiscard]] RectF getPreviewHandleArea(Side side) const { return mSideWidgets[side].previewHandleArea; }
|
||||
[[nodiscard]] RectF getPreviewArea() const { return mPreviewArea; }
|
||||
|
||||
Widget* getSideWidget(Side side) { return mSideWidgets[side].widget; }
|
||||
|
||||
const std::vector<Widget*>& getDockedWidgets();
|
||||
|
||||
private:
|
||||
ualni getVisibleSidesSize();
|
||||
|
||||
void calculateSideAreas();
|
||||
void calculateResizeHandles();
|
||||
void updateChildSideWidgets();
|
||||
void calculateHeaderAreas();
|
||||
|
||||
private:
|
||||
RectF mPreviewArea = {};
|
||||
Side mPreviewSide = NONE;
|
||||
int resizeType[2] = { 0, 0 };
|
||||
|
||||
SideWidgetData mSideWidgets[4];
|
||||
|
||||
std::vector<Widget*> mDockedWidgets;
|
||||
|
||||
private:
|
||||
bool mResizing = false;
|
||||
|
||||
Widget* mCenterWidget = nullptr;
|
||||
RectF mCenterArea {};
|
||||
|
||||
// Parameters
|
||||
const halnf mHandleSplitFactor = 0.3;
|
||||
const halnf mHandleFactor = 0.1;
|
||||
|
||||
halnf mSideSizePadding = 150.f;
|
||||
halnf mPadding = 4;
|
||||
halnf mHeaderSize = 27;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
#include "Widget.hpp"
|
||||
|
||||
namespace tp {
|
||||
class DockLayoutWidget : public Widget {
|
||||
public:
|
||||
enum Side { LEFT, TOP, RIGHT, BOTTOM, NONE };
|
||||
|
||||
private:
|
||||
struct ResizeHandle {
|
||||
RectF area{ 0, 0, 0, 0 };
|
||||
halnf start{ 0 };
|
||||
halnf end{ 0 };
|
||||
bool active = false;
|
||||
bool hover = false;
|
||||
};
|
||||
|
||||
struct SideWidgetData {
|
||||
Widget* widget = nullptr;
|
||||
bool hidden = false;
|
||||
halnf absoluteSize = 200;
|
||||
alni order = -1;
|
||||
|
||||
Side side = { TOP };
|
||||
|
||||
RectF area = {};
|
||||
RectF headerArea = {};
|
||||
RectF previewHandleArea = {};
|
||||
|
||||
ResizeHandle resizeHandle;
|
||||
|
||||
RectF areaBeforeDocking = {};
|
||||
};
|
||||
|
||||
public:
|
||||
DockLayoutWidget();
|
||||
|
||||
public:
|
||||
void pickRect() override {}
|
||||
void adjustChildrenRect() override;
|
||||
|
||||
void process(const EventHandler& events) override;
|
||||
void draw(Canvas& canvas) override;
|
||||
void drawOverlay(Canvas& canvas) override;
|
||||
|
||||
[[nodiscard]] bool propagateEventsToChildren() const override;
|
||||
[[nodiscard]] bool needsNextFrame() const override;
|
||||
|
||||
public:
|
||||
void setCenterWidget(Widget* widget);
|
||||
|
||||
void dockWidget(Widget* widget, Side side);
|
||||
void undockWidget(Side side, bool restoreArea = true);
|
||||
void toggleWidgetVisibility(Side side);
|
||||
|
||||
private:
|
||||
Side getSideFromWidget(Widget*);
|
||||
void calculateSideAreas();
|
||||
void calculateResizeHandles();
|
||||
void handleResizeEvents(const EventHandler& events);
|
||||
void updateChildSideWidgets();
|
||||
|
||||
void calculateHeaderAreas();
|
||||
|
||||
bool isSideVisible(Side side);
|
||||
bool sideExists(DockLayoutWidget::Side side);
|
||||
ualni getVisibleSidesSize();
|
||||
void handlePreview(const EventHandler& events);
|
||||
|
||||
private:
|
||||
RectF mPreviewArea = {};
|
||||
Side mPreviewSide = NONE;
|
||||
int resizeType[2] = { 0, 0 };
|
||||
|
||||
SideWidgetData mSideWidgets[4];
|
||||
|
||||
private:
|
||||
bool mResizing = false;
|
||||
|
||||
Widget* mCenterWidget = nullptr;
|
||||
RectF mCenterArea {};
|
||||
|
||||
// Parameters
|
||||
halnf mSideSizePadding = 150.f;
|
||||
halnf mPadding = 4;
|
||||
halnf mHeaderSize = 27;
|
||||
halnf mRounding = 10;
|
||||
Vec2F mPreviewHandleSize = { 50, 50 };
|
||||
|
||||
RGBA mResizeHandleColorHovered = RGBA(0.3, 0.3, 0.3, 1);
|
||||
RGBA mResizeHandleColorActive = RGBA(0.6, 0.6, 0.6, 1);
|
||||
RGBA mBackgroundColor = RGBA(0, 0, 0, 1);
|
||||
RGBA mPreviewColor = RGBA(0.6, 0.6, 0.6, 0.2);
|
||||
|
||||
public:
|
||||
Widget* mPreviewWidget = nullptr;
|
||||
};
|
||||
}
|
||||
41
WidgetsNew/public/DockWidget.hpp
Normal file
41
WidgetsNew/public/DockWidget.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include "DockLayout.hpp"
|
||||
|
||||
namespace tp {
|
||||
class DockWidget : public Widget {
|
||||
public:
|
||||
DockWidget();
|
||||
|
||||
public:
|
||||
void process(const EventHandler& events) override;
|
||||
void draw(Canvas& canvas) override;
|
||||
void drawOverlay(Canvas& canvas) override;
|
||||
|
||||
[[nodiscard]] bool propagateEventsToChildren() const override;
|
||||
[[nodiscard]] bool needsNextFrame() const override;
|
||||
|
||||
void drawSide(DockLayout::Side side, Canvas& canvas);
|
||||
|
||||
public:
|
||||
void setCenterWidget(Widget* widget);
|
||||
|
||||
void dockWidget(Widget* widget, DockLayout::Side side);
|
||||
void undockWidget(DockLayout::Side side, bool restoreArea = true);
|
||||
void toggleWidgetVisibility(DockLayout::Side side);
|
||||
|
||||
private:
|
||||
DockLayout* layout() { return dynamic_cast<DockLayout*>(mLayout); }
|
||||
const DockLayout* layout() const { return dynamic_cast<const DockLayout*>(mLayout); }
|
||||
|
||||
private:
|
||||
Widget* mPreviewWidget = nullptr;
|
||||
|
||||
private:
|
||||
halnf mRounding = 10;
|
||||
halnf mPadding = 4;
|
||||
|
||||
RGBA mResizeHandleColorHovered = RGBA(0.3, 0.3, 0.3, 1);
|
||||
RGBA mResizeHandleColorActive = RGBA(0.6, 0.6, 0.6, 1);
|
||||
RGBA mBackgroundColor = RGBA(0, 0, 0, 1);
|
||||
RGBA mPreviewColor = RGBA(0.6, 0.6, 0.6, 0.2);
|
||||
};
|
||||
}
|
||||
34
WidgetsNew/public/FloatingLayout.hpp
Normal file
34
WidgetsNew/public/FloatingLayout.hpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "LayoutManager.hpp"
|
||||
|
||||
namespace tp {
|
||||
class FloatingLayout : public BasicLayout {
|
||||
public:
|
||||
FloatingLayout(Widget* widget) :
|
||||
BasicLayout(widget) {}
|
||||
|
||||
public:
|
||||
void startAction(const Vec2F& pointer);
|
||||
void updateAction(const Vec2F& pointer);
|
||||
void endAction();
|
||||
|
||||
bool isFloating() const { return mIsFloating; }
|
||||
|
||||
RectF resizeHandleRect();
|
||||
|
||||
public:
|
||||
void pickRect() override;
|
||||
|
||||
private:
|
||||
bool mIsFloating = false;
|
||||
bool mIsResizing = false;
|
||||
|
||||
Vec2F mPointerStart;
|
||||
Vec2F mPointerCurrent;
|
||||
|
||||
// TODO : remove?
|
||||
halnf mHandleSize = 10;
|
||||
halnf mHandlePadding = 2;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,24 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "SimpleWidgets.hpp"
|
||||
#include "FloatingLayout.hpp"
|
||||
|
||||
namespace tp {
|
||||
class FloatingWidget : public Widget {
|
||||
public:
|
||||
FloatingWidget() {
|
||||
setDebug("float", { 0.0, 0.9, 0.1, 1 });
|
||||
|
||||
mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed };
|
||||
mLayoutPolicy = LayoutPolicy::Horizontal;
|
||||
setLayout(new FloatingLayout(this));
|
||||
}
|
||||
|
||||
void process(const EventHandler& events) override;
|
||||
|
||||
void pickRect() override;
|
||||
|
||||
void draw(Canvas& canvas) override;
|
||||
|
||||
RectF resizeHandleRect();
|
||||
|
||||
[[nodiscard]] bool needsNextFrame() const override;
|
||||
|
||||
|
|
@ -28,14 +24,8 @@ namespace tp {
|
|||
[[nodiscard]] bool isFloating() const;
|
||||
|
||||
private:
|
||||
bool mIsFloating = false;
|
||||
bool mIsResizing = false;
|
||||
|
||||
halnf mHandleSize = 10;
|
||||
halnf mHandlePadding = 2;
|
||||
|
||||
Vec2F mPointerStart;
|
||||
Vec2F mPointerCurrent;
|
||||
FloatingLayout* layout();
|
||||
[[nodiscard]] const FloatingLayout* layout() const;
|
||||
};
|
||||
|
||||
class FloatingMenu : public FloatingWidget {
|
||||
|
|
@ -53,8 +43,8 @@ namespace tp {
|
|||
mHeader.setSizePolicy(SizePolicy::Expanding, SizePolicy::Minimal);
|
||||
mBodyLayout.setSizePolicy(SizePolicy::Expanding, SizePolicy::Expanding);
|
||||
|
||||
setLayoutPolicy(LayoutPolicy::Vertical);
|
||||
mBodyLayout.setLayoutPolicy(LayoutPolicy::Vertical);
|
||||
// getLayout()->setLayoutPolicy(LayoutPolicy::Vertical);
|
||||
// mBodyLayout.getLayout()->setLayoutPolicy(LayoutPolicy::Vertical);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -26,15 +26,39 @@ namespace tp {
|
|||
virtual void pickRect() = 0;
|
||||
virtual void clampRect() = 0;
|
||||
virtual void adjustChildrenRect() = 0;
|
||||
virtual RectF getAvailableChildArea() const;
|
||||
|
||||
protected:
|
||||
public:
|
||||
const Vec2F& getMinSize();
|
||||
void setMinSize(const Vec2F& size);
|
||||
|
||||
const Vec2<SizePolicy>& getSizePolicy() const;
|
||||
void setSizePolicy(SizePolicy x, SizePolicy y);
|
||||
|
||||
public:
|
||||
[[nodiscard]] const RectF& getArea() const;
|
||||
RectF getAnimatedArea() const;
|
||||
|
||||
void setArea(const RectF& area);
|
||||
[[nodiscard]] Widget* parent() const;
|
||||
[[nodiscard]] const std::vector<Widget*>& children() const;
|
||||
|
||||
public:
|
||||
void clampMinMaxSize();
|
||||
|
||||
[[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;
|
||||
|
||||
[[nodiscard]] RectF getChildrenEnclosure() const;
|
||||
[[nodiscard]] RectF getParentEnclosure() const;
|
||||
|
||||
private:
|
||||
Widget* mWidget = nullptr;
|
||||
|
||||
protected:
|
||||
Vec2<SizePolicy> mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed };
|
||||
Vec2F mMinSize = { 50, 50 };
|
||||
Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 };
|
||||
};
|
||||
|
||||
class BasicLayout : public WidgetLayout {
|
||||
|
|
@ -44,31 +68,22 @@ namespace tp {
|
|||
void pickRect() override;
|
||||
void clampRect() override;
|
||||
void adjustChildrenRect() override;
|
||||
|
||||
public:
|
||||
const Vec2F& getMinSize();
|
||||
void setMinSize(const Vec2F& size);
|
||||
RectF getAvailableChildArea() const override;
|
||||
|
||||
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;
|
||||
Vec2<SizePolicy> mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed };
|
||||
|
||||
Vec2F mMinSize = { 50, 50 };
|
||||
Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 };
|
||||
|
||||
halnf mLayoutGap = 5;
|
||||
halnf mLayoutMargin = 10;
|
||||
};
|
||||
|
||||
class LayoutManager {
|
||||
public:
|
||||
LayoutManager() = default;
|
||||
|
||||
void adjust(Widget* root);
|
||||
};
|
||||
}
|
||||
|
|
@ -8,13 +8,6 @@
|
|||
|
||||
namespace tp {
|
||||
class RootWidget : public WidgetManagerInterface {
|
||||
|
||||
struct ActiveTreeNode {
|
||||
ActiveTreeNode* parent = nullptr;
|
||||
std::set<ActiveTreeNode*> children;
|
||||
Widget* widget = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
RootWidget() { setDebug("root", RGBA(1)); }
|
||||
|
||||
|
|
@ -31,29 +24,32 @@ namespace tp {
|
|||
|
||||
private:
|
||||
void updateTreeToProcess();
|
||||
void updateAnimations(ActiveTreeNode* iter);
|
||||
void updateAnimations();
|
||||
void processLayout();
|
||||
void drawRecursion(Canvas& canvas, Widget* active, const Vec2F& pos);
|
||||
void drawDebug(Canvas& canvas, Widget* active, const Vec2F& pos, int depthOrder);
|
||||
void findFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer);
|
||||
void handleFocusChanges(EventHandler& events);
|
||||
void getWidgetPath(Widget* widget, std::vector<Widget*>& out);
|
||||
void processActiveTree(ActiveTreeNode* iter, EventHandler& events, Vec2F pos);
|
||||
void processActiveTree(Widget* iter, EventHandler& events, Vec2F pos);
|
||||
void processFocusItems(EventHandler& events);
|
||||
void adjustSizes(ActiveTreeNode* iter);
|
||||
void updateAreaCache(ActiveTreeNode* iter, bool read);
|
||||
|
||||
void updateAreaCache(Widget* iter, bool read);
|
||||
static void debugDrawWidget(Widget* widget);
|
||||
|
||||
private:
|
||||
LayoutManager mLayoutManager;
|
||||
|
||||
RectF mScreenArea;
|
||||
Widget* mRoot = nullptr;
|
||||
|
||||
// frame to frame changes
|
||||
std::map<Widget*, bool> mTriggeredWidgets;
|
||||
std::map<Widget*, ActiveTreeNode> mWidgetsToProcess;
|
||||
Widget* mInFocusWidget = nullptr;
|
||||
|
||||
bool mDebug = true;
|
||||
bool mDebugStopProcessing = false;
|
||||
bool mDebugRedrawAlways = false;
|
||||
int mDebugWidgetsToProcess = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,32 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "SpringAnimations.hpp"
|
||||
#include "LayoutPolicies.hpp"
|
||||
#include "LayoutManager.hpp"
|
||||
|
||||
#include "EventHandler.hpp"
|
||||
#include "Graphics.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace tp {
|
||||
class WidgetManagerInterface;
|
||||
class WidgetLayout;
|
||||
class LayoutManager;
|
||||
class RootWidget;
|
||||
|
||||
class Widget {
|
||||
friend class RootWidget;
|
||||
friend RootWidget;
|
||||
friend LayoutManager;
|
||||
|
||||
public:
|
||||
Widget();
|
||||
virtual ~Widget();
|
||||
|
||||
void addChild(Widget* child);
|
||||
void addChild(Widget* child, bool front = false);
|
||||
void removeChild(Widget* child);
|
||||
|
||||
void bringToFront();
|
||||
void bringToBack();
|
||||
|
||||
void setLayout(WidgetLayout* layout);
|
||||
void setSizePolicy(SizePolicy x, SizePolicy y) { getLayout()->setSizePolicy(x, y); }
|
||||
|
||||
WidgetLayout* getLayout();
|
||||
const WidgetLayout* getLayout() const;
|
||||
|
||||
void triggerWidgetUpdate(const char* reason = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void process(const EventHandler& events) {}
|
||||
|
|
@ -45,20 +54,34 @@ namespace tp {
|
|||
protected:
|
||||
void setDebug(const char* name, RGBA col);
|
||||
WidgetManagerInterface* getRoot();
|
||||
void triggerWidgetUpdate(const char* reason = nullptr);
|
||||
|
||||
public:
|
||||
[[nodiscard]] RectF getArea() const;
|
||||
[[nodiscard]] RectF getAreaT() const;
|
||||
[[nodiscard]] const RectF& getAreaCache() const;
|
||||
// [[nodiscard]] const RectF& getAreaCache() const;
|
||||
|
||||
[[nodiscard]] RectF getRelativeArea() const;
|
||||
[[nodiscard]] RectF getRelativeAreaT() const;
|
||||
[[nodiscard]] RectF getRelativeAreaCache() const;
|
||||
// [[nodiscard]] RectF getRelativeAreaCache() const;
|
||||
|
||||
void setArea(const RectF& area);
|
||||
void setAreaCache(const RectF& area);
|
||||
|
||||
private:
|
||||
using DFSAction = std::function<void(Widget*)>;
|
||||
|
||||
static void dfs(Widget* iter, const DFSAction& before, const DFSAction& after = [](auto){}) {
|
||||
if (!iter->mNeedsProcessing) return;
|
||||
|
||||
before(iter);
|
||||
|
||||
for (auto child : iter->mDepthOrder) {
|
||||
dfs(child.data(), before, after);
|
||||
}
|
||||
|
||||
after(iter);
|
||||
}
|
||||
|
||||
protected:
|
||||
friend WidgetLayout;
|
||||
|
||||
|
|
@ -73,7 +96,10 @@ namespace tp {
|
|||
|
||||
WidgetLayout* mLayout = nullptr;
|
||||
|
||||
// TODO : make bitfield processing flags
|
||||
bool mInFocus = false;
|
||||
bool mNeedsProcessing = false;
|
||||
bool mTriggered = false;
|
||||
|
||||
// debug
|
||||
struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue