aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/main/main.cpp12
-rw-r--r--include/cru/ui/Base.h4
-rw-r--r--include/cru/ui/controls/Base.h4
-rw-r--r--include/cru/ui/controls/Button.h16
-rw-r--r--include/cru/ui/controls/Container.h16
-rw-r--r--include/cru/ui/controls/ContentControl.h37
-rw-r--r--include/cru/ui/controls/Control.h43
-rw-r--r--include/cru/ui/controls/FlexLayout.h15
-rw-r--r--include/cru/ui/controls/IBorderControl.h1
-rw-r--r--include/cru/ui/controls/IClickableControl.h3
-rw-r--r--include/cru/ui/controls/LayoutControl.h62
-rw-r--r--include/cru/ui/controls/NoChildControl.h7
-rw-r--r--include/cru/ui/controls/RootControl.h12
-rw-r--r--include/cru/ui/controls/ScrollView.h23
-rw-r--r--include/cru/ui/controls/SingleChildControl.h55
-rw-r--r--include/cru/ui/controls/StackLayout.h18
-rw-r--r--include/cru/ui/controls/TextBlock.h4
-rw-r--r--include/cru/ui/controls/TextBox.h1
-rw-r--r--include/cru/ui/controls/TextHostControlService.h2
-rw-r--r--include/cru/ui/events/MouseEventArgs.h2
-rw-r--r--include/cru/ui/host/WindowHost.h1
-rw-r--r--include/cru/ui/render/LayoutRenderObject.h14
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/components/Menu.cpp2
-rw-r--r--src/ui/controls/Button.cpp12
-rw-r--r--src/ui/controls/Container.cpp11
-rw-r--r--src/ui/controls/ContentControl.cpp31
-rw-r--r--src/ui/controls/Control.cpp93
-rw-r--r--src/ui/controls/FlexLayout.cpp53
-rw-r--r--src/ui/controls/LayoutControl.cpp24
-rw-r--r--src/ui/controls/NoChildControl.cpp7
-rw-r--r--src/ui/controls/RootControl.cpp11
-rw-r--r--src/ui/controls/ScrollView.cpp16
-rw-r--r--src/ui/controls/StackLayout.cpp22
-rw-r--r--src/ui/controls/TextBox.cpp4
-rw-r--r--src/ui/controls/Window.cpp7
-rw-r--r--src/ui/host/WindowHost.cpp5
-rw-r--r--src/ui/render/FlexLayoutRenderObject.cpp4
-rw-r--r--src/ui/render/StackLayoutRenderObject.cpp4
39 files changed, 210 insertions, 450 deletions
diff --git a/demos/main/main.cpp b/demos/main/main.cpp
index 38fad739..41320858 100644
--- a/demos/main/main.cpp
+++ b/demos/main/main.cpp
@@ -14,11 +14,7 @@
#include "cru/ui/host/WindowHost.h"
using cru::platform::gui::IUiApplication;
-using cru::ui::controls::Button;
-using cru::ui::controls::FlexLayout;
-using cru::ui::controls::TextBlock;
-using cru::ui::controls::TextBox;
-using cru::ui::controls::Window;
+using namespace cru::ui::controls;
int main() {
IUiApplication* application = cru::platform::bootstrap::CreateUiApplication();
@@ -40,9 +36,9 @@ int main() {
const auto window = Window::Create();
const auto flex_layout = FlexLayout::Create();
- flex_layout->SetFlexDirection(cru::ui::FlexDirection::Vertical);
- flex_layout->SetContentMainAlign(cru::ui::FlexCrossAlignment::Center);
- flex_layout->SetItemCrossAlign(cru::ui::FlexCrossAlignment::Center);
+ flex_layout->SetFlexDirection(FlexDirection::Vertical);
+ flex_layout->SetContentMainAlign(FlexCrossAlignment::Center);
+ flex_layout->SetItemCrossAlign(FlexCrossAlignment::Center);
window->AddChild(flex_layout, 0);
diff --git a/include/cru/ui/Base.h b/include/cru/ui/Base.h
index 182c00f2..b16edbfc 100644
--- a/include/cru/ui/Base.h
+++ b/include/cru/ui/Base.h
@@ -46,10 +46,6 @@ namespace host {
class WindowHost;
}
-namespace render {
-class RenderObject;
-}
-
namespace style {
class StyleRuleSet;
class StyleRuleSetBind;
diff --git a/include/cru/ui/controls/Base.h b/include/cru/ui/controls/Base.h
deleted file mode 100644
index 21f1c563..00000000
--- a/include/cru/ui/controls/Base.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-#include "../Base.h"
-
-namespace cru::ui::controls {} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/Button.h b/include/cru/ui/controls/Button.h
index 00253793..d35d7ef8 100644
--- a/include/cru/ui/controls/Button.h
+++ b/include/cru/ui/controls/Button.h
@@ -1,19 +1,19 @@
#pragma once
-#include "ContentControl.h"
+#include "SingleChildControl.h"
+#include "../controls/SingleChildControl.h"
#include "../helper/ClickDetector.h"
+#include "../render/BorderRenderObject.h"
#include "IBorderControl.h"
#include "IClickableControl.h"
#include "cru/common/Event.h"
-#include "cru/ui/render/BorderRenderObject.h"
-#include "cru/ui/style/ApplyBorderStyleInfo.h"
namespace cru::ui::controls {
-class CRU_UI_API Button : public ContentControl,
+class CRU_UI_API Button : public SingleChildControl<render::BorderRenderObject>,
public virtual IClickableControl,
public virtual IBorderControl {
public:
- static constexpr StringView control_type = u"Button";
+ static constexpr StringView kControlType = u"Button";
static Button* Create() { return new Button(); }
@@ -27,9 +27,7 @@ class CRU_UI_API Button : public ContentControl,
Button& operator=(Button&& other) = delete;
~Button() override;
- String GetControlType() const final { return control_type.ToString(); }
-
- render::RenderObject* GetRenderObject() const override;
+ String GetControlType() const final { return kControlType.ToString(); }
public:
helper::ClickState GetClickState() override {
@@ -47,8 +45,6 @@ class CRU_UI_API Button : public ContentControl,
void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override;
private:
- std::unique_ptr<render::BorderRenderObject> render_object_{};
-
helper::ClickDetector click_detector_;
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/Container.h b/include/cru/ui/controls/Container.h
index 926e395e..adb0fad1 100644
--- a/include/cru/ui/controls/Container.h
+++ b/include/cru/ui/controls/Container.h
@@ -1,11 +1,12 @@
#pragma once
-#include "ContentControl.h"
+#include "SingleChildControl.h"
-#include "cru/ui/render/BorderRenderObject.h"
+#include "../render/BorderRenderObject.h"
namespace cru::ui::controls {
-class CRU_UI_API Container : public ContentControl {
- static constexpr StringView control_type = u"Container";
+class CRU_UI_API Container
+ : public SingleChildControl<render::BorderRenderObject> {
+ static constexpr StringView kControlType = u"Container";
protected:
Container();
@@ -17,11 +18,6 @@ class CRU_UI_API Container : public ContentControl {
~Container() override;
public:
- String GetControlType() const final { return control_type.ToString(); }
-
- render::RenderObject* GetRenderObject() const override;
-
- private:
- std::unique_ptr<render::BorderRenderObject> render_object_;
+ String GetControlType() const final { return kControlType.ToString(); }
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/ContentControl.h b/include/cru/ui/controls/ContentControl.h
deleted file mode 100644
index 5600ec25..00000000
--- a/include/cru/ui/controls/ContentControl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-#include "Control.h"
-
-
-namespace cru::ui::controls {
-class CRU_UI_API ContentControl : public Control {
- protected:
- ContentControl() = default;
-
- public:
- ContentControl(const ContentControl& other) = delete;
- ContentControl(ContentControl&& other) = delete;
- ContentControl& operator=(const ContentControl& other) = delete;
- ContentControl& operator=(ContentControl&& other) = delete;
- ~ContentControl() override = default;
-
- Control* GetChild() const;
- void SetChild(Control* child);
-
- protected:
- virtual void OnChildChanged(Control* old_child, Control* new_child);
-
- render::RenderObject* GetContainerRenderObject() const {
- return container_render_object_;
- }
- void SetContainerRenderObject(render::RenderObject* ro) {
- container_render_object_ = ro;
- }
-
- private:
- using Control::AddChild;
- using Control::RemoveChild;
-
- private:
- render::RenderObject* container_render_object_ = nullptr;
-};
-} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/Control.h b/include/cru/ui/controls/Control.h
index 3927e604..9a237f8b 100644
--- a/include/cru/ui/controls/Control.h
+++ b/include/cru/ui/controls/Control.h
@@ -1,14 +1,18 @@
#pragma once
-#include "Base.h"
-
+#include "../Base.h"
#include "../events/UiEvents.h"
-#include "cru/common/Event.h"
-#include "cru/ui/render/RenderObject.h"
+#include "../render/RenderObject.h"
namespace cru::ui::controls {
-class CRU_UI_API Control : public Object {
- friend host::WindowHost;
+/**
+ * \remarks If you want to write a new control. You should override following
+ * methods:
+ * - GetControlType()
+ * - ForEachChild(const std::function<void(Control*)>& predicate)
+ * - GetRenderObject()
+ */
+class CRU_UI_API Control : public Object {
protected:
Control();
@@ -24,22 +28,12 @@ class CRU_UI_API Control : public Object {
//*************** region: tree ***************
public:
- host::WindowHost* GetWindowHost() const;
+ virtual host::WindowHost* GetWindowHost() const;
Control* GetParent() const { return parent_; }
+ void SetParent(Control* parent);
- const std::vector<Control*>& GetChildren() const { return children_; }
- Index IndexOf(Control* child) const;
-
- // Traverse the tree rooted the control including itself.
- void TraverseDescendants(const std::function<void(Control*)>& predicate);
-
- bool IsAutoDeleteChildren() const { return auto_delete_children_; }
- void SetAutoDeleteChildren(bool auto_delete_children) {
- auto_delete_children_ = auto_delete_children;
- }
-
- void RemoveFromParent();
+ virtual void ForEachChild(const std::function<void(Control*)>& predicate) = 0;
public:
virtual render::RenderObject* GetRenderObject() const = 0;
@@ -135,24 +129,13 @@ class CRU_UI_API Control : public Object {
//*************** region: tree ***************
protected:
- void AddChild(Control* control, Index position);
- void RemoveChild(Index position);
- virtual void OnAddChild(Control* child, Index position);
- virtual void OnRemoveChild(Control* child, Index position);
virtual void OnParentChanged(Control* old_parent, Control* new_parent);
- virtual void OnAttachToHost(host::WindowHost* host);
- virtual void OnDetachFromHost(host::WindowHost* host);
protected:
virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) }
private:
Control* parent_ = nullptr;
- std::vector<Control*> children_;
-
- host::WindowHost* window_host_ = nullptr;
-
- bool auto_delete_children_ = true;
private:
bool is_mouse_over_ = false;
diff --git a/include/cru/ui/controls/FlexLayout.h b/include/cru/ui/controls/FlexLayout.h
index 8fdb3aef..15494742 100644
--- a/include/cru/ui/controls/FlexLayout.h
+++ b/include/cru/ui/controls/FlexLayout.h
@@ -10,9 +10,10 @@ using render::FlexCrossAlignment;
using render::FlexDirection;
using render::FlexMainAlignment;
-class CRU_UI_API FlexLayout : public LayoutControl {
+class CRU_UI_API FlexLayout
+ : public LayoutControl<render::FlexLayoutRenderObject> {
public:
- static constexpr StringView control_type = u"FlexLayout";
+ static constexpr StringView kControlType = u"FlexLayout";
static FlexLayout* Create() { return new FlexLayout(); }
@@ -26,9 +27,7 @@ class CRU_UI_API FlexLayout : public LayoutControl {
FlexLayout& operator=(FlexLayout&& other) = delete;
~FlexLayout() override;
- String GetControlType() const final { return control_type.ToString(); }
-
- render::RenderObject* GetRenderObject() const override;
+ String GetControlType() const final { return kControlType.ToString(); }
FlexMainAlignment GetContentMainAlign() const;
void SetContentMainAlign(FlexMainAlignment value);
@@ -38,11 +37,5 @@ class CRU_UI_API FlexLayout : public LayoutControl {
FlexCrossAlignment GetItemCrossAlign() const;
void SetItemCrossAlign(FlexCrossAlignment alignment);
-
- FlexChildLayoutData GetChildLayoutData(Control* control);
- void SetChildLayoutData(Control* control, FlexChildLayoutData data);
-
- private:
- std::shared_ptr<render::FlexLayoutRenderObject> render_object_;
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/IBorderControl.h b/include/cru/ui/controls/IBorderControl.h
index 3178d7f2..f8f2f88d 100644
--- a/include/cru/ui/controls/IBorderControl.h
+++ b/include/cru/ui/controls/IBorderControl.h
@@ -1,6 +1,5 @@
#pragma once
#include "../style/ApplyBorderStyleInfo.h"
-#include "Base.h"
#include "cru/common/Base.h"
namespace cru::ui::controls {
diff --git a/include/cru/ui/controls/IClickableControl.h b/include/cru/ui/controls/IClickableControl.h
index 48b3ad5f..67fa43ab 100644
--- a/include/cru/ui/controls/IClickableControl.h
+++ b/include/cru/ui/controls/IClickableControl.h
@@ -1,8 +1,7 @@
#pragma once
-#include "Base.h"
+#include "../helper/ClickDetector.h"
#include "cru/common/Event.h"
-#include "cru/ui/helper/ClickDetector.h"
namespace cru::ui::controls {
struct CRU_UI_API IClickableControl : virtual Interface {
diff --git a/include/cru/ui/controls/LayoutControl.h b/include/cru/ui/controls/LayoutControl.h
index 639ecc74..b42cfc9a 100644
--- a/include/cru/ui/controls/LayoutControl.h
+++ b/include/cru/ui/controls/LayoutControl.h
@@ -2,11 +2,12 @@
#include "Control.h"
namespace cru::ui::controls {
+template <typename TRenderObject>
class CRU_UI_API LayoutControl : public Control {
protected:
- LayoutControl() = default;
- explicit LayoutControl(render::RenderObject* container_render_object)
- : container_render_object_(container_render_object) {}
+ LayoutControl() : container_render_object_(new TRenderObject()) {
+ container_render_object_->SetAttachedControl(this);
+ }
public:
LayoutControl(const LayoutControl& other) = delete;
@@ -15,23 +16,54 @@ class CRU_UI_API LayoutControl : public Control {
LayoutControl& operator=(LayoutControl&& other) = delete;
~LayoutControl() override = default;
- using Control::AddChild;
- using Control::RemoveChild;
+ public:
+ void ForEachChild(const std::function<void(Control*)>& callback) override {
+ for (auto child : children_) {
+ callback(child);
+ }
+ }
- void ClearChildren();
+ render::RenderObject* GetRenderObject() const override {
+ return container_render_object_.get();
+ }
- protected:
- // If container render object is not null. Render object of added or removed
- // child control will automatically sync to the container render object.
- render::RenderObject* GetContainerRenderObject() const;
- void SetContainerRenderObject(render::RenderObject* ro) {
- container_render_object_ = ro;
+ TRenderObject* GetContainerRenderObject() const {
+ return container_render_object_.get();
+ }
+
+ void AddChild(Control* child, Index position) {
+ Expects(child);
+ Expects(child->GetParent() == nullptr);
+ if (position < 0) position = 0;
+ if (position > children_.size()) position = children_.size();
+ children_.insert(children_.begin() + position, child);
+ child->SetParent(this);
+
+ assert(child->GetRenderObject());
+ container_render_object_->AddChild(child->GetRenderObject(), position);
+ }
+
+ void RemoveChild(Index position) {
+ if (position < 0 || position >= children_.size()) return;
+ auto child = children_[position];
+ children_.erase(children_.begin() + position);
+ child->SetParent(nullptr);
+ container_render_object_->RemoveChild(position);
}
- void OnAddChild(Control* child, Index position) override;
- void OnRemoveChild(Control* child, Index position) override;
+ const typename TRenderObject::ChildLayoutData& GetChildLayoutData(
+ Index position) {
+ return container_render_object_->GetChildLayoutDataAt(position);
+ }
+
+ void SetChildLayoutData(Index position,
+ typename TRenderObject::ChildLayoutData data) {
+ container_render_object_->SetChildLayoutDataAt(position, data);
+ }
private:
- render::RenderObject* container_render_object_ = nullptr;
+ std::unique_ptr<TRenderObject> container_render_object_;
+
+ std::vector<Control*> children_;
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/NoChildControl.h b/include/cru/ui/controls/NoChildControl.h
index 6d2168cb..1b864b20 100644
--- a/include/cru/ui/controls/NoChildControl.h
+++ b/include/cru/ui/controls/NoChildControl.h
@@ -13,8 +13,7 @@ class CRU_UI_API NoChildControl : public Control {
NoChildControl& operator=(NoChildControl&& other) = delete;
~NoChildControl() override = default;
- private:
- using Control::AddChild;
- using Control::RemoveChild;
+ public:
+ void ForEachChild(const std::function<void(Control*)>& callback) override;
};
-} // namespace cru::ui
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/RootControl.h b/include/cru/ui/controls/RootControl.h
index 41424286..a1878836 100644
--- a/include/cru/ui/controls/RootControl.h
+++ b/include/cru/ui/controls/RootControl.h
@@ -1,16 +1,14 @@
#pragma once
#include "LayoutControl.h"
-#include "cru/common/Base.h"
#include "cru/common/Event.h"
-#include "cru/platform/gui/Base.h"
#include "cru/platform/gui/Window.h"
-#include "cru/ui/Base.h"
#include "cru/ui/host/WindowHost.h"
#include "cru/ui/render/StackLayoutRenderObject.h"
namespace cru::ui::controls {
-class CRU_UI_API RootControl : public LayoutControl {
+class CRU_UI_API RootControl
+ : public LayoutControl<render::StackLayoutRenderObject> {
protected:
explicit RootControl(Control* attached_control);
@@ -20,7 +18,9 @@ class CRU_UI_API RootControl : public LayoutControl {
~RootControl() override;
public:
- render::RenderObject* GetRenderObject() const override;
+ host::WindowHost* GetWindowHost() const override {
+ return window_host_.get();
+ }
platform::gui::INativeWindow* GetNativeWindow();
@@ -30,8 +30,6 @@ class CRU_UI_API RootControl : public LayoutControl {
private:
std::unique_ptr<host::WindowHost> window_host_;
- std::unique_ptr<render::StackLayoutRenderObject> render_object_;
-
Control* attached_control_;
EventRevokerListGuard
diff --git a/include/cru/ui/controls/ScrollView.h b/include/cru/ui/controls/ScrollView.h
index 7bc9b226..43b6390c 100644
--- a/include/cru/ui/controls/ScrollView.h
+++ b/include/cru/ui/controls/ScrollView.h
@@ -1,33 +1,26 @@
#pragma once
-#include "ContentControl.h"
-#include "cru/common/Base.h"
-#include "cru/ui/render/RenderObject.h"
+#include "SingleChildControl.h"
#include "cru/ui/render/ScrollRenderObject.h"
-#include <memory>
-#include <string_view>
-
namespace cru::ui::controls {
-class CRU_UI_API ScrollView : public ContentControl {
+class CRU_UI_API ScrollView
+ : public SingleChildControl<render::ScrollRenderObject> {
public:
static ScrollView* Create() { return new ScrollView(); }
- static constexpr StringView control_type = u"ScrollView";
+ static constexpr StringView kControlType = u"ScrollView";
+ protected:
ScrollView();
+ public:
CRU_DELETE_COPY(ScrollView)
CRU_DELETE_MOVE(ScrollView)
- ~ScrollView() override = default;
+ ~ScrollView() override;
public:
- String GetControlType() const override { return control_type.ToString(); }
-
- render::RenderObject* GetRenderObject() const override;
-
- private:
- std::unique_ptr<render::ScrollRenderObject> scroll_render_object_;
+ String GetControlType() const override { return kControlType.ToString(); }
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/SingleChildControl.h b/include/cru/ui/controls/SingleChildControl.h
new file mode 100644
index 00000000..037d6dd3
--- /dev/null
+++ b/include/cru/ui/controls/SingleChildControl.h
@@ -0,0 +1,55 @@
+#pragma once
+#include "Control.h"
+
+namespace cru::ui::controls {
+template <typename TRenderObject>
+class CRU_UI_API SingleChildControl : public Control {
+ protected:
+ SingleChildControl() : container_render_object_(new TRenderObject()) {
+ container_render_object_->SetAttachedControl(this);
+ }
+
+ public:
+ CRU_DELETE_COPY(SingleChildControl)
+ CRU_DELETE_MOVE(SingleChildControl)
+
+ ~SingleChildControl() override {}
+
+ Control* GetChild() const { return child_; }
+ void SetChild(Control* child) {
+ if (child == child_) return;
+
+ assert(child == nullptr || child->GetParent() == nullptr);
+
+ if (child_) {
+ child_->SetParent(nullptr);
+ }
+
+ child_ = child;
+
+ if (child) {
+ child->SetParent(this);
+ }
+
+ container_render_object_->SetChild(child->GetRenderObject());
+ }
+
+ render::RenderObject* GetRenderObject() const override {
+ return container_render_object_.get();
+ }
+
+ TRenderObject* GetContainerRenderObject() const {
+ return container_render_object_.get();
+ }
+
+ void ForEachChild(const std::function<void(Control*)>& predicate) override {
+ if (child_) {
+ predicate(child_);
+ }
+ }
+
+ private:
+ Control* child_;
+ std::unique_ptr<TRenderObject> container_render_object_;
+};
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/StackLayout.h b/include/cru/ui/controls/StackLayout.h
index 36e8ab43..28e0e796 100644
--- a/include/cru/ui/controls/StackLayout.h
+++ b/include/cru/ui/controls/StackLayout.h
@@ -1,11 +1,13 @@
#pragma once
#include "LayoutControl.h"
-#include "cru/ui/Base.h"
+
+#include "../render/StackLayoutRenderObject.h"
namespace cru::ui::controls {
-class CRU_UI_API StackLayout : public LayoutControl {
+class CRU_UI_API StackLayout
+ : public LayoutControl<render::StackLayoutRenderObject> {
public:
- static constexpr StringView control_type = u"StackLayout";
+ static constexpr StringView kControlType = u"StackLayout";
static StackLayout* Create() { return new StackLayout(); }
@@ -18,14 +20,6 @@ class CRU_UI_API StackLayout : public LayoutControl {
~StackLayout() override;
- String GetControlType() const final { return control_type.ToString(); }
-
- render::RenderObject* GetRenderObject() const override;
-
- const StackChildLayoutData& GetChildLayoutData(Index position);
- void SetChildLayoutData(Index position, StackChildLayoutData data);
-
- private:
- std::shared_ptr<render::StackLayoutRenderObject> render_object_;
+ String GetControlType() const final { return kControlType.ToString(); }
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/TextBlock.h b/include/cru/ui/controls/TextBlock.h
index 3f87d96c..feb5cfa3 100644
--- a/include/cru/ui/controls/TextBlock.h
+++ b/include/cru/ui/controls/TextBlock.h
@@ -8,7 +8,7 @@ namespace cru::ui::controls {
class CRU_UI_API TextBlock : public NoChildControl,
public virtual ITextHostControl {
public:
- static constexpr StringView control_type = u"TextBlock";
+ static constexpr StringView kControlType = u"TextBlock";
static TextBlock* Create();
static TextBlock* Create(String text, bool selectable = false);
@@ -23,7 +23,7 @@ class CRU_UI_API TextBlock : public NoChildControl,
TextBlock& operator=(TextBlock&& other) = delete;
~TextBlock() override;
- String GetControlType() const final { return control_type.ToString(); }
+ String GetControlType() const final { return kControlType.ToString(); }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/TextBox.h b/include/cru/ui/controls/TextBox.h
index 10f67b72..0632cc12 100644
--- a/include/cru/ui/controls/TextBox.h
+++ b/include/cru/ui/controls/TextBox.h
@@ -1,6 +1,7 @@
#pragma once
#include "NoChildControl.h"
+#include "../render/BorderRenderObject.h"
#include "../render/TextRenderObject.h"
#include "IBorderControl.h"
#include "TextHostControlService.h"
diff --git a/include/cru/ui/controls/TextHostControlService.h b/include/cru/ui/controls/TextHostControlService.h
index 67b075c5..0d4a20cf 100644
--- a/include/cru/ui/controls/TextHostControlService.h
+++ b/include/cru/ui/controls/TextHostControlService.h
@@ -1,6 +1,4 @@
#pragma once
-#include "Base.h"
-
#include "../render/TextRenderObject.h"
#include "cru/platform/gui/InputMethod.h"
#include "cru/platform/gui/TimerHelper.h"
diff --git a/include/cru/ui/events/MouseEventArgs.h b/include/cru/ui/events/MouseEventArgs.h
index 11ce6463..1320002d 100644
--- a/include/cru/ui/events/MouseEventArgs.h
+++ b/include/cru/ui/events/MouseEventArgs.h
@@ -1,6 +1,8 @@
#pragma once
#include "UiEventArgs.h"
+#include "../render/RenderObject.h"
+
#include <optional>
namespace cru::ui::events {
diff --git a/include/cru/ui/host/WindowHost.h b/include/cru/ui/host/WindowHost.h
index 80076afd..1de915e0 100644
--- a/include/cru/ui/host/WindowHost.h
+++ b/include/cru/ui/host/WindowHost.h
@@ -1,6 +1,7 @@
#pragma once
#include "../Base.h"
+#include "../render/RenderObject.h"
#include "cru/common/Event.h"
#include "cru/platform/gui/Cursor.h"
#include "cru/platform/gui/UiApplication.h"
diff --git a/include/cru/ui/render/LayoutRenderObject.h b/include/cru/ui/render/LayoutRenderObject.h
index 62ee9005..d6882f9a 100644
--- a/include/cru/ui/render/LayoutRenderObject.h
+++ b/include/cru/ui/render/LayoutRenderObject.h
@@ -11,7 +11,7 @@ class CRU_UI_API LayoutRenderObject : public RenderObject {
private:
struct ChildData {
- RenderObject* child;
+ RenderObject* render_object;
ChildLayoutData layout_data;
};
@@ -43,19 +43,19 @@ class CRU_UI_API LayoutRenderObject : public RenderObject {
children_.erase(children_.begin() + position);
}
- void SetChildLayoutData(Index position, ChildLayoutData data) {
+ const ChildLayoutData& GetChildLayoutDataAt(Index position) const {
Expects(position >= 0 && position < GetChildCount());
- children_[position].layout_data = std::move(data);
- InvalidateLayout();
+ return children_[position].layout_data;
}
- const ChildLayoutData& GetChildLayoutData(Index position) const {
+ void SetChildLayoutDataAt(Index position, ChildLayoutData data) {
Expects(position >= 0 && position < GetChildCount());
- return children_[position].layout_data;
+ children_[position].layout_data = std::move(data);
+ InvalidateLayout();
}
void Draw(platform::graphics::IPainter* painter) override {
- for (auto& child : children_) {
+ for (const auto& child : children_) {
painter->PushState();
painter->ConcatTransform(
Matrix::Translation(child.render_object->GetOffset()));
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index d358940f..98d21c9e 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -5,10 +5,8 @@ add_library(cru_ui SHARED
components/Menu.cpp
controls/Button.cpp
controls/Container.cpp
- controls/ContentControl.cpp
controls/Control.cpp
controls/FlexLayout.cpp
- controls/LayoutControl.cpp
controls/NoChildControl.cpp
controls/Popup.cpp
controls/RootControl.cpp
diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp
index c6db8e4a..3134bbb6 100644
--- a/src/ui/components/Menu.cpp
+++ b/src/ui/components/Menu.cpp
@@ -33,7 +33,7 @@ void MenuItem::SetText(String text) { text_->SetText(std::move(text)); }
Menu::Menu() {
container_ = controls::FlexLayout::Create();
- container_->SetFlexDirection(FlexDirection::Vertical);
+ container_->SetFlexDirection(controls::FlexDirection::Vertical);
}
Menu::~Menu() {
diff --git a/src/ui/controls/Button.cpp b/src/ui/controls/Button.cpp
index e42bfae7..d7d157c5 100644
--- a/src/ui/controls/Button.cpp
+++ b/src/ui/controls/Button.cpp
@@ -10,11 +10,7 @@
namespace cru::ui::controls {
Button::Button() : click_detector_(this) {
- render_object_ = std::make_unique<render::BorderRenderObject>();
- render_object_->SetAttachedControl(this);
- SetContainerRenderObject(render_object_.get());
- render_object_->SetBorderEnabled(true);
-
+ GetContainerRenderObject()->SetBorderEnabled(true);
auto default_button_style =
ThemeManager::GetInstance()->GetResourceStyleRuleSet(u"button.style");
GetStyleRuleSet()->SetParent(std::move(default_button_style));
@@ -22,11 +18,7 @@ Button::Button() : click_detector_(this) {
Button::~Button() = default;
-render::RenderObject* Button::GetRenderObject() const {
- return render_object_.get();
-}
-
void Button::ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) {
- render_object_->ApplyBorderStyle(style);
+ GetContainerRenderObject()->ApplyBorderStyle(style);
}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/Container.cpp b/src/ui/controls/Container.cpp
index 92ac3847..7b0c10a9 100644
--- a/src/ui/controls/Container.cpp
+++ b/src/ui/controls/Container.cpp
@@ -5,16 +5,7 @@
#include "cru/ui/render/RenderObject.h"
namespace cru::ui::controls {
-Container::Container() {
- render_object_ = std::make_unique<render::BorderRenderObject>();
- render_object_->SetBorderEnabled(false);
- render_object_->SetAttachedControl(this);
- SetContainerRenderObject(render_object_.get());
-}
+Container::Container() {}
Container::~Container() = default;
-
-render::RenderObject* Container::GetRenderObject() const {
- return render_object_.get();
-}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/ContentControl.cpp b/src/ui/controls/ContentControl.cpp
deleted file mode 100644
index 8b421e09..00000000
--- a/src/ui/controls/ContentControl.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "cru/ui/controls/ContentControl.h"
-
-namespace cru::ui::controls {
-Control* ContentControl::GetChild() const {
- if (GetChildren().empty()) return nullptr;
- return GetChildren()[0];
-}
-
-void ContentControl::SetChild(Control* child) {
- Control* old_child = nullptr;
- if (!GetChildren().empty()) {
- old_child = GetChildren()[0];
- this->RemoveChild(0);
- }
- if (child) {
- this->AddChild(child, 0);
- }
- OnChildChanged(old_child, child);
-}
-
-void ContentControl::OnChildChanged(Control* old_child, Control* new_child) {
- if (container_render_object_) {
- if (old_child) {
- container_render_object_->RemoveChild(0);
- }
- if (new_child) {
- container_render_object_->AddChild(new_child->GetRenderObject(), 0);
- }
- }
-}
-} // namespace cru::ui::controls
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
index 36d5cd60..df71f660 100644
--- a/src/ui/controls/Control.cpp
+++ b/src/ui/controls/Control.cpp
@@ -31,31 +31,21 @@ Control::Control() {
});
}
-Control::~Control() {
- if (auto_delete_children_) {
- for (const auto child : children_) {
- delete child;
- }
- }
-}
-
-host::WindowHost* Control::GetWindowHost() const { return window_host_; }
+Control::~Control() {}
-Index Control::IndexOf(Control* child) const {
- for (Index i = 0; i < children_.size(); ++i) {
- if (children_[i] == child) return i;
+host::WindowHost* Control::GetWindowHost() const {
+ auto parent = GetParent();
+ if (parent) {
+ return parent->GetWindowHost();
}
- return -1;
+ return nullptr;
}
-void Control::TraverseDescendants(
- const std::function<void(Control*)>& predicate) {
- predicate(this);
- for (auto c : GetChildren()) c->TraverseDescendants(predicate);
-}
-
-void Control::RemoveFromParent() {
- if (parent_) parent_->RemoveChild(parent_->IndexOf(this));
+void Control::SetParent(Control* parent) {
+ if (parent_ == parent) return;
+ auto old_parent = parent_;
+ parent_ = parent;
+ OnParentChanged(old_parent, parent);
}
bool Control::HasFocus() {
@@ -117,65 +107,4 @@ void Control::SetCursor(std::shared_ptr<ICursor> cursor) {
std::shared_ptr<style::StyleRuleSet> Control::GetStyleRuleSet() {
return style_rule_set_;
}
-
-void Control::AddChild(Control* control, const Index position) {
- Expects(control->GetParent() ==
- nullptr); // The control already has a parent.
- Expects(position >= 0);
- Expects(position <= static_cast<Index>(
- children_.size())); // The position is out of range.
-
- children_.insert(children_.cbegin() + position, control);
-
- const auto old_parent = control->parent_;
- control->parent_ = this;
-
- OnAddChild(control, position);
- control->OnParentChanged(old_parent, this);
-
- if (window_host_)
- control->TraverseDescendants([this](Control* control) {
- control->window_host_ = window_host_;
- control->OnAttachToHost(window_host_);
- });
-}
-
-void Control::RemoveChild(const Index position) {
- Expects(position >= 0);
- Expects(position < static_cast<Index>(
- children_.size())); // The position is out of range.
-
- const auto i = children_.cbegin() + position;
- const auto control = *i;
-
- children_.erase(i);
- control->parent_ = nullptr;
-
- OnRemoveChild(control, position);
- control->OnParentChanged(this, nullptr);
-
- if (window_host_)
- control->TraverseDescendants([this](Control* control) {
- control->window_host_ = nullptr;
- control->OnDetachFromHost(window_host_);
- });
-}
-
-void Control::OnAddChild(Control* child, Index position) {
- CRU_UNUSED(child)
- CRU_UNUSED(position)
-}
-void Control::OnRemoveChild(Control* child, Index position) {
- CRU_UNUSED(child)
- CRU_UNUSED(position)
-}
-
-void Control::OnParentChanged(Control* old_parent, Control* new_parent) {
- CRU_UNUSED(old_parent)
- CRU_UNUSED(new_parent)
-}
-
-void Control::OnAttachToHost(host::WindowHost* host) { CRU_UNUSED(host) }
-
-void Control::OnDetachFromHost(host::WindowHost* host) { CRU_UNUSED(host) }
} // namespace cru::ui::controls
diff --git a/src/ui/controls/FlexLayout.cpp b/src/ui/controls/FlexLayout.cpp
index ecf4d428..8d71cfdb 100644
--- a/src/ui/controls/FlexLayout.cpp
+++ b/src/ui/controls/FlexLayout.cpp
@@ -1,70 +1,31 @@
#include "cru/ui/controls/FlexLayout.h"
namespace cru::ui::controls {
-using render::FlexLayoutRenderObject;
-
-FlexLayout::FlexLayout() {
- render_object_.reset(new FlexLayoutRenderObject());
- render_object_->SetAttachedControl(this);
- SetContainerRenderObject(render_object_.get());
-}
+FlexLayout::FlexLayout() = default;
FlexLayout::~FlexLayout() = default;
-render::RenderObject* FlexLayout::GetRenderObject() const {
- return render_object_.get();
-}
-
-namespace {
-Index FindPosition(render::RenderObject* parent, render::RenderObject* child) {
- const auto& render_objects = parent->GetChildren();
- const auto find_result =
- std::find(render_objects.cbegin(), render_objects.cend(), child);
- if (find_result == render_objects.cend()) {
- throw std::logic_error("Control is not a child of FlexLayout.");
- }
- return static_cast<Index>(find_result - render_objects.cbegin());
-}
-} // namespace
-
-FlexChildLayoutData FlexLayout::GetChildLayoutData(Control* control) {
- Expects(control);
- return render_object_->GetChildLayoutData(
- FindPosition(render_object_.get(), control->GetRenderObject()));
-}
-
-void FlexLayout::SetChildLayoutData(Control* control,
- FlexChildLayoutData data) {
- Expects(control);
- render_object_->SetChildLayoutData(
- FindPosition(render_object_.get(), control->GetRenderObject()),
- std::move(data));
-}
-
FlexMainAlignment FlexLayout::GetContentMainAlign() const {
- return render_object_->GetContentMainAlign();
+ return GetContainerRenderObject()->GetContentMainAlign();
}
void FlexLayout::SetContentMainAlign(FlexMainAlignment value) {
- if (value == GetContentMainAlign()) return;
- render_object_->SetContentMainAlign(value);
+ GetContainerRenderObject()->SetContentMainAlign(value);
}
FlexDirection FlexLayout::GetFlexDirection() const {
- return render_object_->GetFlexDirection();
+ return GetContainerRenderObject()->GetFlexDirection();
}
void FlexLayout::SetFlexDirection(FlexDirection direction) {
- if (direction == GetFlexDirection()) return;
- render_object_->SetFlexDirection(direction);
+ GetContainerRenderObject()->SetFlexDirection(direction);
}
FlexCrossAlignment FlexLayout::GetItemCrossAlign() const {
- return render_object_->GetItemCrossAlign();
+ return GetContainerRenderObject()->GetItemCrossAlign();
}
void FlexLayout::SetItemCrossAlign(FlexCrossAlignment alignment) {
- if (alignment == GetItemCrossAlign()) return;
- render_object_->SetItemCrossAlign(alignment);
+ GetContainerRenderObject()->SetItemCrossAlign(alignment);
}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/LayoutControl.cpp b/src/ui/controls/LayoutControl.cpp
deleted file mode 100644
index 5c67bc86..00000000
--- a/src/ui/controls/LayoutControl.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "cru/ui/controls/LayoutControl.h"
-
-#include "cru/ui/render/RenderObject.h"
-
-namespace cru::ui::controls {
-void LayoutControl::ClearChildren() {
- while (GetChildren().size() > 0) {
- RemoveChild(0);
- }
-}
-
-void LayoutControl::OnAddChild(Control* child, Index position) {
- if (container_render_object_ != nullptr) {
- container_render_object_->AddChild(child->GetRenderObject(), position);
- }
-}
-
-void LayoutControl::OnRemoveChild(Control* child, Index position) {
- CRU_UNUSED(child)
- if (container_render_object_ != nullptr) {
- container_render_object_->RemoveChild(position);
- }
-}
-} // namespace cru::ui::controls
diff --git a/src/ui/controls/NoChildControl.cpp b/src/ui/controls/NoChildControl.cpp
index 29177828..4a9002ed 100644
--- a/src/ui/controls/NoChildControl.cpp
+++ b/src/ui/controls/NoChildControl.cpp
@@ -1,3 +1,8 @@
#include "cru/ui/controls/NoChildControl.h"
-namespace cru::ui::controls {}
+namespace cru::ui::controls {
+void NoChildControl::ForEachChild(
+ const std::function<void(Control*)>& callback) {
+ CRU_UNUSED(callback);
+}
+} // namespace cru::ui::controls
diff --git a/src/ui/controls/RootControl.cpp b/src/ui/controls/RootControl.cpp
index 828822c6..07647024 100644
--- a/src/ui/controls/RootControl.cpp
+++ b/src/ui/controls/RootControl.cpp
@@ -12,21 +12,14 @@
namespace cru::ui::controls {
RootControl::RootControl(Control* attached_control)
: attached_control_(attached_control) {
- render_object_ = std::make_unique<render::StackLayoutRenderObject>();
- render_object_->SetAttachedControl(this);
- render_object_->SetDefaultHorizontalAlignment(Alignment::Stretch);
- render_object_->SetDefaultVertialAlignment(Alignment::Stretch);
- SetContainerRenderObject(render_object_.get());
+ GetContainerRenderObject()->SetDefaultHorizontalAlignment(Alignment::Stretch);
+ GetContainerRenderObject()->SetDefaultVertialAlignment(Alignment::Stretch);
window_host_ = std::make_unique<host::WindowHost>(this);
window_host_->SetLayoutPreferToFillWindow(true);
}
RootControl::~RootControl() {}
-render::RenderObject* RootControl::GetRenderObject() const {
- return render_object_.get();
-}
-
platform::gui::INativeWindow* RootControl::GetNativeWindow() {
return window_host_->GetNativeWindow();
}
diff --git a/src/ui/controls/ScrollView.cpp b/src/ui/controls/ScrollView.cpp
index e87ede4b..f3b3750f 100644
--- a/src/ui/controls/ScrollView.cpp
+++ b/src/ui/controls/ScrollView.cpp
@@ -1,19 +1,7 @@
#include "cru/ui/controls/ScrollView.h"
-#include "cru/ui/render/RenderObject.h"
-#include "cru/ui/render/ScrollRenderObject.h"
-
-#include <memory>
-
namespace cru::ui::controls {
-ScrollView::ScrollView() {
- scroll_render_object_ = std::make_unique<render::ScrollRenderObject>();
- scroll_render_object_->SetAttachedControl(this);
-
- SetContainerRenderObject(scroll_render_object_.get());
-}
+ScrollView::ScrollView() {}
-render::RenderObject* ScrollView::GetRenderObject() const {
- return scroll_render_object_.get();
-}
+ScrollView::~ScrollView() {}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/StackLayout.cpp b/src/ui/controls/StackLayout.cpp
index 7e45a555..55964bcd 100644
--- a/src/ui/controls/StackLayout.cpp
+++ b/src/ui/controls/StackLayout.cpp
@@ -1,29 +1,9 @@
#include "cru/ui/controls/StackLayout.h"
-#include <memory>
-
-#include "cru/ui/render/StackLayoutRenderObject.h"
namespace cru::ui::controls {
using render::StackLayoutRenderObject;
-StackLayout::StackLayout() {
- render_object_ = std::make_unique<StackLayoutRenderObject>();
- render_object_->SetAttachedControl(this);
- SetContainerRenderObject(render_object_.get());
-}
+StackLayout::StackLayout() = default;
StackLayout::~StackLayout() = default;
-
-render::RenderObject* StackLayout::GetRenderObject() const {
- return render_object_.get();
-}
-
-const StackChildLayoutData& StackLayout::GetChildLayoutData(Index position) {
- return render_object_->GetChildLayoutData(position);
-}
-
-void StackLayout::SetChildLayoutData(Index position,
- StackChildLayoutData data) {
- render_object_->SetChildLayoutData(position, std::move(data));
-}
} // namespace cru::ui::controls
diff --git a/src/ui/controls/TextBox.cpp b/src/ui/controls/TextBox.cpp
index 11b77e99..66b6bd43 100644
--- a/src/ui/controls/TextBox.cpp
+++ b/src/ui/controls/TextBox.cpp
@@ -24,8 +24,8 @@ TextBox::TextBox()
theme_manager->GetResourceBrush(u"text.caret.brush"));
text_render_object_->SetEditMode(true);
- border_render_object_->AddChild(scroll_render_object_.get(), 0);
- scroll_render_object_->AddChild(text_render_object_.get(), 0);
+ border_render_object_->SetChild(scroll_render_object_.get());
+ scroll_render_object_->SetChild(text_render_object_.get());
border_render_object_->SetAttachedControl(this);
scroll_render_object_->SetAttachedControl(this);
diff --git a/src/ui/controls/Window.cpp b/src/ui/controls/Window.cpp
index 998395f3..6891c918 100644
--- a/src/ui/controls/Window.cpp
+++ b/src/ui/controls/Window.cpp
@@ -1,12 +1,5 @@
#include "cru/ui/controls/Window.h"
-#include "cru/common/Base.h"
-#include "cru/platform/gui/Base.h"
-#include "cru/ui/controls/RootControl.h"
-#include "cru/ui/host/WindowHost.h"
-#include "cru/ui/render/Base.h"
-#include "cru/ui/render/StackLayoutRenderObject.h"
-
namespace cru::ui::controls {
Window* Window::Create(Control* attached_control) {
return new Window(attached_control);
diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp
index 9773c117..6849d000 100644
--- a/src/ui/host/WindowHost.cpp
+++ b/src/ui/host/WindowHost.cpp
@@ -105,11 +105,6 @@ inline void BindNativeEvent(
WindowHost::WindowHost(controls::Control* root_control)
: root_control_(root_control), focus_control_(root_control) {
- root_control_->TraverseDescendants([this](controls::Control* control) {
- control->window_host_ = this;
- control->OnAttachToHost(this);
- });
-
root_render_object_ = root_control->GetRenderObject();
this->layout_paint_cycler_ = std::make_unique<LayoutPaintCycler>(this);
diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp
index ebe60395..6475d005 100644
--- a/src/ui/render/FlexLayoutRenderObject.cpp
+++ b/src/ui/render/FlexLayoutRenderObject.cpp
@@ -333,7 +333,7 @@ Size FlexLayoutRenderObject::OnMeasureContent(
std::vector<FlexChildLayoutData> layout_data_list;
for (int i = 0; i < GetChildCount(); i++) {
children.push_back(GetChildAt(i));
- layout_data_list.push_back(GetChildLayoutData(i));
+ layout_data_list.push_back(GetChildLayoutDataAt(i));
}
if (horizontal) {
@@ -353,7 +353,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
std::vector<FlexChildLayoutData> layout_data_list;
for (int i = 0; i < child_count; i++) {
children.push_back(GetChildAt(i));
- layout_data_list.push_back(GetChildLayoutData(i));
+ layout_data_list.push_back(GetChildLayoutDataAt(i));
}
if (direction_ == FlexDirection::Horizontal) {
diff --git a/src/ui/render/StackLayoutRenderObject.cpp b/src/ui/render/StackLayoutRenderObject.cpp
index 6c79716f..fda9a420 100644
--- a/src/ui/render/StackLayoutRenderObject.cpp
+++ b/src/ui/render/StackLayoutRenderObject.cpp
@@ -35,7 +35,7 @@ Size StackLayoutRenderObject::OnMeasureContent(
child_max_size = Max(requirement.min.GetSizeOr0(), child_max_size);
for (Index i = 0; i < GetChildCount(); ++i) {
- auto child_layout_data = GetChildLayoutData(i);
+ auto child_layout_data = GetChildLayoutDataAt(i);
auto horizontal_stretch =
child_layout_data.horizontal.value_or(default_horizontal_alignment_) ==
Alignment::Stretch;
@@ -67,7 +67,7 @@ void StackLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
for (int i = 0; i < count; i++) {
const auto child = GetChildAt(i);
- const auto& layout_data = GetChildLayoutData(i);
+ const auto& layout_data = GetChildLayoutDataAt(i);
const auto& size = child->GetDesiredSize();
child->Layout(Point{
CalculateAnchorByAlignment(