From 74bb9cd27242b9320f99ff4d2b50c3051576cc14 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 8 Feb 2022 16:53:51 +0800 Subject: ... --- include/cru/ui/controls/Base.h | 4 + include/cru/ui/controls/Base.hpp | 4 - include/cru/ui/controls/Button.h | 53 +++++ include/cru/ui/controls/Button.hpp | 53 ----- include/cru/ui/controls/Container.h | 25 +++ include/cru/ui/controls/Container.hpp | 25 --- include/cru/ui/controls/ContentControl.h | 38 ++++ include/cru/ui/controls/ContentControl.hpp | 38 ---- include/cru/ui/controls/Control.h | 157 +++++++++++++++ include/cru/ui/controls/Control.hpp | 157 --------------- include/cru/ui/controls/FlexLayout.h | 40 ++++ include/cru/ui/controls/FlexLayout.hpp | 40 ---- include/cru/ui/controls/IBorderControl.h | 10 + include/cru/ui/controls/IBorderControl.hpp | 10 - include/cru/ui/controls/IClickableControl.h | 12 ++ include/cru/ui/controls/IClickableControl.hpp | 12 -- include/cru/ui/controls/LayoutControl.h | 37 ++++ include/cru/ui/controls/LayoutControl.hpp | 37 ---- include/cru/ui/controls/NoChildControl.h | 20 ++ include/cru/ui/controls/NoChildControl.hpp | 20 -- include/cru/ui/controls/Popup.h | 26 +++ include/cru/ui/controls/Popup.hpp | 26 --- include/cru/ui/controls/RootControl.h | 39 ++++ include/cru/ui/controls/RootControl.hpp | 39 ---- include/cru/ui/controls/ScrollView.h | 32 +++ include/cru/ui/controls/ScrollView.hpp | 32 --- include/cru/ui/controls/StackLayout.h | 31 +++ include/cru/ui/controls/StackLayout.hpp | 31 --- include/cru/ui/controls/TextBlock.h | 44 +++++ include/cru/ui/controls/TextBlock.hpp | 44 ----- include/cru/ui/controls/TextBox.h | 46 +++++ include/cru/ui/controls/TextBox.hpp | 46 ----- include/cru/ui/controls/TextHostControlService.h | 219 +++++++++++++++++++++ include/cru/ui/controls/TextHostControlService.hpp | 219 --------------------- include/cru/ui/controls/Window.h | 27 +++ include/cru/ui/controls/Window.hpp | 27 --- 36 files changed, 860 insertions(+), 860 deletions(-) create mode 100644 include/cru/ui/controls/Base.h delete mode 100644 include/cru/ui/controls/Base.hpp create mode 100644 include/cru/ui/controls/Button.h delete mode 100644 include/cru/ui/controls/Button.hpp create mode 100644 include/cru/ui/controls/Container.h delete mode 100644 include/cru/ui/controls/Container.hpp create mode 100644 include/cru/ui/controls/ContentControl.h delete mode 100644 include/cru/ui/controls/ContentControl.hpp create mode 100644 include/cru/ui/controls/Control.h delete mode 100644 include/cru/ui/controls/Control.hpp create mode 100644 include/cru/ui/controls/FlexLayout.h delete mode 100644 include/cru/ui/controls/FlexLayout.hpp create mode 100644 include/cru/ui/controls/IBorderControl.h delete mode 100644 include/cru/ui/controls/IBorderControl.hpp create mode 100644 include/cru/ui/controls/IClickableControl.h delete mode 100644 include/cru/ui/controls/IClickableControl.hpp create mode 100644 include/cru/ui/controls/LayoutControl.h delete mode 100644 include/cru/ui/controls/LayoutControl.hpp create mode 100644 include/cru/ui/controls/NoChildControl.h delete mode 100644 include/cru/ui/controls/NoChildControl.hpp create mode 100644 include/cru/ui/controls/Popup.h delete mode 100644 include/cru/ui/controls/Popup.hpp create mode 100644 include/cru/ui/controls/RootControl.h delete mode 100644 include/cru/ui/controls/RootControl.hpp create mode 100644 include/cru/ui/controls/ScrollView.h delete mode 100644 include/cru/ui/controls/ScrollView.hpp create mode 100644 include/cru/ui/controls/StackLayout.h delete mode 100644 include/cru/ui/controls/StackLayout.hpp create mode 100644 include/cru/ui/controls/TextBlock.h delete mode 100644 include/cru/ui/controls/TextBlock.hpp create mode 100644 include/cru/ui/controls/TextBox.h delete mode 100644 include/cru/ui/controls/TextBox.hpp create mode 100644 include/cru/ui/controls/TextHostControlService.h delete mode 100644 include/cru/ui/controls/TextHostControlService.hpp create mode 100644 include/cru/ui/controls/Window.h delete mode 100644 include/cru/ui/controls/Window.hpp (limited to 'include/cru/ui/controls') diff --git a/include/cru/ui/controls/Base.h b/include/cru/ui/controls/Base.h new file mode 100644 index 00000000..21f1c563 --- /dev/null +++ b/include/cru/ui/controls/Base.h @@ -0,0 +1,4 @@ +#pragma once +#include "../Base.h" + +namespace cru::ui::controls {} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Base.hpp b/include/cru/ui/controls/Base.hpp deleted file mode 100644 index 7c85cdb2..00000000 --- a/include/cru/ui/controls/Base.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::controls {} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.h b/include/cru/ui/controls/Button.h new file mode 100644 index 00000000..ab1ef8eb --- /dev/null +++ b/include/cru/ui/controls/Button.h @@ -0,0 +1,53 @@ +#pragma once +#include "ContentControl.h" + +#include "../helper/ClickDetector.h" +#include "IBorderControl.h" +#include "IClickableControl.h" +#include "cru/common/Event.h" +#include "cru/ui/style/ApplyBorderStyleInfo.h" + +namespace cru::ui::controls { +class CRU_UI_API Button : public ContentControl, + public virtual IClickableControl, + public virtual IBorderControl { + public: + static constexpr StringView control_type = u"Button"; + + static Button* Create() { return new Button(); } + + protected: + Button(); + + public: + Button(const Button& other) = delete; + Button(Button&& other) = delete; + Button& operator=(const Button& other) = delete; + Button& operator=(Button&& other) = delete; + ~Button() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + public: + helper::ClickState GetClickState() override { + return click_detector_.GetState(); + } + + IEvent* ClickStateChangeEvent() override { + return click_detector_.StateChangeEvent(); + } + + IEvent* ClickEvent() { + return click_detector_.ClickEvent(); + } + + void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; + + private: + std::unique_ptr render_object_{}; + + helper::ClickDetector click_detector_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.hpp b/include/cru/ui/controls/Button.hpp deleted file mode 100644 index 77e0989c..00000000 --- a/include/cru/ui/controls/Button.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "ContentControl.hpp" - -#include "../helper/ClickDetector.hpp" -#include "IBorderControl.hpp" -#include "IClickableControl.hpp" -#include "cru/common/Event.hpp" -#include "cru/ui/style/ApplyBorderStyleInfo.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Button : public ContentControl, - public virtual IClickableControl, - public virtual IBorderControl { - public: - static constexpr StringView control_type = u"Button"; - - static Button* Create() { return new Button(); } - - protected: - Button(); - - public: - Button(const Button& other) = delete; - Button(Button&& other) = delete; - Button& operator=(const Button& other) = delete; - Button& operator=(Button&& other) = delete; - ~Button() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - public: - helper::ClickState GetClickState() override { - return click_detector_.GetState(); - } - - IEvent* ClickStateChangeEvent() override { - return click_detector_.StateChangeEvent(); - } - - IEvent* ClickEvent() { - return click_detector_.ClickEvent(); - } - - void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; - - private: - std::unique_ptr 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 new file mode 100644 index 00000000..f250807d --- /dev/null +++ b/include/cru/ui/controls/Container.h @@ -0,0 +1,25 @@ +#pragma once +#include "ContentControl.h" + +namespace cru::ui::controls { +class CRU_UI_API Container : public ContentControl { + static constexpr StringView control_type = u"Container"; + + protected: + Container(); + + public: + CRU_DELETE_COPY(Container) + CRU_DELETE_MOVE(Container) + + ~Container() override; + + public: + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + private: + std::unique_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Container.hpp b/include/cru/ui/controls/Container.hpp deleted file mode 100644 index 4385c23f..00000000 --- a/include/cru/ui/controls/Container.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "ContentControl.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Container : public ContentControl { - static constexpr StringView control_type = u"Container"; - - protected: - Container(); - - public: - CRU_DELETE_COPY(Container) - CRU_DELETE_MOVE(Container) - - ~Container() override; - - public: - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - private: - std::unique_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ContentControl.h b/include/cru/ui/controls/ContentControl.h new file mode 100644 index 00000000..86e90dae --- /dev/null +++ b/include/cru/ui/controls/ContentControl.h @@ -0,0 +1,38 @@ +#pragma once +#include "Control.h" + +#include "cru/ui/render/RenderObject.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/ContentControl.hpp b/include/cru/ui/controls/ContentControl.hpp deleted file mode 100644 index 7b40de64..00000000 --- a/include/cru/ui/controls/ContentControl.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "Control.hpp" - -#include "cru/ui/render/RenderObject.hpp" - -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 new file mode 100644 index 00000000..c00e3a65 --- /dev/null +++ b/include/cru/ui/controls/Control.h @@ -0,0 +1,157 @@ +#pragma once +#include "Base.h" + +#include "../events/UiEvents.h" +#include "../render/Base.h" +#include "cru/common/Event.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API Control : public Object { + friend host::WindowHost; + + protected: + Control(); + + public: + Control(const Control& other) = delete; + Control(Control&& other) = delete; + Control& operator=(const Control& other) = delete; + Control& operator=(Control&& other) = delete; + ~Control() override; + + public: + virtual String GetControlType() const = 0; + + //*************** region: tree *************** + public: + host::WindowHost* GetWindowHost() const; + + Control* GetParent() const { return parent_; } + + const std::vector& GetChildren() const { return children_; } + + // Traverse the tree rooted the control including itself. + void TraverseDescendants(const std::function& predicate); + + public: + virtual render::RenderObject* GetRenderObject() const = 0; + + //*************** region: focus *************** + public: + bool HasFocus(); + + void SetFocus(); + + //*************** region: mouse *************** + public: + bool IsMouseOver() const { return is_mouse_over_; } + + bool CaptureMouse(); + + bool ReleaseMouse(); + + bool IsMouseCaptured(); + + //*************** region: cursor *************** + // Cursor is inherited from parent recursively if not set. + public: + // null for not set + std::shared_ptr GetCursor(); + + // will not return nullptr + std::shared_ptr GetInheritedCursor(); + + // null to unset + void SetCursor(std::shared_ptr cursor); + + public: + std::shared_ptr GetStyleRuleSet(); + + //*************** region: events *************** + public: + // Raised when mouse enter the control. Even when the control itself captures + // the mouse, this event is raised as regular. But if mouse is captured by + // another control, the control will not receive any mouse enter event. You + // can use `IsMouseCaptured` to get more info. + events::RoutedEvent* MouseEnterEvent() { + return &mouse_enter_event_; + } + // Raised when mouse is leave the control. Even when the control itself + // captures the mouse, this event is raised as regular. But if mouse is + // captured by another control, the control will not receive any mouse leave + // event. You can use `IsMouseCaptured` to get more info. + events::RoutedEvent* MouseLeaveEvent() { + return &mouse_leave_event_; + } + // Raised when mouse is move in the control. + events::RoutedEvent* MouseMoveEvent() { + return &mouse_move_event_; + } + // Raised when a mouse button is pressed in the control. + events::RoutedEvent* MouseDownEvent() { + return &mouse_down_event_; + } + // Raised when a mouse button is released in the control. + events::RoutedEvent* MouseUpEvent() { + return &mouse_up_event_; + } + events::RoutedEvent* MouseWheelEvent() { + return &mouse_wheel_event_; + } + events::RoutedEvent* KeyDownEvent() { + return &key_down_event_; + } + events::RoutedEvent* KeyUpEvent() { + return &key_up_event_; + } + events::RoutedEvent* GainFocusEvent() { + return &gain_focus_event_; + } + events::RoutedEvent* LoseFocusEvent() { + return &lose_focus_event_; + } + + private: + events::RoutedEvent mouse_enter_event_; + events::RoutedEvent mouse_leave_event_; + events::RoutedEvent mouse_move_event_; + events::RoutedEvent mouse_down_event_; + events::RoutedEvent mouse_up_event_; + events::RoutedEvent mouse_wheel_event_; + + events::RoutedEvent key_down_event_; + events::RoutedEvent key_up_event_; + + events::RoutedEvent gain_focus_event_; + events::RoutedEvent lose_focus_event_; + + //*************** 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 children_; + + host::WindowHost* window_host_ = nullptr; + + private: + bool is_mouse_over_ = false; + + std::shared_ptr cursor_ = nullptr; + + std::shared_ptr style_rule_set_; + std::unique_ptr style_rule_set_bind_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Control.hpp b/include/cru/ui/controls/Control.hpp deleted file mode 100644 index c51643be..00000000 --- a/include/cru/ui/controls/Control.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "../events/UiEvents.hpp" -#include "../render/Base.hpp" -#include "cru/common/Event.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API Control : public Object { - friend host::WindowHost; - - protected: - Control(); - - public: - Control(const Control& other) = delete; - Control(Control&& other) = delete; - Control& operator=(const Control& other) = delete; - Control& operator=(Control&& other) = delete; - ~Control() override; - - public: - virtual String GetControlType() const = 0; - - //*************** region: tree *************** - public: - host::WindowHost* GetWindowHost() const; - - Control* GetParent() const { return parent_; } - - const std::vector& GetChildren() const { return children_; } - - // Traverse the tree rooted the control including itself. - void TraverseDescendants(const std::function& predicate); - - public: - virtual render::RenderObject* GetRenderObject() const = 0; - - //*************** region: focus *************** - public: - bool HasFocus(); - - void SetFocus(); - - //*************** region: mouse *************** - public: - bool IsMouseOver() const { return is_mouse_over_; } - - bool CaptureMouse(); - - bool ReleaseMouse(); - - bool IsMouseCaptured(); - - //*************** region: cursor *************** - // Cursor is inherited from parent recursively if not set. - public: - // null for not set - std::shared_ptr GetCursor(); - - // will not return nullptr - std::shared_ptr GetInheritedCursor(); - - // null to unset - void SetCursor(std::shared_ptr cursor); - - public: - std::shared_ptr GetStyleRuleSet(); - - //*************** region: events *************** - public: - // Raised when mouse enter the control. Even when the control itself captures - // the mouse, this event is raised as regular. But if mouse is captured by - // another control, the control will not receive any mouse enter event. You - // can use `IsMouseCaptured` to get more info. - events::RoutedEvent* MouseEnterEvent() { - return &mouse_enter_event_; - } - // Raised when mouse is leave the control. Even when the control itself - // captures the mouse, this event is raised as regular. But if mouse is - // captured by another control, the control will not receive any mouse leave - // event. You can use `IsMouseCaptured` to get more info. - events::RoutedEvent* MouseLeaveEvent() { - return &mouse_leave_event_; - } - // Raised when mouse is move in the control. - events::RoutedEvent* MouseMoveEvent() { - return &mouse_move_event_; - } - // Raised when a mouse button is pressed in the control. - events::RoutedEvent* MouseDownEvent() { - return &mouse_down_event_; - } - // Raised when a mouse button is released in the control. - events::RoutedEvent* MouseUpEvent() { - return &mouse_up_event_; - } - events::RoutedEvent* MouseWheelEvent() { - return &mouse_wheel_event_; - } - events::RoutedEvent* KeyDownEvent() { - return &key_down_event_; - } - events::RoutedEvent* KeyUpEvent() { - return &key_up_event_; - } - events::RoutedEvent* GainFocusEvent() { - return &gain_focus_event_; - } - events::RoutedEvent* LoseFocusEvent() { - return &lose_focus_event_; - } - - private: - events::RoutedEvent mouse_enter_event_; - events::RoutedEvent mouse_leave_event_; - events::RoutedEvent mouse_move_event_; - events::RoutedEvent mouse_down_event_; - events::RoutedEvent mouse_up_event_; - events::RoutedEvent mouse_wheel_event_; - - events::RoutedEvent key_down_event_; - events::RoutedEvent key_up_event_; - - events::RoutedEvent gain_focus_event_; - events::RoutedEvent lose_focus_event_; - - //*************** 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 children_; - - host::WindowHost* window_host_ = nullptr; - - private: - bool is_mouse_over_ = false; - - std::shared_ptr cursor_ = nullptr; - - std::shared_ptr style_rule_set_; - std::unique_ptr style_rule_set_bind_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/FlexLayout.h b/include/cru/ui/controls/FlexLayout.h new file mode 100644 index 00000000..1255b119 --- /dev/null +++ b/include/cru/ui/controls/FlexLayout.h @@ -0,0 +1,40 @@ +#pragma once +#include "LayoutControl.h" + +namespace cru::ui::controls { +class CRU_UI_API FlexLayout : public LayoutControl { + public: + static constexpr StringView control_type = u"FlexLayout"; + + static FlexLayout* Create() { return new FlexLayout(); } + + protected: + FlexLayout(); + + public: + FlexLayout(const FlexLayout& other) = delete; + FlexLayout(FlexLayout&& other) = delete; + FlexLayout& operator=(const FlexLayout& other) = delete; + FlexLayout& operator=(FlexLayout&& other) = delete; + ~FlexLayout() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + FlexMainAlignment GetContentMainAlign() const; + void SetContentMainAlign(FlexMainAlignment value); + + FlexDirection GetFlexDirection() const; + void SetFlexDirection(FlexDirection direction); + + FlexCrossAlignment GetItemCrossAlign() const; + void SetItemCrossAlign(FlexCrossAlignment alignment); + + FlexChildLayoutData GetChildLayoutData(Control* control); + void SetChildLayoutData(Control* control, FlexChildLayoutData data); + + private: + std::shared_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/FlexLayout.hpp b/include/cru/ui/controls/FlexLayout.hpp deleted file mode 100644 index 7724c4c6..00000000 --- a/include/cru/ui/controls/FlexLayout.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" - -namespace cru::ui::controls { -class CRU_UI_API FlexLayout : public LayoutControl { - public: - static constexpr StringView control_type = u"FlexLayout"; - - static FlexLayout* Create() { return new FlexLayout(); } - - protected: - FlexLayout(); - - public: - FlexLayout(const FlexLayout& other) = delete; - FlexLayout(FlexLayout&& other) = delete; - FlexLayout& operator=(const FlexLayout& other) = delete; - FlexLayout& operator=(FlexLayout&& other) = delete; - ~FlexLayout() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - FlexMainAlignment GetContentMainAlign() const; - void SetContentMainAlign(FlexMainAlignment value); - - FlexDirection GetFlexDirection() const; - void SetFlexDirection(FlexDirection direction); - - FlexCrossAlignment GetItemCrossAlign() const; - void SetItemCrossAlign(FlexCrossAlignment alignment); - - FlexChildLayoutData GetChildLayoutData(Control* control); - void SetChildLayoutData(Control* control, FlexChildLayoutData data); - - private: - std::shared_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IBorderControl.h b/include/cru/ui/controls/IBorderControl.h new file mode 100644 index 00000000..3178d7f2 --- /dev/null +++ b/include/cru/ui/controls/IBorderControl.h @@ -0,0 +1,10 @@ +#pragma once +#include "../style/ApplyBorderStyleInfo.h" +#include "Base.h" +#include "cru/common/Base.h" + +namespace cru::ui::controls { +struct CRU_UI_API IBorderControl : virtual Interface { + virtual void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) = 0; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IBorderControl.hpp b/include/cru/ui/controls/IBorderControl.hpp deleted file mode 100644 index a8bc0b51..00000000 --- a/include/cru/ui/controls/IBorderControl.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "../style/ApplyBorderStyleInfo.hpp" -#include "Base.hpp" -#include "cru/common/Base.hpp" - -namespace cru::ui::controls { -struct CRU_UI_API IBorderControl : virtual Interface { - virtual void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) = 0; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IClickableControl.h b/include/cru/ui/controls/IClickableControl.h new file mode 100644 index 00000000..48b3ad5f --- /dev/null +++ b/include/cru/ui/controls/IClickableControl.h @@ -0,0 +1,12 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Event.h" +#include "cru/ui/helper/ClickDetector.h" + +namespace cru::ui::controls { +struct CRU_UI_API IClickableControl : virtual Interface { + virtual helper::ClickState GetClickState() = 0; + virtual IEvent* ClickStateChangeEvent() = 0; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IClickableControl.hpp b/include/cru/ui/controls/IClickableControl.hpp deleted file mode 100644 index af9ae100..00000000 --- a/include/cru/ui/controls/IClickableControl.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Event.hpp" -#include "cru/ui/helper/ClickDetector.hpp" - -namespace cru::ui::controls { -struct CRU_UI_API IClickableControl : virtual Interface { - virtual helper::ClickState GetClickState() = 0; - virtual IEvent* ClickStateChangeEvent() = 0; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/LayoutControl.h b/include/cru/ui/controls/LayoutControl.h new file mode 100644 index 00000000..639ecc74 --- /dev/null +++ b/include/cru/ui/controls/LayoutControl.h @@ -0,0 +1,37 @@ +#pragma once +#include "Control.h" + +namespace cru::ui::controls { +class CRU_UI_API LayoutControl : public Control { + protected: + LayoutControl() = default; + explicit LayoutControl(render::RenderObject* container_render_object) + : container_render_object_(container_render_object) {} + + public: + LayoutControl(const LayoutControl& other) = delete; + LayoutControl(LayoutControl&& other) = delete; + LayoutControl& operator=(const LayoutControl& other) = delete; + LayoutControl& operator=(LayoutControl&& other) = delete; + ~LayoutControl() override = default; + + using Control::AddChild; + using Control::RemoveChild; + + void ClearChildren(); + + 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; + } + + void OnAddChild(Control* child, Index position) override; + void OnRemoveChild(Control* child, Index position) override; + + private: + render::RenderObject* container_render_object_ = nullptr; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/LayoutControl.hpp b/include/cru/ui/controls/LayoutControl.hpp deleted file mode 100644 index 3999e9bc..00000000 --- a/include/cru/ui/controls/LayoutControl.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "Control.hpp" - -namespace cru::ui::controls { -class CRU_UI_API LayoutControl : public Control { - protected: - LayoutControl() = default; - explicit LayoutControl(render::RenderObject* container_render_object) - : container_render_object_(container_render_object) {} - - public: - LayoutControl(const LayoutControl& other) = delete; - LayoutControl(LayoutControl&& other) = delete; - LayoutControl& operator=(const LayoutControl& other) = delete; - LayoutControl& operator=(LayoutControl&& other) = delete; - ~LayoutControl() override = default; - - using Control::AddChild; - using Control::RemoveChild; - - void ClearChildren(); - - 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; - } - - void OnAddChild(Control* child, Index position) override; - void OnRemoveChild(Control* child, Index position) override; - - private: - render::RenderObject* container_render_object_ = nullptr; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/NoChildControl.h b/include/cru/ui/controls/NoChildControl.h new file mode 100644 index 00000000..6d2168cb --- /dev/null +++ b/include/cru/ui/controls/NoChildControl.h @@ -0,0 +1,20 @@ +#pragma once +#include "Control.h" + +namespace cru::ui::controls { +class CRU_UI_API NoChildControl : public Control { + protected: + NoChildControl() = default; + + public: + NoChildControl(const NoChildControl& other) = delete; + NoChildControl(NoChildControl&& other) = delete; + NoChildControl& operator=(const NoChildControl& other) = delete; + NoChildControl& operator=(NoChildControl&& other) = delete; + ~NoChildControl() override = default; + + private: + using Control::AddChild; + using Control::RemoveChild; +}; +} // namespace cru::ui diff --git a/include/cru/ui/controls/NoChildControl.hpp b/include/cru/ui/controls/NoChildControl.hpp deleted file mode 100644 index 0c432532..00000000 --- a/include/cru/ui/controls/NoChildControl.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Control.hpp" - -namespace cru::ui::controls { -class CRU_UI_API NoChildControl : public Control { - protected: - NoChildControl() = default; - - public: - NoChildControl(const NoChildControl& other) = delete; - NoChildControl(NoChildControl&& other) = delete; - NoChildControl& operator=(const NoChildControl& other) = delete; - NoChildControl& operator=(NoChildControl&& other) = delete; - ~NoChildControl() override = default; - - private: - using Control::AddChild; - using Control::RemoveChild; -}; -} // namespace cru::ui diff --git a/include/cru/ui/controls/Popup.h b/include/cru/ui/controls/Popup.h new file mode 100644 index 00000000..271ad4b7 --- /dev/null +++ b/include/cru/ui/controls/Popup.h @@ -0,0 +1,26 @@ +#pragma once +#include "RootControl.h" + +#include "cru/platform/gui/Base.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API Popup : public RootControl { + public: + static constexpr StringView kControlType = u"Popup"; + + static Popup* Create(Control* attached_control = nullptr) { + return new Popup(attached_control); + } + + explicit Popup(Control* attached_control = nullptr); + + CRU_DELETE_COPY(Popup) + CRU_DELETE_MOVE(Popup) + + ~Popup() override; + + String GetControlType() const override { return kControlType.ToString(); } +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Popup.hpp b/include/cru/ui/controls/Popup.hpp deleted file mode 100644 index 4076e45b..00000000 --- a/include/cru/ui/controls/Popup.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "RootControl.hpp" - -#include "cru/platform/gui/Base.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API Popup : public RootControl { - public: - static constexpr StringView kControlType = u"Popup"; - - static Popup* Create(Control* attached_control = nullptr) { - return new Popup(attached_control); - } - - explicit Popup(Control* attached_control = nullptr); - - CRU_DELETE_COPY(Popup) - CRU_DELETE_MOVE(Popup) - - ~Popup() override; - - String GetControlType() const override { return kControlType.ToString(); } -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/RootControl.h b/include/cru/ui/controls/RootControl.h new file mode 100644 index 00000000..c7ed916a --- /dev/null +++ b/include/cru/ui/controls/RootControl.h @@ -0,0 +1,39 @@ +#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" + +namespace cru::ui::controls { +class CRU_UI_API RootControl : public LayoutControl { + protected: + explicit RootControl(Control* attached_control); + + public: + CRU_DELETE_COPY(RootControl) + CRU_DELETE_MOVE(RootControl) + ~RootControl() override; + + public: + render::RenderObject* GetRenderObject() const override; + + platform::gui::INativeWindow* GetNativeWindow(); + + protected: + void SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value); + + private: + std::unique_ptr window_host_; + + std::unique_ptr render_object_; + + Control* attached_control_; + + EventRevokerListGuard + gain_focus_on_create_and_destroy_when_lose_focus_event_guard_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/RootControl.hpp b/include/cru/ui/controls/RootControl.hpp deleted file mode 100644 index f70f2eeb..00000000 --- a/include/cru/ui/controls/RootControl.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" - -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/Window.hpp" -#include "cru/ui/Base.hpp" -#include "cru/ui/host/WindowHost.hpp" - -namespace cru::ui::controls { -class CRU_UI_API RootControl : public LayoutControl { - protected: - explicit RootControl(Control* attached_control); - - public: - CRU_DELETE_COPY(RootControl) - CRU_DELETE_MOVE(RootControl) - ~RootControl() override; - - public: - render::RenderObject* GetRenderObject() const override; - - platform::gui::INativeWindow* GetNativeWindow(); - - protected: - void SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value); - - private: - std::unique_ptr window_host_; - - std::unique_ptr render_object_; - - Control* attached_control_; - - EventRevokerListGuard - gain_focus_on_create_and_destroy_when_lose_focus_event_guard_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ScrollView.h b/include/cru/ui/controls/ScrollView.h new file mode 100644 index 00000000..46c23691 --- /dev/null +++ b/include/cru/ui/controls/ScrollView.h @@ -0,0 +1,32 @@ +#pragma once +#include "ContentControl.h" +#include "cru/common/Base.h" +#include "cru/ui/render/RenderObject.h" +#include "cru/ui/render/ScrollRenderObject.h" + +#include +#include + +namespace cru::ui::controls { +class CRU_UI_API ScrollView : public ContentControl { + public: + static ScrollView* Create() { return new ScrollView(); } + + static constexpr StringView control_type = u"ScrollView"; + + ScrollView(); + + CRU_DELETE_COPY(ScrollView) + CRU_DELETE_MOVE(ScrollView) + + ~ScrollView() override = default; + + public: + String GetControlType() const override { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + private: + std::unique_ptr scroll_render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ScrollView.hpp b/include/cru/ui/controls/ScrollView.hpp deleted file mode 100644 index 18a9bf97..00000000 --- a/include/cru/ui/controls/ScrollView.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "ContentControl.hpp" -#include "cru/common/Base.hpp" -#include "cru/ui/render/RenderObject.hpp" -#include "cru/ui/render/ScrollRenderObject.hpp" - -#include -#include - -namespace cru::ui::controls { -class CRU_UI_API ScrollView : public ContentControl { - public: - static ScrollView* Create() { return new ScrollView(); } - - static constexpr StringView control_type = u"ScrollView"; - - ScrollView(); - - CRU_DELETE_COPY(ScrollView) - CRU_DELETE_MOVE(ScrollView) - - ~ScrollView() override = default; - - public: - String GetControlType() const override { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - private: - std::unique_ptr scroll_render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/StackLayout.h b/include/cru/ui/controls/StackLayout.h new file mode 100644 index 00000000..36e8ab43 --- /dev/null +++ b/include/cru/ui/controls/StackLayout.h @@ -0,0 +1,31 @@ +#pragma once +#include "LayoutControl.h" +#include "cru/ui/Base.h" + +namespace cru::ui::controls { +class CRU_UI_API StackLayout : public LayoutControl { + public: + static constexpr StringView control_type = u"StackLayout"; + + static StackLayout* Create() { return new StackLayout(); } + + protected: + StackLayout(); + + public: + CRU_DELETE_COPY(StackLayout) + CRU_DELETE_MOVE(StackLayout) + + ~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_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/StackLayout.hpp b/include/cru/ui/controls/StackLayout.hpp deleted file mode 100644 index 5d90dfda..00000000 --- a/include/cru/ui/controls/StackLayout.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" -#include "cru/ui/Base.hpp" - -namespace cru::ui::controls { -class CRU_UI_API StackLayout : public LayoutControl { - public: - static constexpr StringView control_type = u"StackLayout"; - - static StackLayout* Create() { return new StackLayout(); } - - protected: - StackLayout(); - - public: - CRU_DELETE_COPY(StackLayout) - CRU_DELETE_MOVE(StackLayout) - - ~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_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBlock.h b/include/cru/ui/controls/TextBlock.h new file mode 100644 index 00000000..5e5674a2 --- /dev/null +++ b/include/cru/ui/controls/TextBlock.h @@ -0,0 +1,44 @@ +#pragma once +#include "NoChildControl.h" + +#include "TextHostControlService.h" + +namespace cru::ui::controls { +class CRU_UI_API TextBlock : public NoChildControl, public virtual ITextHostControl { + public: + static constexpr StringView control_type = u"TextBlock"; + + static TextBlock* Create(); + static TextBlock* Create(String text, bool selectable = false); + + protected: + TextBlock(); + + public: + TextBlock(const TextBlock& other) = delete; + TextBlock(TextBlock&& other) = delete; + TextBlock& operator=(const TextBlock& other) = delete; + TextBlock& operator=(TextBlock&& other) = delete; + ~TextBlock() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + String GetText() const; + void SetText(String text); + + bool IsSelectable() const; + void SetSelectable(bool value); + + gsl::not_null GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override { + return nullptr; + } + + private: + std::unique_ptr text_render_object_; + + std::unique_ptr service_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBlock.hpp b/include/cru/ui/controls/TextBlock.hpp deleted file mode 100644 index 68e9ced1..00000000 --- a/include/cru/ui/controls/TextBlock.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include "NoChildControl.hpp" - -#include "TextHostControlService.hpp" - -namespace cru::ui::controls { -class CRU_UI_API TextBlock : public NoChildControl, public virtual ITextHostControl { - public: - static constexpr StringView control_type = u"TextBlock"; - - static TextBlock* Create(); - static TextBlock* Create(String text, bool selectable = false); - - protected: - TextBlock(); - - public: - TextBlock(const TextBlock& other) = delete; - TextBlock(TextBlock&& other) = delete; - TextBlock& operator=(const TextBlock& other) = delete; - TextBlock& operator=(TextBlock&& other) = delete; - ~TextBlock() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - String GetText() const; - void SetText(String text); - - bool IsSelectable() const; - void SetSelectable(bool value); - - gsl::not_null GetTextRenderObject() override; - render::ScrollRenderObject* GetScrollRenderObject() override { - return nullptr; - } - - private: - std::unique_ptr text_render_object_; - - std::unique_ptr service_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBox.h b/include/cru/ui/controls/TextBox.h new file mode 100644 index 00000000..2ed7db5e --- /dev/null +++ b/include/cru/ui/controls/TextBox.h @@ -0,0 +1,46 @@ +#pragma once +#include "NoChildControl.h" + +#include "IBorderControl.h" +#include "TextHostControlService.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API TextBox : public NoChildControl, + public virtual IBorderControl, + public virtual ITextHostControl { + public: + static constexpr StringView control_type = u"TextBox"; + + static TextBox* Create() { return new TextBox(); } + + protected: + TextBox(); + + public: + CRU_DELETE_COPY(TextBox) + CRU_DELETE_MOVE(TextBox) + + ~TextBox() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + gsl::not_null GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override; + + bool GetMultiLine() const; + void SetMultiLine(bool value); + + void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; + + private: + std::unique_ptr border_render_object_; + std::unique_ptr scroll_render_object_; + std::unique_ptr text_render_object_; + + std::unique_ptr service_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBox.hpp b/include/cru/ui/controls/TextBox.hpp deleted file mode 100644 index 241a8a16..00000000 --- a/include/cru/ui/controls/TextBox.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "NoChildControl.hpp" - -#include "IBorderControl.hpp" -#include "TextHostControlService.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API TextBox : public NoChildControl, - public virtual IBorderControl, - public virtual ITextHostControl { - public: - static constexpr StringView control_type = u"TextBox"; - - static TextBox* Create() { return new TextBox(); } - - protected: - TextBox(); - - public: - CRU_DELETE_COPY(TextBox) - CRU_DELETE_MOVE(TextBox) - - ~TextBox() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - gsl::not_null GetTextRenderObject() override; - render::ScrollRenderObject* GetScrollRenderObject() override; - - bool GetMultiLine() const; - void SetMultiLine(bool value); - - void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; - - private: - std::unique_ptr border_render_object_; - std::unique_ptr scroll_render_object_; - std::unique_ptr text_render_object_; - - std::unique_ptr service_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextHostControlService.h b/include/cru/ui/controls/TextHostControlService.h new file mode 100644 index 00000000..5178107f --- /dev/null +++ b/include/cru/ui/controls/TextHostControlService.h @@ -0,0 +1,219 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/gui/InputMethod.h" +#include "cru/platform/gui/TimerHelper.h" +#include "cru/platform/gui/UiApplication.h" +#include "cru/ui/controls/Control.h" +#include "cru/ui/helper/ShortcutHub.h" + +#include +#include + +namespace cru::ui::render { +class TextRenderObject; +class ScrollRenderObject; +} // namespace cru::ui::render + +namespace cru::ui::components { +class PopupMenu; +} + +namespace cru::ui::controls { +constexpr int k_default_caret_blink_duration = 500; + +struct CRU_UI_API ITextHostControl : virtual Interface { + virtual gsl::not_null GetTextRenderObject() = 0; + // May return nullptr. + virtual render::ScrollRenderObject* GetScrollRenderObject() = 0; +}; + +class TextHostControlService; + +class TextControlMovePattern : public Object { + public: + static TextControlMovePattern kLeft; + static TextControlMovePattern kRight; + static TextControlMovePattern kCtrlLeft; + static TextControlMovePattern kCtrlRight; + static TextControlMovePattern kUp; + static TextControlMovePattern kDown; + static TextControlMovePattern kHome; + static TextControlMovePattern kEnd; + static TextControlMovePattern kCtrlHome; + static TextControlMovePattern kCtrlEnd; + static TextControlMovePattern kPageUp; + static TextControlMovePattern kPageDown; + + static std::vector kDefaultPatterns; + + using MoveFunction = + std::function; + + TextControlMovePattern(String name, helper::ShortcutKeyBind key_bind, + MoveFunction move_function) + : name_(std::move(name)), + key_bind_(key_bind), + move_function_(move_function) {} + + CRU_DEFAULT_COPY(TextControlMovePattern) + CRU_DEFAULT_MOVE(TextControlMovePattern) + + ~TextControlMovePattern() override = default; + + public: + String GetName() const { return name_; } + helper::ShortcutKeyBind GetKeyBind() const { return key_bind_; } + gsl::index Move(TextHostControlService* service, StringView text, + gsl::index current_position) const { + return move_function_(service, text, current_position); + } + + private: + String name_; + helper::ShortcutKeyBind key_bind_; + MoveFunction move_function_; +}; + +class CRU_UI_API TextHostControlService : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") + + public: + TextHostControlService(gsl::not_null control); + + CRU_DELETE_COPY(TextHostControlService) + CRU_DELETE_MOVE(TextHostControlService) + + ~TextHostControlService(); + + public: + bool IsEnabled() { return enable_; } + void SetEnabled(bool enable); + + bool IsEditable() { return this->editable_; } + void SetEditable(bool editable); + + bool IsContextMenuEnabled() { return this->context_menu_enabled_; } + void SetContextMenuEnabled(bool enabled); + + bool IsMultiLine() { return this->multi_line_; } + // If text contains line feed characters, it will be converted to space. + void SetMultiLine(bool multi_line); + + String GetText() { return this->text_; } + StringView GetTextView() { return this->text_; } + void SetText(String text, bool stop_composition = false); + + void InsertText(gsl::index position, StringView text, + bool stop_composition = false); + void DeleteChar(gsl::index position, bool stop_composition = false); + + // Return the position of deleted character. + gsl::index DeleteCharPrevious(gsl::index position, + bool stop_composition = false); + void DeleteText(TextRange range, bool stop_composition = false); + + void CancelComposition(); + + std::optional GetCompositionInfo(); + + bool IsCaretVisible() { return caret_visible_; } + void SetCaretVisible(bool visible); + + int GetCaretBlinkDuration() { return caret_blink_duration_; } + void SetCaretBlinkDuration(int milliseconds); + + gsl::index GetCaretPosition() { return selection_.GetEnd(); } + TextRange GetSelection() { return selection_; } + + StringView GetSelectedText(); + + void SetSelection(gsl::index caret_position); + void SetSelection(TextRange selection, bool scroll_to_caret = true); + + void SelectAll(); + + void ChangeSelectionEnd(gsl::index new_end); + void AbortSelection(); + + void DeleteSelectedText(); + // If some text is selected, then they are deleted first. Then insert text + // into caret position. + void ReplaceSelectedText(StringView text); + + void ScrollToCaret(); + + void Cut(); + void Copy(); + void Paste(); + + gsl::not_null GetTextRenderObject(); + render::ScrollRenderObject* GetScrollRenderObject(); + + private: + // May return nullptr. + platform::gui::IInputMethodContext* GetInputMethodContext(); + + void CoerceSelection(); + + void SetupCaret(); + void TearDownCaret(); + + void SyncTextRenderObject(); + + void UpdateInputMethodPosition(); + + template + void SetupOneHandler(events::RoutedEvent* (Control::*event)(), + void (TextHostControlService::*handler)( + typename events::RoutedEvent::EventArgs)) { + this->event_guard_ += (this->control_->*event)()->Bubble()->AddHandler( + std::bind(handler, this, std::placeholders::_1)); + } + + void MouseMoveHandler(events::MouseEventArgs& args); + void MouseDownHandler(events::MouseButtonEventArgs& args); + void MouseUpHandler(events::MouseButtonEventArgs& args); + void GainFocusHandler(events::FocusChangeEventArgs& args); + void LoseFocusHandler(events::FocusChangeEventArgs& args); + + void SetUpShortcuts(); + + enum ContextMenuItem : unsigned { + kSelectAll = 0b1, + kCut = 0b10, + kCopy = 0b100, + kPaste = 0b1000 + }; + + void OpenContextMenu(const Point& position, ContextMenuItem items); + + private: + gsl::not_null control_; + gsl::not_null text_host_control_; + + EventRevokerListGuard event_guard_; + EventRevokerListGuard input_method_context_event_guard_; + + String text_; + TextRange selection_; + + bool enable_ = false; + bool editable_ = false; + bool multi_line_ = false; + bool context_menu_enabled_ = true; + + bool caret_visible_ = false; + platform::gui::TimerAutoCanceler caret_timer_canceler_; + int caret_blink_duration_ = k_default_caret_blink_duration; + + helper::ShortcutHub shortcut_hub_; + + // true if left mouse is down and selecting + bool mouse_move_selecting_ = false; + + bool context_menu_dirty_ = true; + std::unique_ptr context_menu_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextHostControlService.hpp b/include/cru/ui/controls/TextHostControlService.hpp deleted file mode 100644 index be6a7c39..00000000 --- a/include/cru/ui/controls/TextHostControlService.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/gui/InputMethod.hpp" -#include "cru/platform/gui/TimerHelper.hpp" -#include "cru/platform/gui/UiApplication.hpp" -#include "cru/ui/controls/Control.hpp" -#include "cru/ui/helper/ShortcutHub.hpp" - -#include -#include - -namespace cru::ui::render { -class TextRenderObject; -class ScrollRenderObject; -} // namespace cru::ui::render - -namespace cru::ui::components { -class PopupMenu; -} - -namespace cru::ui::controls { -constexpr int k_default_caret_blink_duration = 500; - -struct CRU_UI_API ITextHostControl : virtual Interface { - virtual gsl::not_null GetTextRenderObject() = 0; - // May return nullptr. - virtual render::ScrollRenderObject* GetScrollRenderObject() = 0; -}; - -class TextHostControlService; - -class TextControlMovePattern : public Object { - public: - static TextControlMovePattern kLeft; - static TextControlMovePattern kRight; - static TextControlMovePattern kCtrlLeft; - static TextControlMovePattern kCtrlRight; - static TextControlMovePattern kUp; - static TextControlMovePattern kDown; - static TextControlMovePattern kHome; - static TextControlMovePattern kEnd; - static TextControlMovePattern kCtrlHome; - static TextControlMovePattern kCtrlEnd; - static TextControlMovePattern kPageUp; - static TextControlMovePattern kPageDown; - - static std::vector kDefaultPatterns; - - using MoveFunction = - std::function; - - TextControlMovePattern(String name, helper::ShortcutKeyBind key_bind, - MoveFunction move_function) - : name_(std::move(name)), - key_bind_(key_bind), - move_function_(move_function) {} - - CRU_DEFAULT_COPY(TextControlMovePattern) - CRU_DEFAULT_MOVE(TextControlMovePattern) - - ~TextControlMovePattern() override = default; - - public: - String GetName() const { return name_; } - helper::ShortcutKeyBind GetKeyBind() const { return key_bind_; } - gsl::index Move(TextHostControlService* service, StringView text, - gsl::index current_position) const { - return move_function_(service, text, current_position); - } - - private: - String name_; - helper::ShortcutKeyBind key_bind_; - MoveFunction move_function_; -}; - -class CRU_UI_API TextHostControlService : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") - - public: - TextHostControlService(gsl::not_null control); - - CRU_DELETE_COPY(TextHostControlService) - CRU_DELETE_MOVE(TextHostControlService) - - ~TextHostControlService(); - - public: - bool IsEnabled() { return enable_; } - void SetEnabled(bool enable); - - bool IsEditable() { return this->editable_; } - void SetEditable(bool editable); - - bool IsContextMenuEnabled() { return this->context_menu_enabled_; } - void SetContextMenuEnabled(bool enabled); - - bool IsMultiLine() { return this->multi_line_; } - // If text contains line feed characters, it will be converted to space. - void SetMultiLine(bool multi_line); - - String GetText() { return this->text_; } - StringView GetTextView() { return this->text_; } - void SetText(String text, bool stop_composition = false); - - void InsertText(gsl::index position, StringView text, - bool stop_composition = false); - void DeleteChar(gsl::index position, bool stop_composition = false); - - // Return the position of deleted character. - gsl::index DeleteCharPrevious(gsl::index position, - bool stop_composition = false); - void DeleteText(TextRange range, bool stop_composition = false); - - void CancelComposition(); - - std::optional GetCompositionInfo(); - - bool IsCaretVisible() { return caret_visible_; } - void SetCaretVisible(bool visible); - - int GetCaretBlinkDuration() { return caret_blink_duration_; } - void SetCaretBlinkDuration(int milliseconds); - - gsl::index GetCaretPosition() { return selection_.GetEnd(); } - TextRange GetSelection() { return selection_; } - - StringView GetSelectedText(); - - void SetSelection(gsl::index caret_position); - void SetSelection(TextRange selection, bool scroll_to_caret = true); - - void SelectAll(); - - void ChangeSelectionEnd(gsl::index new_end); - void AbortSelection(); - - void DeleteSelectedText(); - // If some text is selected, then they are deleted first. Then insert text - // into caret position. - void ReplaceSelectedText(StringView text); - - void ScrollToCaret(); - - void Cut(); - void Copy(); - void Paste(); - - gsl::not_null GetTextRenderObject(); - render::ScrollRenderObject* GetScrollRenderObject(); - - private: - // May return nullptr. - platform::gui::IInputMethodContext* GetInputMethodContext(); - - void CoerceSelection(); - - void SetupCaret(); - void TearDownCaret(); - - void SyncTextRenderObject(); - - void UpdateInputMethodPosition(); - - template - void SetupOneHandler(events::RoutedEvent* (Control::*event)(), - void (TextHostControlService::*handler)( - typename events::RoutedEvent::EventArgs)) { - this->event_guard_ += (this->control_->*event)()->Bubble()->AddHandler( - std::bind(handler, this, std::placeholders::_1)); - } - - void MouseMoveHandler(events::MouseEventArgs& args); - void MouseDownHandler(events::MouseButtonEventArgs& args); - void MouseUpHandler(events::MouseButtonEventArgs& args); - void GainFocusHandler(events::FocusChangeEventArgs& args); - void LoseFocusHandler(events::FocusChangeEventArgs& args); - - void SetUpShortcuts(); - - enum ContextMenuItem : unsigned { - kSelectAll = 0b1, - kCut = 0b10, - kCopy = 0b100, - kPaste = 0b1000 - }; - - void OpenContextMenu(const Point& position, ContextMenuItem items); - - private: - gsl::not_null control_; - gsl::not_null text_host_control_; - - EventRevokerListGuard event_guard_; - EventRevokerListGuard input_method_context_event_guard_; - - String text_; - TextRange selection_; - - bool enable_ = false; - bool editable_ = false; - bool multi_line_ = false; - bool context_menu_enabled_ = true; - - bool caret_visible_ = false; - platform::gui::TimerAutoCanceler caret_timer_canceler_; - int caret_blink_duration_ = k_default_caret_blink_duration; - - helper::ShortcutHub shortcut_hub_; - - // true if left mouse is down and selecting - bool mouse_move_selecting_ = false; - - bool context_menu_dirty_ = true; - std::unique_ptr context_menu_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Window.h b/include/cru/ui/controls/Window.h new file mode 100644 index 00000000..5fb6d594 --- /dev/null +++ b/include/cru/ui/controls/Window.h @@ -0,0 +1,27 @@ +#pragma once +#include "cru/platform/gui/Base.h" +#include "cru/ui/controls/RootControl.h" + +#include "cru/common/Base.h" + +namespace cru::ui::controls { +class CRU_UI_API Window final : public RootControl { + public: + static constexpr StringView control_type = u"Window"; + + public: + static Window* Create(Control* attached_control = nullptr); + + private: + explicit Window(Control* attached_control); + + public: + CRU_DELETE_COPY(Window) + CRU_DELETE_MOVE(Window) + + ~Window() override; + + public: + String GetControlType() const final { return control_type.ToString(); } +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Window.hpp b/include/cru/ui/controls/Window.hpp deleted file mode 100644 index c304a839..00000000 --- a/include/cru/ui/controls/Window.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "cru/platform/gui/Base.hpp" -#include "cru/ui/controls/RootControl.hpp" - -#include "cru/common/Base.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Window final : public RootControl { - public: - static constexpr StringView control_type = u"Window"; - - public: - static Window* Create(Control* attached_control = nullptr); - - private: - explicit Window(Control* attached_control); - - public: - CRU_DELETE_COPY(Window) - CRU_DELETE_MOVE(Window) - - ~Window() override; - - public: - String GetControlType() const final { return control_type.ToString(); } -}; -} // namespace cru::ui::controls -- cgit v1.2.3