diff options
Diffstat (limited to 'CruUI/ui/controls')
| -rw-r--r-- | CruUI/ui/controls/linear_layout.cpp | 88 | ||||
| -rw-r--r-- | CruUI/ui/controls/linear_layout.h | 25 | ||||
| -rw-r--r-- | CruUI/ui/controls/text_block.cpp | 18 |
3 files changed, 124 insertions, 7 deletions
diff --git a/CruUI/ui/controls/linear_layout.cpp b/CruUI/ui/controls/linear_layout.cpp new file mode 100644 index 00000000..f639720d --- /dev/null +++ b/CruUI/ui/controls/linear_layout.cpp @@ -0,0 +1,88 @@ +#include "linear_layout.h" + +namespace cru::ui::controls +{ + LinearLayout::LinearLayout(const Orientation orientation) + : Control(true), orientation_(orientation) + { + + } + + Size LinearLayout::OnMeasure(const Size& available_size) + { + const auto layout_params = GetLayoutParams(); + + if (!layout_params->Validate()) + throw std::runtime_error("LayoutParams is not valid. Please check it."); + + auto&& get_available_length_for_child = [](const MeasureLength& 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 total_available_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) + ); + + auto rest_available_size_for_children = total_available_size_for_children; + + ForeachChild([this, &rest_available_size_for_children](Control* const control) + { + control->Measure(rest_available_size_for_children); + if (orientation_ == Orientation::Horizontal) + rest_available_size_for_children.width -= control->GetDesiredSize().width; + else + rest_available_size_for_children.height -= control->GetDesiredSize().height; + }); + + auto actual_size_for_children = total_available_size_for_children - rest_available_size_for_children; + + auto&& calculate_final_length = [](const MeasureLength& 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, total_available_size_for_children.width, actual_size_for_children.width), + calculate_final_length(layout_params->height, total_available_size_for_children.height, actual_size_for_children.height) + ); + } + + void LinearLayout::OnLayout(const Rect& rect) + { + auto current_anchor = Point::zero; + ForeachChild([this, ¤t_anchor](Control* control) + { + const auto size = control->GetDesiredSize(); + control->Layout(Rect(current_anchor, size)); + + if (orientation_ == Orientation::Horizontal) + current_anchor.x += size.width; + else + current_anchor.y += size.height; + }); + } +} diff --git a/CruUI/ui/controls/linear_layout.h b/CruUI/ui/controls/linear_layout.h new file mode 100644 index 00000000..b8722b6f --- /dev/null +++ b/CruUI/ui/controls/linear_layout.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ui/control.h" + +namespace cru::ui::controls +{ + class LinearLayout : public Control + { + public: + enum class Orientation + { + Horizontal, + Vertical + }; + + explicit LinearLayout(Orientation orientation = Orientation::Vertical); + + protected: + Size OnMeasure(const Size& available_size) override; + void OnLayout(const Rect& rect) override; + + private: + Orientation orientation_; + }; +} diff --git a/CruUI/ui/controls/text_block.cpp b/CruUI/ui/controls/text_block.cpp index 86d01896..3649aea6 100644 --- a/CruUI/ui/controls/text_block.cpp +++ b/CruUI/ui/controls/text_block.cpp @@ -53,7 +53,8 @@ namespace cru void TextBlock::OnDraw(ID2D1DeviceContext* device_context) { - device_context->DrawTextLayout(D2D1::Point2F(), text_layout_.Get(), brush_.Get()); + if (text_layout_ != nullptr) + device_context->DrawTextLayout(D2D1::Point2F(), text_layout_.Get(), brush_.Get()); } Size TextBlock::OnMeasure(const Size& available_size) @@ -67,7 +68,7 @@ namespace cru if (layout_params->width.mode == MeasureMode::Stretch && layout_params->height.mode == MeasureMode::Stretch) return available_size; - Size measure_size; + Size measure_size; // NOLINT(cppcoreguidelines-pro-type-member-init) auto&& get_measure_length = [](const MeasureLength& layout_length, const float available_length) -> float { @@ -95,8 +96,9 @@ namespace cru const auto dwrite_factory = GetDWriteFactory(); - dwrite_factory->CreateTextLayout(text_.c_str(), text_.size(), - text_format_.Get(), measure_size.width, measure_size.height, &measure_text_layout); + ThrowIfFailed(dwrite_factory->CreateTextLayout(text_.c_str(), text_.size(), + text_format_.Get(), measure_size.width, measure_size.height, &measure_text_layout) + ); DWRITE_TEXT_METRICS metrics{}; measure_text_layout->GetMetrics(&metrics); @@ -113,10 +115,12 @@ namespace cru return measure_result_length; }; - return Size( + const Size result_size( calculate_final_length(layout_params->width, measure_size.width, measure_result.width), calculate_final_length(layout_params->height, measure_size.height, measure_result.height) ); + + return result_size; } void TextBlock::OnTextChangedCore(const String& old_text, const String& new_text) @@ -162,12 +166,12 @@ namespace cru const auto&& size = GetSize(); - dwrite_factory->CreateTextLayout( + ThrowIfFailed(dwrite_factory->CreateTextLayout( text_.c_str(), text_.size(), text_format_.Get(), size.width, size.height, &text_layout_ - ); + )); std::for_each(text_layout_handlers_.cbegin(), text_layout_handlers_.cend(), [this](const std::shared_ptr<TextLayoutHandler>& handler) { |
