aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/cru/ui/base.hpp14
-rw-r--r--include/cru/ui/controls/flex_layout.hpp5
-rw-r--r--include/cru/ui/controls/stack_layout.hpp37
-rw-r--r--include/cru/ui/controls/text_box.hpp20
-rw-r--r--include/cru/ui/render/flex_layout_render_object.hpp25
-rw-r--r--include/cru/ui/render/layout_render_object.hpp91
-rw-r--r--include/cru/ui/render/render_object.hpp16
-rw-r--r--include/cru/ui/render/stack_layout_render_object.hpp22
8 files changed, 198 insertions, 32 deletions
diff --git a/include/cru/ui/base.hpp b/include/cru/ui/base.hpp
index 90a3f746..703d61fc 100644
--- a/include/cru/ui/base.hpp
+++ b/include/cru/ui/base.hpp
@@ -27,4 +27,18 @@ using cru::platform::colors::black;
using cru::platform::colors::skyblue;
using cru::platform::colors::white;
} // namespace colors
+
+namespace internal {
+constexpr int align_start = 0;
+constexpr int align_end = align_start + 1;
+constexpr int align_center = align_end + 1;
+constexpr int align_stretch = align_center + 1;
+} // namespace internal
+
+enum class Alignment {
+ Start = internal::align_start,
+ End = internal::align_end,
+ Center = internal::align_center,
+ Stretch = internal::align_stretch
+};
} // namespace cru::ui
diff --git a/include/cru/ui/controls/flex_layout.hpp b/include/cru/ui/controls/flex_layout.hpp
index ff8ec53b..7861534a 100644
--- a/include/cru/ui/controls/flex_layout.hpp
+++ b/include/cru/ui/controls/flex_layout.hpp
@@ -2,7 +2,6 @@
#include "../layout_control.hpp"
#include "../render/flex_layout_render_object.hpp"
-#include "../window.hpp"
#include <memory>
@@ -29,9 +28,7 @@ class FlexLayout : public LayoutControl {
FlexLayout& operator=(FlexLayout&& other) = delete;
~FlexLayout() override = default;
- std::string_view GetControlType() const final {
- return control_type;
- }
+ std::string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/stack_layout.hpp b/include/cru/ui/controls/stack_layout.hpp
new file mode 100644
index 00000000..298de089
--- /dev/null
+++ b/include/cru/ui/controls/stack_layout.hpp
@@ -0,0 +1,37 @@
+#pragma once
+#include "../layout_control.hpp"
+
+#include <memory>
+
+namespace cru::ui::render {
+class StackLayoutRenderObject;
+}
+
+namespace cru::ui::controls {
+class StackLayout : public LayoutControl {
+ public:
+ static constexpr std::string_view control_type = "StackLayout";
+
+ static StackLayout* Create() { return new StackLayout(); }
+
+ protected:
+ StackLayout();
+
+ public:
+ CRU_DELETE_COPY(StackLayout)
+ CRU_DELETE_MOVE(StackLayout)
+
+ ~StackLayout() override;
+
+ std::string_view GetControlType() const final { return control_type; }
+
+ render::RenderObject* GetRenderObject() const override;
+
+ protected:
+ void OnAddChild(Control* child, int position) override;
+ void OnRemoveChild(Control* child, int position) override;
+
+ private:
+ std::shared_ptr<render::StackLayoutRenderObject> render_object_;
+};
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/text_box.hpp b/include/cru/ui/controls/text_box.hpp
new file mode 100644
index 00000000..48168e9d
--- /dev/null
+++ b/include/cru/ui/controls/text_box.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include "../no_child_control.hpp"
+
+namespace cru::ui::controls {
+class TextBox : public NoChildControl {
+ public:
+ static constexpr std::string_view control_type = "TextBox";
+
+ protected:
+ TextBox();
+
+ public:
+ CRU_DELETE_COPY(TextBox)
+ CRU_DELETE_MOVE(TextBox)
+
+ ~TextBox() override;
+
+ std::string_view GetControlType() const final { return control_type; }
+};
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/render/flex_layout_render_object.hpp b/include/cru/ui/render/flex_layout_render_object.hpp
index ab6265d6..c2bc5fd1 100644
--- a/include/cru/ui/render/flex_layout_render_object.hpp
+++ b/include/cru/ui/render/flex_layout_render_object.hpp
@@ -1,5 +1,5 @@
#pragma once
-#include "render_object.hpp"
+#include "layout_render_object.hpp"
#include <optional>
@@ -39,9 +39,9 @@ struct FlexChildLayoutData {
std::optional<FlexCrossAlignment> cross_alignment = std::nullopt;
};
-class FlexLayoutRenderObject : public RenderObject {
+class FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> {
public:
- FlexLayoutRenderObject();
+ FlexLayoutRenderObject() = default;
FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete;
FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) =
delete;
@@ -67,25 +67,7 @@ class FlexLayoutRenderObject : public RenderObject {
InvalidateLayout();
}
- FlexChildLayoutData GetChildLayoutData(int position) {
- assert(position >= 0 && position < static_cast<int>(child_layout_data_.size()));
- return child_layout_data_[position];
- }
-
- void SetChildLayoutData(int position, const FlexChildLayoutData& data) {
- assert(position >= 0 && position < static_cast<int>(child_layout_data_.size()));
- child_layout_data_[position] = data;
- InvalidateLayout();
- }
-
- void Draw(platform::graph::IPainter* painter) override;
-
- RenderObject* HitTest(const Point& point) override;
-
protected:
- void OnAddChild(RenderObject* new_child, int position) override;
- void OnRemoveChild(RenderObject* removed_child, int position) override;
-
Size OnMeasureContent(const Size& available_size) override;
void OnLayoutContent(const Rect& content_rect) override;
@@ -93,6 +75,5 @@ class FlexLayoutRenderObject : public RenderObject {
FlexDirection direction_ = FlexDirection::Horizontal;
FlexMainAlignment content_main_align_ = FlexMainAlignment::Start;
FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center;
- std::vector<FlexChildLayoutData> child_layout_data_{};
};
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/layout_render_object.hpp b/include/cru/ui/render/layout_render_object.hpp
new file mode 100644
index 00000000..db6daba9
--- /dev/null
+++ b/include/cru/ui/render/layout_render_object.hpp
@@ -0,0 +1,91 @@
+#pragma once
+#include "render_object.hpp"
+
+#include "cru/platform/graph/util/painter.hpp"
+
+#include <cassert>
+#include <functional>
+
+namespace cru::ui::render {
+template <typename TChildLayoutData>
+class LayoutRenderObject : public RenderObject {
+ public:
+ using ChildLayoutData = TChildLayoutData;
+
+ protected:
+ LayoutRenderObject() : RenderObject(ChildMode::Multiple) {}
+
+ public:
+ CRU_DELETE_COPY(LayoutRenderObject)
+ CRU_DELETE_MOVE(LayoutRenderObject)
+
+ ~LayoutRenderObject() override = default;
+
+ ChildLayoutData* GetChildLayoutData(int position) {
+ assert(position >= 0 &&
+ position < static_cast<int>(child_layout_data_.size()));
+ return &child_layout_data_[position];
+ }
+
+ void Draw(platform::graph::IPainter* painter) override;
+
+ RenderObject* HitTest(const Point& point) override;
+
+ protected:
+ void OnAddChild(RenderObject* new_child, int position) override;
+ void OnRemoveChild(RenderObject* removed_child, int position) override;
+
+ private:
+ std::vector<ChildLayoutData> child_layout_data_{};
+};
+
+template <typename TChildLayoutData>
+void LayoutRenderObject<TChildLayoutData>::Draw(
+ platform::graph::IPainter* painter) {
+ for (const auto child : GetChildren()) {
+ auto offset = child->GetOffset();
+ platform::graph::util::WithTransform(
+ painter, platform::Matrix::Translation(offset.x, offset.y),
+ [child](auto p) { child->Draw(p); });
+ }
+}
+
+template <typename TChildLayoutData>
+RenderObject* LayoutRenderObject<TChildLayoutData>::HitTest(
+ const Point& point) {
+ const auto& children = GetChildren();
+ for (auto i = children.crbegin(); i != children.crend(); ++i) {
+ auto offset = (*i)->GetOffset();
+ Point p{point.x - offset.x, point.y - offset.y};
+ const auto result = (*i)->HitTest(p);
+ if (result != nullptr) {
+ return result;
+ }
+ }
+
+ const auto margin = GetMargin();
+ const auto size = GetSize();
+ return Rect{margin.left, margin.top,
+ std::max(size.width - margin.GetHorizontalTotal(), 0.0f),
+ std::max(size.height - margin.GetVerticalTotal(), 0.0f)}
+ .IsPointInside(point)
+ ? this
+ : nullptr;
+} // namespace cru::ui::render
+
+template <typename TChildLayoutData>
+void LayoutRenderObject<TChildLayoutData>::OnAddChild(RenderObject* new_child,
+ int position) {
+ CRU_UNUSED(new_child)
+
+ child_layout_data_.emplace(child_layout_data_.cbegin() + position);
+}
+
+template <typename TChildLayoutData>
+void LayoutRenderObject<TChildLayoutData>::OnRemoveChild(
+ RenderObject* removed_child, int position) {
+ CRU_UNUSED(removed_child)
+
+ child_layout_data_.erase(child_layout_data_.cbegin() + position);
+}
+} // namespace cru::ui::render
diff --git a/include/cru/ui/render/render_object.hpp b/include/cru/ui/render/render_object.hpp
index 3e351d34..73543aa3 100644
--- a/include/cru/ui/render/render_object.hpp
+++ b/include/cru/ui/render/render_object.hpp
@@ -34,7 +34,16 @@ struct IRenderHost : Interface {
class RenderObject : public Object {
protected:
+ enum class ChildMode {
+ None,
+ Single,
+ Multiple,
+ };
+
RenderObject() = default;
+ RenderObject(ChildMode child_mode) : RenderObject() {
+ SetChildMode(child_mode);
+ }
public:
RenderObject(const RenderObject& other) = delete;
@@ -52,6 +61,7 @@ class RenderObject : public Object {
RenderObject* GetParent() const { return parent_; }
const std::vector<RenderObject*>& GetChildren() const { return children_; }
+ int GetChildCount() const { return static_cast<int>(children_.size()); }
void AddChild(RenderObject* render_object, int position);
void RemoveChild(int position);
@@ -79,12 +89,6 @@ class RenderObject : public Object {
virtual RenderObject* HitTest(const Point& point) = 0;
protected:
- enum class ChildMode {
- None,
- Single,
- Multiple,
- };
-
void SetChildMode(ChildMode mode) { child_mode_ = mode; }
void InvalidateLayout() const {
diff --git a/include/cru/ui/render/stack_layout_render_object.hpp b/include/cru/ui/render/stack_layout_render_object.hpp
new file mode 100644
index 00000000..0d33e7e3
--- /dev/null
+++ b/include/cru/ui/render/stack_layout_render_object.hpp
@@ -0,0 +1,22 @@
+#pragma once
+#include "layout_render_object.hpp"
+
+namespace cru::ui::render {
+struct StackChildLayoutData {
+ Alignment horizontal = Alignment::Start;
+ Alignment vertical = Alignment::Start;
+};
+
+class StackLayoutRenderObject
+ : public LayoutRenderObject<StackChildLayoutData> {
+ public:
+ StackLayoutRenderObject() = default;
+ CRU_DELETE_COPY(StackLayoutRenderObject)
+ CRU_DELETE_MOVE(StackLayoutRenderObject)
+ ~StackLayoutRenderObject() = default;
+
+ protected:
+ Size OnMeasureContent(const Size& available_size) override;
+ void OnLayoutContent(const Rect& content_rect) override;
+};
+} // namespace cru::ui::render