aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2018-12-06 21:09:12 +0800
committercrupest <crupest@outlook.com>2018-12-06 21:09:12 +0800
commit03ef76f769a55b694905898c16a176fc6bd4b0d7 (patch)
tree41e11ed127f9a35f543473c39109487785383daa /src
parent81fd0725d020e9f302c0d40fd5a5700d3dc871aa (diff)
downloadcru-03ef76f769a55b694905898c16a176fc6bd4b0d7.tar.gz
cru-03ef76f769a55b694905898c16a176fc6bd4b0d7.tar.bz2
cru-03ef76f769a55b694905898c16a176fc6bd4b0d7.zip
Fix position cache bug.
Diffstat (limited to 'src')
-rw-r--r--src/ui/control.cpp33
-rw-r--r--src/ui/control.hpp16
-rw-r--r--src/ui/controls/scroll_control.cpp3
-rw-r--r--src/ui/window.cpp2
-rw-r--r--src/ui/window.hpp2
5 files changed, 45 insertions, 11 deletions
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<Control*>& 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<Control*>& 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;