aboutsummaryrefslogtreecommitdiff
path: root/src/ui/render/StackLayoutRenderObject.cpp
blob: fda9a420bc8a18c6a76796ad2c9bcba3d0f1e9be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "cru/ui/render/StackLayoutRenderObject.h"

#include "cru/common/Logger.h"
#include "cru/ui/render/LayoutHelper.h"
#include "cru/ui/render/MeasureRequirement.h"

#include <algorithm>

namespace cru::ui::render {
void StackLayoutRenderObject::SetDefaultHorizontalAlignment(
    Alignment alignment) {
  default_horizontal_alignment_ = alignment;
  InvalidateLayout();
}

void StackLayoutRenderObject::SetDefaultVertialAlignment(Alignment alignment) {
  default_vertical_alignment_ = alignment;
  InvalidateLayout();
}

Size StackLayoutRenderObject::OnMeasureContent(
    const MeasureRequirement& requirement, const MeasureSize& preferred_size) {
  Size child_max_size;
  for (int i = 0; i < GetChildCount(); i++) {
    auto child = GetChildAt(i);
    child->Measure(
        MeasureRequirement(requirement.max, MeasureSize::NotSpecified()),
        MeasureSize::NotSpecified());
    const auto size = child->GetDesiredSize();
    child_max_size.width = std::max(child_max_size.width, size.width);
    child_max_size.height = std::max(child_max_size.height, size.height);
  }

  child_max_size = Max(preferred_size.GetSizeOr0(), child_max_size);
  child_max_size = Max(requirement.min.GetSizeOr0(), child_max_size);

  for (Index i = 0; i < GetChildCount(); ++i) {
    auto child_layout_data = GetChildLayoutDataAt(i);
    auto horizontal_stretch =
        child_layout_data.horizontal.value_or(default_horizontal_alignment_) ==
        Alignment::Stretch;
    auto vertical_stretch =
        child_layout_data.vertical.value_or(default_vertical_alignment_) ==
        Alignment::Stretch;
    if (horizontal_stretch || vertical_stretch) {
      auto child = GetChildAt(i);
      auto child_size = child->GetDesiredSize();
      MeasureRequirement child_requirement(child_size, child_size);
      if (horizontal_stretch) {
        child_requirement.min.width = child_requirement.max.width =
            child_max_size.width;
      }

      if (vertical_stretch) {
        child_requirement.min.height = child_requirement.max.height =
            child_max_size.height;
      }
      child->Measure(child_requirement, MeasureSize::NotSpecified());
    }
  }

  return child_max_size;
}

void StackLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
  const auto count = GetChildCount();

  for (int i = 0; i < count; i++) {
    const auto child = GetChildAt(i);
    const auto& layout_data = GetChildLayoutDataAt(i);
    const auto& size = child->GetDesiredSize();
    child->Layout(Point{
        CalculateAnchorByAlignment(
            layout_data.horizontal.value_or(default_horizontal_alignment_),
            content_rect.left, content_rect.width, size.width),
        CalculateAnchorByAlignment(
            layout_data.vertical.value_or(default_vertical_alignment_),
            content_rect.top, content_rect.height, size.height)});
  }
}
}  // namespace cru::ui::render