From 88765aab936724cb01fa2ffd86d65181182a1cd2 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 30 Sep 2018 20:38:10 +0800 Subject: Create border delegate. --- src/ui/control.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/ui/control.cpp') diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 81cfe9b1..480f7d46 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -257,7 +257,7 @@ namespace cru { { SetPositionRelative(rect.GetLeftTop()); SetSize(rect.GetSize()); - OnLayout(rect); + OnLayout(Rect(Point::Zero(), rect.GetSize())); } Size Control::GetDesiredSize() const @@ -617,24 +617,24 @@ namespace cru { const auto layout_params = control->GetLayoutParams(); const auto size = control->GetDesiredSize(); - auto&& calculate_anchor = [](const Alignment alignment, const float layout_length, const float control_length) -> float + auto&& calculate_anchor = [](const float anchor, const Alignment alignment, const float layout_length, const float control_length) -> float { switch (alignment) { case Alignment::Center: - return (layout_length - control_length) / 2; + return anchor + (layout_length - control_length) / 2; case Alignment::Start: - return 0; + return anchor; case Alignment::End: - return layout_length - control_length; + return anchor + layout_length - control_length; default: UnreachableCode(); } }; control->Layout(Rect(Point( - calculate_anchor(layout_params->width.alignment, rect.width, size.width), - calculate_anchor(layout_params->height.alignment, rect.height, size.height) + calculate_anchor(rect.left, layout_params->width.alignment, rect.width, size.width), + calculate_anchor(rect.top, layout_params->height.alignment, rect.height, size.height) ), size)); }); } -- cgit v1.2.3 From f55a20fd3bad952481339d47ff844ad816192f50 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 2 Oct 2018 00:32:21 +0800 Subject: Fix measure system of border. --- src/ui/control.cpp | 113 ++++++++++++++++++++++++++++++++++++ src/ui/control.h | 3 + src/ui/controls/border_delegate.cpp | 12 ---- src/ui/controls/border_delegate.h | 6 +- src/ui/controls/button.cpp | 10 ++++ src/ui/controls/button.h | 3 + 6 files changed, 133 insertions(+), 14 deletions(-) (limited to 'src/ui/control.cpp') diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 480f7d46..86101f9a 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -639,6 +639,119 @@ namespace cru { }); } + inline Size ThicknessToSize(const Thickness& thickness) + { + return Size(thickness.left + thickness.right, thickness.top + thickness.bottom); + } + + inline float AtLeast0(const float value) + { + return value < 0 ? 0 : value; + } + + inline Size AtLeast0(const Size& size) + { + return Size(AtLeast0(size.width), AtLeast0(size.height)); + } + + Size Control::DefaultMeasureWithPadding(const Size& available_size, const Thickness& padding) + { + const auto layout_params = GetLayoutParams(); + const auto padding_size = ThicknessToSize(padding); + + if (!layout_params->Validate()) + throw std::runtime_error("LayoutParams is not valid. Please check it."); + + auto&& get_available_length_for_child = [](const LayoutSideParams& layout_length, const float available_length) -> float + { + switch (layout_length.mode) + { + case MeasureMode::Exactly: + { + return std::min(layout_length.length, available_length); + } + case MeasureMode::Stretch: + case MeasureMode::Content: + { + return available_length; + } + default: + UnreachableCode(); + } + }; + + Size size_for_children(get_available_length_for_child(layout_params->width, available_size.width), + get_available_length_for_child(layout_params->height, available_size.height)); + + size_for_children = AtLeast0(size_for_children - padding_size); + + auto max_child_size = Size::Zero(); + ForeachChild([&](Control* control) + { + control->Measure(size_for_children); + const auto&& size = control->GetDesiredSize(); + if (max_child_size.width < size.width) + max_child_size.width = size.width; + if (max_child_size.height < size.height) + max_child_size.height = size.height; + }); + + auto&& calculate_final_length = [](const LayoutSideParams& layout_length, const float length_for_children, const float max_child_length) -> float + { + switch (layout_length.mode) + { + case MeasureMode::Exactly: + case MeasureMode::Stretch: + return length_for_children; + case MeasureMode::Content: + return max_child_length; + default: + UnreachableCode(); + } + }; + + return Size( + calculate_final_length(layout_params->width, size_for_children.width, max_child_size.width), + calculate_final_length(layout_params->height, size_for_children.height, max_child_size.height) + ) + padding_size; + } + + void Control::DefaultLayoutWithPadding(const Rect& rect, const Thickness& padding) + { + const Rect final_rect( + rect.left + padding.left, + rect.top + padding.top, + rect.width - padding.left - padding.right, + rect.height - padding.top - padding.bottom + ); + + ForeachChild([final_rect](Control* control) + { + const auto layout_params = control->GetLayoutParams(); + const auto size = control->GetDesiredSize(); + + auto&& calculate_anchor = [](const float anchor, const Alignment alignment, const float layout_length, const float control_length) -> float + { + switch (alignment) + { + case Alignment::Center: + return anchor + (layout_length - control_length) / 2; + case Alignment::Start: + return anchor; + case Alignment::End: + return anchor + layout_length - control_length; + default: + UnreachableCode(); + } + }; + + control->Layout(Rect(Point( + calculate_anchor(final_rect.left, layout_params->width.alignment, final_rect.width, size.width), + calculate_anchor(final_rect.top, layout_params->height.alignment, final_rect.height, size.height) + ), size)); + }); + } + void Control::CheckAndNotifyPositionChanged() { if (this->old_position_ != this->position_) diff --git a/src/ui/control.h b/src/ui/control.h index 98d41d0d..964b61c4 100644 --- a/src/ui/control.h +++ b/src/ui/control.h @@ -309,6 +309,9 @@ namespace cru virtual Size OnMeasure(const Size& available_size); virtual void OnLayout(const Rect& rect); + Size DefaultMeasureWithPadding(const Size& available_size, const Thickness& padding); + void DefaultLayoutWithPadding(const Rect& rect, const Thickness& padding); + private: // Only for layout manager to use. // Check if the old position is updated to current position. diff --git a/src/ui/controls/border_delegate.cpp b/src/ui/controls/border_delegate.cpp index ec7ba437..0b460997 100644 --- a/src/ui/controls/border_delegate.cpp +++ b/src/ui/controls/border_delegate.cpp @@ -82,16 +82,4 @@ namespace cru::ui::controls border_property_->GetStrokeStyle().Get() ); } - - Size BorderDelegate::GetBorderSize() const - { - const auto width = border_property_->GetWidth(); - return Size(width * 2, width * 2); - } - - Rect BorderDelegate::CoerceLayoutRect(const Rect& rect) const - { - const auto width = border_property_->GetWidth(); - return Rect(rect.left + width, rect.top + width, rect.width - width * 2, rect.height - width * 2); - } } diff --git a/src/ui/controls/border_delegate.h b/src/ui/controls/border_delegate.h index 5a7dfbed..6d3b31db 100644 --- a/src/ui/controls/border_delegate.h +++ b/src/ui/controls/border_delegate.h @@ -90,8 +90,10 @@ namespace cru::ui::controls void Draw(ID2D1DeviceContext* device_context, const Size& size) const; - Size GetBorderSize() const; - Rect CoerceLayoutRect(const Rect& rect) const; + Thickness GetBorderThickness() const + { + return Thickness(border_property_->GetWidth()); + } private: Control* control_; diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp index 630c0c39..2ecc9f14 100644 --- a/src/ui/controls/button.cpp +++ b/src/ui/controls/button.cpp @@ -29,6 +29,16 @@ namespace cru::ui::controls border_delegate_->Draw(device_context, GetSize()); } + Size Button::OnMeasure(const Size& available_size) + { + return Control::DefaultMeasureWithPadding(available_size, border_delegate_->GetBorderThickness()); + } + + void Button::OnLayout(const Rect& rect) + { + Control::DefaultLayoutWithPadding(rect, border_delegate_->GetBorderThickness()); + } + void Button::OnMouseClickBegin(MouseButton button) { border_delegate_->SetBorderProperty(pressed_border_border_); diff --git a/src/ui/controls/button.h b/src/ui/controls/button.h index 7a303984..4b57a5a3 100644 --- a/src/ui/controls/button.h +++ b/src/ui/controls/button.h @@ -31,6 +31,9 @@ namespace cru::ui::controls protected: void OnDraw(ID2D1DeviceContext* device_context) override; + Size OnMeasure(const Size& available_size) override; + void OnLayout(const Rect& rect) override; + void OnMouseClickBegin(MouseButton button) override final; void OnMouseClickEnd(MouseButton button) override final; -- cgit v1.2.3