diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/control.cpp | 64 | ||||
-rw-r--r-- | src/ui/controls/linear_layout.cpp | 31 | ||||
-rw-r--r-- | src/ui/controls/text_block.h | 2 | ||||
-rw-r--r-- | src/ui/layout_base.h | 9 |
4 files changed, 51 insertions, 55 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 93d26e81..79def066 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -5,6 +5,7 @@ #include "window.h" #include "graph/graph.h" #include "exception.h" +#include "cru_debug.h" namespace cru { namespace ui { @@ -697,6 +698,9 @@ namespace cru { { const auto layout_params = GetLayoutParams(); + if (!layout_params->Validate()) + throw std::runtime_error("LayoutParams is not valid. Please check it."); + auto border_size = Size::Zero(); if (is_bordered_) { @@ -704,54 +708,39 @@ namespace cru { border_size = Size(border_width * 2.0f, border_width * 2.0f); } + // the total size of padding, border and margin const auto outer_size = ThicknessToSize(layout_params->padding) + ThicknessToSize(layout_params->margin) + border_size; - 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 + auto&& get_content_measure_length = [](const LayoutSideParams& layout_length, const float available_length, const float outer_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(); - } + if (layout_length.mode == MeasureMode::Exactly) + return layout_length.length; + if (available_length > outer_length) + return available_length - outer_length; + return 0.0; }; - const auto size_for_children = AtLeast0(Size( - get_available_length_for_child(layout_params->width, available_size.width), - get_available_length_for_child(layout_params->height, available_size.height) - ) - outer_size); + // if padding, margin and border exceeded, then content size is 0. + const auto content_measure_size = Size( + get_content_measure_length(layout_params->width, available_size.width, outer_size.width), + get_content_measure_length(layout_params->height, available_size.height, outer_size.height) + ); - const auto actual_size_for_children = OnMeasureContent(size_for_children); + const auto content_actual_size = OnMeasureContent(content_measure_size); - auto&& calculate_final_length = [](const LayoutSideParams& layout_length, const float length_for_children, const float actual_length_for_children) -> float + auto&& calculate_final_length = [](const LayoutSideParams& layout_length, const float measure_length, const float actual_length) -> float { - switch (layout_length.mode) - { - case MeasureMode::Exactly: - case MeasureMode::Stretch: - return length_for_children; - case MeasureMode::Content: - return actual_length_for_children; - default: - UnreachableCode(); - } + // only use measure length when stretch and actual length is smaller than measure length, that is "stretch" + if (layout_length.mode == MeasureMode::Stretch && actual_length < measure_length) + return measure_length; + return actual_length; }; const auto final_size = Size( - calculate_final_length(layout_params->width, size_for_children.width, actual_size_for_children.width), - calculate_final_length(layout_params->height, size_for_children.height, actual_size_for_children.height) + calculate_final_length(layout_params->width, content_measure_size.width, content_actual_size.width), + calculate_final_length(layout_params->height, content_measure_size.height, content_actual_size.height) ) + outer_size; return final_size; @@ -774,6 +763,11 @@ namespace cru { rect.height - layout_params->padding.GetVerticalTotal() - layout_params->margin.GetVerticalTotal() - border_width * 2.0f ); + if (content_rect.width < 0.0) + throw std::runtime_error(Format("Width to layout must sufficient. But in {}, width for content is {}.", ToUtf8String(GetControlType()), content_rect.width)); + if (content_rect.height < 0.0) + throw std::runtime_error(Format("Height to layout must sufficient. But in {}, height for content is {}.", ToUtf8String(GetControlType()), content_rect.height)); + OnLayoutContent(content_rect); } diff --git a/src/ui/controls/linear_layout.cpp b/src/ui/controls/linear_layout.cpp index c23957ed..ed445f4c 100644 --- a/src/ui/controls/linear_layout.cpp +++ b/src/ui/controls/linear_layout.cpp @@ -27,7 +27,7 @@ namespace cru::ui::controls Size LinearLayout::OnMeasureContent(const Size& available_size) { - auto rest_available_size_for_children = available_size; + auto actual_size_for_children = Size::Zero(); float secondary_side_child_max_length = 0; @@ -40,9 +40,10 @@ namespace cru::ui::controls const auto mode = control->GetLayoutParams()->width.mode; if (mode == MeasureMode::Content || mode == MeasureMode::Exactly) { - control->Measure(AtLeast0(rest_available_size_for_children)); + Size current_available_size(AtLeast0(available_size.width - actual_size_for_children.width), available_size.height); + control->Measure(current_available_size); const auto size = control->GetDesiredSize(); - rest_available_size_for_children.width -= size.width; + actual_size_for_children.width += size.width; secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length); } else @@ -54,9 +55,10 @@ namespace cru::ui::controls const auto mode = control->GetLayoutParams()->height.mode; if (mode == MeasureMode::Content || mode == MeasureMode::Exactly) { - control->Measure(AtLeast0(rest_available_size_for_children)); + Size current_available_size(available_size.width, AtLeast0(available_size.height - actual_size_for_children.height)); + control->Measure(current_available_size); const auto size = control->GetDesiredSize(); - rest_available_size_for_children.height -= size.height; + actual_size_for_children.height += size.height; secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length); } else @@ -65,38 +67,31 @@ namespace cru::ui::controls if (orientation_ == Orientation::Horizontal) { - const auto available_width = rest_available_size_for_children.width / stretch_control_list.size(); + const auto available_width = AtLeast0(available_size.width - actual_size_for_children.width) / stretch_control_list.size(); for (const auto control : stretch_control_list) { - control->Measure(Size(AtLeast0(available_width), rest_available_size_for_children.height)); + control->Measure(Size(available_width, available_size.height)); const auto size = control->GetDesiredSize(); - rest_available_size_for_children.width -= size.width; + actual_size_for_children.width += size.width; secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length); } } else { - const auto available_height = rest_available_size_for_children.height / stretch_control_list.size(); + const auto available_height = AtLeast0(available_size.height - actual_size_for_children.height) / stretch_control_list.size(); for (const auto control : stretch_control_list) { - control->Measure(Size(rest_available_size_for_children.width, AtLeast0(available_height))); + control->Measure(Size(available_size.width, available_height)); const auto size = control->GetDesiredSize(); - rest_available_size_for_children.height -= size.height; + actual_size_for_children.height += size.height; secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length); } } - auto actual_size_for_children = available_size; if (orientation_ == Orientation::Horizontal) - { - actual_size_for_children.width -= rest_available_size_for_children.width; actual_size_for_children.height = secondary_side_child_max_length; - } else - { actual_size_for_children.width = secondary_side_child_max_length; - actual_size_for_children.height -= rest_available_size_for_children.height; - } return actual_size_for_children; } diff --git a/src/ui/controls/text_block.h b/src/ui/controls/text_block.h index cd0af1cc..681dc47b 100644 --- a/src/ui/controls/text_block.h +++ b/src/ui/controls/text_block.h @@ -19,6 +19,8 @@ namespace cru::ui::controls return text_block; } + using TextControl::SetSelectable; // Make this public. + protected: TextBlock( const Microsoft::WRL::ComPtr<IDWriteTextFormat>& init_text_format, diff --git a/src/ui/layout_base.h b/src/ui/layout_base.h index 0d924436..662210bd 100644 --- a/src/ui/layout_base.h +++ b/src/ui/layout_base.h @@ -63,6 +63,11 @@ namespace cru return top + bottom; } + float Validate() const + { + return left >= 0.0 && top >= 0.0 && right >= 0.0 && bottom >= 0.0; + } + float left; float top; float right; @@ -96,7 +101,7 @@ namespace cru constexpr bool Validate() const { - return !(mode == MeasureMode::Exactly && length < 0.0); + return length >= 0.0; } float length = 0.0; @@ -115,7 +120,7 @@ namespace cru bool Validate() const { - return width.Validate() && height.Validate(); + return width.Validate() && height.Validate() && margin.Validate() && padding.Validate(); } LayoutSideParams width; |