aboutsummaryrefslogtreecommitdiff
path: root/CruUI/ui/controls
diff options
context:
space:
mode:
Diffstat (limited to 'CruUI/ui/controls')
-rw-r--r--CruUI/ui/controls/linear_layout.cpp88
-rw-r--r--CruUI/ui/controls/linear_layout.h25
-rw-r--r--CruUI/ui/controls/text_block.cpp18
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, &current_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)
{