blob: 6b6d899c31993ca0f0c01e286e4a27b3e90614c3 (
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include "scroll_control.hpp"
#include <limits>
#include "cru_debug.hpp"
#include "format.hpp"
namespace cru::ui::controls
{
ScrollControl::ScrollControl(const bool container) : Control(container)
{
SetClipContent(true);
}
ScrollControl::~ScrollControl()
{
}
void ScrollControl::SetHorizontalScrollEnabled(const bool enable)
{
horizontal_scroll_enabled_ = enable;
InvalidateLayout();
InvalidateDraw();
}
void ScrollControl::SetVerticalScrollEnabled(const bool enable)
{
vertical_scroll_enabled_ = enable;
InvalidateLayout();
InvalidateDraw();
}
Control* ScrollControl::HitTest(const Point& point)
{
}
void ScrollControl::SetViewWidth(const float length)
{
view_width_ = length;
}
void ScrollControl::SetViewHeight(const float length)
{
view_height_ = length;
}
Size ScrollControl::OnMeasureContent(const Size& available_size)
{
const auto layout_params = GetLayoutParams();
auto available_size_for_children = available_size;
if (IsHorizontalScrollEnabled())
{
if (layout_params->width.mode == MeasureMode::Content)
debug::DebugMessage(L"ScrollView: Width measure mode is Content and horizontal scroll is enabled. So Stretch is used instead.");
for (auto child : GetChildren())
{
const auto child_layout_params = child->GetLayoutParams();
if (child_layout_params->width.mode == MeasureMode::Stretch)
throw std::runtime_error(Format("ScrollView: Horizontal scroll is enabled but a child {} 's width measure mode is Stretch which may cause infinite length.", ToUtf8String(child->GetControlType())));
}
available_size_for_children.width = std::numeric_limits<float>::max();
}
if (IsVerticalScrollEnabled())
{
if (layout_params->height.mode == MeasureMode::Content)
debug::DebugMessage(L"ScrollView: Height measure mode is Content and vertical scroll is enabled. So Stretch is used instead.");
for (auto child : GetChildren())
{
const auto child_layout_params = child->GetLayoutParams();
if (child_layout_params->height.mode == MeasureMode::Stretch)
throw std::runtime_error(Format("ScrollView: Vertical scroll is enabled but a child {} 's height measure mode is Stretch which may cause infinite length.", ToUtf8String(child->GetControlType())));
}
available_size_for_children.height = std::numeric_limits<float>::max();
}
auto max_child_size = Size::Zero();
for (auto control: GetChildren())
{
control->Measure(available_size_for_children);
const auto&& size = control->GetDesiredSize();
if (max_child_size.width < size.width)
max_child_size.width = size.width;
if (max_child_size.height < size.height)
max_child_size.height = size.height;
}
// coerce size fro stretch.
for (auto control: GetChildren())
{
auto size = control->GetDesiredSize();
const auto child_layout_params = control->GetLayoutParams();
if (child_layout_params->width.mode == MeasureMode::Stretch)
size.width = max_child_size.width;
if (child_layout_params->height.mode == MeasureMode::Stretch)
size.height = max_child_size.height;
control->SetDesiredSize(size);
}
auto result = max_child_size;
if (IsHorizontalScrollEnabled())
{
SetViewWidth(max_child_size.width);
result.width = available_size.width;
}
if (IsVerticalScrollEnabled())
{
SetViewHeight(max_child_size.height);
result.height = available_size.height;
}
return result;
}
void ScrollControl::OnLayoutContent(const Rect& rect)
{
auto layout_rect = rect;
if (IsHorizontalScrollEnabled())
layout_rect.width = GetViewWidth();
if (IsVerticalScrollEnabled())
layout_rect.height = GetViewHeight();
for (auto control: GetChildren())
{
const auto size = control->GetDesiredSize();
// Ignore alignment, always center aligned.
auto&& calculate_anchor = [](const float anchor, const float layout_length, const float control_length) -> float
{
return anchor + (layout_length - control_length) / 2;
};
control->Layout(Rect(Point(
calculate_anchor(rect.left, layout_rect.width, size.width),
calculate_anchor(rect.top, layout_rect.height, size.height)
), size));
}
}
}
|