diff options
author | crupest <crupest@outlook.com> | 2018-09-29 11:13:31 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-09-29 11:13:31 +0800 |
commit | 177765d0d9d74525a9db9e756f614636828ea980 (patch) | |
tree | 50c67f028f18486dc4a7656c82eff31cac86ec71 /src | |
parent | b0b5a481c9b0460f275887b15e8edecc34e99186 (diff) | |
download | cru-177765d0d9d74525a9db9e756f614636828ea980.tar.gz cru-177765d0d9d74525a9db9e756f614636828ea980.tar.bz2 cru-177765d0d9d74525a9db9e756f614636828ea980.zip |
Fix relayout system.
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/control.cpp | 10 | ||||
-rw-r--r-- | src/ui/control.h | 2 | ||||
-rw-r--r-- | src/ui/controls/margin_container.cpp | 2 | ||||
-rw-r--r-- | src/ui/layout_base.cpp | 24 | ||||
-rw-r--r-- | src/ui/layout_base.h | 12 | ||||
-rw-r--r-- | src/ui/window.cpp | 16 | ||||
-rw-r--r-- | src/ui/window.h | 10 |
7 files changed, 66 insertions, 10 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 8aec8640..81cfe9b1 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -242,10 +242,10 @@ namespace cru { return window->GetFocusControl() == this; } - void Control::Relayout() + void Control::InvalidateLayout() { - OnMeasure(GetSize()); - OnLayout(Rect(GetPositionRelative(), GetSize())); + if (const auto window = GetWindow()) + LayoutManager::GetInstance()->InvalidateWindowLayout(window); } void Control::Measure(const Size& available_size) @@ -278,8 +278,8 @@ namespace cru { control->OnAttachToWindow(window); }); window->RefreshControlList(); + InvalidateLayout(); } - Relayout(); } void Control::OnRemoveChild(Control* child) @@ -290,8 +290,8 @@ namespace cru { control->OnDetachToWindow(window); }); window->RefreshControlList(); + InvalidateLayout(); } - Relayout(); } void Control::OnAttachToWindow(Window* window) diff --git a/src/ui/control.h b/src/ui/control.h index d6cbae40..98d41d0d 100644 --- a/src/ui/control.h +++ b/src/ui/control.h @@ -155,7 +155,7 @@ namespace cru //*************** region: layout *************** - void Relayout(); + void InvalidateLayout(); void Measure(const Size& available_size); diff --git a/src/ui/controls/margin_container.cpp b/src/ui/controls/margin_container.cpp index 8f9101b2..1f331d32 100644 --- a/src/ui/controls/margin_container.cpp +++ b/src/ui/controls/margin_container.cpp @@ -20,7 +20,7 @@ namespace cru::ui::controls void MarginContainer::SetMargin(const Thickness& margin) { margin_ = margin; - Relayout(); + InvalidateLayout(); } Size MarginContainer::OnMeasure(const Size& available_size) diff --git a/src/ui/layout_base.cpp b/src/ui/layout_base.cpp index a26379a0..40c7a724 100644 --- a/src/ui/layout_base.cpp +++ b/src/ui/layout_base.cpp @@ -2,6 +2,7 @@ #include "application.h" #include "control.h" +#include "window.h" namespace cru::ui { @@ -33,8 +34,8 @@ namespace cru::ui if (cache_invalid_controls_.size() == 1) // when insert just now and not repeat to "InvokeLater". { InvokeLater([this] { - - RefreshInvalidControlPositionCache(); // first refresh position cache. + for (const auto i : cache_invalid_controls_) + RefreshControlPositionCache(i); for (const auto i : cache_invalid_controls_) // traverse all descendants of position-invalid controls and notify position change event i->TraverseDescendants([](Control* control) { @@ -50,6 +51,7 @@ namespace cru::ui { for (const auto i : cache_invalid_controls_) RefreshControlPositionCache(i); + cache_invalid_controls_.clear(); } void LayoutManager::RefreshControlPositionCache(Control * control) @@ -64,6 +66,24 @@ namespace cru::ui RefreshControlPositionCacheInternal(control, point); } + void LayoutManager::InvalidateWindowLayout(Window* window) + { + layout_invalid_windows_.insert(window); + + if (layout_invalid_windows_.size() == 1) + InvokeLater([this]() + { + this->RefreshInvalidWindowLayout(); + }); + } + + void LayoutManager::RefreshInvalidWindowLayout() + { + for (const auto window : layout_invalid_windows_) + window->Relayout(); + layout_invalid_windows_.clear(); + } + void LayoutManager::RefreshControlPositionCacheInternal(Control * control, const Point & parent_lefttop_absolute) { const auto position = control->GetPositionRelative(); diff --git a/src/ui/layout_base.h b/src/ui/layout_base.h index 163b99b2..126437cd 100644 --- a/src/ui/layout_base.h +++ b/src/ui/layout_base.h @@ -11,6 +11,7 @@ namespace cru namespace ui { class Control; + class Window; enum class Alignment { @@ -114,6 +115,9 @@ namespace cru LayoutManager& operator=(LayoutManager&& other) = delete; ~LayoutManager() override = default; + + //*************** region: position cache *************** + //Mark position cache of the control and its descendants invalid, //(which is saved as an auto-managed list internal) //and send a message to refresh them. @@ -126,11 +130,19 @@ namespace cru //Refresh position cache of the control and its descendants immediately. static void RefreshControlPositionCache(Control* control); + + //*************** region: layout *************** + + void InvalidateWindowLayout(Window* window); + + void RefreshInvalidWindowLayout(); + private: static void RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute); private: std::unordered_set<Control*> cache_invalid_controls_; + std::unordered_set<Window*> layout_invalid_windows_; }; } } diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 34a54512..39528550 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -352,6 +352,12 @@ namespace cru } + void Window::Relayout() + { + OnMeasure(GetSize()); + OnLayout(Rect(Point::Zero(), GetSize())); + } + void Window::RefreshControlList() { control_list_.clear(); TraverseDescendants([this](Control* control) { @@ -456,6 +462,16 @@ namespace cru return ::PeekMessageW(&msg, hwnd_, message, message, PM_NOREMOVE) != 0; } + Size Window::OnMeasure(const Size& available_size) + { + ForeachChild([available_size](Control* control) + { + control->Measure(available_size); + }); + + return available_size; + } + void Window::OnDestroyInternal() { Application::GetInstance()->GetWindowManager()->UnregisterWindow(hwnd_); hwnd_ = nullptr; diff --git a/src/ui/window.h b/src/ui/window.h index 40d81a06..4d0a07bc 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -155,8 +155,11 @@ namespace cru { //This method has no effect for a window. Use SetClientSize instead. void SetSize(const Size& size) override final; + //*************** region: layout *************** - //*************** region: features *************** + void Relayout(); + + //*************** region: functions *************** //Refresh control list. //It should be invoked every time a control is added or removed from the tree. @@ -206,6 +209,11 @@ namespace cru { bool IsMessageInQueue(UINT message); + //*************** region: layout *************** + + Size OnMeasure(const Size& available_size) override; + + //*************** region: native messages *************** void OnDestroyInternal(); |