diff options
Diffstat (limited to 'include/cru/ui')
21 files changed, 167 insertions, 173 deletions
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())); |