diff options
author | crupest <crupest@outlook.com> | 2018-11-28 19:18:34 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-28 19:18:34 +0800 |
commit | 4c926755a112f5e7da5da82035fa2f624ceef863 (patch) | |
tree | e52021d9d01ced774a2e9e0281515a09bd2ae4fb /CruUI-Generate/cru_ui.hpp | |
parent | f78458173c1baf567cc96880571b380e95a1039a (diff) | |
download | cru-4c926755a112f5e7da5da82035fa2f624ceef863.tar.gz cru-4c926755a112f5e7da5da82035fa2f624ceef863.tar.bz2 cru-4c926755a112f5e7da5da82035fa2f624ceef863.zip |
Update merged sources.
Diffstat (limited to 'CruUI-Generate/cru_ui.hpp')
-rw-r--r-- | CruUI-Generate/cru_ui.hpp | 312 |
1 files changed, 134 insertions, 178 deletions
diff --git a/CruUI-Generate/cru_ui.hpp b/CruUI-Generate/cru_ui.hpp index 6dff57cd..1912e243 100644 --- a/CruUI-Generate/cru_ui.hpp +++ b/CruUI-Generate/cru_ui.hpp @@ -586,6 +586,7 @@ namespace cru // ReSharper disable once CppUnusedIncludeDirective +#include <list> #include <map> #include <memory> @@ -996,7 +997,7 @@ namespace cru::ui #include <type_traits> #include <functional> -#include <unordered_map> +#include <map> namespace cru { @@ -1066,13 +1067,15 @@ namespace cru { (handler.second)(args); } + + //TODO: Remove this! bool IsNoHandler() const { return handlers_.empty(); } private: - std::unordered_map<EventHandlerToken, EventHandler> handlers_; + std::map<EventHandlerToken, EventHandler> handlers_; EventHandlerToken current_token_ = 0; }; @@ -1092,7 +1095,7 @@ namespace cru::ui::events { public: UiEventArgs(Object* sender, Object* original_sender) - : BasicEventArgs(sender), original_sender_(original_sender) + : BasicEventArgs(sender), original_sender_(original_sender), handled_(false) { } @@ -1108,10 +1111,40 @@ namespace cru::ui::events return original_sender_; } + bool IsHandled() const + { + return handled_; + } + + void SetHandled(const bool handled = true) + { + handled_ = handled; + } + private: Object* original_sender_; + bool handled_; }; + template <typename TEventArgs> + class RoutedEvent + { + public: + static_assert(std::is_base_of_v<UiEventArgs, TEventArgs>, "TEventArgs must be subclass of UiEventArgs."); + + using EventArgs = TEventArgs; + + RoutedEvent() = default; + RoutedEvent(const RoutedEvent& other) = delete; + RoutedEvent(RoutedEvent&& other) = delete; + RoutedEvent& operator=(const RoutedEvent& other) = delete; + RoutedEvent& operator=(RoutedEvent&& other) = delete; + ~RoutedEvent() = default; + + Event<TEventArgs> direct; + Event<TEventArgs> bubble; + Event<TEventArgs> tunnel; + }; class MouseEventArgs : public UiEventArgs { @@ -1397,19 +1430,6 @@ namespace cru::ui::events private: wchar_t c_; }; - - using UiEvent = Event<UiEventArgs>; - using MouseEvent = Event<MouseEventArgs>; - using MouseButtonEvent = Event<MouseButtonEventArgs>; - using MouseWheelEvent = Event<MouseWheelEventArgs>; - using DrawEvent = Event<DrawEventArgs>; - using PositionChangedEvent = Event<PositionChangedEventArgs>; - using SizeChangedEvent = Event<SizeChangedEventArgs>; - using FocusChangeEvent = Event<FocusChangeEventArgs>; - using ToggleEvent = Event<ToggleEventArgs>; - using WindowNativeMessageEvent = Event<WindowNativeMessageEventArgs>; - using KeyEvent = Event<KeyEventArgs>; - using CharEvent = Event<CharEventArgs>; } //-------------------------------------------------------- //-------end of file: src\ui\events\ui_event.hpp @@ -1782,34 +1802,35 @@ namespace cru::ui //*************** region: events *************** //Raised when mouse enter the control. - events::MouseEvent mouse_enter_event; + events::RoutedEvent<events::MouseEventArgs> mouse_enter_event; //Raised when mouse is leave the control. - events::MouseEvent mouse_leave_event; + events::RoutedEvent<events::MouseEventArgs> mouse_leave_event; //Raised when mouse is move in the control. - events::MouseEvent mouse_move_event; + events::RoutedEvent<events::MouseEventArgs> mouse_move_event; //Raised when a mouse button is pressed in the control. - events::MouseButtonEvent mouse_down_event; + events::RoutedEvent<events::MouseButtonEventArgs> mouse_down_event; //Raised when a mouse button is released in the control. - events::MouseButtonEvent mouse_up_event; + events::RoutedEvent<events::MouseButtonEventArgs> mouse_up_event; //Raised when a mouse button is pressed in the control and released in the control with mouse not leaving it between two operations. - events::MouseButtonEvent mouse_click_event; + events::RoutedEvent<events::MouseButtonEventArgs> mouse_click_event; - events::MouseWheelEvent mouse_wheel_event; + events::RoutedEvent<events::MouseWheelEventArgs> mouse_wheel_event; - events::KeyEvent key_down_event; - events::KeyEvent key_up_event; - events::CharEvent char_event; + events::RoutedEvent<events::KeyEventArgs> key_down_event; + events::RoutedEvent<events::KeyEventArgs> key_up_event; + events::RoutedEvent<events::CharEventArgs> char_event; - events::FocusChangeEvent get_focus_event; - events::FocusChangeEvent lose_focus_event; + events::RoutedEvent<events::FocusChangeEventArgs> get_focus_event; + events::RoutedEvent<events::FocusChangeEventArgs> lose_focus_event; - events::DrawEvent draw_content_event; - events::DrawEvent draw_background_event; - events::DrawEvent draw_foreground_event; + Event<events::DrawEventArgs> draw_content_event; + Event<events::DrawEventArgs> draw_background_event; + Event<events::DrawEventArgs> draw_foreground_event; - events::PositionChangedEvent position_changed_event; - events::SizeChangedEvent size_changed_event; + Event<events::PositionChangedEventArgs> position_changed_event; + Event<events::SizeChangedEventArgs> size_changed_event; + //*************** region: tree event *************** protected: //Invoked when a child is added. Overrides should invoke base. virtual void OnAddChild(Control* child); @@ -1821,32 +1842,15 @@ namespace cru::ui //Invoked when the control is detached to a window. Overrides should invoke base. virtual void OnDetachToWindow(Window* window); - //*************** region: graphic events *************** + + //*************** region: graphic event *************** private: void OnDrawDecoration(ID2D1DeviceContext* device_context); void OnDrawCore(ID2D1DeviceContext* device_context); - protected: - virtual void OnDrawContent(ID2D1DeviceContext* device_context); - virtual void OnDrawForeground(ID2D1DeviceContext* device_context); - virtual void OnDrawBackground(ID2D1DeviceContext* device_context); - // For a event, the window event system will first dispatch event to core functions. - // Therefore for particular controls, you should do essential actions in core functions, - // and override version should invoke base version. The base core function - // in "Control" class will call corresponding non-core function and call "Raise" on - // event objects. So user custom actions should be done by overriding non-core function - // and calling the base version is optional. //*************** region: position and size event *************** - virtual void OnPositionChanged(events::PositionChangedEventArgs& args); - virtual void OnSizeChanged(events::SizeChangedEventArgs& args); - - virtual void OnPositionChangedCore(events::PositionChangedEventArgs& args); - virtual void OnSizeChangedCore(events::SizeChangedEventArgs& args); - - void RaisePositionChangedEvent(events::PositionChangedEventArgs& args); - void RaiseSizeChangedEvent(events::SizeChangedEventArgs& args); - + protected: void RegenerateGeometryInfo(); const GeometryInfo& GetGeometryInfo() const @@ -1854,63 +1858,19 @@ namespace cru::ui return geometry_info_; } - //*************** region: mouse event *************** - virtual void OnMouseEnter(events::MouseEventArgs& args); - virtual void OnMouseLeave(events::MouseEventArgs& args); - virtual void OnMouseMove(events::MouseEventArgs& args); - virtual void OnMouseDown(events::MouseButtonEventArgs& args); - virtual void OnMouseUp(events::MouseButtonEventArgs& args); - virtual void OnMouseClick(events::MouseButtonEventArgs& args); - - virtual void OnMouseEnterCore(events::MouseEventArgs& args); - virtual void OnMouseLeaveCore(events::MouseEventArgs& args); - virtual void OnMouseMoveCore(events::MouseEventArgs& args); - virtual void OnMouseDownCore(events::MouseButtonEventArgs& args); - virtual void OnMouseUpCore(events::MouseButtonEventArgs& args); - virtual void OnMouseClickCore(events::MouseButtonEventArgs& args); - - virtual void OnMouseWheel(events::MouseWheelEventArgs& args); - virtual void OnMouseWheelCore(events::MouseWheelEventArgs& args); - - void RaiseMouseEnterEvent(events::MouseEventArgs& args); - void RaiseMouseLeaveEvent(events::MouseEventArgs& args); - void RaiseMouseMoveEvent(events::MouseEventArgs& args); - void RaiseMouseDownEvent(events::MouseButtonEventArgs& args); - void RaiseMouseUpEvent(events::MouseButtonEventArgs& args); - void RaiseMouseClickEvent(events::MouseButtonEventArgs& args); - - void RaiseMouseWheelEvent(events::MouseWheelEventArgs& args); + //*************** region: mouse event *************** + protected: virtual void OnMouseClickBegin(MouseButton button); virtual void OnMouseClickEnd(MouseButton button); - //*************** region: keyboard event *************** - virtual void OnKeyDown(events::KeyEventArgs& args); - virtual void OnKeyUp(events::KeyEventArgs& args); - virtual void OnChar(events::CharEventArgs& args); - - virtual void OnKeyDownCore(events::KeyEventArgs& args); - virtual void OnKeyUpCore(events::KeyEventArgs& args); - virtual void OnCharCore(events::CharEventArgs& args); - - void RaiseKeyDownEvent(events::KeyEventArgs& args); - void RaiseKeyUpEvent(events::KeyEventArgs& args); - void RaiseCharEvent(events::CharEventArgs& args); - - //*************** region: focus event *************** - virtual void OnGetFocus(events::FocusChangeEventArgs& args); - virtual void OnLoseFocus(events::FocusChangeEventArgs& args); - - virtual void OnGetFocusCore(events::FocusChangeEventArgs& args); - virtual void OnLoseFocusCore(events::FocusChangeEventArgs& args); - - void RaiseGetFocusEvent(events::FocusChangeEventArgs& args); - void RaiseLoseFocusEvent(events::FocusChangeEventArgs& args); //*************** region: layout *************** + private: Size OnMeasureCore(const Size& available_size); void OnLayoutCore(const Rect& rect); + protected: virtual Size OnMeasureContent(const Size& available_size); virtual void OnLayoutContent(const Rect& rect); @@ -1949,8 +1909,6 @@ namespace cru::ui ControlPositionCache position_cache_{}; - bool is_mouse_inside_ = false; - std::unordered_map<MouseButton, bool> is_mouse_click_valid_map_ { { MouseButton::Left, true }, @@ -1983,6 +1941,71 @@ namespace cru::ui Cursor::Ptr cursor_{}; }; + + //*************** 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); @@ -2001,6 +2024,8 @@ namespace cru::ui } + //*************** region: create helper *************** + template <typename TControl, typename... Args> TControl* CreateWithLayout(const Thickness& padding, const Thickness& margin, Args&&... args) { @@ -2260,10 +2285,10 @@ namespace cru::ui public: //*************** region: events *************** - events::UiEvent activated_event; - events::UiEvent deactivated_event; - - events::WindowNativeMessageEvent native_message_event; + Event<events::UiEventArgs> activated_event; + Event<events::UiEventArgs> deactivated_event; + + Event<events::WindowNativeMessageEventArgs> native_message_event; private: //*************** region: native operations *************** @@ -2300,30 +2325,6 @@ namespace cru::ui //*************** region: event dispatcher helper *************** - template<typename EventArgs> - using EventMethod = void (Control::*)(EventArgs&); - - // Dispatch the event. - // - // This will invoke the "event_method" of the control and its parent and parent's - // parent ... (until "last_receiver" if it's not nullptr) with appropriate args. - // - // 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* original_sender, EventMethod<EventArgs> event_method, Control* last_receiver, Args&&... args) - { - auto control = original_sender; - while (control != nullptr && control != last_receiver) - { - EventArgs event_args(control, original_sender, std::forward<Args>(args)...); - (control->*event_method)(event_args); - control = control->GetParent(); - } - } - void DispatchMouseHoverControlChangeEvent(Control* old_control, Control * new_control, const Point& point); private: @@ -2522,18 +2523,7 @@ namespace cru::ui::controls protected: void SetSelectable(bool is_selectable); - protected: - void OnSizeChangedCore(events::SizeChangedEventArgs& args) override final; - void OnDrawContent(ID2D1DeviceContext* device_context) override; - - void OnMouseDownCore(events::MouseButtonEventArgs& args) override final; - void OnMouseMoveCore(events::MouseEventArgs& args) override final; - void OnMouseUpCore(events::MouseButtonEventArgs& args) override final; - - void OnLoseFocusCore(events::FocusChangeEventArgs& args) override; - - Size OnMeasureContent(const Size& available_size) override; - + Size OnMeasureContent(const Size& available_size) override final; virtual void RequestChangeCaretPosition(unsigned position); @@ -2639,23 +2629,12 @@ namespace cru::ui::controls void Toggle(); - public: - events::ToggleEvent toggle_event; - - protected: - virtual void OnToggle(events::ToggleEventArgs& args); + Event<events::ToggleEventArgs> toggle_event; protected: - void OnDrawContent(ID2D1DeviceContext* device_context) override; - - void OnMouseClickCore(events::MouseButtonEventArgs& args) override; - Size OnMeasureContent(const Size& available_size) override; private: - void RaiseToggleEvent(bool new_state); - - private: bool state_ = false; float current_circle_position_; @@ -2747,14 +2726,6 @@ namespace cru::ui::controls StringView GetControlType() const override final; protected: - void OnDrawContent(ID2D1DeviceContext* device_context) override; - - void OnGetFocusCore(events::FocusChangeEventArgs& args) override final; - void OnLoseFocusCore(events::FocusChangeEventArgs& args) override final; - - void OnKeyDownCore(events::KeyEventArgs& args) override final; - void OnCharCore(events::CharEventArgs& args) override final; - void RequestChangeCaretPosition(unsigned position) override final; private: @@ -2831,13 +2802,6 @@ namespace cru::ui::controls void SetState(State state); - protected: - void OnDrawForeground(ID2D1DeviceContext* device_context) override; - - void OnMouseEnterCore(events::MouseEventArgs& args) override final; - void OnMouseLeaveCore(events::MouseEventArgs& args) override final; - void OnMouseClickCore(events::MouseButtonEventArgs& args) override final; - private: State state_ = State::Normal; std::map<State, StateBrush> brushes_{}; @@ -3034,14 +2998,6 @@ namespace cru::ui::controls void AfterLayoutSelf() override; - void OnDrawForeground(ID2D1DeviceContext* device_context) override; - - void OnMouseDownCore(events::MouseButtonEventArgs& args) override final; - void OnMouseMoveCore(events::MouseEventArgs& args) override final; - void OnMouseUpCore(events::MouseButtonEventArgs& args) override final; - - void OnMouseWheelCore(events::MouseWheelEventArgs& args) override; - private: void CoerceAndSetOffsets(float offset_x, float offset_y, bool update_children = true); void UpdateScrollBarVisibility(); |