From 2188845a7acffa653015a1000139ec0a9a3984bc Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 8 Nov 2020 17:45:41 +0800 Subject: ... --- include/cru/ui/controls/Base.hpp | 10 +- include/cru/ui/controls/Button.hpp | 7 +- include/cru/ui/controls/Container.hpp | 2 +- include/cru/ui/controls/ContentControl.hpp | 26 +++++ include/cru/ui/controls/Control.hpp | 151 +++++++++++++++++++++++++++++ include/cru/ui/controls/FlexLayout.hpp | 2 +- include/cru/ui/controls/LayoutControl.hpp | 19 ++++ include/cru/ui/controls/NoChildControl.hpp | 20 ++++ include/cru/ui/controls/StackLayout.hpp | 2 +- include/cru/ui/controls/TextBlock.hpp | 2 +- include/cru/ui/controls/TextBox.hpp | 3 +- include/cru/ui/controls/Window.hpp | 36 +++++++ 12 files changed, 265 insertions(+), 15 deletions(-) create mode 100644 include/cru/ui/controls/ContentControl.hpp create mode 100644 include/cru/ui/controls/Control.hpp create mode 100644 include/cru/ui/controls/LayoutControl.hpp create mode 100644 include/cru/ui/controls/NoChildControl.hpp create mode 100644 include/cru/ui/controls/Window.hpp (limited to 'include/cru/ui/controls') diff --git a/include/cru/ui/controls/Base.hpp b/include/cru/ui/controls/Base.hpp index b550601b..82c31d1e 100644 --- a/include/cru/ui/controls/Base.hpp +++ b/include/cru/ui/controls/Base.hpp @@ -2,7 +2,7 @@ #include "../Base.hpp" namespace cru::ui::controls { -using ButtonStateStyle = BorderStyle; +using ButtonStateStyle = ui::BorderStyle; struct ButtonStyle { // corresponds to ClickState::None @@ -16,9 +16,9 @@ struct ButtonStyle { }; struct TextBoxBorderStyle { - BorderStyle normal; - BorderStyle hover; - BorderStyle focus; - BorderStyle focus_hover; + ui::BorderStyle normal; + ui::BorderStyle hover; + ui::BorderStyle focus; + ui::BorderStyle focus_hover; }; } // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.hpp b/include/cru/ui/controls/Button.hpp index a4f727d6..e8285507 100644 --- a/include/cru/ui/controls/Button.hpp +++ b/include/cru/ui/controls/Button.hpp @@ -1,8 +1,7 @@ #pragma once -#include "../ContentControl.hpp" -#include "Base.hpp" +#include "ContentControl.hpp" -#include "../ClickDetector.hpp" +#include "../helper/ClickDetector.hpp" namespace cru::ui::controls { class Button : public ContentControl { @@ -37,6 +36,6 @@ class Button : public ContentControl { ButtonStyle style_; - ClickDetector click_detector_; + helper::ClickDetector click_detector_; }; } // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Container.hpp b/include/cru/ui/controls/Container.hpp index 304d402c..d9cb8aec 100644 --- a/include/cru/ui/controls/Container.hpp +++ b/include/cru/ui/controls/Container.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../ContentControl.hpp" +#include "ContentControl.hpp" namespace cru::ui::controls { class Container : public ContentControl { diff --git a/include/cru/ui/controls/ContentControl.hpp b/include/cru/ui/controls/ContentControl.hpp new file mode 100644 index 00000000..47720a87 --- /dev/null +++ b/include/cru/ui/controls/ContentControl.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "Control.hpp" + +namespace cru::ui::controls { +class 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); + + private: + using Control::AddChild; + using Control::RemoveChild; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Control.hpp b/include/cru/ui/controls/Control.hpp new file mode 100644 index 00000000..96aad2bd --- /dev/null +++ b/include/cru/ui/controls/Control.hpp @@ -0,0 +1,151 @@ +#pragma once +#include "Base.hpp" + +#include "../events/UiEvent.hpp" +#include "../render/Base.hpp" +#include "cru/common/Event.hpp" + +#include + +namespace cru::ui::controls { +class 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 std::u16string_view 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); + + //*************** 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. + event::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. + event::RoutedEvent* MouseLeaveEvent() { + return &mouse_leave_event_; + } + // Raised when mouse is move in the control. + event::RoutedEvent* MouseMoveEvent() { + return &mouse_move_event_; + } + // Raised when a mouse button is pressed in the control. + event::RoutedEvent* MouseDownEvent() { + return &mouse_down_event_; + } + // Raised when a mouse button is released in the control. + event::RoutedEvent* MouseUpEvent() { + return &mouse_up_event_; + } + event::RoutedEvent* MouseWheelEvent() { + return &mouse_wheel_event_; + } + event::RoutedEvent* KeyDownEvent() { + return &key_down_event_; + } + event::RoutedEvent* KeyUpEvent() { + return &key_up_event_; + } + event::RoutedEvent* GainFocusEvent() { + return &gain_focus_event_; + } + event::RoutedEvent* LoseFocusEvent() { + return &lose_focus_event_; + } + + private: + event::RoutedEvent mouse_enter_event_; + event::RoutedEvent mouse_leave_event_; + event::RoutedEvent mouse_move_event_; + event::RoutedEvent mouse_down_event_; + event::RoutedEvent mouse_up_event_; + event::RoutedEvent mouse_wheel_event_; + + event::RoutedEvent key_down_event_; + event::RoutedEvent key_up_event_; + + event::RoutedEvent gain_focus_event_; + event::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; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/FlexLayout.hpp b/include/cru/ui/controls/FlexLayout.hpp index 0ffedba5..a6c6a40c 100644 --- a/include/cru/ui/controls/FlexLayout.hpp +++ b/include/cru/ui/controls/FlexLayout.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../LayoutControl.hpp" +#include "LayoutControl.hpp" namespace cru::ui::controls { class FlexLayout : public LayoutControl { diff --git a/include/cru/ui/controls/LayoutControl.hpp b/include/cru/ui/controls/LayoutControl.hpp new file mode 100644 index 00000000..cbdb8aa2 --- /dev/null +++ b/include/cru/ui/controls/LayoutControl.hpp @@ -0,0 +1,19 @@ +#pragma once +#include "Control.hpp" + +namespace cru::ui::controls { +class LayoutControl : public Control { + protected: + LayoutControl() = default; + + 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; +}; +} // namespace cru::ui diff --git a/include/cru/ui/controls/NoChildControl.hpp b/include/cru/ui/controls/NoChildControl.hpp new file mode 100644 index 00000000..562137f1 --- /dev/null +++ b/include/cru/ui/controls/NoChildControl.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "Control.hpp" + +namespace cru::ui::controls { +class 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/StackLayout.hpp b/include/cru/ui/controls/StackLayout.hpp index c0b95044..373b4681 100644 --- a/include/cru/ui/controls/StackLayout.hpp +++ b/include/cru/ui/controls/StackLayout.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../LayoutControl.hpp" +#include "LayoutControl.hpp" namespace cru::ui::controls { class StackLayout : public LayoutControl { diff --git a/include/cru/ui/controls/TextBlock.hpp b/include/cru/ui/controls/TextBlock.hpp index 8a9a3bff..fdfdb2fa 100644 --- a/include/cru/ui/controls/TextBlock.hpp +++ b/include/cru/ui/controls/TextBlock.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../NoChildControl.hpp" +#include "NoChildControl.hpp" namespace cru::ui::controls { template diff --git a/include/cru/ui/controls/TextBox.hpp b/include/cru/ui/controls/TextBox.hpp index 5976f6da..91d38c61 100644 --- a/include/cru/ui/controls/TextBox.hpp +++ b/include/cru/ui/controls/TextBox.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../NoChildControl.hpp" -#include "Base.hpp" +#include "NoChildControl.hpp" #include diff --git a/include/cru/ui/controls/Window.hpp b/include/cru/ui/controls/Window.hpp new file mode 100644 index 00000000..616e2ee7 --- /dev/null +++ b/include/cru/ui/controls/Window.hpp @@ -0,0 +1,36 @@ +#pragma once +#include "LayoutControl.hpp" + +namespace cru::ui::controls { +class Window final : public LayoutControl { + public: + static constexpr std::u16string_view control_type = u"Window"; + + public: + static Window* CreateOverlapped(); + + private: + Window(); + + public: + Window(const Window& other) = delete; + Window(Window&& other) = delete; + Window& operator=(const Window& other) = delete; + Window& operator=(Window&& other) = delete; + ~Window() override; + + public: + std::u16string_view GetControlType() const final; + + render::RenderObject* GetRenderObject() const override; + + protected: + void OnAddChild(Control* child, Index position) override; + void OnRemoveChild(Control* child, Index position) override; + + private: + std::unique_ptr window_host_; + + std::unique_ptr render_object_; +}; +} // namespace cru::ui -- cgit v1.2.3