aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-10-29 00:01:26 +0800
committercrupest <crupest@outlook.com>2020-10-29 00:01:26 +0800
commit52594324b302f6e9da10ac01fe803196371bb2d9 (patch)
tree38dd36e0bf934b283dd80f808531a2ee862b174b /include
parentdf4df679e157f974773dad7776b204e9d4f3009e (diff)
downloadcru-52594324b302f6e9da10ac01fe803196371bb2d9.tar.gz
cru-52594324b302f6e9da10ac01fe803196371bb2d9.tar.bz2
cru-52594324b302f6e9da10ac01fe803196371bb2d9.zip
...
Diffstat (limited to 'include')
-rw-r--r--include/cru/ui/ContentControl.hpp13
-rw-r--r--include/cru/ui/Control.hpp29
-rw-r--r--include/cru/ui/LayoutControl.hpp18
-rw-r--r--include/cru/ui/NoChildControl.hpp10
-rw-r--r--include/cru/ui/Window.hpp18
-rw-r--r--include/cru/ui/WindowHost.hpp72
-rw-r--r--include/cru/ui/render/Base.hpp1
-rw-r--r--include/cru/ui/render/RenderObject.hpp20
-rw-r--r--include/cru/ui/render/WindowRenderObject.hpp34
9 files changed, 73 insertions, 142 deletions
diff --git a/include/cru/ui/ContentControl.hpp b/include/cru/ui/ContentControl.hpp
index 19f13a1d..ba5b6b2f 100644
--- a/include/cru/ui/ContentControl.hpp
+++ b/include/cru/ui/ContentControl.hpp
@@ -4,26 +4,23 @@
namespace cru::ui {
class ContentControl : public Control {
protected:
- ContentControl();
+ 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;
+ ~ContentControl() override = default;
- const std::vector<Control*>& GetChildren() const override final {
- return child_vector_;
- }
- Control* GetChild() const { return child_; }
+ Control* GetChild() const;
void SetChild(Control* child);
protected:
virtual void OnChildChanged(Control* old_child, Control* new_child);
private:
- std::vector<Control*> child_vector_;
- Control*& child_;
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/Control.hpp b/include/cru/ui/Control.hpp
index 692dcc9b..0021ad62 100644
--- a/include/cru/ui/Control.hpp
+++ b/include/cru/ui/Control.hpp
@@ -1,9 +1,9 @@
#pragma once
#include "Base.hpp"
+#include "UiEvent.hpp"
#include "cru/common/Event.hpp"
#include "render/Base.hpp"
-#include "UiEvent.hpp"
#include <string_view>
@@ -19,39 +19,31 @@ class Control : public Object {
Control(Control&& other) = delete;
Control& operator=(const Control& other) = delete;
Control& operator=(Control&& other) = delete;
- ~Control() override = default;
+ ~Control() override;
public:
virtual std::u16string_view GetControlType() const = 0;
//*************** region: tree ***************
public:
- // Get the ui host if attached, otherwise, return nullptr.
- WindowHost* GetWindowHost() const { return ui_host_; }
+ WindowHost* GetWindowHost() const;
Control* GetParent() const { return parent_; }
- virtual const std::vector<Control*>& GetChildren() const = 0;
+ const std::vector<Control*>& GetChildren() const { return children_; }
// Traverse the tree rooted the control including itself.
void TraverseDescendants(const std::function<void(Control*)>& predicate);
- void _SetParent(Control* parent);
- void _SetDescendantWindowHost(WindowHost* host);
-
- private:
- static void _TraverseDescendants(
- Control* control, const std::function<void(Control*)>& predicate);
-
public:
virtual render::RenderObject* GetRenderObject() const = 0;
//*************** region: focus ***************
public:
- bool RequestFocus();
-
bool HasFocus();
+ void SetFocus();
+
//*************** region: mouse ***************
public:
bool IsMouseOver() const { return is_mouse_over_; }
@@ -134,15 +126,22 @@ class 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(WindowHost* host);
virtual void OnDetachFromHost(WindowHost* host);
+ protected:
virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) }
private:
- WindowHost* ui_host_ = nullptr;
Control* parent_ = nullptr;
+ std::vector<Control*> children_;
+
+ WindowHost* window_host_ = nullptr;
private:
bool is_mouse_over_ = false;
diff --git a/include/cru/ui/LayoutControl.hpp b/include/cru/ui/LayoutControl.hpp
index 7997b37e..69d5cd0b 100644
--- a/include/cru/ui/LayoutControl.hpp
+++ b/include/cru/ui/LayoutControl.hpp
@@ -11,21 +11,9 @@ class LayoutControl : public Control {
LayoutControl(LayoutControl&& other) = delete;
LayoutControl& operator=(const LayoutControl& other) = delete;
LayoutControl& operator=(LayoutControl&& other) = delete;
- ~LayoutControl() override;
+ ~LayoutControl() override = default;
- const std::vector<Control*>& GetChildren() const override final {
- return children_;
- }
-
- void AddChild(Control* control, Index position);
-
- void RemoveChild(Index position);
-
- protected:
- virtual void OnAddChild(Control* child, Index position);
- virtual void OnRemoveChild(Control* child, Index position);
-
- private:
- std::vector<Control*> children_;
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/NoChildControl.hpp b/include/cru/ui/NoChildControl.hpp
index 1a31ae7e..0d8a8e34 100644
--- a/include/cru/ui/NoChildControl.hpp
+++ b/include/cru/ui/NoChildControl.hpp
@@ -3,9 +3,6 @@
namespace cru::ui {
class NoChildControl : public Control {
- private:
- static const std::vector<Control*> empty_control_vector;
-
protected:
NoChildControl() = default;
@@ -16,9 +13,8 @@ class NoChildControl : public Control {
NoChildControl& operator=(NoChildControl&& other) = delete;
~NoChildControl() override = default;
- protected:
- const std::vector<Control*>& GetChildren() const override final {
- return empty_control_vector;
- }
+ private:
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/Window.hpp b/include/cru/ui/Window.hpp
index 5ea24855..0739e3dc 100644
--- a/include/cru/ui/Window.hpp
+++ b/include/cru/ui/Window.hpp
@@ -1,10 +1,8 @@
#pragma once
-#include "ContentControl.hpp"
+#include "LayoutControl.hpp"
namespace cru::ui {
-class Window final : public ContentControl {
- friend WindowHost;
-
+class Window final : public LayoutControl {
public:
static constexpr std::u16string_view control_type = u"Window";
@@ -12,9 +10,7 @@ class Window final : public ContentControl {
static Window* CreateOverlapped();
private:
- struct tag_overlapped_constructor {};
-
- explicit Window(tag_overlapped_constructor);
+ Window();
public:
Window(const Window& other) = delete;
@@ -29,12 +25,12 @@ class Window final : public ContentControl {
render::RenderObject* GetRenderObject() const override;
protected:
- void OnChildChanged(Control* old_child, Control* new_child) override;
+ void OnAddChild(Control* child, Index position) override;
+ void OnRemoveChild(Control* child, Index position) override;
private:
- std::unique_ptr<WindowHost> managed_ui_host_;
+ std::unique_ptr<WindowHost> window_host_;
- // WindowHost is responsible to take care of lifetime of this.
- render::WindowRenderObject* render_object_;
+ std::unique_ptr<render::StackLayoutRenderObject> render_object_;
};
} // namespace cru::ui
diff --git a/include/cru/ui/WindowHost.hpp b/include/cru/ui/WindowHost.hpp
index 83ef2f64..8efb505d 100644
--- a/include/cru/ui/WindowHost.hpp
+++ b/include/cru/ui/WindowHost.hpp
@@ -1,20 +1,22 @@
#pragma once
-#include <functional>
#include "Base.hpp"
#include "cru/common/Event.hpp"
-#include "cru/common/SelfResolvable.hpp"
+#include "cru/platform/native/UiApplication.hpp"
+#include "cru/platform/native/Window.hpp"
#include "render/Base.hpp"
+#include <functional>
+
namespace cru::ui {
struct AfterLayoutEventArgs {};
-class WindowHost : public Object, public SelfResolvable<WindowHost> {
+
+// The bridge between control tree and native window.
+class WindowHost : public Object {
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::WindowHost")
public:
- // This will create root window render object and attach it to window.
- // It will also create and manage a native window.
- WindowHost(Window* window);
+ WindowHost(Control* root_control);
CRU_DELETE_COPY(WindowHost)
CRU_DELETE_MOVE(WindowHost)
@@ -22,6 +24,8 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
~WindowHost() override;
public:
+ platform::native::INativeWindow* GetNativeWindow() { return native_window_; }
+
// Mark the layout as invalid, and arrange a re-layout later.
// This method could be called more than one times in a message cycle. But
// layout only takes place once.
@@ -36,13 +40,18 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
return &after_layout_event_;
}
+ void Relayout();
+ void Relayout(const Size& available_size);
+
+ // Is layout is invalid, wait for relayout and then run the action. Otherwist
+ // run it right now.
+ void RunAfterLayoutStable(std::function<void()> action);
+
// If true, preferred size of root render object is set to window size when
// measure. Default is true.
bool IsLayoutPreferToFillWindow() const;
void SetLayoutPreferToFillWindow(bool value);
- void Relayout();
-
// Get current control that mouse hovers on. This ignores the mouse-capture
// control. Even when mouse is captured by another control, this function
// return the control under cursor. You can use `GetMouseCaptureControl` to
@@ -51,12 +60,10 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
//*************** region: focus ***************
- // Request focus for specified control.
- bool RequestFocusFor(Control* control);
-
- // Get the control that has focus.
Control* GetFocusControl();
+ void SetFocusControl(Control* control);
+
//*************** region: focus ***************
// Pass nullptr to release capture. If mouse is already capture by a control,
@@ -78,19 +85,6 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
void UpdateCursor();
- std::shared_ptr<platform::native::INativeWindowResolver>
- GetNativeWindowResolver() {
- return native_window_resolver_;
- }
-
- bool IsRetainAfterDestroy() { return retain_after_destroy_; }
-
- void SetRetainAfterDestroy(bool destroy) { retain_after_destroy_ = destroy; }
-
- // Is layout is invalid, wait for relayout and then run the action. Otherwist
- // run it right now.
- void RunAfterLayoutStable(std::function<void()> action);
-
private:
//*************** region: native messages ***************
void OnNativeDestroy(platform::native::INativeWindow* window, std::nullptr_t);
@@ -126,33 +120,21 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
bool no_enter);
private:
- bool need_layout_ = false;
+ Control* root_control_;
+ render::RenderObject* root_render_object_;
+
+ platform::native::INativeWindow* native_window_;
+ bool need_layout_ = false;
+ platform::native::TimerAutoCanceler relayout_timer_canceler_;
Event<AfterLayoutEventArgs> after_layout_event_;
std::vector<std::function<void()> > after_layout_stable_action_;
- std::shared_ptr<platform::native::INativeWindowResolver>
- native_window_resolver_;
-
- // See remarks of WindowHost.
- bool retain_after_destroy_ = false;
- // See remarks of WindowHost.
- bool deleting_ = false;
-
- // We need this because calling Resolve on resolver in handler of destroy
- // event is bad and will always get the dying window. But we need to label the
- // window as destroyed so the destructor will not destroy native window
- // repeatedly. See remarks of WindowHost.
- bool native_window_destroyed_ = false;
-
std::vector<EventRevokerGuard> event_revoker_guards_;
- Window* window_control_;
- std::unique_ptr<render::WindowRenderObject> root_render_object_;
-
- Control* mouse_hover_control_;
+ Control* mouse_hover_control_ = nullptr;
- Control* focus_control_; // "focus_control_" can't be nullptr
+ Control* focus_control_;
Control* mouse_captured_control_;
diff --git a/include/cru/ui/render/Base.hpp b/include/cru/ui/render/Base.hpp
index 801d58bd..ac67349e 100644
--- a/include/cru/ui/render/Base.hpp
+++ b/include/cru/ui/render/Base.hpp
@@ -9,5 +9,4 @@ class FlexLayoutRenderObject;
class ScrollRenderObject;
class StackLayoutRenderObject;
class TextRenderObject;
-class WindowRenderObject;
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp
index f052221e..4e5c9060 100644
--- a/include/cru/ui/render/RenderObject.hpp
+++ b/include/cru/ui/render/RenderObject.hpp
@@ -3,12 +3,13 @@
#include "MeasureRequirement.hpp"
#include "cru/common/Event.hpp"
+#include "cru/ui/Base.hpp"
+#include <cstddef>
#include <string>
#include <string_view>
namespace cru::ui::render {
-
// Render object will not destroy its children when destroyed. Control must
// manage lifecycle of its render objects. Since control will destroy its
// children when destroyed, render objects will be destroyed along with it.
@@ -38,7 +39,7 @@ namespace cru::ui::render {
// Size OnMeasureContent(const MeasureRequirement& requirement) override;
// void OnLayoutContent(const Rect& content_rect) override;
class RenderObject : public Object {
- friend WindowRenderObject;
+ friend WindowHost;
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject")
@@ -64,7 +65,7 @@ class RenderObject : public Object {
Control* GetAttachedControl() const { return control_; }
void SetAttachedControl(Control* new_control) { control_ = new_control; }
- WindowHost* GetWindowHost() const { return ui_host_; }
+ WindowHost* GetWindowHost() const { return window_host_; }
RenderObject* GetParent() const { return parent_; }
@@ -132,6 +133,11 @@ class RenderObject : public Object {
// Add offset before pass point to children.
virtual RenderObject* HitTest(const Point& point) = 0;
+ IEvent<WindowHost*>* AttachToHostEvent() { return &attach_to_host_event_; }
+ IEvent<std::nullptr_t>* DetachFromHostEvent() {
+ return &detach_from_host_event_;
+ }
+
public:
void InvalidateLayout();
void InvalidatePaint();
@@ -190,7 +196,6 @@ class RenderObject : public Object {
virtual void OnLayoutContent(const Rect& content_rect) = 0;
virtual void OnAfterLayout();
- static void NotifyAfterLayoutRecursive(RenderObject* render_object);
virtual Rect GetPaddingRect() const;
virtual Rect GetContentRect() const;
@@ -198,11 +203,11 @@ class RenderObject : public Object {
private:
void SetParent(RenderObject* new_parent);
- void SetRenderHostRecursive(WindowHost* host);
+ void SetWindowHostRecursive(WindowHost* host);
private:
Control* control_ = nullptr;
- WindowHost* ui_host_ = nullptr;
+ WindowHost* window_host_ = nullptr;
RenderObject* parent_ = nullptr;
std::vector<RenderObject*> children_{};
@@ -217,5 +222,8 @@ class RenderObject : public Object {
Thickness margin_{};
Thickness padding_{};
+
+ Event<WindowHost*> attach_to_host_event_;
+ Event<std::nullptr_t> detach_from_host_event_;
};
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp
deleted file mode 100644
index 23fd8748..00000000
--- a/include/cru/ui/render/WindowRenderObject.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-#include "RenderObject.hpp"
-
-#include <string_view>
-
-namespace cru::ui::render {
-class WindowRenderObject : public RenderObject {
- public:
- WindowRenderObject(WindowHost* host);
- WindowRenderObject(const WindowRenderObject& other) = delete;
- WindowRenderObject(WindowRenderObject&& other) = delete;
- WindowRenderObject& operator=(const WindowRenderObject& other) = delete;
- WindowRenderObject& operator=(WindowRenderObject&& other) = delete;
- ~WindowRenderObject() override = default;
-
- RenderObject* HitTest(const Point& point) override;
-
- public:
- std::u16string_view GetName() const override;
-
- protected:
- Size OnMeasureContent(const MeasureRequirement& requirement,
- const MeasureSize& preferred_size) override;
- void OnLayoutContent(const Rect& content_rect) override;
-
- private:
- RenderObject* GetChild() const {
- return GetChildren().empty() ? nullptr : GetChildren()[0];
- }
-
- private:
- EventRevokerGuard after_layout_event_guard_;
-};
-} // namespace cru::ui::render