diff options
author | crupest <crupest@outlook.com> | 2022-02-09 23:53:18 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-02-09 23:53:18 +0800 |
commit | b8863c403a44c1c7ac35f1a1da92bbf3c8858552 (patch) | |
tree | 7e38f029f0657e6c1210a53f1cba331cdb8feab6 | |
parent | d18b5453d7ffd19667ee8ac125b34ab5328f0dc3 (diff) | |
download | cru-b8863c403a44c1c7ac35f1a1da92bbf3c8858552.tar.gz cru-b8863c403a44c1c7ac35f1a1da92bbf3c8858552.tar.bz2 cru-b8863c403a44c1c7ac35f1a1da92bbf3c8858552.zip |
...
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( |