aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/control.cpp10
-rw-r--r--src/ui/control.h2
-rw-r--r--src/ui/controls/margin_container.cpp2
-rw-r--r--src/ui/layout_base.cpp24
-rw-r--r--src/ui/layout_base.h12
-rw-r--r--src/ui/window.cpp16
-rw-r--r--src/ui/window.h10
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();