#pragma once #include "Base.h" #include "../events/UiEvents.h" #include "../render/Base.h" #include "cru/common/Event.h" 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_; } Index IndexOf(Control* child) const; // Traverse the tree rooted the control including itself. void TraverseDescendants(const std::function& predicate); bool IsAutoDeleteChildren() const { return auto_delete_children_; } void SetAutoDeleteChildren(bool auto_delete_children) { auto_delete_children_ = auto_delete_children; } void RemoveFromParent(); 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; bool auto_delete_children_ = true; 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