From e18c4fb46d7913f337cc25b9a6e3a25359c3f10a Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 9 Feb 2022 22:29:17 +0800 Subject: ... --- src/ui/render/BorderRenderObject.cpp | 52 ++++---- src/ui/render/CanvasRenderObject.cpp | 4 +- src/ui/render/FlexLayoutRenderObject.cpp | 61 +++++---- src/ui/render/RenderObject.cpp | 206 ++++++++---------------------- src/ui/render/ScrollBar.cpp | 16 +-- src/ui/render/ScrollRenderObject.cpp | 60 +++++---- src/ui/render/StackLayoutRenderObject.cpp | 16 +-- src/ui/render/TextRenderObject.cpp | 13 +- src/ui/render/TreeRenderObject.cpp | 12 +- 9 files changed, 183 insertions(+), 257 deletions(-) (limited to 'src/ui/render') diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp index 61af27bc..5916c7aa 100644 --- a/src/ui/render/BorderRenderObject.cpp +++ b/src/ui/render/BorderRenderObject.cpp @@ -12,13 +12,18 @@ #include namespace cru::ui::render { -BorderRenderObject::BorderRenderObject() { - SetChildMode(ChildMode::Single); - RecreateGeometry(); -} +BorderRenderObject::BorderRenderObject() { RecreateGeometry(); } BorderRenderObject::~BorderRenderObject() {} +void BorderRenderObject::SetChild(RenderObject* new_child) { + if (child_ == new_child) return; + if (child_ != nullptr) child_->SetParent(nullptr); + child_ = new_child; + if (child_ != nullptr) child_->SetParent(this); + InvalidateLayout(); +} + void BorderRenderObject::ApplyBorderStyle( const style::ApplyBorderStyleInfo& style) { if (style.border_brush) border_brush_ = *style.border_brush; @@ -30,10 +35,8 @@ void BorderRenderObject::ApplyBorderStyle( } RenderObject* BorderRenderObject::HitTest(const Point& point) { - 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); + if (child_) { + const auto result = child_->HitTest(point - child_->GetOffset()); if (result != nullptr) { return result; } @@ -45,7 +48,7 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) { return contains ? this : nullptr; } else { const auto margin = GetMargin(); - const auto size = GetSize(); + const auto size = GetDesiredSize(); return Rect{margin.left, margin.top, std::max(size.width - margin.GetHorizontalTotal(), 0.0f), std::max(size.height - margin.GetVerticalTotal(), 0.0f)} @@ -55,7 +58,7 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) { } } -void BorderRenderObject::OnDrawCore(platform::graphics::IPainter* painter) { +void BorderRenderObject::Draw(platform::graphics::IPainter* painter) { if constexpr (debug_flags::draw) { log::TagDebug( log_tag, u"BorderRenderObject draw, background: {}, foreground: {}.", @@ -77,34 +80,35 @@ void BorderRenderObject::OnDrawCore(platform::graphics::IPainter* painter) { } } - DefaultDrawContent(painter); + if (child_) { + painter->PushState(); + painter->ConcatTransform(Matrix::Translation(child_->GetOffset())); + child_->Draw(painter); + painter->PopState(); + } if (foreground_brush_ != nullptr) painter->FillGeometry(border_inner_geometry_.get(), foreground_brush_.get()); - - DefaultDrawChildren(painter); } Size BorderRenderObject::OnMeasureContent(const MeasureRequirement& requirement, const MeasureSize& preferred_size) { - const auto child = GetSingleChild(); - if (child) { - child->Measure(requirement, preferred_size); - return child->GetSize(); + if (child_) { + child_->Measure(requirement, preferred_size); + return child_->GetDesiredSize(); } else { return Size{}; } } void BorderRenderObject::OnLayoutContent(const Rect& content_rect) { - const auto child = GetSingleChild(); - if (child) { - child->Layout(content_rect.GetLeftTop()); + if (child_) { + child_->Layout(content_rect.GetLeftTop()); } } -void BorderRenderObject::OnAfterLayout() { RecreateGeometry(); } +void BorderRenderObject::OnResize(const Size& new_size) { RecreateGeometry(); } Thickness BorderRenderObject::GetOuterSpaceThickness() const { return is_border_enabled_ @@ -113,7 +117,7 @@ Thickness BorderRenderObject::GetOuterSpaceThickness() const { } Rect BorderRenderObject::GetPaddingRect() const { - const auto size = GetSize(); + const auto size = GetDesiredSize(); Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); if (is_border_enabled_) rect = rect.Shrink(border_thickness_); @@ -125,7 +129,7 @@ Rect BorderRenderObject::GetPaddingRect() const { } Rect BorderRenderObject::GetContentRect() const { - const auto size = GetSize(); + const auto size = GetDesiredSize(); Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); if (is_border_enabled_) rect = rect.Shrink(border_thickness_); @@ -180,7 +184,7 @@ void BorderRenderObject::RecreateGeometry() { builder->CloseFigure(true); }; - const auto size = GetSize(); + const auto size = GetDesiredSize(); const auto margin = GetMargin(); const Rect outer_rect{margin.left, margin.top, size.width - margin.GetHorizontalTotal(), diff --git a/src/ui/render/CanvasRenderObject.cpp b/src/ui/render/CanvasRenderObject.cpp index 985a2dae..e818333c 100644 --- a/src/ui/render/CanvasRenderObject.cpp +++ b/src/ui/render/CanvasRenderObject.cpp @@ -1,7 +1,7 @@ #include "cru/ui/render/CanvasRenderObject.h" namespace cru::ui::render { -CanvasRenderObject::CanvasRenderObject() : RenderObject(ChildMode::None) {} +CanvasRenderObject::CanvasRenderObject() : RenderObject() {} CanvasRenderObject::~CanvasRenderObject() = default; @@ -10,7 +10,7 @@ RenderObject* CanvasRenderObject::HitTest(const Point& point) { return padding_rect.IsPointInside(point) ? this : nullptr; } -void CanvasRenderObject::OnDrawContent(platform::graphics::IPainter* painter) { +void CanvasRenderObject::Draw(platform::graphics::IPainter* painter) { const auto rect = GetContentRect(); CanvasPaintEventArgs args{painter, rect.GetSize()}; paint_event_.Raise(args); diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp index e4d16169..261a0f43 100644 --- a/src/ui/render/FlexLayoutRenderObject.cpp +++ b/src/ui/render/FlexLayoutRenderObject.cpp @@ -11,8 +11,7 @@ #include namespace cru::ui::render { - -std::u16string_view FlexLayoutRenderObject::GetName() const { +String FlexLayoutRenderObject::GetName() const { return u"FlexLayoutRenderObject"; } @@ -121,7 +120,7 @@ Size FlexLayoutMeasureContentImpl( float total_length = 0.f; for (auto child : children) { - total_length += GetMain(child->GetSize(), direction_tag); + total_length += GetMain(child->GetDesiredSize(), direction_tag); } // step 2. @@ -190,7 +189,7 @@ Size FlexLayoutMeasureContentImpl( const float shrink_length = layout_data[i].shrink_factor / total_shrink_factor * total_shrink_length; float new_measure_length = - GetMain(child->GetSize(), direction_tag) - shrink_length; + GetMain(child->GetDesiredSize(), direction_tag) - shrink_length; MeasureLength child_min_main_length = GetMain(child->GetMinSize(), direction_tag); @@ -210,7 +209,7 @@ Size FlexLayoutMeasureContentImpl( MeasureLength::NotSpecified(), direction_tag)); - const Size new_size = child->GetSize(); + const Size new_size = child->GetDesiredSize(); const float new_main_length = GetMain(new_size, direction_tag); if (new_main_length > new_measure_length) { to_remove.push_back(i); @@ -219,7 +218,7 @@ Size FlexLayoutMeasureContentImpl( total_length = 0.f; for (auto child : children) { - total_length += GetMain(child->GetSize(), direction_tag); + total_length += GetMain(child->GetDesiredSize(), direction_tag); } if (total_length <= target_length) break; @@ -250,7 +249,7 @@ Size FlexLayoutMeasureContentImpl( const float expand_length = layout_data[i].expand_factor / total_expand_factor * total_expand_length; float new_measure_length = - GetMain(child->GetSize(), direction_tag) + expand_length; + GetMain(child->GetDesiredSize(), direction_tag) + expand_length; MeasureLength child_max_main_length = GetMain(child->GetMaxSize(), direction_tag); @@ -271,7 +270,7 @@ Size FlexLayoutMeasureContentImpl( MeasureLength::NotSpecified(), direction_tag)); - const Size new_size = child->GetSize(); + const Size new_size = child->GetDesiredSize(); const float new_main_length = GetMain(new_size, direction_tag); if (new_main_length < new_measure_length) { to_remove.push_back(i); @@ -280,7 +279,7 @@ Size FlexLayoutMeasureContentImpl( total_length = 0.f; for (auto child : children) { - total_length += GetMain(child->GetSize(), direction_tag); + total_length += GetMain(child->GetDesiredSize(), direction_tag); } if (total_length >= target_length) break; @@ -292,7 +291,7 @@ Size FlexLayoutMeasureContentImpl( float child_max_cross_length = 0.f; for (auto child : children) { - const float cross_length = GetCross(child->GetSize(), direction_tag); + const float cross_length = GetCross(child->GetDesiredSize(), direction_tag); if (cross_length > child_max_cross_length) { child_max_cross_length = cross_length; } @@ -319,7 +318,7 @@ Size FlexLayoutMeasureContentImpl( auto child = children[i]; if (child_layout_data.cross_alignment.value_or(item_cross_align) == Alignment::Stretch) { - auto size = child->GetSize(); + auto size = child->GetDesiredSize(); GetCross(size, direction_tag) = child_max_cross_length; child->Measure({size, size}, MeasureSize::NotSpecified()); } @@ -333,29 +332,40 @@ Size FlexLayoutRenderObject::OnMeasureContent( const MeasureRequirement& requirement, const MeasureSize& preferred_size) { const bool horizontal = (direction_ == FlexDirection::Horizontal || direction_ == FlexDirection::HorizontalReverse); + std::vector children; + std::vector layout_data_list; + for (int i = 0; i < GetChildCount(); i++) { + children.push_back(GetChildAt(i)); + layout_data_list.push_back(GetChildLayoutData(i)); + } + if (horizontal) { return FlexLayoutMeasureContentImpl( - requirement, preferred_size, GetChildren(), GetChildLayoutDataList(), + requirement, preferred_size, children, layout_data_list, item_cross_align_, log_tag); } else { return FlexLayoutMeasureContentImpl( - requirement, preferred_size, GetChildren(), GetChildLayoutDataList(), + requirement, preferred_size, children, layout_data_list, item_cross_align_, log_tag); } } void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { - const auto& children = GetChildren(); - const Index child_count = children.size(); + const auto child_count = GetChildCount(); + std::vector children; + std::vector layout_data_list; + for (int i = 0; i < child_count; i++) { + children.push_back(GetChildAt(i)); + layout_data_list.push_back(GetChildLayoutData(i)); + } if (direction_ == FlexDirection::Horizontal) { float current_main_offset = 0; for (Index i = 0; i < child_count; i++) { const auto child = children[i]; - const auto size = child->GetSize(); + const auto size = child->GetDesiredSize(); const auto cross_align = - GetChildLayoutDataList()[i].cross_alignment.value_or( - GetItemCrossAlign()); + layout_data_list[i].cross_alignment.value_or(GetItemCrossAlign()); child->Layout( Point{content_rect.left + current_main_offset, CalculateAnchorByAlignment(cross_align, content_rect.top, @@ -367,10 +377,9 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { float current_main_offset = 0; for (Index i = 0; i < child_count; i++) { const auto child = children[i]; - const auto size = child->GetSize(); + const auto size = child->GetDesiredSize(); const auto cross_align = - GetChildLayoutDataList()[i].cross_alignment.value_or( - GetItemCrossAlign()); + layout_data_list[i].cross_alignment.value_or(GetItemCrossAlign()); child->Layout( Point{content_rect.GetRight() - current_main_offset, CalculateAnchorByAlignment(cross_align, content_rect.top, @@ -381,10 +390,9 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { float current_main_offset = 0; for (Index i = 0; i < child_count; i++) { const auto child = children[i]; - const auto size = child->GetSize(); + const auto size = child->GetDesiredSize(); const auto cross_align = - GetChildLayoutDataList()[i].cross_alignment.value_or( - GetItemCrossAlign()); + layout_data_list[i].cross_alignment.value_or(GetItemCrossAlign()); child->Layout(Point{ CalculateAnchorByAlignment(cross_align, content_rect.left, content_rect.width, size.width), @@ -396,10 +404,9 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { float current_main_offset = 0; for (Index i = 0; i < child_count; i++) { const auto child = children[i]; - const auto size = child->GetSize(); + const auto size = child->GetDesiredSize(); const auto cross_align = - GetChildLayoutDataList()[i].cross_alignment.value_or( - GetItemCrossAlign()); + layout_data_list[i].cross_alignment.value_or(GetItemCrossAlign()); child->Layout( Point{CalculateAnchorByAlignment(cross_align, content_rect.left, content_rect.width, size.width), diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp index 00488425..67bbae12 100644 --- a/src/ui/render/RenderObject.cpp +++ b/src/ui/render/RenderObject.cpp @@ -1,66 +1,15 @@ #include "cru/ui/render/RenderObject.h" #include "cru/common/Logger.h" -#include "cru/platform/GraphicsBase.h" -#include "cru/platform/graphics/util/Painter.h" -#include "cru/ui/Base.h" #include "cru/ui/DebugFlags.h" +#include "cru/ui/controls/Control.h" #include "cru/ui/host/WindowHost.h" -#include -#include -#include -#include - namespace cru::ui::render { void RenderObject::SetAttachedControl(controls::Control* new_control) { + auto old_control = control_; control_ = new_control; - OnAttachedControlChanged(new_control); -} - -void RenderObject::AddChild(RenderObject* render_object, const Index position) { - Expects(child_mode_ != ChildMode::None); - Expects(!(child_mode_ == ChildMode::Single && children_.size() > 0)); - - Expects(render_object->GetParent() == - nullptr); // Render object already has a parent. - Expects(position >= 0); // Position index is less than 0. - Expects( - position <= - static_cast(children_.size())); // Position index is out of bound. - - children_.insert(children_.cbegin() + position, render_object); - render_object->SetParent(this); - render_object->SetWindowHostRecursive(GetWindowHost()); - OnAddChild(render_object, position); -} - -void RenderObject::RemoveChild(const Index position) { - Expects(position >= 0); // Position index is less than 0. - Expects(position < static_cast( - children_.size())); // Position index is out of bound. - - const auto i = children_.cbegin() + position; - const auto removed_child = *i; - children_.erase(i); - removed_child->SetParent(nullptr); - removed_child->SetWindowHostRecursive(nullptr); - OnRemoveChild(removed_child, position); -} - -RenderObject* RenderObject::GetFirstChild() const { - const auto& children = GetChildren(); - if (children.empty()) { - return nullptr; - } else { - return children.front(); - } -} - -void RenderObject::TraverseDescendants( - const std::function& action) { - action(this); - for (auto child : children_) child->TraverseDescendants(action); + OnAttachedControlChanged(old_control, new_control); } Point RenderObject::GetTotalOffset() const { @@ -84,6 +33,31 @@ Point RenderObject::FromRootToContent(const Point& point) const { point.y - (offset.y + rect.top)}; } +void RenderObject::SetMargin(const Thickness& margin) { + margin_ = margin; + InvalidateLayout(); +} + +void RenderObject::SetPadding(const Thickness& padding) { + padding_ = padding; + InvalidateLayout(); +} + +void RenderObject::SetPreferredSize(const MeasureSize& preferred_size) { + preferred_size_ = preferred_size; + InvalidateLayout(); +} + +void RenderObject::SetMinSize(const MeasureSize& min_size) { + custom_measure_requirement_.min = min_size; + InvalidateLayout(); +} + +void RenderObject::SetMaxSize(const MeasureSize& max_size) { + custom_measure_requirement_.max = max_size; + InvalidateLayout(); +} + void RenderObject::Measure(const MeasureRequirement& requirement, const MeasureSize& preferred_size) { MeasureRequirement merged_requirement = @@ -98,23 +72,27 @@ void RenderObject::Measure(const MeasureRequirement& requirement, preferred_size.ToDebugString()); } - size_ = OnMeasureCore(merged_requirement, merged_preferred_size); + desired_size_ = OnMeasureCore(merged_requirement, merged_preferred_size); if constexpr (cru::ui::debug_flags::layout) { log::Debug(u"{} Measure ends :\nresult size: {}", - this->GetDebugPathInTree(), size_); + this->GetDebugPathInTree(), desired_size_); } - Ensures(size_.width >= 0); - Ensures(size_.height >= 0); + Ensures(desired_size_.width >= 0); + Ensures(desired_size_.height >= 0); } void RenderObject::Layout(const Point& offset) { if constexpr (cru::ui::debug_flags::layout) { log::Debug(u"{} Layout :\noffset: {} size: {}", this->GetDebugPathInTree(), - offset, GetSize()); + offset, desired_size_); } offset_ = offset; + size_ = desired_size_; + + OnResize(size_); + OnLayoutCore(); } @@ -122,67 +100,6 @@ Thickness RenderObject::GetOuterSpaceThickness() const { return margin_ + padding_; } -void RenderObject::Draw(platform::graphics::IPainter* painter) { - OnDrawCore(painter); -} - -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) - CRU_UNUSED(new_parent) -} - -void RenderObject::OnAddChild(RenderObject* new_child, Index position) { - CRU_UNUSED(new_child) - CRU_UNUSED(position) - - InvalidateLayout(); - InvalidatePaint(); -} - -void RenderObject::OnRemoveChild(RenderObject* removed_child, Index position) { - CRU_UNUSED(removed_child) - CRU_UNUSED(position) - - InvalidateLayout(); - InvalidatePaint(); -} - -void RenderObject::DefaultDrawChildren(platform::graphics::IPainter* painter) { - for (const auto child : GetChildren()) { - auto offset = child->GetOffset(); - platform::graphics::util::WithTransform( - painter, platform::Matrix::Translation(offset.x, offset.y), - [child](auto p) { child->Draw(p); }); - } -} - -void RenderObject::DefaultDrawContent(platform::graphics::IPainter* painter) { - const auto content_rect = GetContentRect(); - - platform::graphics::util::WithTransform( - painter, Matrix::Translation(content_rect.left, content_rect.top), - [this](auto p) { this->OnDrawContent(p); }); -} - -void RenderObject::OnDrawCore(platform::graphics::IPainter* painter) { - DefaultDrawContent(painter); - DefaultDrawChildren(painter); -} - -void RenderObject::OnDrawContent(platform::graphics::IPainter* painter) { - CRU_UNUSED(painter); -} - Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement, const MeasureSize& preferred_size) { const Thickness outer_space = GetOuterSpaceThickness(); @@ -204,7 +121,7 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement, } void RenderObject::OnLayoutCore() { - Size total_size = GetSize(); + Size total_size = GetDesiredSize(); const Thickness outer_space = GetOuterSpaceThickness(); const Size space_size{outer_space.GetHorizontalTotal(), outer_space.GetVerticalTotal()}; @@ -231,10 +148,8 @@ void RenderObject::OnLayoutCore() { OnLayoutContent(content_rect); } -void RenderObject::OnAfterLayout() {} - Rect RenderObject::GetPaddingRect() const { - const auto size = GetSize(); + const auto size = GetDesiredSize(); Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); rect.left = std::min(rect.left, size.width); @@ -245,7 +160,7 @@ Rect RenderObject::GetPaddingRect() const { } Rect RenderObject::GetContentRect() const { - const auto size = GetSize(); + const auto size = GetDesiredSize(); Rect rect{Point{}, size}; rect = rect.Shrink(GetMargin()); rect = rect.Shrink(GetPadding()); @@ -256,33 +171,37 @@ Rect RenderObject::GetContentRect() const { return rect; } -void RenderObject::SetParent(RenderObject* new_parent) { - const auto old_parent = parent_; - parent_ = new_parent; - OnParentChanged(old_parent, new_parent); +host::WindowHost* RenderObject::GetWindowHost() { + if (control_) { + return control_->GetWindowHost(); + } + return nullptr; } void RenderObject::InvalidateLayout() { - if (window_host_ != nullptr) window_host_->InvalidateLayout(); + if (auto window_host = GetWindowHost()) { + window_host->InvalidateLayout(); + } } void RenderObject::InvalidatePaint() { - if (window_host_ != nullptr) window_host_->InvalidatePaint(); + if (auto window_host = GetWindowHost()) { + window_host->InvalidatePaint(); + } } -constexpr std::u16string_view kUnamedName(u"UNNAMED"); - -std::u16string_view RenderObject::GetName() const { return kUnamedName; } +String kUnamedName(u"UNNAMED"); +String RenderObject::GetName() const { return kUnamedName; } -std::u16string RenderObject::GetDebugPathInTree() const { - std::vector chain; +String RenderObject::GetDebugPathInTree() const { + std::vector chain; const RenderObject* parent = this; while (parent != nullptr) { chain.push_back(parent->GetName()); parent = parent->GetParent(); } - std::u16string result(chain.back()); + String result(chain.back()); for (auto iter = chain.crbegin() + 1; iter != chain.crend(); ++iter) { result += u" -> "; result += *iter; @@ -290,17 +209,4 @@ std::u16string RenderObject::GetDebugPathInTree() const { return result; } - -void RenderObject::SetWindowHostRecursive(host::WindowHost* host) { - if (window_host_ != nullptr) { - detach_from_host_event_.Raise(nullptr); - } - window_host_ = host; - if (host != nullptr) { - attach_to_host_event_.Raise(nullptr); - } - for (const auto child : GetChildren()) { - child->SetWindowHostRecursive(host); - } -} } // namespace cru::ui::render diff --git a/src/ui/render/ScrollBar.cpp b/src/ui/render/ScrollBar.cpp index e3cc006b..e6389e16 100644 --- a/src/ui/render/ScrollBar.cpp +++ b/src/ui/render/ScrollBar.cpp @@ -452,7 +452,7 @@ bool HorizontalScrollBar::IsShowBar() { if (child == nullptr) return false; const auto view_rect = render_object_->GetViewRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); if (view_rect.width >= child_size.width) return false; @@ -469,7 +469,7 @@ std::optional HorizontalScrollBar::GetExpandedAreaRect( const auto child = render_object_->GetFirstChild(); const auto view_rect = render_object_->GetViewRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); const float start_percentage = view_rect.left / child_size.width; const float length_percentage = view_rect.width / child_size.width; @@ -521,7 +521,7 @@ std::optional HorizontalScrollBar::GetCollapsedThumbRect() { const auto child = render_object_->GetFirstChild(); const auto view_rect = render_object_->GetViewRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); const float start_percentage = view_rect.left / child_size.width; const float length_percentage = view_rect.width / child_size.width; @@ -547,7 +547,7 @@ float HorizontalScrollBar::CalculateNewScrollPosition( auto thumb_head_end = scroll_area_end - thumb_original_rect.width; const auto child = render_object_->GetFirstChild(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); new_thumb_start = std::clamp(new_thumb_start, scroll_area_start, thumb_head_end); @@ -601,7 +601,7 @@ bool VerticalScrollBar::IsShowBar() { if (child == nullptr) return false; const auto view_rect = render_object_->GetViewRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); if (view_rect.height >= child_size.height) return false; @@ -618,7 +618,7 @@ std::optional VerticalScrollBar::GetExpandedAreaRect( const auto child = render_object_->GetFirstChild(); const auto view_rect = render_object_->GetViewRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); const float start_percentage = view_rect.top / child_size.height; const float length_percentage = view_rect.height / child_size.height; @@ -668,7 +668,7 @@ std::optional VerticalScrollBar::GetCollapsedThumbRect() { const auto view_rect = render_object_->GetViewRect(); const auto padding_rect = render_object_->GetPaddingRect(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); if (view_rect.height >= child_size.height) return std::nullopt; @@ -694,7 +694,7 @@ float VerticalScrollBar::CalculateNewScrollPosition( auto thumb_head_end = scroll_area_end - thumb_original_rect.height; const auto child = render_object_->GetFirstChild(); - const auto child_size = child->GetSize(); + const auto child_size = child->GetDesiredSize(); new_thumb_start = std::clamp(new_thumb_start, scroll_area_start, thumb_head_end); diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp index 2400cc11..e2710de4 100644 --- a/src/ui/render/ScrollRenderObject.cpp +++ b/src/ui/render/ScrollRenderObject.cpp @@ -38,12 +38,19 @@ Point CoerceScroll(const Point& scroll_offset, const Size& content_size, } } // namespace -ScrollRenderObject::ScrollRenderObject() : RenderObject(ChildMode::Single) { +ScrollRenderObject::ScrollRenderObject() : RenderObject() { scroll_bar_delegate_ = std::make_unique(this); scroll_bar_delegate_->ScrollAttemptEvent()->AddHandler( [this](const struct Scroll& scroll) { this->ApplyScroll(scroll); }); } +void ScrollRenderObject::SetChild(RenderObject* new_child) { + if (child_ == new_child) return; + if (child_) child_->SetParent(nullptr); + child_ = new_child; + if (child_) child_->SetParent(this); +} + void ScrollRenderObject::ApplyScroll(const struct Scroll& scroll) { auto direction = scroll.direction; @@ -72,9 +79,9 @@ void ScrollRenderObject::ApplyScroll(const struct Scroll& scroll) { } RenderObject* ScrollRenderObject::HitTest(const Point& point) { - if (const auto child = GetSingleChild()) { - const auto offset = child->GetOffset(); - const auto r = child->HitTest(point - offset); + if (child_) { + const auto offset = child_->GetOffset(); + const auto r = child_->HitTest(point - offset); if (r != nullptr) return r; } @@ -82,23 +89,23 @@ RenderObject* ScrollRenderObject::HitTest(const Point& point) { return rect.IsPointInside(point) ? this : nullptr; } // namespace cru::ui::render -void ScrollRenderObject::OnDrawCore(platform::graphics::IPainter* painter) { - DefaultDrawContent(painter); - if (const auto child = GetSingleChild()) { +void ScrollRenderObject::Draw(platform::graphics::IPainter* painter) { + if (child_) { painter->PushLayer(this->GetContentRect()); - const auto offset = child->GetOffset(); - platform::graphics::util::WithTransform( - painter, Matrix::Translation(offset.x, offset.y), - [child](platform::graphics::IPainter* p) { child->Draw(p); }); + const auto offset = child_->GetOffset(); + painter->PushState(); + painter->ConcatTransform(Matrix::Translation(offset)); + child_->Draw(painter); + painter->PopState(); painter->PopLayer(); } scroll_bar_delegate_->DrawScrollBar(painter); } Point ScrollRenderObject::GetScrollOffset() { - if (const auto child = GetSingleChild()) + if (child_) return CoerceScroll(scroll_offset_, GetContentRect().GetSize(), - child->GetSize()); + child_->GetDesiredSize()); else return scroll_offset_; } @@ -164,12 +171,12 @@ void ScrollRenderObject::SetMouseWheelScrollEnabled(bool enable) { Size ScrollRenderObject::OnMeasureContent(const MeasureRequirement& requirement, const MeasureSize& preferred_size) { - if (const auto child = GetSingleChild()) { - child->Measure(MeasureRequirement{MeasureSize::NotSpecified(), - MeasureSize::NotSpecified()}, - MeasureSize::NotSpecified()); + if (child_) { + child_->Measure(MeasureRequirement{MeasureSize::NotSpecified(), + MeasureSize::NotSpecified()}, + MeasureSize::NotSpecified()); - Size result = requirement.Coerce(child->GetSize()); + Size result = requirement.Coerce(child_->GetDesiredSize()); if (preferred_size.width.IsSpecified()) { result.width = preferred_size.width.GetLengthOrUndefined(); } @@ -189,16 +196,17 @@ Size ScrollRenderObject::OnMeasureContent(const MeasureRequirement& requirement, } // namespace cru::ui::render void ScrollRenderObject::OnLayoutContent(const Rect& content_rect) { - if (const auto child = GetSingleChild()) { - child->Layout(content_rect.GetLeftTop() - GetScrollOffset()); + if (child_) { + child_->Layout(content_rect.GetLeftTop() - GetScrollOffset()); } } -void ScrollRenderObject::OnAttachedControlChanged(controls::Control* control) { - if (control) { - scroll_bar_delegate_->InstallHandlers(control); +void ScrollRenderObject::OnAttachedControlChanged( + controls::Control* old_control, controls::Control* new_control) { + if (new_control) { + scroll_bar_delegate_->InstallHandlers(new_control); if (is_mouse_wheel_enabled_) { - InstallMouseWheelHandler(control); + InstallMouseWheelHandler(new_control); } } else { InstallMouseWheelHandler(nullptr); @@ -248,7 +256,7 @@ bool ScrollRenderObject::HorizontalCanScrollUp() { bool ScrollRenderObject::HorizontalCanScrollDown() { return GetScrollOffset().x < - GetFirstChild()->GetSize().width - GetViewRect().width; + child_->GetDesiredSize().width - GetViewRect().width; } bool ScrollRenderObject::VerticalCanScrollUp() { @@ -257,6 +265,6 @@ bool ScrollRenderObject::VerticalCanScrollUp() { bool ScrollRenderObject::VerticalCanScrollDown() { return GetScrollOffset().y < - GetFirstChild()->GetSize().height - GetViewRect().height; + child_->GetDesiredSize().height - GetViewRect().height; } } // namespace cru::ui::render diff --git a/src/ui/render/StackLayoutRenderObject.cpp b/src/ui/render/StackLayoutRenderObject.cpp index ea65fe02..6c79716f 100644 --- a/src/ui/render/StackLayoutRenderObject.cpp +++ b/src/ui/render/StackLayoutRenderObject.cpp @@ -21,11 +21,12 @@ void StackLayoutRenderObject::SetDefaultVertialAlignment(Alignment alignment) { Size StackLayoutRenderObject::OnMeasureContent( const MeasureRequirement& requirement, const MeasureSize& preferred_size) { Size child_max_size; - for (const auto child : GetChildren()) { + for (int i = 0; i < GetChildCount(); i++) { + auto child = GetChildAt(i); child->Measure( MeasureRequirement(requirement.max, MeasureSize::NotSpecified()), MeasureSize::NotSpecified()); - const auto size = child->GetSize(); + const auto size = child->GetDesiredSize(); child_max_size.width = std::max(child_max_size.width, size.width); child_max_size.height = std::max(child_max_size.height, size.height); } @@ -33,7 +34,7 @@ Size StackLayoutRenderObject::OnMeasureContent( child_max_size = Max(preferred_size.GetSizeOr0(), child_max_size); child_max_size = Max(requirement.min.GetSizeOr0(), child_max_size); - for (Index i = 0; i < GetChildren().size(); ++i) { + for (Index i = 0; i < GetChildCount(); ++i) { auto child_layout_data = GetChildLayoutData(i); auto horizontal_stretch = child_layout_data.horizontal.value_or(default_horizontal_alignment_) == @@ -42,8 +43,8 @@ Size StackLayoutRenderObject::OnMeasureContent( child_layout_data.vertical.value_or(default_vertical_alignment_) == Alignment::Stretch; if (horizontal_stretch || vertical_stretch) { - auto child = GetChildren()[i]; - auto child_size = child->GetSize(); + auto child = GetChildAt(i); + auto child_size = child->GetDesiredSize(); MeasureRequirement child_requirement(child_size, child_size); if (horizontal_stretch) { child_requirement.min.width = child_requirement.max.width = @@ -63,12 +64,11 @@ Size StackLayoutRenderObject::OnMeasureContent( void StackLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { const auto count = GetChildCount(); - const auto& children = GetChildren(); for (int i = 0; i < count; i++) { - const auto child = children[i]; + const auto child = GetChildAt(i); const auto& layout_data = GetChildLayoutData(i); - const auto& size = child->GetSize(); + const auto& size = child->GetDesiredSize(); child->Layout(Point{ CalculateAnchorByAlignment( layout_data.horizontal.value_or(default_horizontal_alignment_), diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp index 675bac3c..ec5ce662 100644 --- a/src/ui/render/TextRenderObject.cpp +++ b/src/ui/render/TextRenderObject.cpp @@ -21,8 +21,6 @@ TextRenderObject::TextRenderObject( Expects(selection_brush); Expects(caret_brush); - SetChildMode(ChildMode::None); - brush.swap(brush_); font.swap(font_); selection_brush.swap(selection_brush_); @@ -176,16 +174,19 @@ RenderObject* TextRenderObject::HitTest(const Point& point) { return padding_rect.IsPointInside(point) ? this : nullptr; } -void TextRenderObject::OnDrawContent(platform::graphics::IPainter* painter) { +void TextRenderObject::Draw(platform::graphics::IPainter* painter) { if constexpr (debug_flags::draw) { log::TagDebug(log_tag, u"Begin to paint, total_offset: {}, size: {}, text_layout: " u"{}, brush: {}.", - this->GetTotalOffset(), this->GetSize(), + this->GetTotalOffset(), this->GetDesiredSize(), this->text_layout_->GetDebugString(), this->brush_->GetDebugString()); } + painter->PushState(); + painter->ConcatTransform(Matrix::Translation(GetOffset())); + if (this->selection_range_.has_value()) { const auto&& rects = text_layout_->TextRangeRect(this->selection_range_.value()); @@ -198,6 +199,8 @@ void TextRenderObject::OnDrawContent(platform::graphics::IPainter* painter) { if (this->draw_caret_ && this->caret_width_ != 0.0f) { painter->FillRectangle(GetCaretRectInContent(), this->caret_brush_.get()); } + + painter->PopState(); } Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement, @@ -229,6 +232,4 @@ Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement, void TextRenderObject::OnLayoutContent(const Rect& content_rect) { CRU_UNUSED(content_rect) } - -void TextRenderObject::OnAfterLayout() {} } // namespace cru::ui::render diff --git a/src/ui/render/TreeRenderObject.cpp b/src/ui/render/TreeRenderObject.cpp index bea5b9de..9bf74535 100644 --- a/src/ui/render/TreeRenderObject.cpp +++ b/src/ui/render/TreeRenderObject.cpp @@ -34,7 +34,6 @@ void TreeRenderObjectItem::RemoveItem(Index position) { } TreeRenderObject::TreeRenderObject() { - SetChildMode(ChildMode::None); root_item_ = new TreeRenderObjectItem(this, nullptr); } @@ -81,7 +80,7 @@ void TreeRenderObjectItemDraw(TreeRenderObjectItem* item, } } -void TreeRenderObject::OnDrawCore(platform::graphics::IPainter* painter) { +void TreeRenderObject::Draw(platform::graphics::IPainter* painter) { TreeRenderObjectItemDraw(root_item_, painter); } @@ -95,7 +94,7 @@ static Size MeasureTreeRenderObjectItem(MeasureSize max_size, MeasureSize::NotSpecified()); } - Size item_size = render_object ? render_object->GetSize() : Size{}; + Size item_size = render_object ? render_object->GetDesiredSize() : Size{}; if (max_size.width.IsSpecified()) { max_size.width = max_size.width.GetLengthOrUndefined() - tab_width; @@ -133,7 +132,7 @@ static void LayoutTreeRenderObjectItem(Rect rect, TreeRenderObjectItem* item, float item_height = 0.f; if (render_object) { render_object->Layout(rect.GetLeftTop()); - item_height = render_object->GetSize().height; + item_height = render_object->GetDesiredSize().height; } rect.left += tab_width; @@ -144,8 +143,9 @@ static void LayoutTreeRenderObjectItem(Rect rect, TreeRenderObjectItem* item, for (auto child : item->GetChildren()) { LayoutTreeRenderObjectItem(rect, child, tab_width); auto child_render_object = child->GetRenderObject(); - auto child_height = - child_render_object ? child_render_object->GetSize().height : 0.f; + auto child_height = child_render_object + ? child_render_object->GetDesiredSize().height + : 0.f; rect.top += child_height; rect.height -= child_height; } -- cgit v1.2.3