aboutsummaryrefslogtreecommitdiff
path: root/src/ui/render
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-06-25 23:44:43 +0800
committercrupest <crupest@outlook.com>2020-06-25 23:44:43 +0800
commita48ff30f9d4ac8ae6cc9adef4a07f8d9beb69e7a (patch)
tree077a74943214da7627cca2ba9966d90d5bed144a /src/ui/render
parentce0ae2c3727f83f1943d528b006eec94ad80ece9 (diff)
downloadcru-a48ff30f9d4ac8ae6cc9adef4a07f8d9beb69e7a.tar.gz
cru-a48ff30f9d4ac8ae6cc9adef4a07f8d9beb69e7a.tar.bz2
cru-a48ff30f9d4ac8ae6cc9adef4a07f8d9beb69e7a.zip
Write layout logic at half way.
Diffstat (limited to 'src/ui/render')
-rw-r--r--src/ui/render/BorderRenderObject.cpp68
-rw-r--r--src/ui/render/CanvasRenderObject.cpp9
-rw-r--r--src/ui/render/FlexLayoutRenderObject.cpp385
-rw-r--r--src/ui/render/LayoutUtility.cpp15
-rw-r--r--src/ui/render/RenderObject.cpp86
-rw-r--r--src/ui/render/ScrollRenderObject.cpp40
-rw-r--r--src/ui/render/StackLayoutRenderObject.cpp86
-rw-r--r--src/ui/render/TextRenderObject.cpp44
-rw-r--r--src/ui/render/WindowRenderObject.cpp10
9 files changed, 415 insertions, 328 deletions
diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp
index ad0c6455..74e50561 100644
--- a/src/ui/render/BorderRenderObject.cpp
+++ b/src/ui/render/BorderRenderObject.cpp
@@ -73,9 +73,10 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) {
}
}
-Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement) {
+Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
if (!is_border_enabled_) {
- return RenderObject::OnMeasureCore(requirement);
+ return RenderObject::OnMeasureCore(requirement, preferred_size);
}
const auto margin = GetMargin();
@@ -90,36 +91,51 @@ Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement) {
MeasureRequirement content_requirement = requirement;
- if (!requirement.max_width.IsNotSpecify()) {
- const auto max_width = requirement.max_width.GetLength();
+ if (!requirement.max.width.IsNotSpecified()) {
+ const auto max_width = requirement.max.width.GetLengthOrMax();
if (coerced_space_size.width > max_width) {
log::Warn(
- "Measure: horizontal length of padding and margin is bigger than "
- "available length.");
+ "BorderRenderObject: During measure, horizontal length of padding, "
+ "border and margin is bigger than required max length.");
coerced_space_size.width = max_width;
}
- content_requirement.max_width = max_width - coerced_space_size.width;
+ content_requirement.max.width = max_width - coerced_space_size.width;
}
- if (!requirement.max_height.IsNotSpecify()) {
- const auto max_height = requirement.max_height.GetLength();
+ if (!requirement.min.width.IsNotSpecified()) {
+ const auto min_width = requirement.min.width.GetLengthOr0();
+ content_requirement.min.width = std::max(0.f, min_width - space_size.width);
+ }
+
+ if (!requirement.max.height.IsNotSpecified()) {
+ const auto max_height = requirement.max.height.GetLengthOrMax();
if (coerced_space_size.height > max_height) {
log::Warn(
- "Measure: horizontal length of padding and margin is bigger than "
- "available length.");
+ "BorderRenderObject: During measure, vertical length of padding, "
+ "border and margin is bigger than required max length.");
coerced_space_size.height = max_height;
}
- content_requirement.max_height = max_height - coerced_space_size.height;
+ content_requirement.max.height = max_height - coerced_space_size.height;
}
- const auto content_size = OnMeasureContent(content_requirement);
+ if (!requirement.min.height.IsNotSpecified()) {
+ const auto min_height = requirement.min.height.GetLengthOr0();
+ content_requirement.min.height =
+ std::max(0.f, min_height - space_size.height);
+ }
+
+ MeasureSize content_preferred_size =
+ content_requirement.Coerce(preferred_size.Minus(space_size));
+
+ const auto content_size =
+ OnMeasureContent(content_requirement, content_preferred_size);
return coerced_space_size + content_size;
-} // namespace cru::ui::render
+}
-void BorderRenderObject::OnLayoutCore(const Size& size) {
+void BorderRenderObject::OnLayoutCore() {
if (!is_border_enabled_) {
- return RenderObject::OnLayoutCore(size);
+ return RenderObject::OnLayoutCore();
}
const auto margin = GetMargin();
@@ -129,18 +145,20 @@ void BorderRenderObject::OnLayoutCore(const Size& size) {
margin.GetVerticalTotal() + padding.GetVerticalTotal() +
border_thickness_.GetVerticalTotal()};
+ const auto size = GetSize();
+
auto content_size = size - space_size;
if (content_size.width < 0) {
log::Warn(
- "Layout: horizontal length of padding, border and margin is bigger "
- "than available length.");
+ "BorderRenderObject: During layout, horizontal length of padding, "
+ "border and margin is bigger than available length.");
content_size.width = 0;
}
if (content_size.height < 0) {
log::Warn(
- "Layout: vertical length of padding, border and margin is bigger "
- "than available length.");
+ "BorderRenderObject: During layout, vertical length of padding, "
+ "border and margin is bigger than available length.");
content_size.height = 0;
}
@@ -158,12 +176,12 @@ void BorderRenderObject::OnLayoutCore(const Size& size) {
OnLayoutContent(content_rect);
}
-Size BorderRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
+Size BorderRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
const auto child = GetSingleChild();
if (child) {
- child->Measure(requirement);
- return child->GetMeasuredSize();
+ child->Measure(requirement, preferred_size);
+ return child->GetSize();
} else {
return Size{};
}
@@ -172,7 +190,7 @@ Size BorderRenderObject::OnMeasureContent(
void BorderRenderObject::OnLayoutContent(const Rect& content_rect) {
const auto child = GetSingleChild();
if (child) {
- child->Layout(content_rect);
+ child->Layout(content_rect.GetLeftTop());
}
}
diff --git a/src/ui/render/CanvasRenderObject.cpp b/src/ui/render/CanvasRenderObject.cpp
index 72eb3570..211d1fce 100644
--- a/src/ui/render/CanvasRenderObject.cpp
+++ b/src/ui/render/CanvasRenderObject.cpp
@@ -1,7 +1,5 @@
#include "cru/ui/render/CanvasRenderObject.hpp"
-#include "cru/ui/render/LayoutUtility.hpp"
-
namespace cru::ui::render {
CanvasRenderObject::CanvasRenderObject() : RenderObject(ChildMode::None) {}
@@ -18,9 +16,10 @@ RenderObject* CanvasRenderObject::HitTest(const Point& point) {
return padding_rect.IsPointInside(point) ? this : nullptr;
}
-Size CanvasRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
- return Min(requirement.GetMaxSize(), GetDesiredSize());
+Size CanvasRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
+ return requirement.Coerce(Size{preferred_size.width.GetLengthOr(100),
+ preferred_size.height.GetLengthOr(100)});
}
void CanvasRenderObject::OnLayoutContent(const Rect& content_rect) {
diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp
index 72341a64..fcaf6f9a 100644
--- a/src/ui/render/FlexLayoutRenderObject.cpp
+++ b/src/ui/render/FlexLayoutRenderObject.cpp
@@ -7,194 +7,207 @@
namespace cru::ui::render {
Size FlexLayoutRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
- const bool horizontal = (direction_ == FlexDirection::Horizontal ||
- direction_ == FlexDirection::HorizontalReverse);
-
- const auto main_max_length =
- horizontal ? requirement.max_width : requirement.max_height;
- const auto cross_max_length =
- horizontal ? requirement.max_height : requirement.max_width;
-
- std::function<float(const Size&)> get_main_length;
- std::function<float(const Size&)> get_cross_length;
- std::function<void(Size&, const Size&)> calculate_result_size;
- std::function<MeasureRequirement(MeasureLength main, MeasureLength cross)>
- create_requirement;
-
- if (horizontal) {
- get_main_length = [](const Size& size) { return size.width; };
- get_cross_length = [](const Size& size) { return size.height; };
- calculate_result_size = [](Size& result, const Size& child_size) {
- result.width += child_size.width;
- result.height = std::max(result.height, child_size.height);
- };
- create_requirement = [](MeasureLength main, MeasureLength cross) {
- return MeasureRequirement{main, cross};
- };
- } else {
- get_main_length = [](const Size& size) { return size.height; };
- get_cross_length = [](const Size& size) { return size.width; };
- calculate_result_size = [](Size& result, const Size& child_size) {
- result.height += child_size.height;
- result.width = std::max(result.width, child_size.width);
- };
- create_requirement = [](MeasureLength main, MeasureLength cross) {
- return MeasureRequirement{cross, main};
- };
- }
-
- const auto& children = GetChildren();
- Index children_count = children.size();
-
- if (!main_max_length.IsNotSpecify()) {
- float remain_main_length = main_max_length.GetLength();
-
- for (Index i = 0; i < children_count; i++) {
- const auto child = children[i];
- child->Measure(create_requirement(remain_main_length, cross_max_length));
- const auto measure_result = child->GetMeasuredSize();
- remain_main_length -= get_main_length(measure_result);
- }
-
- if (remain_main_length > 0) {
- std::vector<Index> expand_children;
- float total_expand_factor = 0;
-
- for (Index i = 0; i < children_count; i++) {
- const auto factor = GetChildLayoutData(i)->expand_factor;
- if (factor > 0) {
- expand_children.push_back(i);
- total_expand_factor += factor;
- }
- }
-
- for (const Index i : expand_children) {
- const float distributed_grow_length =
- remain_main_length *
- (GetChildLayoutData(i)->expand_factor / total_expand_factor);
- const auto child = children[i];
- const float new_main_length =
- get_main_length(child->GetMeasuredSize()) + distributed_grow_length;
- child->Measure(create_requirement(new_main_length, cross_max_length));
- }
- } else if (remain_main_length < 0) {
- std::vector<Index> shrink_children;
- float total_shrink_factor = 0;
-
- for (Index i = 0; i < children_count; i++) {
- const auto factor = GetChildLayoutData(i)->shrink_factor;
- if (factor > 0) {
- shrink_children.push_back(i);
- total_shrink_factor += factor;
- }
- }
-
- for (const Index i : shrink_children) {
- const float distributed_shrink_length = // negative
- remain_main_length *
- (GetChildLayoutData(i)->shrink_factor / total_shrink_factor);
- const auto child = children[i];
- float new_main_length = get_main_length(child->GetMeasuredSize()) +
- distributed_shrink_length;
- new_main_length = new_main_length > 0 ? new_main_length : 0;
- child->Measure(create_requirement(new_main_length, cross_max_length));
- }
- }
- } else {
- for (Index i = 0; i < children_count; i++) {
- const auto child = children[i];
- child->Measure(requirement);
- }
- }
-
- Size result;
- for (auto child : children) {
- calculate_result_size(result, child->GetMeasuredSize());
- }
-
- return result;
+ const MeasureRequirement& requirement, const MeasureSize& preferred_size) {
+ // TODO: Rewrite this.
+ CRU_UNUSED(requirement);
+ CRU_UNUSED(preferred_size);
+ throw std::runtime_error("Not implemented.");
+
+ // const bool horizontal = (direction_ == FlexDirection::Horizontal ||
+ // direction_ == FlexDirection::HorizontalReverse);
+
+ // const auto main_max_length =
+ // horizontal ? requirement.max_width : requirement.max_height;
+ // const auto cross_max_length =
+ // horizontal ? requirement.max_height : requirement.max_width;
+
+ // std::function<float(const Size&)> get_main_length;
+ // std::function<float(const Size&)> get_cross_length;
+ // std::function<void(Size&, const Size&)> calculate_result_size;
+ // std::function<MeasureRequirement(MeasureLength main, MeasureLength cross)>
+ // create_requirement;
+
+ // if (horizontal) {
+ // get_main_length = [](const Size& size) { return size.width; };
+ // get_cross_length = [](const Size& size) { return size.height; };
+ // calculate_result_size = [](Size& result, const Size& child_size) {
+ // result.width += child_size.width;
+ // result.height = std::max(result.height, child_size.height);
+ // };
+ // create_requirement = [](MeasureLength main, MeasureLength cross) {
+ // return MeasureRequirement{main, cross};
+ // };
+ // } else {
+ // get_main_length = [](const Size& size) { return size.height; };
+ // get_cross_length = [](const Size& size) { return size.width; };
+ // calculate_result_size = [](Size& result, const Size& child_size) {
+ // result.height += child_size.height;
+ // result.width = std::max(result.width, child_size.width);
+ // };
+ // create_requirement = [](MeasureLength main, MeasureLength cross) {
+ // return MeasureRequirement{cross, main};
+ // };
+ // }
+
+ // const auto& children = GetChildren();
+ // Index children_count = children.size();
+
+ // if (!main_max_length.IsNotSpecify()) {
+ // float remain_main_length = main_max_length.GetLengthOrMax();
+
+ // for (Index i = 0; i < children_count; i++) {
+ // const auto child = children[i];
+ // child->Measure(create_requirement(remain_main_length,
+ // cross_max_length)); const auto measure_result =
+ // child->GetMeasuredSize(); remain_main_length -=
+ // get_main_length(measure_result);
+ // }
+
+ // if (remain_main_length > 0) {
+ // std::vector<Index> expand_children;
+ // float total_expand_factor = 0;
+
+ // for (Index i = 0; i < children_count; i++) {
+ // const auto factor = GetChildLayoutData(i)->expand_factor;
+ // if (factor > 0) {
+ // expand_children.push_back(i);
+ // total_expand_factor += factor;
+ // }
+ // }
+
+ // for (const Index i : expand_children) {
+ // const float distributed_grow_length =
+ // remain_main_length *
+ // (GetChildLayoutData(i)->expand_factor / total_expand_factor);
+ // const auto child = children[i];
+ // const float new_main_length =
+ // get_main_length(child->GetMeasuredSize()) +
+ // distributed_grow_length;
+ // child->Measure(create_requirement(new_main_length,
+ // cross_max_length));
+ // }
+ // } else if (remain_main_length < 0) {
+ // std::vector<Index> shrink_children;
+ // float total_shrink_factor = 0;
+
+ // for (Index i = 0; i < children_count; i++) {
+ // const auto factor = GetChildLayoutData(i)->shrink_factor;
+ // if (factor > 0) {
+ // shrink_children.push_back(i);
+ // total_shrink_factor += factor;
+ // }
+ // }
+
+ // for (const Index i : shrink_children) {
+ // const float distributed_shrink_length = // negative
+ // remain_main_length *
+ // (GetChildLayoutData(i)->shrink_factor / total_shrink_factor);
+ // const auto child = children[i];
+ // float new_main_length = get_main_length(child->GetMeasuredSize()) +
+ // distributed_shrink_length;
+ // new_main_length = new_main_length > 0 ? new_main_length : 0;
+ // child->Measure(create_requirement(new_main_length,
+ // cross_max_length));
+ // }
+ // }
+ // } else {
+ // for (Index i = 0; i < children_count; i++) {
+ // const auto child = children[i];
+ // child->Measure(requirement);
+ // }
+ // }
+
+ // Size result;
+ // for (auto child : children) {
+ // calculate_result_size(result, child->GetMeasuredSize());
+ // }
+
+ // return result;
}
void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
- auto calculate_anchor = [](int alignment, float start_point,
- float total_length,
- float content_length) -> float {
- switch (alignment) {
- case internal::align_start:
- return start_point;
- case internal::align_center:
- return start_point + (total_length - content_length) / 2.0f;
- case internal::align_end:
- return start_point + total_length - content_length;
- default:
- return start_point;
- }
- };
-
- const auto& children = GetChildren();
- if (direction_ == FlexDirection::Horizontal ||
- direction_ == FlexDirection::HorizontalReverse) {
- float actual_content_width = 0;
- for (const auto child : children) {
- actual_content_width += child->GetMeasuredSize().width;
- }
-
- const float content_anchor_x =
- calculate_anchor(static_cast<int>(content_main_align_), 0,
- content_rect.width, actual_content_width);
-
- float anchor_x = 0;
- for (int i = 0; i < static_cast<int>(children.size()); i++) {
- const auto child = children[i];
- const auto size = child->GetMeasuredSize();
-
- float real_anchor_x = anchor_x + content_anchor_x;
- if (direction_ == FlexDirection::Horizontal)
- real_anchor_x = content_rect.left + real_anchor_x;
- else
- real_anchor_x = content_rect.GetRight() - real_anchor_x;
- child->Layout(Rect{
- real_anchor_x,
- calculate_anchor(
- static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
- this->item_cross_align_)),
- content_rect.top, content_rect.height, size.height),
- size.width, size.height});
-
- anchor_x += size.width;
- }
- } else {
- float actual_content_height = 0;
- for (const auto child : children) {
- actual_content_height = child->GetMeasuredSize().height;
- }
-
- const float content_anchor_y =
- calculate_anchor(static_cast<int>(content_main_align_), 0,
- content_rect.height, actual_content_height);
-
- float anchor_y = 0;
- for (int i = 0; i < static_cast<int>(children.size()); i++) {
- const auto child = children[i];
- const auto size = child->GetMeasuredSize();
-
- float real_anchor_y = anchor_y + content_anchor_y;
- if (direction_ == FlexDirection::Vertical) {
- real_anchor_y = content_rect.top + real_anchor_y;
- } else {
- real_anchor_y = content_rect.GetBottom() - real_anchor_y;
- }
- child->Layout(Rect{
- real_anchor_y,
- calculate_anchor(
- static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
- this->item_cross_align_)),
- content_rect.left, content_rect.width, size.width),
- size.width, size.height});
-
- anchor_y += size.height;
- }
- }
+ // TODO: Rewrite this.
+ CRU_UNUSED(content_rect);
+ throw std::runtime_error("Not implemented.");
+
+ // auto calculate_anchor = [](int alignment, float start_point,
+ // float total_length,
+ // float content_length) -> float {
+ // switch (alignment) {
+ // case internal::align_start:
+ // return start_point;
+ // case internal::align_center:
+ // return start_point + (total_length - content_length) / 2.0f;
+ // case internal::align_end:
+ // return start_point + total_length - content_length;
+ // default:
+ // return start_point;
+ // }
+ // };
+
+ // const auto& children = GetChildren();
+ // if (direction_ == FlexDirection::Horizontal ||
+ // direction_ == FlexDirection::HorizontalReverse) {
+ // float actual_content_width = 0;
+ // for (const auto child : children) {
+ // actual_content_width += child->GetMeasuredSize().width;
+ // }
+
+ // const float content_anchor_x =
+ // calculate_anchor(static_cast<int>(content_main_align_), 0,
+ // content_rect.width, actual_content_width);
+
+ // float anchor_x = 0;
+ // for (int i = 0; i < static_cast<int>(children.size()); i++) {
+ // const auto child = children[i];
+ // const auto size = child->GetMeasuredSize();
+
+ // float real_anchor_x = anchor_x + content_anchor_x;
+ // if (direction_ == FlexDirection::Horizontal)
+ // real_anchor_x = content_rect.left + real_anchor_x;
+ // else
+ // real_anchor_x = content_rect.GetRight() - real_anchor_x;
+ // child->Layout(Rect{
+ // real_anchor_x,
+ // calculate_anchor(
+ // static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
+ // this->item_cross_align_)),
+ // content_rect.top, content_rect.height, size.height),
+ // size.width, size.height});
+
+ // anchor_x += size.width;
+ // }
+ // } else {
+ // float actual_content_height = 0;
+ // for (const auto child : children) {
+ // actual_content_height = child->GetMeasuredSize().height;
+ // }
+
+ // const float content_anchor_y =
+ // calculate_anchor(static_cast<int>(content_main_align_), 0,
+ // content_rect.height, actual_content_height);
+
+ // float anchor_y = 0;
+ // for (int i = 0; i < static_cast<int>(children.size()); i++) {
+ // const auto child = children[i];
+ // const auto size = child->GetMeasuredSize();
+
+ // float real_anchor_y = anchor_y + content_anchor_y;
+ // if (direction_ == FlexDirection::Vertical) {
+ // real_anchor_y = content_rect.top + real_anchor_y;
+ // } else {
+ // real_anchor_y = content_rect.GetBottom() - real_anchor_y;
+ // }
+ // child->Layout(Rect{
+ // real_anchor_y,
+ // calculate_anchor(
+ // static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
+ // this->item_cross_align_)),
+ // content_rect.left, content_rect.width, size.width),
+ // size.width, size.height});
+
+ // anchor_y += size.height;
+ // }
+ // }
}
} // namespace cru::ui::render
diff --git a/src/ui/render/LayoutUtility.cpp b/src/ui/render/LayoutUtility.cpp
deleted file mode 100644
index 03252f1c..00000000
--- a/src/ui/render/LayoutUtility.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "cru/ui/render/LayoutUtility.hpp"
-
-#include <algorithm>
-
-namespace cru::ui::render {
-Size Min(const Size& left, const Size& right) {
- return Size{std::min(left.width, right.width),
- std::min(left.height, right.height)};
-}
-
-Size Max(const Size& left, const Size& right) {
- return Size{std::max(left.width, right.width),
- std::max(left.height, right.height)};
-}
-} // namespace cru::ui::render
diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp
index abd5e1c4..ac38c6b5 100644
--- a/src/ui/render/RenderObject.cpp
+++ b/src/ui/render/RenderObject.cpp
@@ -57,20 +57,23 @@ Point RenderObject::FromRootToContent(const Point& point) const {
point.y - (offset.y + rect.top)};
}
-void RenderObject::Measure(const MeasureRequirement& requirement) {
- measured_size_ = OnMeasureCore(requirement);
+void RenderObject::Measure(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
+ MeasureRequirement merged_requirement =
+ MeasureRequirement::Merge(requirement, custom_measure_requirement_)
+ .Normalize();
+ MeasureSize merged_preferred_size =
+ preferred_size.OverrideBy(preferred_size_);
- Ensures(measured_size_.width >= 0);
- Ensures(measured_size_.height >= 0);
- Ensures(requirement.Satisfy(measured_size_));
+ size_ = OnMeasureCore(merged_requirement, merged_preferred_size);
+ Ensures(size_.width >= 0);
+ Ensures(size_.height >= 0);
+ Ensures(requirement.Satisfy(size_));
}
-void RenderObject::Layout(const Rect& rect) {
- Expects(rect.width >= 0);
- Expects(rect.height >= 0);
- offset_ = rect.GetLeftTop();
- size_ = rect.GetSize();
- OnLayoutCore(rect.GetSize());
+void RenderObject::Layout(const Point& offset) {
+ offset_ = offset;
+ OnLayoutCore();
}
RenderObject* RenderObject::GetSingleChild() const {
@@ -104,7 +107,8 @@ void RenderObject::OnRemoveChild(RenderObject* removed_child, Index position) {
InvalidatePaint();
}
-Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement) {
+Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
const Size space_size{
margin_.GetHorizontalTotal() + padding_.GetHorizontalTotal(),
margin_.GetVerticalTotal() + padding_.GetVerticalTotal()};
@@ -113,58 +117,74 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement) {
MeasureRequirement content_requirement = requirement;
- if (!requirement.max_width.IsNotSpecify()) {
- const auto max_width = requirement.max_width.GetLength();
+ if (!requirement.max.width.IsNotSpecified()) {
+ const auto max_width = requirement.max.width.GetLengthOrMax();
if (coerced_space_size.width > max_width) {
log::Warn(
- "Measure: horizontal length of padding and margin is bigger than "
- "available length.");
+ "RenderObject: During measure, horizontal length of padding and "
+ "margin is bigger than required max length.");
coerced_space_size.width = max_width;
}
- content_requirement.max_width = max_width - coerced_space_size.width;
+ content_requirement.max.width = max_width - coerced_space_size.width;
}
- if (!requirement.max_height.IsNotSpecify()) {
- const auto max_height = requirement.max_height.GetLength();
+ if (!requirement.min.width.IsNotSpecified()) {
+ const auto min_width = requirement.min.width.GetLengthOr0();
+ content_requirement.min.width = std::max(0.f, min_width - space_size.width);
+ }
+
+ if (!requirement.max.height.IsNotSpecified()) {
+ const auto max_height = requirement.max.height.GetLengthOrMax();
if (coerced_space_size.height > max_height) {
log::Warn(
- "Measure: horizontal length of padding and margin is bigger than "
- "available length.");
+ "RenderObject: During measure, vertical length of padding and "
+ "margin is bigger than required max length.");
coerced_space_size.height = max_height;
}
- content_requirement.max_height = max_height - coerced_space_size.height;
+ content_requirement.max.height = max_height - coerced_space_size.height;
}
- const auto content_size = OnMeasureContent(content_requirement);
+ if (!requirement.min.height.IsNotSpecified()) {
+ const auto min_height = requirement.min.height.GetLengthOr0();
+ content_requirement.min.height =
+ std::max(0.f, min_height - space_size.height);
+ }
+
+ MeasureSize content_preferred_size =
+ content_requirement.Coerce(preferred_size.Minus(space_size));
+
+ const auto content_size =
+ OnMeasureContent(content_requirement, content_preferred_size);
return coerced_space_size + content_size;
}
-void RenderObject::OnLayoutCore(const Size& size) {
+void RenderObject::OnLayoutCore() {
+ Size total_size = GetSize();
Size space_size{margin_.GetHorizontalTotal() + padding_.GetHorizontalTotal(),
margin_.GetVerticalTotal() + padding_.GetVerticalTotal()};
- auto content_size = size - space_size;
+ auto content_size = total_size - space_size;
if (content_size.width < 0) {
log::Warn(
- "Layout: horizontal length of padding and margin is bigger than "
- "available length.");
+ "RenderObject: During layout, horizontal length of padding and margin "
+ "is bigger than available length.");
content_size.width = 0;
}
if (content_size.height < 0) {
log::Warn(
- "Layout: vertical length of padding and margin is bigger than "
- "available length.");
+ "RenderObject: During layout, vertical length of padding and margin "
+ "is bigger than available length.");
content_size.height = 0;
}
Point lefttop{margin_.left + padding_.left, margin_.top + padding_.top};
- if (lefttop.x > size.width) {
- lefttop.x = size.width;
+ if (lefttop.x > total_size.width) {
+ lefttop.x = total_size.width;
}
- if (lefttop.y > size.height) {
- lefttop.y = size.height;
+ if (lefttop.y > total_size.height) {
+ lefttop.y = total_size.height;
}
const Rect content_rect{lefttop, content_size};
diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp
index 98254690..e4cc27f3 100644
--- a/src/ui/render/ScrollRenderObject.cpp
+++ b/src/ui/render/ScrollRenderObject.cpp
@@ -2,7 +2,6 @@
#include "cru/platform/graph/Painter.hpp"
#include "cru/platform/graph/util/Painter.hpp"
-#include "cru/ui/render/LayoutUtility.hpp"
#include <algorithm>
@@ -67,23 +66,32 @@ void ScrollRenderObject::SetScrollOffset(const Point& offset) {
InvalidateLayout();
}
-Size ScrollRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
- if (const auto child = GetSingleChild()) {
- child->Measure(MeasureRequirement::Infinate());
- const auto preferred_size = child->GetMeasuredSize();
- return Min(preferred_size, requirement.GetMaxSize());
- } else {
- return Size{};
- }
+Size ScrollRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
+ // TODO: Rewrite this.
+ CRU_UNUSED(requirement);
+ CRU_UNUSED(preferred_size);
+ throw std::runtime_error("Not implemented.");
+
+ // if (const auto child = GetSingleChild()) {
+ // child->Measure(MeasureRequirement::Infinate());
+ // const auto preferred_size = child->GetMeasuredSize();
+ // return Min(preferred_size, requirement.GetMaxSize());
+ // } else {
+ // return Size{};
+ // }
} // namespace cru::ui::render
void ScrollRenderObject::OnLayoutContent(const Rect& content_rect) {
- if (const auto child = GetSingleChild()) {
- const auto child_size = child->GetMeasuredSize();
- const auto true_scroll =
- CoerceScroll(scroll_offset_, content_rect.GetSize(), child_size);
- child->Layout(Rect{content_rect.GetLeftTop() - true_scroll, child_size});
- }
+ // TODO: Rewrite this.
+ CRU_UNUSED(content_rect);
+ throw std::runtime_error("Not implemented.");
+
+ // if (const auto child = GetSingleChild()) {
+ // const auto child_size = child->GetMeasuredSize();
+ // const auto true_scroll =
+ // CoerceScroll(scroll_offset_, content_rect.GetSize(), child_size);
+ // child->Layout(Rect{content_rect.GetLeftTop() - true_scroll, child_size});
+ // }
}
} // namespace cru::ui::render
diff --git a/src/ui/render/StackLayoutRenderObject.cpp b/src/ui/render/StackLayoutRenderObject.cpp
index 7dce1a83..b953ae7e 100644
--- a/src/ui/render/StackLayoutRenderObject.cpp
+++ b/src/ui/render/StackLayoutRenderObject.cpp
@@ -4,47 +4,57 @@
namespace cru::ui::render {
Size StackLayoutRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
- auto size = Size{};
- for (const auto child : GetChildren()) {
- child->Measure(requirement);
- const auto& measure_result = child->GetMeasuredSize();
- size.width = std::max(size.width, measure_result.width);
- size.height = std::max(size.height, measure_result.height);
- }
- return size;
+ const MeasureRequirement& requirement, const MeasureSize& preferred_size) {
+ // TODO: Rewrite this.
+ CRU_UNUSED(requirement);
+ CRU_UNUSED(preferred_size);
+ throw std::runtime_error("Not implemented.");
+
+ // throw std::runtime_error("Not implemented.");
+ // auto size = Size{};
+ // for (const auto child : GetChildren()) {
+ // child->Measure(requirement);
+ // const auto& measure_result = child->GetMeasuredSize();
+ // size.width = std::max(size.width, measure_result.width);
+ // size.height = std::max(size.height, measure_result.height);
+ // }
+ // return size;
}
-void StackLayoutRenderObject::OnLayoutContent(const Rect& rect) {
- auto calculate_anchor = [](int alignment, float start_point,
- float total_length,
- float content_length) -> float {
- switch (alignment) {
- case internal::align_start:
- return start_point;
- case internal::align_center:
- return start_point + (total_length - content_length) / 2.0f;
- case internal::align_end:
- return start_point + total_length - content_length;
- default:
- return start_point;
- }
- };
+void StackLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
+ // TODO: Rewrite this.
+ CRU_UNUSED(content_rect);
+ throw std::runtime_error("Not implemented.");
- const auto count = GetChildCount();
- const auto& children = GetChildren();
+ // auto calculate_anchor = [](int alignment, float start_point,
+ // float total_length,
+ // float content_length) -> float {
+ // switch (alignment) {
+ // case internal::align_start:
+ // return start_point;
+ // case internal::align_center:
+ // return start_point + (total_length - content_length) / 2.0f;
+ // case internal::align_end:
+ // return start_point + total_length - content_length;
+ // default:
+ // return start_point;
+ // }
+ // };
- for (int i = 0; i < count; i++) {
- const auto layout_data = GetChildLayoutData(i);
- const auto child = children[i];
- const auto& size = child->GetMeasuredSize();
- child->Layout(
- Rect{calculate_anchor(static_cast<int>(layout_data->horizontal),
- rect.left, rect.width, size.width),
- calculate_anchor(static_cast<int>(layout_data->vertical), rect.top,
- rect.height, size.height),
- size.width, size.height});
- }
-}
+ // const auto count = GetChildCount();
+ // const auto& children = GetChildren();
+ // for (int i = 0; i < count; i++) {
+ // const auto layout_data = GetChildLayoutData(i);
+ // const auto child = children[i];
+ // const auto& size = child->GetMeasuredSize();
+ // child->Layout(
+ // Rect{calculate_anchor(static_cast<int>(layout_data->horizontal),
+ // rect.left, rect.width, size.width),
+ // calculate_anchor(static_cast<int>(layout_data->vertical),
+ // rect.top,
+ // rect.height, size.height),
+ // size.width, size.height});
+ // }
+}
} // namespace cru::ui::render
diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp
index ececfbc2..9cae65d6 100644
--- a/src/ui/render/TextRenderObject.cpp
+++ b/src/ui/render/TextRenderObject.cpp
@@ -1,10 +1,10 @@
#include "cru/ui/render/TextRenderObject.hpp"
#include "../Helper.hpp"
+#include "cru/common/Logger.hpp"
#include "cru/platform/graph/Factory.hpp"
#include "cru/platform/graph/TextLayout.hpp"
#include "cru/platform/graph/util/Painter.hpp"
-#include "cru/ui/render/LayoutUtility.hpp"
#include <algorithm>
#include <limits>
@@ -160,10 +160,44 @@ RenderObject* TextRenderObject::HitTest(const Point& point) {
return padding_rect.IsPointInside(point) ? this : nullptr;
}
-Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement) {
- text_layout_->SetMaxWidth(requirement.max_height.GetLength());
- text_layout_->SetMaxHeight(requirement.max_height.GetLength());
- return Min(text_layout_->GetTextBounds().GetSize(), requirement.GetMaxSize());
+Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
+ float measure_width;
+ if (preferred_size.width.IsSpecified())
+ measure_width = preferred_size.width.GetLengthOrUndefined();
+ else
+ measure_width = preferred_size.width.GetLengthOrMax();
+
+ text_layout_->SetMaxWidth(measure_width);
+ text_layout_->SetMaxHeight(std::numeric_limits<float>::max());
+
+ const auto text_size = text_layout_->GetTextBounds().GetSize();
+ auto result = text_size;
+
+ if (requirement.max.width.IsSpecified() &&
+ text_size.width > requirement.max.width.GetLengthOrUndefined()) {
+ log::Warn(
+ "TextRenderObject: Text actual width exceeds the required max width.");
+ result.width = requirement.max.width.GetLengthOrUndefined();
+ } else {
+ result.width = std::max(result.width, preferred_size.width.GetLengthOr0());
+ result.width = std::max(result.width, requirement.min.width.GetLengthOr0());
+ }
+
+ if (requirement.max.height.IsSpecified() &&
+ text_size.height > requirement.max.height.GetLengthOrUndefined()) {
+ log::Warn(
+ "TextRenderObject: Text actual height exceeds the required max "
+ "height.");
+ result.width = requirement.max.width.GetLengthOrUndefined();
+ } else {
+ result.height =
+ std::max(result.height, preferred_size.height.GetLengthOr0());
+ result.width =
+ std::max(result.height, requirement.min.height.GetLengthOr0());
+ }
+
+ return result;
}
void TextRenderObject::OnLayoutContent(const Rect& content_rect) {
diff --git a/src/ui/render/WindowRenderObject.cpp b/src/ui/render/WindowRenderObject.cpp
index 28afe01d..a2c7ae4d 100644
--- a/src/ui/render/WindowRenderObject.cpp
+++ b/src/ui/render/WindowRenderObject.cpp
@@ -34,17 +34,17 @@ RenderObject* WindowRenderObject::HitTest(const Point& point) {
return Rect{Point{}, GetSize()}.IsPointInside(point) ? this : nullptr;
}
-Size WindowRenderObject::OnMeasureContent(
- const MeasureRequirement& requirement) {
+Size WindowRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) {
if (const auto child = GetChild()) {
- child->Measure(requirement);
- return child->GetMeasuredSize();
+ child->Measure(requirement, preferred_size);
+ return child->GetSize();
} else {
return Size{};
}
}
void WindowRenderObject::OnLayoutContent(const Rect& content_rect) {
- if (const auto child = GetChild()) child->Layout(content_rect);
+ if (const auto child = GetChild()) child->Layout(content_rect.GetLeftTop());
}
} // namespace cru::ui::render