aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/control.cpp113
-rw-r--r--src/ui/control.h3
-rw-r--r--src/ui/controls/border_delegate.cpp12
-rw-r--r--src/ui/controls/border_delegate.h6
-rw-r--r--src/ui/controls/button.cpp10
-rw-r--r--src/ui/controls/button.h3
6 files changed, 133 insertions, 14 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 480f7d46..86101f9a 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -639,6 +639,119 @@ namespace cru {
});
}
+ inline Size ThicknessToSize(const Thickness& thickness)
+ {
+ return Size(thickness.left + thickness.right, thickness.top + thickness.bottom);
+ }
+
+ inline float AtLeast0(const float value)
+ {
+ return value < 0 ? 0 : value;
+ }
+
+ inline Size AtLeast0(const Size& size)
+ {
+ return Size(AtLeast0(size.width), AtLeast0(size.height));
+ }
+
+ Size Control::DefaultMeasureWithPadding(const Size& available_size, const Thickness& padding)
+ {
+ const auto layout_params = GetLayoutParams();
+ const auto padding_size = ThicknessToSize(padding);
+
+ if (!layout_params->Validate())
+ throw std::runtime_error("LayoutParams is not valid. Please check it.");
+
+ auto&& get_available_length_for_child = [](const LayoutSideParams& 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 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));
+
+ size_for_children = AtLeast0(size_for_children - padding_size);
+
+ auto max_child_size = Size::Zero();
+ ForeachChild([&](Control* control)
+ {
+ control->Measure(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;
+ });
+
+ auto&& calculate_final_length = [](const LayoutSideParams& 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, size_for_children.width, max_child_size.width),
+ calculate_final_length(layout_params->height, size_for_children.height, max_child_size.height)
+ ) + padding_size;
+ }
+
+ void Control::DefaultLayoutWithPadding(const Rect& rect, const Thickness& padding)
+ {
+ const Rect final_rect(
+ rect.left + padding.left,
+ rect.top + padding.top,
+ rect.width - padding.left - padding.right,
+ rect.height - padding.top - padding.bottom
+ );
+
+ ForeachChild([final_rect](Control* control)
+ {
+ const auto layout_params = control->GetLayoutParams();
+ const auto size = control->GetDesiredSize();
+
+ auto&& calculate_anchor = [](const float anchor, const Alignment alignment, const float layout_length, const float control_length) -> float
+ {
+ switch (alignment)
+ {
+ case Alignment::Center:
+ return anchor + (layout_length - control_length) / 2;
+ case Alignment::Start:
+ return anchor;
+ case Alignment::End:
+ return anchor + layout_length - control_length;
+ default:
+ UnreachableCode();
+ }
+ };
+
+ control->Layout(Rect(Point(
+ calculate_anchor(final_rect.left, layout_params->width.alignment, final_rect.width, size.width),
+ calculate_anchor(final_rect.top, layout_params->height.alignment, final_rect.height, size.height)
+ ), size));
+ });
+ }
+
void Control::CheckAndNotifyPositionChanged()
{
if (this->old_position_ != this->position_)
diff --git a/src/ui/control.h b/src/ui/control.h
index 98d41d0d..964b61c4 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -309,6 +309,9 @@ namespace cru
virtual Size OnMeasure(const Size& available_size);
virtual void OnLayout(const Rect& rect);
+ Size DefaultMeasureWithPadding(const Size& available_size, const Thickness& padding);
+ void DefaultLayoutWithPadding(const Rect& rect, const Thickness& padding);
+
private:
// Only for layout manager to use.
// Check if the old position is updated to current position.
diff --git a/src/ui/controls/border_delegate.cpp b/src/ui/controls/border_delegate.cpp
index ec7ba437..0b460997 100644
--- a/src/ui/controls/border_delegate.cpp
+++ b/src/ui/controls/border_delegate.cpp
@@ -82,16 +82,4 @@ namespace cru::ui::controls
border_property_->GetStrokeStyle().Get()
);
}
-
- Size BorderDelegate::GetBorderSize() const
- {
- const auto width = border_property_->GetWidth();
- return Size(width * 2, width * 2);
- }
-
- Rect BorderDelegate::CoerceLayoutRect(const Rect& rect) const
- {
- const auto width = border_property_->GetWidth();
- return Rect(rect.left + width, rect.top + width, rect.width - width * 2, rect.height - width * 2);
- }
}
diff --git a/src/ui/controls/border_delegate.h b/src/ui/controls/border_delegate.h
index 5a7dfbed..6d3b31db 100644
--- a/src/ui/controls/border_delegate.h
+++ b/src/ui/controls/border_delegate.h
@@ -90,8 +90,10 @@ namespace cru::ui::controls
void Draw(ID2D1DeviceContext* device_context, const Size& size) const;
- Size GetBorderSize() const;
- Rect CoerceLayoutRect(const Rect& rect) const;
+ Thickness GetBorderThickness() const
+ {
+ return Thickness(border_property_->GetWidth());
+ }
private:
Control* control_;
diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp
index 630c0c39..2ecc9f14 100644
--- a/src/ui/controls/button.cpp
+++ b/src/ui/controls/button.cpp
@@ -29,6 +29,16 @@ namespace cru::ui::controls
border_delegate_->Draw(device_context, GetSize());
}
+ Size Button::OnMeasure(const Size& available_size)
+ {
+ return Control::DefaultMeasureWithPadding(available_size, border_delegate_->GetBorderThickness());
+ }
+
+ void Button::OnLayout(const Rect& rect)
+ {
+ Control::DefaultLayoutWithPadding(rect, border_delegate_->GetBorderThickness());
+ }
+
void Button::OnMouseClickBegin(MouseButton button)
{
border_delegate_->SetBorderProperty(pressed_border_border_);
diff --git a/src/ui/controls/button.h b/src/ui/controls/button.h
index 7a303984..4b57a5a3 100644
--- a/src/ui/controls/button.h
+++ b/src/ui/controls/button.h
@@ -31,6 +31,9 @@ namespace cru::ui::controls
protected:
void OnDraw(ID2D1DeviceContext* device_context) override;
+ Size OnMeasure(const Size& available_size) override;
+ void OnLayout(const Rect& rect) override;
+
void OnMouseClickBegin(MouseButton button) override final;
void OnMouseClickEnd(MouseButton button) override final;