aboutsummaryrefslogtreecommitdiff
path: root/CruUI/ui/controls
diff options
context:
space:
mode:
Diffstat (limited to 'CruUI/ui/controls')
-rw-r--r--CruUI/ui/controls/margin_container.cpp63
-rw-r--r--CruUI/ui/controls/margin_container.h44
2 files changed, 107 insertions, 0 deletions
diff --git a/CruUI/ui/controls/margin_container.cpp b/CruUI/ui/controls/margin_container.cpp
new file mode 100644
index 00000000..8f9101b2
--- /dev/null
+++ b/CruUI/ui/controls/margin_container.cpp
@@ -0,0 +1,63 @@
+#include "margin_container.h"
+
+namespace cru::ui::controls
+{
+ 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));
+ }
+
+ MarginContainer::MarginContainer(const Thickness& margin)
+ : Control(true), margin_(margin)
+ {
+ }
+
+ void MarginContainer::SetMargin(const Thickness& margin)
+ {
+ margin_ = margin;
+ Relayout();
+ }
+
+ Size MarginContainer::OnMeasure(const Size& available_size)
+ {
+ const auto margin_size = Size(margin_.left + margin_.right, margin_.top + margin_.bottom);
+ const auto coerced_available_size = AtLeast0(available_size - margin_size);
+ return Control::OnMeasure(coerced_available_size) + margin_size;
+ }
+
+ void MarginContainer::OnLayout(const Rect& rect)
+ {
+ const auto anchor = Point(margin_.left, margin_.top);
+ const auto margin_size = Size(margin_.left + margin_.right, margin_.top + margin_.bottom);
+ ForeachChild([anchor, margin_size, 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(anchor.x, layout_params->width.alignment, rect.width - margin_size.width, size.width),
+ calculate_anchor(anchor.y, layout_params->height.alignment, rect.height - margin_size.height, size.height)
+ ), size));
+ });
+ }
+}
diff --git a/CruUI/ui/controls/margin_container.h b/CruUI/ui/controls/margin_container.h
new file mode 100644
index 00000000..0eafc40e
--- /dev/null
+++ b/CruUI/ui/controls/margin_container.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <initializer_list>
+
+#include "ui/control.h"
+
+namespace cru::ui::controls
+{
+ class MarginContainer : public Control
+ {
+ public:
+ static MarginContainer* Create(const Thickness& margin = Thickness::Zero(), const std::initializer_list<Control*>& children = std::initializer_list<Control*>())
+ {
+ const auto margin_container = new MarginContainer(margin);
+ for (const auto control : children)
+ margin_container->AddChild(control);
+ return margin_container;
+ }
+
+ protected:
+ explicit MarginContainer(const Thickness& margin);
+
+ public:
+ MarginContainer(const MarginContainer& other) = delete;
+ MarginContainer(MarginContainer&& other) = delete;
+ MarginContainer& operator=(const MarginContainer& other) = delete;
+ MarginContainer& operator=(MarginContainer&& other) = delete;
+ ~MarginContainer() override = default;
+
+ Thickness GetMargin() const
+ {
+ return margin_;
+ }
+
+ void SetMargin(const Thickness& margin);
+
+ protected:
+ Size OnMeasure(const Size& available_size) override;
+ void OnLayout(const Rect& rect) override;
+
+ private:
+ Thickness margin_;
+ };
+}