From ce0ae2c3727f83f1943d528b006eec94ad80ece9 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 25 Jun 2020 16:31:23 +0800 Subject: ... --- src/ui/render/BorderRenderObject.cpp | 37 ++++++++++++++++---- src/ui/render/FlexLayoutRenderObject.cpp | 2 +- src/ui/render/RenderObject.cpp | 23 ++++++++++--- src/ui/render/ScrollRenderObject.cpp | 59 +++++++++++++++++++------------- 4 files changed, 86 insertions(+), 35 deletions(-) (limited to 'src/ui/render') diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp index fbc3c65f..ad0c6455 100644 --- a/src/ui/render/BorderRenderObject.cpp +++ b/src/ui/render/BorderRenderObject.cpp @@ -27,7 +27,7 @@ void BorderRenderObject::Draw(platform::graph::IPainter* painter) { painter->FillGeometry(geometry_.get(), border_brush_.get()); } } - if (const auto child = GetChild()) { + if (const auto child = GetSingleChild()) { auto offset = child->GetOffset(); platform::graph::util::WithTransform( painter, platform::Matrix::Translation(offset.x, offset.y), @@ -48,7 +48,7 @@ void BorderRenderObject::SetBorderStyle(const BorderStyle& style) { } RenderObject* BorderRenderObject::HitTest(const Point& point) { - if (const auto child = GetChild()) { + if (const auto child = GetSingleChild()) { auto offset = child->GetOffset(); Point p{point.x - offset.x, point.y - offset.y}; const auto result = child->HitTest(p); @@ -90,7 +90,7 @@ Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement) { MeasureRequirement content_requirement = requirement; - if (!requirement.max_width.IsInfinate()) { + if (!requirement.max_width.IsNotSpecify()) { const auto max_width = requirement.max_width.GetLength(); if (coerced_space_size.width > max_width) { log::Warn( @@ -101,7 +101,7 @@ Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement) { content_requirement.max_width = max_width - coerced_space_size.width; } - if (!requirement.max_height.IsInfinate()) { + if (!requirement.max_height.IsNotSpecify()) { const auto max_height = requirement.max_height.GetLength(); if (coerced_space_size.height > max_height) { log::Warn( @@ -160,7 +160,7 @@ void BorderRenderObject::OnLayoutCore(const Size& size) { Size BorderRenderObject::OnMeasureContent( const MeasureRequirement& requirement) { - const auto child = GetChild(); + const auto child = GetSingleChild(); if (child) { child->Measure(requirement); return child->GetMeasuredSize(); @@ -170,7 +170,7 @@ Size BorderRenderObject::OnMeasureContent( } void BorderRenderObject::OnLayoutContent(const Rect& content_rect) { - const auto child = GetChild(); + const auto child = GetSingleChild(); if (child) { child->Layout(content_rect); } @@ -178,6 +178,31 @@ void BorderRenderObject::OnLayoutContent(const Rect& content_rect) { void BorderRenderObject::OnAfterLayout() { RecreateGeometry(); } +Rect BorderRenderObject::GetPaddingRect() const { + const auto size = GetSize(); + Rect rect{Point{}, size}; + rect = rect.Shrink(GetMargin()); + if (is_border_enabled_) rect = rect.Shrink(border_thickness_); + rect.left = std::min(rect.left, size.width); + rect.top = std::min(rect.top, size.height); + rect.width = std::max(rect.width, 0.0f); + rect.height = std::max(rect.height, 0.0f); + return rect; +} + +Rect BorderRenderObject::GetContentRect() const { + const auto size = GetSize(); + Rect rect{Point{}, size}; + rect = rect.Shrink(GetMargin()); + if (is_border_enabled_) rect = rect.Shrink(border_thickness_); + rect = rect.Shrink(GetPadding()); + rect.left = std::min(rect.left, size.width); + rect.top = std::min(rect.top, size.height); + rect.width = std::max(rect.width, 0.0f); + rect.height = std::max(rect.height, 0.0f); + return rect; +} + void BorderRenderObject::RecreateGeometry() { geometry_.reset(); border_outer_geometry_.reset(); diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp index 98eda066..72341a64 100644 --- a/src/ui/render/FlexLayoutRenderObject.cpp +++ b/src/ui/render/FlexLayoutRenderObject.cpp @@ -47,7 +47,7 @@ Size FlexLayoutRenderObject::OnMeasureContent( const auto& children = GetChildren(); Index children_count = children.size(); - if (!main_max_length.IsInfinate()) { + if (!main_max_length.IsNotSpecify()) { float remain_main_length = main_max_length.GetLength(); for (Index i = 0; i < children_count; i++) { diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp index cdc3032f..abd5e1c4 100644 --- a/src/ui/render/RenderObject.cpp +++ b/src/ui/render/RenderObject.cpp @@ -73,6 +73,15 @@ void RenderObject::Layout(const Rect& rect) { OnLayoutCore(rect.GetSize()); } +RenderObject* RenderObject::GetSingleChild() const { + Expects(child_mode_ == ChildMode::Single); + const auto& children = GetChildren(); + if (children.empty()) + return nullptr; + else + return children.front(); +} + void RenderObject::OnParentChanged(RenderObject* old_parent, RenderObject* new_parent) { CRU_UNUSED(old_parent) @@ -104,7 +113,7 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement) { MeasureRequirement content_requirement = requirement; - if (!requirement.max_width.IsInfinate()) { + if (!requirement.max_width.IsNotSpecify()) { const auto max_width = requirement.max_width.GetLength(); if (coerced_space_size.width > max_width) { log::Warn( @@ -115,7 +124,7 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement) { content_requirement.max_width = max_width - coerced_space_size.width; } - if (!requirement.max_height.IsInfinate()) { + if (!requirement.max_height.IsNotSpecify()) { const auto max_height = requirement.max_height.GetLength(); if (coerced_space_size.height > max_height) { log::Warn( @@ -166,17 +175,23 @@ void RenderObject::OnLayoutCore(const Size& size) { void RenderObject::OnAfterLayout() {} Rect RenderObject::GetPaddingRect() const { - Rect rect{Point{}, GetSize()}; + const auto size = GetSize(); + Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); + rect.left = std::min(rect.left, size.width); + rect.top = std::min(rect.top, size.height); rect.width = std::max(rect.width, 0.0f); rect.height = std::max(rect.height, 0.0f); return rect; } Rect RenderObject::GetContentRect() const { - Rect rect{Point{}, GetSize()}; + const auto size = GetSize(); + Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); rect = rect.Shrink(GetPadding()); + rect.left = std::min(rect.left, size.width); + rect.top = std::min(rect.top, size.height); rect.width = std::max(rect.width, 0.0f); rect.height = std::max(rect.height, 0.0f); return rect; diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp index f1df9d8b..98254690 100644 --- a/src/ui/render/ScrollRenderObject.cpp +++ b/src/ui/render/ScrollRenderObject.cpp @@ -2,6 +2,7 @@ #include "cru/platform/graph/Painter.hpp" #include "cru/platform/graph/util/Painter.hpp" +#include "cru/ui/render/LayoutUtility.hpp" #include @@ -9,13 +10,11 @@ namespace cru::ui::render { namespace { // This method assumes margin offset is already considered. // It promises that it won't return negetive value. -Point CalculateChildOffsetOfScroll(const Point& scroll_offset, - const Size& content_area_size, - const Thickness& padding, - const Size& child_size) { +Point CoerceScroll(const Point& scroll_offset, const Size& content_size, + const Size& child_size) { Point result(scroll_offset); - Point max_scroll(child_size - content_area_size); + Point max_scroll(child_size - content_size); max_scroll.x = std::max(max_scroll.x, 0.f); max_scroll.y = std::max(max_scroll.y, 0.f); @@ -29,50 +28,62 @@ Point CalculateChildOffsetOfScroll(const Point& scroll_offset, coerce(result.x, scroll_offset.x); coerce(result.y, scroll_offset.y); - result.x += padding.left; - result.y += padding.top; - return result; } } // namespace void ScrollRenderObject::Draw(platform::graph::IPainter* painter) { - for (auto child : this->GetChildren()) { + if (const auto child = GetSingleChild()) { painter->PushLayer(this->GetPaddingRect()); - const auto true_offset = - CalculateChildOffsetOfScroll(scroll_offset_, GetContentRect().GetSize(), - GetPadding(), child->GetSize()); + const auto offset = child->GetOffset(); platform::graph::util::WithTransform( - painter, Matrix::Translation(true_offset.x, true_offset.y), + painter, Matrix::Translation(offset.x, offset.y), [child](platform::graph::IPainter* p) { child->Draw(p); }); painter->PopLayer(); } } RenderObject* ScrollRenderObject::HitTest(const Point& point) { + if (const auto child = GetSingleChild()) { + const auto offset = child->GetOffset(); + const auto r = child->HitTest(point - offset); + if (r != nullptr) return r; + } + const auto rect = GetPaddingRect(); return rect.IsPointInside(point) ? this : nullptr; +} // namespace cru::ui::render + +Point ScrollRenderObject::GetScrollOffset() { + if (const auto child = GetSingleChild()) + return CoerceScroll(scroll_offset_, GetContentRect().GetSize(), + child->GetSize()); + else + return scroll_offset_; } void ScrollRenderObject::SetScrollOffset(const Point& offset) { scroll_offset_ = offset; - InvalidatePaint(); + InvalidateLayout(); } Size ScrollRenderObject::OnMeasureContent( const MeasureRequirement& requirement) { - CRU_UNUSED(requirement); - // TODO! - // const auto& children = GetChildren(); - // if (children.empty()) return Size{}; - // const auto child = children.front(); - // child->Measure(MeasureRequirement::Infinate()); - // const auto preferred_size = child->GetMeasuredSize(); - return Size{}; + if (const auto child = GetSingleChild()) { + child->Measure(MeasureRequirement::Infinate()); + const auto preferred_size = child->GetMeasuredSize(); + return Min(preferred_size, requirement.GetMaxSize()); + } else { + return Size{}; + } } // namespace cru::ui::render void ScrollRenderObject::OnLayoutContent(const Rect& content_rect) { - CRU_UNUSED(content_rect); - // TODO! + if (const auto child = GetSingleChild()) { + const auto child_size = child->GetMeasuredSize(); + const auto true_scroll = + CoerceScroll(scroll_offset_, content_rect.GetSize(), child_size); + child->Layout(Rect{content_rect.GetLeftTop() - true_scroll, child_size}); + } } } // namespace cru::ui::render -- cgit v1.2.3