diff options
author | crupest <crupest@outlook.com> | 2019-03-21 22:22:02 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-03-21 22:22:02 +0800 |
commit | 962dc18ee4827b464764ec3708be3d00a9143971 (patch) | |
tree | 3eea13894a14a26f2e2de07d3d6bc7789d409864 /src/ui/control.hpp | |
parent | afa2a079562d810e5ef611071b21a3568da9dfca (diff) | |
download | cru-962dc18ee4827b464764ec3708be3d00a9143971.tar.gz cru-962dc18ee4827b464764ec3708be3d00a9143971.tar.bz2 cru-962dc18ee4827b464764ec3708be3d00a9143971.zip |
...
Diffstat (limited to 'src/ui/control.hpp')
-rw-r--r-- | src/ui/control.hpp | 136 |
1 files changed, 1 insertions, 135 deletions
diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 9ff407b0..8454e981 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -48,7 +48,7 @@ class Control : public Object { void _SetDescendantWindow(Window* window); private: - static void TraverseDescendantsInternal( + static void _TraverseDescendants( Control* control, const std::function<void(Control*)>& predicate); public: @@ -110,138 +110,4 @@ class Control : public Object { Cursor::Ptr cursor_{}; }; - -class NoChildControl : public Control { - private: - static const std::vector<Control*> empty_control_vector; - - 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; - - protected: - const std::vector<Control*>& GetChildren() const override final { - return empty_control_vector; - } -}; - -class ContentControl : public Control { - protected: - ContentControl(); - - public: - ContentControl(const ContentControl& other) = delete; - ContentControl(ContentControl&& other) = delete; - ContentControl& operator=(const ContentControl& other) = delete; - ContentControl& operator=(ContentControl&& other) = delete; - ~ContentControl() override; - - const std::vector<Control*>& GetChildren() const override final { - return child_vector_; - } - Control* GetChild() const { return child_; } - void SetChild(Control* child); - - protected: - virtual void OnChildChanged(Control* old_child, Control* new_child); - - private: - std::vector<Control*> child_vector_; - Control*& child_; -}; - -class Layout : public Control { - protected: - Layout() = default; - - public: - Layout(const Layout& other) = delete; - Layout(Layout&& other) = delete; - Layout& operator=(const Layout& other) = delete; - Layout& operator=(Layout&& other) = delete; - ~Layout() override; - - const std::vector<Control*>& GetChildren() const override final { - return children_; - } - - void AddChild(Control* control, int position); - - void RemoveChild(int position); - - protected: - virtual void OnAddChild(Control* child, int position); - virtual void OnRemoveChild(Control* child, int position); - - private: - std::vector<Control*> children_; -}; - -//*************** region: event dispatcher helper *************** - -// Dispatch the event. -// -// This will raise routed event of the control and its parent and parent's -// parent ... (until "last_receiver" if it's not nullptr) with appropriate args. -// -// First tunnel from top to bottom possibly stopped by "handled" flag in -// EventArgs. Second bubble from bottom to top possibly stopped by "handled" -// flag in EventArgs. Last direct to each control. -// -// Args is of type "EventArgs". The first init argument is "sender", which is -// automatically bound to each receiving control. The second init argument is -// "original_sender", which is unchanged. And "args" will be perfectly forwarded -// as the rest arguments. -template <typename EventArgs, typename... Args> -void DispatchEvent(Control* const original_sender, - events::RoutedEvent<EventArgs> Control::*event_ptr, - Control* const last_receiver, Args&&... args) { - std::list<Control*> receive_list; - - auto parent = original_sender; - while (parent != last_receiver) { - receive_list.push_back(parent); - parent = parent->GetParent(); - } - - auto handled = false; - - // tunnel - for (auto i = receive_list.crbegin(); i != receive_list.crend(); ++i) { - EventArgs event_args(*i, original_sender, std::forward<Args>(args)...); - (*i->*event_ptr).tunnel.Raise(event_args); - if (event_args.IsHandled()) { - handled = true; - break; - } - } - - // bubble - if (!handled) { - for (auto i : receive_list) { - EventArgs event_args(i, original_sender, std::forward<Args>(args)...); - (i->*event_ptr).bubble.Raise(event_args); - if (event_args.IsHandled()) break; - } - } - - // direct - for (auto i : receive_list) { - EventArgs event_args(i, original_sender, std::forward<Args>(args)...); - (i->*event_ptr).direct.Raise(event_args); - } -} - -//*************** region: tree helper *************** - -// Find the lowest common ancestor. -// Return nullptr if "left" and "right" are not in the same tree. -Control* FindLowestCommonAncestor(Control* left, Control* right); - } // namespace cru::ui |