From 81fd0725d020e9f302c0d40fd5a5700d3dc871aa Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 6 Dec 2018 05:44:38 +0800 Subject: Done. --- src/ui/window.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/ui/window.cpp') diff --git a/src/ui/window.cpp b/src/ui/window.cpp index dfc6db43..6f1c4071 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -116,7 +116,7 @@ namespace cru::ui const auto cursor = control->GetCursor(); if (cursor != nullptr) return cursor; - control = control->GetParent(); + control = control->GetInternalParent(); } return cursors::arrow; } @@ -132,8 +132,11 @@ namespace cru::ui return new Window(tag_popup_constructor{}, parent, caption); } - Window::Window(tag_overlapped_constructor) : Control(WindowConstructorTag{}, this) + + Window::Window(tag_overlapped_constructor) { + BeforeCreateHwnd(); + const auto window_manager = WindowManager::GetInstance(); hwnd_ = CreateWindowEx(0, @@ -149,11 +152,13 @@ namespace cru::ui AfterCreateHwnd(window_manager); } - Window::Window(tag_popup_constructor, Window* parent, const bool caption) : Control(WindowConstructorTag{}, this) + Window::Window(tag_popup_constructor, Window* parent, const bool caption) { if (parent != nullptr && !parent->IsWindowValid()) throw std::runtime_error("Parent window is not valid."); + BeforeCreateHwnd(); + parent_window_ = parent; const auto window_manager = WindowManager::GetInstance(); @@ -172,6 +177,11 @@ namespace cru::ui AfterCreateHwnd(window_manager); } + void Window::BeforeCreateHwnd() + { + window_ = this; + } + void Window::AfterCreateHwnd(WindowManager* window_manager) { window_manager->RegisterWindow(hwnd_, this); -- cgit v1.2.3 From 03ef76f769a55b694905898c16a176fc6bd4b0d7 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 6 Dec 2018 21:09:12 +0800 Subject: Fix position cache bug. --- src/ui/control.cpp | 33 ++++++++++++++++++++++++++++++--- src/ui/control.hpp | 16 +++++++++++----- src/ui/controls/scroll_control.cpp | 3 ++- src/ui/window.cpp | 2 +- src/ui/window.hpp | 2 +- 5 files changed, 45 insertions(+), 11 deletions(-) (limited to 'src/ui/window.cpp') diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 32168891..3987e818 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -125,7 +125,7 @@ namespace cru::ui TraverseDescendantsInternal(this, predicate); } - Point Control::GetPositionRelative() + Point Control::GetOffset() { return rect_.GetLeftTop(); } @@ -186,6 +186,33 @@ namespace cru::ui point.y - position_cache_.lefttop_position_absolute.y); } + void Control::RefreshDescendantPositionCache() + { + auto point = Point::Zero(); + auto parent = this; + while ((parent = parent->GetParent())) + { + const auto p = parent->GetOffset(); + point.x += p.x; + point.y += p.y; + } + RefreshControlPositionCacheInternal(this, point); + } + + void Control::RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute) + { + const auto position = control->GetOffset(); + const Point lefttop( + parent_lefttop_absolute.x + position.x, + parent_lefttop_absolute.y + position.y + ); + control->position_cache_.lefttop_position_absolute = lefttop; + for(auto c : control->GetInternalChildren()) + { + RefreshControlPositionCacheInternal(c, lefttop); + } + } + bool Control::IsPointInside(const Point & point) { const auto border_geometry = geometry_info_.border_geometry; @@ -230,7 +257,7 @@ namespace cru::ui for (auto i = children.crbegin(); i != children.crend(); ++i) { - const auto&& lefttop = (*i)->GetPositionRelative(); + const auto&& lefttop = (*i)->GetOffset(); const auto&& coerced_point = Point(point.x - lefttop.x, point.y - lefttop.y); const auto child_hit_test_result = (*i)->HitTest(coerced_point); if (child_hit_test_result != nullptr) @@ -254,7 +281,7 @@ namespace cru::ui D2D1::Matrix3x2F old_transform; device_context->GetTransform(&old_transform); - const auto position = GetPositionRelative(); + const auto position = GetOffset(); device_context->SetTransform(old_transform * D2D1::Matrix3x2F::Translation(position.x, position.y)); OnDrawDecoration(device_context); diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 41d1cfe9..6abcc365 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -18,7 +18,6 @@ namespace cru::ui { - class Control; class Window; @@ -68,6 +67,8 @@ namespace cru::ui //*************** region: tree *************** virtual StringView GetControlType() const = 0; + virtual const std::vector& GetInternalChildren() const = 0; + Control* GetParent() const { return parent_ == nullptr ? internal_parent_ : parent_; @@ -84,9 +85,6 @@ namespace cru::ui return window_; } - - virtual const std::vector& GetInternalChildren() const = 0; - void SetParent(Control* parent); void SetInternalParent(Control* internal_parent); @@ -100,11 +98,12 @@ namespace cru::ui //*************** region: position and size *************** //Get the lefttop relative to its parent. - virtual Point GetPositionRelative(); + virtual Point GetOffset(); //Get the actual size. virtual Size GetSize(); + // If offset changes, call RefreshDescendantPositionCache. virtual void SetRect(const Rect& rect); //Get lefttop relative to ancestor. This is only valid when @@ -118,6 +117,13 @@ namespace cru::ui //Absolute point to local point. Point WindowToControl(const Point& point) const; + void RefreshDescendantPositionCache(); + + private: + static void RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute); + + public: + // Default implement in Control is test point in border geometry's // fill and stroke with width of border. virtual bool IsPointInside(const Point& point); diff --git a/src/ui/controls/scroll_control.cpp b/src/ui/controls/scroll_control.cpp index ae99f414..622b4e4c 100644 --- a/src/ui/controls/scroll_control.cpp +++ b/src/ui/controls/scroll_control.cpp @@ -328,11 +328,12 @@ namespace cru::ui::controls { if (const auto child = GetChild()) { - const auto old_position = child->GetPositionRelative(); + const auto old_position = child->GetOffset(); child->SetRect(Rect(Point( old_position.x + old_offset_x - offset_x_, old_position.y + old_offset_y - offset_y_ ), child->GetSize())); + child->RefreshDescendantPositionCache(); } } InvalidateDraw(); diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 6f1c4071..86fa4436 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -469,7 +469,7 @@ namespace cru::ui return PiToDip(point); } - Point Window::GetPositionRelative() + Point Window::GetOffset() { return Point(); } diff --git a/src/ui/window.hpp b/src/ui/window.hpp index e4c910e8..e96d4d92 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -189,7 +189,7 @@ namespace cru::ui //*************** region: position and size *************** //Always return (0, 0) for a window. - Point GetPositionRelative() override final; + Point GetOffset() override final; //Get the size of client area for a window. Size GetSize() override final; -- cgit v1.2.3