aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CruUI-Generate/cru_ui.cpp337
-rw-r--r--CruUI-Generate/cru_ui.hpp183
2 files changed, 124 insertions, 396 deletions
diff --git a/CruUI-Generate/cru_ui.cpp b/CruUI-Generate/cru_ui.cpp
index 6db99a0e..8f64a791 100644
--- a/CruUI-Generate/cru_ui.cpp
+++ b/CruUI-Generate/cru_ui.cpp
@@ -990,27 +990,25 @@ namespace cru::ui
Point Control::GetPositionRelative()
{
- return position_;
+ return rect_.GetLeftTop();
}
- void Control::SetPositionRelative(const Point & position)
+ Size Control::GetSize()
{
- if (position != position_)
- {
- if (old_position_ == position) // if cache has been refreshed and no pending notify
- old_position_ = position_;
- position_ = position;
- LayoutManager::GetInstance()->InvalidateControlPositionCache(this);
- if (auto window = GetWindow())
- {
- window->InvalidateDraw();
- }
- }
+ return rect_.GetSize();
}
- Size Control::GetSize()
+ void Control::SetRect(const Rect& rect)
{
- return size_;
+ const auto old_rect = rect_;
+ rect_ = rect;
+
+ RegenerateGeometryInfo();
+
+ OnRectChange(old_rect, rect);
+
+ if (auto window = GetWindow())
+ window->InvalidateDraw();
}
namespace
@@ -1034,24 +1032,6 @@ namespace cru::ui
#endif
}
- void Control::SetSize(const Size & size)
- {
- const auto old_size = size_;
- size_ = size;
- events::SizeChangedEventArgs args(this, this, old_size, size);
- size_changed_event.Raise(args);
-
- RegenerateGeometryInfo();
-
-#ifdef CRU_DEBUG_LAYOUT
- margin_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Margin), GetRect(RectRange::FullBorder));
- padding_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Padding), GetRect(RectRange::Content));
-#endif
-
- if (auto window = GetWindow())
- window->InvalidateDraw();
- }
-
Point Control::GetPositionAbsolute() const
{
return position_cache_.lefttop_position_absolute;
@@ -1187,17 +1167,21 @@ namespace cru::ui
window->WindowInvalidateLayout();
}
- void Control::Measure(const Size& available_size)
+ void Control::Measure(const Size& available_size, const AdditionalMeasureInfo& additional_info)
{
- SetDesiredSize(OnMeasureCore(available_size));
+ SetDesiredSize(OnMeasureCore(available_size, additional_info));
}
- void Control::Layout(const Rect& rect)
+ void Control::Layout(const Rect& rect, const AdditionalLayoutInfo& additional_info)
{
- SetPositionRelative(rect.GetLeftTop());
- SetSize(rect.GetSize());
- AfterLayoutSelf();
- OnLayoutCore(Rect(Point::Zero(), rect.GetSize()));
+ auto my_additional_info = additional_info;
+ my_additional_info.total_offset.x += rect.left;
+ my_additional_info.total_offset.y += rect.top;
+ position_cache_.lefttop_position_absolute.x = my_additional_info.total_offset.x;
+ position_cache_.lefttop_position_absolute.y = my_additional_info.total_offset.y;
+
+ SetRect(rect);
+ OnLayoutCore(Rect(Point::Zero(), rect.GetSize()), my_additional_info);
}
Size Control::GetDesiredSize() const
@@ -1380,6 +1364,11 @@ namespace cru::ui
});
}
+ void Control::OnRectChange(const Rect& old_rect, const Rect& new_rect)
+ {
+
+ }
+
void Control::RegenerateGeometryInfo()
{
if (IsBordered())
@@ -1439,6 +1428,12 @@ namespace cru::ui
);
geometry_info_.content_geometry = std::move(geometry2);
}
+
+ //TODO: generate debug geometry
+#ifdef CRU_DEBUG_LAYOUT
+ margin_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Margin), GetRect(RectRange::FullBorder));
+ padding_geometry_ = CalculateSquareRingGeometry(GetRect(RectRange::Padding), GetRect(RectRange::Content));
+#endif
}
void Control::OnMouseClickBegin(MouseButton button)
@@ -1454,13 +1449,28 @@ namespace cru::ui
return Size(thickness.left + thickness.right, thickness.top + thickness.bottom);
}
- Size Control::OnMeasureCore(const Size& available_size)
+ Size Control::OnMeasureCore(const Size& available_size, const AdditionalMeasureInfo& additional_info)
{
const auto layout_params = GetLayoutParams();
if (!layout_params->Validate())
throw std::runtime_error("LayoutParams is not valid. Please check it.");
+ auto my_additional_info = additional_info;
+
+ if (layout_params->width.mode == MeasureMode::Content)
+ my_additional_info.horizontal_stretchable = false;
+ else if (layout_params->width.mode == MeasureMode::Exactly)
+ my_additional_info.horizontal_stretchable = true;
+ // if stretch, then inherent parent's value
+
+ if (layout_params->height.mode == MeasureMode::Content)
+ my_additional_info.vertical_stretchable = false;
+ else if (layout_params->height.mode == MeasureMode::Exactly)
+ my_additional_info.vertical_stretchable = true;
+ // if stretch, then inherent parent's value
+
+
auto border_size = Size::Zero();
if (is_bordered_)
{
@@ -1491,66 +1501,9 @@ namespace cru::ui
get_content_measure_length(layout_params->height, available_size.height, outer_size.height)
);
- const auto content_actual_size = OnMeasureContent(content_measure_size);
-
- auto stretch_width = false;
- auto stretch_width_determined = true;
- auto stretch_height = false;
- auto stretch_height_determined = true;
+ const auto content_actual_size = OnMeasureContent(content_measure_size, my_additional_info);
- // if it is stretch, init is stretch, and undetermined.
- if (layout_params->width.mode == MeasureMode::Stretch)
- {
- stretch_width = true;
- stretch_width_determined = false;
- }
- if (layout_params->height.mode == MeasureMode::Stretch)
- {
- stretch_height = true;
- stretch_width_determined = false;
- }
- if (!stretch_width_determined || !stretch_height_determined)
- {
- auto parent = GetParent();
- while (parent != nullptr)
- {
- const auto lp = parent->GetLayoutParams();
-
- if (!stretch_width_determined)
- {
- if (lp->width.mode == MeasureMode::Content) // if the first ancestor that is not stretch is content, then it can't stretch.
- {
- stretch_width = false;
- stretch_width_determined = true;
- }
- if (lp->width.mode == MeasureMode::Exactly) // if the first ancestor that is not stretch is content, then it must be stretch.
- {
- stretch_width = true;
- stretch_width_determined = true;
- }
- }
-
- if (!stretch_height_determined) // the same as width
- {
- if (lp->height.mode == MeasureMode::Content) // if the first ancestor that is not stretch is content, then it can't stretch.
- {
- stretch_height = false;
- stretch_height_determined = true;
- }
- if (lp->height.mode == MeasureMode::Exactly) // if the first ancestor that is not stretch is content, then it must be stretch.
- {
- stretch_height = true;
- stretch_height_determined = true;
- }
- }
-
- if (stretch_width_determined && stretch_height_determined) // if both are determined.
- break;
-
- parent = GetParent();
- }
- }
auto&& calculate_final_length = [](const bool stretch, const std::optional<float> min_length, const float measure_length, const float actual_length) -> float
{
@@ -1561,14 +1514,14 @@ namespace cru::ui
};
const auto final_size = Size(
- calculate_final_length(stretch_width, layout_params->width.min, content_measure_size.width, content_actual_size.width),
- calculate_final_length(stretch_height, layout_params->height.min, content_measure_size.height, content_actual_size.height)
+ calculate_final_length(my_additional_info.horizontal_stretchable, layout_params->width.min, content_measure_size.width, content_actual_size.width),
+ calculate_final_length(my_additional_info.vertical_stretchable, layout_params->height.min, content_measure_size.height, content_actual_size.height)
) + outer_size;
return final_size;
}
- void Control::OnLayoutCore(const Rect& rect)
+ void Control::OnLayoutCore(const Rect& rect, const AdditionalLayoutInfo& additional_info)
{
const auto layout_params = GetLayoutParams();
@@ -1590,15 +1543,15 @@ namespace cru::ui
if (content_rect.height < 0.0)
throw std::runtime_error(Format("Height to layout must sufficient. But in {}, height for content is {}.", ToUtf8String(GetControlType()), content_rect.height));
- OnLayoutContent(content_rect);
+ OnLayoutContent(content_rect, additional_info);
}
- Size Control::OnMeasureContent(const Size& available_size)
+ Size Control::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info)
{
auto max_child_size = Size::Zero();
for (auto control: GetChildren())
{
- control->Measure(available_size);
+ control->Measure(available_size, additional_info);
const auto&& size = control->GetDesiredSize();
if (max_child_size.width < size.width)
max_child_size.width = size.width;
@@ -1621,7 +1574,7 @@ namespace cru::ui
return max_child_size;
}
- void Control::OnLayoutContent(const Rect& rect)
+ void Control::OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info)
{
for (auto control: GetChildren())
{
@@ -1646,22 +1599,7 @@ namespace cru::ui
control->Layout(Rect(Point(
calculate_anchor(rect.left, layout_params->width.alignment, rect.width, size.width),
calculate_anchor(rect.top, layout_params->height.alignment, rect.height, size.height)
- ), size));
- }
- }
-
- void Control::AfterLayoutSelf()
- {
-
- }
-
- void Control::CheckAndNotifyPositionChanged()
- {
- if (this->old_position_ != this->position_)
- {
- events::PositionChangedEventArgs args(this, this, this->old_position_, this->position_);
- position_changed_event.Raise(args);
- this->old_position_ = this->position_;
+ ), size), additional_info);
}
}
@@ -1768,84 +1706,9 @@ namespace cru::ui
//-------begin of file: src\ui\layout_base.cpp
//--------------------------------------------------------
-
namespace cru::ui
{
- LayoutManager* LayoutManager::GetInstance()
- {
- return Application::GetInstance()->ResolveSingleton<LayoutManager>([](auto)
- {
- return new LayoutManager{};
- });
- }
-
- void LayoutManager::InvalidateControlPositionCache(Control * control)
- {
- if (cache_invalid_controls_.count(control) == 1)
- return;
-
- // find descendant then erase it; find ancestor then just return.
- auto i = cache_invalid_controls_.cbegin();
- while (i != cache_invalid_controls_.cend())
- {
- auto current_i = i++;
- const auto result = IsAncestorOrDescendant(*current_i, control);
- if (result == control)
- cache_invalid_controls_.erase(current_i);
- else if (result != nullptr)
- return; // find a ancestor of "control", just return
- }
-
- cache_invalid_controls_.insert(control);
-
- if (cache_invalid_controls_.size() == 1) // when insert just now and not repeat to "InvokeLater".
- {
- InvokeLater([this] {
- for (const auto i : cache_invalid_controls_)
- RefreshControlPositionCache(i);
- for (const auto i : cache_invalid_controls_) // traverse all descendants of position-invalid controls and notify position change event
- i->TraverseDescendants([](Control* control)
- {
- control->CheckAndNotifyPositionChanged();
- });
- cache_invalid_controls_.clear(); // after update and notify, clear the set.
-
- });
- }
- }
- void LayoutManager::RefreshInvalidControlPositionCache()
- {
- for (const auto i : cache_invalid_controls_)
- RefreshControlPositionCache(i);
- cache_invalid_controls_.clear();
- }
-
- void LayoutManager::RefreshControlPositionCache(Control * control)
- {
- auto point = Point::Zero();
- auto parent = control;
- while ((parent = parent->GetParent())) {
- const auto p = parent->GetPositionRelative();
- point.x += p.x;
- point.y += p.y;
- }
- RefreshControlPositionCacheInternal(control, point);
- }
-
- void LayoutManager::RefreshControlPositionCacheInternal(Control * control, const Point & parent_lefttop_absolute)
- {
- const auto position = control->GetPositionRelative();
- const Point lefttop(
- parent_lefttop_absolute.x + position.x,
- parent_lefttop_absolute.y + position.y
- );
- control->position_cache_.lefttop_position_absolute = lefttop;
- for(auto c : control->GetChildren())
- {
- RefreshControlPositionCacheInternal(c, lefttop);
- }
- }
}
//--------------------------------------------------------
//-------end of file: src\ui\layout_base.cpp
@@ -2449,17 +2312,12 @@ namespace cru::ui
return Point();
}
- void Window::SetPositionRelative(const Point & position)
- {
-
- }
-
Size Window::GetSize()
{
return GetClientSize();
}
- void Window::SetSize(const Size & size)
+ void Window::SetRect(const Rect& size)
{
}
@@ -2484,16 +2342,16 @@ namespace cru::ui
void Window::Relayout()
{
- Measure(GetSize());
- OnLayoutCore(Rect(Point::Zero(), GetSize()));
+ Measure(GetSize(), AdditionalMeasureInfo{});
+ OnLayoutCore(Rect(Point::Zero(), GetSize()), AdditionalLayoutInfo{});
is_layout_invalid_ = false;
}
void Window::SetSizeFitContent(const Size& max_size)
{
- Measure(max_size);
+ Measure(max_size, AdditionalMeasureInfo{});
SetClientSize(GetDesiredSize());
- OnLayoutCore(Rect(Point::Zero(), GetSize()));
+ OnLayoutCore(Rect(Point::Zero(), GetSize()), AdditionalLayoutInfo{});
is_layout_invalid_ = false;
}
@@ -3025,7 +2883,7 @@ namespace cru::ui::controls
return control_type;
}
- Size LinearLayout::OnMeasureContent(const Size& available_size)
+ Size LinearLayout::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info)
{
auto actual_size_for_children = Size::Zero();
@@ -3041,7 +2899,7 @@ namespace cru::ui::controls
if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
{
Size current_available_size(AtLeast0(available_size.width - actual_size_for_children.width), available_size.height);
- control->Measure(current_available_size);
+ control->Measure(current_available_size, additional_info);
const auto size = control->GetDesiredSize();
actual_size_for_children.width += size.width;
secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length);
@@ -3056,7 +2914,7 @@ namespace cru::ui::controls
if (mode == MeasureMode::Content || mode == MeasureMode::Exactly)
{
Size current_available_size(available_size.width, AtLeast0(available_size.height - actual_size_for_children.height));
- control->Measure(current_available_size);
+ control->Measure(current_available_size, additional_info);
const auto size = control->GetDesiredSize();
actual_size_for_children.height += size.height;
secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length);
@@ -3070,7 +2928,7 @@ namespace cru::ui::controls
const auto available_width = AtLeast0(available_size.width - actual_size_for_children.width) / stretch_control_list.size();
for (const auto control : stretch_control_list)
{
- control->Measure(Size(available_width, available_size.height));
+ control->Measure(Size(available_width, available_size.height), additional_info);
const auto size = control->GetDesiredSize();
actual_size_for_children.width += size.width;
secondary_side_child_max_length = std::max(size.height, secondary_side_child_max_length);
@@ -3081,7 +2939,7 @@ namespace cru::ui::controls
const auto available_height = AtLeast0(available_size.height - actual_size_for_children.height) / stretch_control_list.size();
for (const auto control : stretch_control_list)
{
- control->Measure(Size(available_size.width, available_height));
+ control->Measure(Size(available_size.width, available_height), additional_info);
const auto size = control->GetDesiredSize();
actual_size_for_children.height += size.height;
secondary_side_child_max_length = std::max(size.width, secondary_side_child_max_length);
@@ -3115,7 +2973,7 @@ namespace cru::ui::controls
return actual_size_for_children;
}
- void LinearLayout::OnLayoutContent(const Rect& rect)
+ void LinearLayout::OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info)
{
float current_main_side_anchor = 0;
for(auto control: GetChildren())
@@ -3146,12 +3004,12 @@ namespace cru::ui::controls
if (orientation_ == Orientation::Horizontal)
{
- control->Layout(calculate_rect(current_main_side_anchor, calculate_secondary_side_anchor(rect.height, size.height)));
+ control->Layout(calculate_rect(current_main_side_anchor, calculate_secondary_side_anchor(rect.height, size.height)), additional_info);
current_main_side_anchor += size.width;
}
else
{
- control->Layout(calculate_rect(calculate_secondary_side_anchor(rect.width, size.width), current_main_side_anchor));
+ control->Layout(calculate_rect(calculate_secondary_side_anchor(rect.width, size.width), current_main_side_anchor), additional_info);
current_main_side_anchor += size.height;
}
}
@@ -3505,7 +3363,7 @@ namespace cru::ui::controls
view_height_ = length;
}
- Size ScrollControl::OnMeasureContent(const Size& available_size)
+ Size ScrollControl::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info)
{
const auto layout_params = GetLayoutParams();
@@ -3515,13 +3373,6 @@ namespace cru::ui::controls
if (layout_params->width.mode == MeasureMode::Content)
debug::DebugMessage(L"ScrollControl: 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("ScrollControl: 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();
}
@@ -3530,20 +3381,13 @@ namespace cru::ui::controls
if (layout_params->height.mode == MeasureMode::Content)
debug::DebugMessage(L"ScrollControl: 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("ScrollControl: 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);
+ control->Measure(available_size_for_children, AdditionalMeasureInfo{false, false});
const auto&& size = control->GetDesiredSize();
if (max_child_size.width < size.width)
max_child_size.width = size.width;
@@ -3551,7 +3395,7 @@ namespace cru::ui::controls
max_child_size.height = size.height;
}
- // coerce size fro stretch.
+ // coerce size for stretch.
for (auto control: GetChildren())
{
auto size = control->GetDesiredSize();
@@ -3578,7 +3422,7 @@ namespace cru::ui::controls
return result;
}
- void ScrollControl::OnLayoutContent(const Rect& rect)
+ void ScrollControl::OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info)
{
auto layout_rect = rect;
@@ -3599,11 +3443,11 @@ namespace cru::ui::controls
control->Layout(Rect(Point(
calculate_anchor(rect.left, layout_rect.width, size.width, offset_x_),
calculate_anchor(rect.top, layout_rect.height, size.height, offset_y_)
- ), size));
+ ), size), additional_info);
}
}
- void ScrollControl::AfterLayoutSelf()
+ void ScrollControl::OnRectChange(const Rect& old_rect, const Rect& new_rect)
{
UpdateScrollBarBorderInfo();
CoerceAndSetOffsets(offset_x_, offset_y_, false);
@@ -3625,10 +3469,10 @@ namespace cru::ui::controls
for (auto child : GetChildren())
{
const auto old_position = child->GetPositionRelative();
- child->SetPositionRelative(Point(
+ child->SetRect(Rect(Point(
old_position.x + old_offset_x - offset_x_,
old_position.y + old_offset_y - offset_y_
- ));
+ ), child->GetSize()));
}
}
InvalidateDraw();
@@ -3959,14 +3803,6 @@ namespace cru::ui::controls
SetClipContent(true);
- size_changed_event.AddHandler([this](events::SizeChangedEventArgs& args)
- {
- const auto content = GetRect(RectRange::Content);
- ThrowIfFailed(text_layout_->SetMaxWidth(content.width));
- ThrowIfFailed(text_layout_->SetMaxHeight(content.height));
- InvalidateDraw();
- });
-
draw_content_event.AddHandler([this](events::DrawEventArgs& args)
{
const auto device_context = args.GetDeviceContext();
@@ -4080,7 +3916,7 @@ namespace cru::ui::controls
}
}
- Size TextControl::OnMeasureContent(const Size& available_size)
+ Size TextControl::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo&)
{
ThrowIfFailed(text_layout_->SetMaxWidth(available_size.width));
ThrowIfFailed(text_layout_->SetMaxHeight(available_size.height));
@@ -4099,6 +3935,13 @@ namespace cru::ui::controls
}
+ void TextControl::OnRectChange(const Rect& old_rect, const Rect& new_rect)
+ {
+ const auto content = GetRect(RectRange::Content);
+ ThrowIfFailed(text_layout_->SetMaxWidth(content.width));
+ ThrowIfFailed(text_layout_->SetMaxHeight(content.height));
+ }
+
void TextControl::OnTextChangedCore(const String& old_text, const String& new_text)
{
RecreateTextLayout();
@@ -4260,7 +4103,7 @@ namespace cru::ui::controls
SetState(!GetState());
}
- Size ToggleButton::OnMeasureContent(const Size& available_size)
+ Size ToggleButton::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo&)
{
const Size result_size(
half_width * 2 + stroke_width,
diff --git a/CruUI-Generate/cru_ui.hpp b/CruUI-Generate/cru_ui.hpp
index f662f4bd..fe27a1e6 100644
--- a/CruUI-Generate/cru_ui.hpp
+++ b/CruUI-Generate/cru_ui.hpp
@@ -586,7 +586,6 @@ namespace cru
// ReSharper disable once CppUnusedIncludeDirective
-#include <list>
#include <map>
#include <memory>
@@ -840,14 +839,9 @@ namespace cru::ui
// ReSharper disable once CppUnusedIncludeDirective
-#include <unordered_set>
-
namespace cru::ui
{
- class Control;
- class Window;
-
enum class Alignment
{
Center,
@@ -940,43 +934,6 @@ namespace cru::ui
Thickness padding;
Thickness margin;
};
-
-
- class LayoutManager : public Object
- {
- public:
- static LayoutManager* GetInstance();
- private:
- LayoutManager() = default;
- public:
- LayoutManager(const LayoutManager& other) = delete;
- LayoutManager(LayoutManager&& other) = delete;
- LayoutManager& operator=(const LayoutManager& other) = delete;
- LayoutManager& operator=(LayoutManager&& other) = delete;
- ~LayoutManager() override = default;
-
-
- //*************** region: position cache ***************
-
- //Mark position cache of the control and its descendants invalid,
- //(which is saved as an auto-managed list internal)
- //and send a message to refresh them.
- void InvalidateControlPositionCache(Control* control);
-
- //Refresh position cache of the control and its descendants whose cache
- //has been marked as invalid.
- void RefreshInvalidControlPositionCache();
-
- //Refresh position cache of the control and its descendants immediately.
- static void RefreshControlPositionCache(Control* control);
-
- private:
- static void RefreshControlPositionCacheInternal(Control* control, const Point& parent_lefttop_absolute);
-
- private:
- std::unordered_set<Control*> cache_invalid_controls_;
- std::unordered_set<Window*> layout_invalid_windows_;
- };
}
//--------------------------------------------------------
//-------end of file: src\ui\layout_base.hpp
@@ -1232,65 +1189,6 @@ namespace cru::ui::events
};
- class PositionChangedEventArgs : public UiEventArgs
- {
- public:
- PositionChangedEventArgs(Object* sender, Object* original_sender, const Point& old_position, const Point& new_position)
- : UiEventArgs(sender, original_sender), old_position_(old_position), new_position_(new_position)
- {
-
- }
- PositionChangedEventArgs(const PositionChangedEventArgs& other) = default;
- PositionChangedEventArgs(PositionChangedEventArgs&& other) = default;
- PositionChangedEventArgs& operator=(const PositionChangedEventArgs& other) = default;
- PositionChangedEventArgs& operator=(PositionChangedEventArgs&& other) = default;
- ~PositionChangedEventArgs() override = default;
-
- Point GetOldPosition() const
- {
- return old_position_;
- }
-
- Point GetNewPosition() const
- {
- return new_position_;
- }
-
- private:
- Point old_position_;
- Point new_position_;
- };
-
-
- class SizeChangedEventArgs : public UiEventArgs
- {
- public:
- SizeChangedEventArgs(Object* sender, Object* original_sender, const Size& old_size, const Size& new_size)
- : UiEventArgs(sender, original_sender), old_size_(old_size), new_size_(new_size)
- {
-
- }
- SizeChangedEventArgs(const SizeChangedEventArgs& other) = default;
- SizeChangedEventArgs(SizeChangedEventArgs&& other) = default;
- SizeChangedEventArgs& operator=(const SizeChangedEventArgs& other) = default;
- SizeChangedEventArgs& operator=(SizeChangedEventArgs&& other) = default;
- ~SizeChangedEventArgs() override = default;
-
- Size GetOldSize() const
- {
- return old_size_;
- }
-
- Size GetNewSize() const
- {
- return new_size_;
- }
-
- private:
- Size old_size_;
- Size new_size_;
- };
-
class FocusChangeEventArgs : public UiEventArgs
{
public:
@@ -1568,18 +1466,28 @@ namespace cru::ui
class Window;
+ struct AdditionalMeasureInfo
+ {
+ bool horizontal_stretchable = true;
+ bool vertical_stretchable = true;
+ };
+
+ struct AdditionalLayoutInfo
+ {
+ Point total_offset = Point::Zero();
+ };
+
//the position cache
struct ControlPositionCache
{
//The lefttop relative to the ancestor.
- Point lefttop_position_absolute;
+ Point lefttop_position_absolute = Point::Zero();
};
class Control : public Object
{
friend class Window;
- friend class LayoutManager;
protected:
struct GeometryInfo
@@ -1649,21 +1557,14 @@ namespace cru::ui
void TraverseDescendants(const std::function<void(Control*)>& predicate);
//*************** region: position and size ***************
- // Position and size part must be isolated from layout part.
- // All the operations in this part must be done independently.
- // And layout part must use api of this part.
//Get the lefttop relative to its parent.
virtual Point GetPositionRelative();
- //Set the lefttop relative to its parent.
- virtual void SetPositionRelative(const Point& position);
-
//Get the actual size.
virtual Size GetSize();
- //Set the actual size directly without re-layout.
- virtual void SetSize(const Size& size);
+ virtual void SetRect(const Rect& rect);
//Get lefttop relative to ancestor. This is only valid when
//attached to window. Notice that the value is cached.
@@ -1740,9 +1641,9 @@ namespace cru::ui
void InvalidateLayout();
- void Measure(const Size& available_size);
+ void Measure(const Size& available_size, const AdditionalMeasureInfo& additional_info);
- void Layout(const Rect& rect);
+ void Layout(const Rect& rect, const AdditionalLayoutInfo& additional_info);
Size GetDesiredSize() const;
@@ -1820,8 +1721,6 @@ namespace cru::ui
Event<events::DrawEventArgs> draw_background_event;
Event<events::DrawEventArgs> draw_foreground_event;
- Event<events::PositionChangedEventArgs> position_changed_event;
- Event<events::SizeChangedEventArgs> size_changed_event;
//*************** region: tree event ***************
protected:
@@ -1844,6 +1743,8 @@ namespace cru::ui
//*************** region: position and size event ***************
protected:
+ virtual void OnRectChange(const Rect& old_rect, const Rect& new_rect);
+
void RegenerateGeometryInfo();
const GeometryInfo& GetGeometryInfo() const
@@ -1860,23 +1761,15 @@ namespace cru::ui
//*************** region: layout ***************
private:
- Size OnMeasureCore(const Size& available_size);
- void OnLayoutCore(const Rect& rect);
+ Size OnMeasureCore(const Size& available_size, const AdditionalMeasureInfo& additional_info);
+ void OnLayoutCore(const Rect& rect, const AdditionalLayoutInfo& additional_info);
protected:
- virtual Size OnMeasureContent(const Size& available_size);
- virtual void OnLayoutContent(const Rect& rect);
+ virtual Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info);
+ virtual void OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info);
- // Called by Layout after set position and size.
- virtual void AfterLayoutSelf();
private:
- // Only for layout manager to use.
- // Check if the old position is updated to current position.
- // If not, then a notify of position change and update will
- // be done.
- void CheckAndNotifyPositionChanged();
-
void ThrowIfNotContainer() const
{
if (!is_container_)
@@ -1891,15 +1784,8 @@ namespace cru::ui
Control * parent_ = nullptr;
std::vector<Control*> children_{};
- // When position is changed and notification hasn't been
- // sent, it will be the old position. When position is changed
- // more than once, it will be the oldest position since last
- // notification. If notification has been sent, it will be updated
- // to position_.
- Point old_position_ = Point::Zero();
- Point position_ = Point::Zero();
- Size size_ = Size::Zero();
-
+ Rect rect_{};
+
ControlPositionCache position_cache_{};
std::unordered_map<MouseButton, bool> is_mouse_click_valid_map_
@@ -2227,14 +2113,11 @@ namespace cru::ui
//Always return (0, 0) for a window.
Point GetPositionRelative() override final;
- //This method has no effect for a window.
- void SetPositionRelative(const Point& position) override final;
-
//Get the size of client area for a window.
Size GetSize() override final;
//This method has no effect for a window. Use SetClientSize instead.
- void SetSize(const Size& size) override final;
+ void SetRect(const Rect& size) override final;
//Override. If point is in client area, it is in window.
bool IsPointInside(const Point& point) override final;
@@ -2319,7 +2202,7 @@ namespace cru::ui
//*************** region: event dispatcher helper ***************
void DispatchMouseHoverControlChangeEvent(Control* old_control, Control * new_control, const Point& point);
-
+
private:
bool delete_this_on_destroy_ = true;
@@ -2436,8 +2319,8 @@ namespace cru::ui::controls
StringView GetControlType() const override final;
protected:
- Size OnMeasureContent(const Size& available_size) override;
- void OnLayoutContent(const Rect& rect) override;
+ Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info) override;
+ void OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info) override;
private:
Orientation orientation_;
@@ -2516,10 +2399,12 @@ namespace cru::ui::controls
protected:
void SetSelectable(bool is_selectable);
- Size OnMeasureContent(const Size& available_size) override final;
+ Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo&) override final;
virtual void RequestChangeCaretPosition(unsigned position);
+ void OnRectChange(const Rect& old_rect, const Rect& new_rect) override;
+
private:
void OnTextChangedCore(const String& old_text, const String& new_text);
@@ -2625,7 +2510,7 @@ namespace cru::ui::controls
Event<events::ToggleEventArgs> toggle_event;
protected:
- Size OnMeasureContent(const Size& available_size) override;
+ Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo&) override;
private:
bool state_ = false;
@@ -2986,10 +2871,10 @@ namespace cru::ui::controls
void SetViewWidth(float length);
void SetViewHeight(float length);
- Size OnMeasureContent(const Size& available_size) override final;
- void OnLayoutContent(const Rect& rect) override final;
+ Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info) override final;
+ void OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info) override final;
- void AfterLayoutSelf() override;
+ void OnRectChange(const Rect& old_rect, const Rect& new_rect) override;
private:
void CoerceAndSetOffsets(float offset_x, float offset_y, bool update_children = true);