diff options
author | 杨宇千 <crupest@outlook.com> | 2019-08-11 01:09:49 +0800 |
---|---|---|
committer | 杨宇千 <crupest@outlook.com> | 2019-08-11 01:09:49 +0800 |
commit | 0e35b2c022599bca2df61488945f07e4d6b4eb35 (patch) | |
tree | 71daef6f9725a250b9fcaf97fdecc9bdf46bd6e3 | |
parent | 9eed31954c14f2d60c906adb5b49b58fbee4ff7f (diff) | |
download | cru-0e35b2c022599bca2df61488945f07e4d6b4eb35.tar.gz cru-0e35b2c022599bca2df61488945f07e4d6b4eb35.tar.bz2 cru-0e35b2c022599bca2df61488945f07e4d6b4eb35.zip |
...
-rw-r--r-- | include/cru/common/event.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/exception.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/native/basic_types.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/control.hpp | 16 | ||||
-rw-r--r-- | include/cru/ui/controls/button.hpp | 79 | ||||
-rw-r--r-- | include/cru/ui/event/ui_event.hpp | 20 | ||||
-rw-r--r-- | include/cru/ui/render/border_render_object.hpp | 36 | ||||
-rw-r--r-- | src/ui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/ui/control.cpp | 73 | ||||
-rw-r--r-- | src/ui/controls/button.cpp | 14 | ||||
-rw-r--r-- | src/ui/render/border_render_object.cpp | 27 | ||||
-rw-r--r-- | src/ui/routed_event_dispatch.hpp | 60 | ||||
-rw-r--r-- | src/ui/window.cpp | 56 | ||||
-rw-r--r-- | tools/win_build.py | 2 |
14 files changed, 301 insertions, 92 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index 50918dd0..12c0d0cd 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -148,7 +148,7 @@ class Event : public details::EventBase, public IEvent<TEventArgs> { // Thanks to this behavior, all handlers will be taken a snapshot when Raise // is called, so even if you delete a handler during this period, all handlers // in the snapshot will be executed. - void Raise(EventArgs args) { + void Raise(typename IEvent<TEventArgs>::EventArgs args) { std::forward_list<EventHandler> handlers; auto iter = handlers.cbefore_begin(); for (const auto& data : this->handler_data_list_) { diff --git a/include/cru/platform/exception.hpp b/include/cru/platform/exception.hpp index b1e505e0..ad6827c0 100644 --- a/include/cru/platform/exception.hpp +++ b/include/cru/platform/exception.hpp @@ -11,7 +11,7 @@ class PlatformException : public std::runtime_error { // This exception is throwed when a resource has been disposed and not usable // again. -// For example, calling Build twice on a GeometryBuild will lead to this +// For example, calling Build twice on a GeometryBuilder::Build will lead to this // exception. class ReuseException : public std::runtime_error { public: diff --git a/include/cru/platform/native/basic_types.hpp b/include/cru/platform/native/basic_types.hpp index 573a9e76..5a7155ee 100644 --- a/include/cru/platform/native/basic_types.hpp +++ b/include/cru/platform/native/basic_types.hpp @@ -7,5 +7,5 @@ struct Dpi { float y; }; -enum class MouseButton { Left, Right, Middle }; -} // namespace cru::platform +enum MouseButton : unsigned { Left = 1, Right = 2, Middle = 4 }; +} // namespace cru::platform::native diff --git a/include/cru/ui/control.hpp b/include/cru/ui/control.hpp index 15eeb6fa..f78557a3 100644 --- a/include/cru/ui/control.hpp +++ b/include/cru/ui/control.hpp @@ -1,6 +1,6 @@ #pragma once -#include "cru/common/base.hpp" #include "base.hpp" +#include "cru/common/base.hpp" #include "cru/platform/native/basic_types.hpp" #include "event/ui_event.hpp" @@ -58,6 +58,10 @@ class Control : public Object { bool HasFocus(); + //*************** region: focus *************** + public: + bool IsMouseOver() const { return is_mouse_over_; } + //*************** region: events *************** public: // Raised when mouse enter the control. @@ -130,9 +134,19 @@ class Control : public Object { protected: virtual void OnMouseClickBegin(platform::native::MouseButton button); virtual void OnMouseClickEnd(platform::native::MouseButton button); + virtual void OnMouseClickCancel(platform::native::MouseButton button); private: Window* window_ = nullptr; Control* parent_ = nullptr; + + private: + bool is_mouse_over_ = false; + + struct { + bool left; + bool middle; + bool right; + } click_map_; }; } // namespace cru::ui diff --git a/include/cru/ui/controls/button.hpp b/include/cru/ui/controls/button.hpp index 348416c5..648bb6bc 100644 --- a/include/cru/ui/controls/button.hpp +++ b/include/cru/ui/controls/button.hpp @@ -1,6 +1,11 @@ #pragma once #include "../content_control.hpp" +#include "cru/platform/graph/brush.hpp" +#include "cru/platform/native/basic_types.hpp" +#include "cru/ui/base.hpp" +#include "cru/ui/render/border_render_object.hpp" + #include <memory> namespace cru::ui::render { @@ -8,6 +13,24 @@ class BorderRenderObject; } namespace cru::ui::controls { +struct ButtonBorderStyle { + // corresponds to ButtonState::Normal + render::BorderStyle normal; + // corresponds to ButtonState::Hover + render::BorderStyle hover; + // corresponds to ButtonState::Press + render::BorderStyle press; +}; + +enum class ButtonState { + // mouse is not in it + Normal, + // mouse is in it and not pressed + Hover, + // mouse is pressed in it (click begins) + Press +}; + class Button : public ContentControl { public: static constexpr auto control_type = L"Button"; @@ -30,10 +53,66 @@ class Button : public ContentControl { render::RenderObject* GetRenderObject() const override; + public: + render::BorderStyle GetNormalBorderStyle() const { + return border_style_.normal; + } + void SetNormalBorderStyle(render::BorderStyle newStyle) { + border_style_.normal = std::move(newStyle); + } + + render::BorderStyle GetHoverBorderStyle() const { + return border_style_.hover; + } + void SetHoverBorderStyle(render::BorderStyle newStyle) { + border_style_.hover = std::move(newStyle); + } + + render::BorderStyle GetPressBorderStyle() const { + return border_style_.press; + } + void SetPressBorderStyle(render::BorderStyle newStyle) { + border_style_.press = std::move(newStyle); + } + + ButtonBorderStyle GetBorderStyle() const { return border_style_; } + void SetBorderStyle(ButtonBorderStyle newStyle) { + border_style_ = std::move(newStyle); + } + + ButtonState GetState() const { return state_; } + + // Get the trigger mouse button(s). Return value might be a union of Left, + // Middle and Right. + MouseButton GetTriggerButton() const { return trigger_button_; } + // Set the trigger mouse button(s). You can set multiple buttons by passing a + // union of Left, Middle and Right. If you disable a button when user is + // pressing the same one, click will be stopped. + // Default is only Left. + void SetTriggerButton(MouseButton newTrigger); + protected: void OnChildChanged(Control* old_child, Control* new_child) override; + void OnMouseClickBegin(platform::native::MouseButton button) override; + void OnMouseClickEnd(platform::native::MouseButton button) override; + + virtual void OnStateChange(ButtonState oldState, ButtonState newState); + + private: + void SetState(ButtonState newState) { + const auto oldState = state_; + state_ = newState; + OnStateChange(oldState, newState); + } + private: std::shared_ptr<render::BorderRenderObject> render_object_{}; + + ButtonState state_ = ButtonState::Normal; + + MouseButton trigger_button_ = MouseButton::Left; + + ButtonBorderStyle border_style_; }; } // namespace cru::ui::controls diff --git a/include/cru/ui/event/ui_event.hpp b/include/cru/ui/event/ui_event.hpp index 62045808..f36e40a2 100644 --- a/include/cru/ui/event/ui_event.hpp +++ b/include/cru/ui/event/ui_event.hpp @@ -4,6 +4,7 @@ #include "../base.hpp" #include "cru/common/event.hpp" +#include <memory> #include <optional> namespace cru::platform::graph { @@ -37,6 +38,8 @@ class UiEventArgs : public Object { bool handled_; }; +// TEventArgs must not be a reference type. This class help add reference. +// EventArgs must be reference because the IsHandled property must be settable. template <typename TEventArgs> class RoutedEvent { public: @@ -45,16 +48,19 @@ class RoutedEvent { using EventArgs = TEventArgs; - RoutedEvent() = default; + RoutedEvent() + : direct(new Event<TEventArgs&>()), + bubble(new Event<TEventArgs&>()), + tunnel(new Event<TEventArgs&>()) {} 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; + const std::unique_ptr<IEvent<TEventArgs&>> direct; + const std::unique_ptr<IEvent<TEventArgs&>> bubble; + const std::unique_ptr<IEvent<TEventArgs&>> tunnel; }; class MouseEventArgs : public UiEventArgs { @@ -77,9 +83,11 @@ class MouseEventArgs : public UiEventArgs { class MouseButtonEventArgs : public MouseEventArgs { public: MouseButtonEventArgs(Object* sender, Object* original_sender, - const Point& point, - const MouseButton button) + const Point& point, const MouseButton button) : MouseEventArgs(sender, original_sender, point), button_(button) {} + MouseButtonEventArgs(Object* sender, Object* original_sender, + const MouseButton button) + : MouseEventArgs(sender, original_sender), button_(button) {} MouseButtonEventArgs(const MouseButtonEventArgs& other) = default; MouseButtonEventArgs(MouseButtonEventArgs&& other) = default; MouseButtonEventArgs& operator=(const MouseButtonEventArgs& other) = default; diff --git a/include/cru/ui/render/border_render_object.hpp b/include/cru/ui/render/border_render_object.hpp index ab424e60..69372eb8 100644 --- a/include/cru/ui/render/border_render_object.hpp +++ b/include/cru/ui/render/border_render_object.hpp @@ -1,4 +1,6 @@ #pragma once +#include "cru/platform/graph/brush.hpp" +#include "cru/ui/base.hpp" #include "render_object.hpp" #include <memory> @@ -30,6 +32,12 @@ struct CornerRadius { Point right_bottom; }; +struct BorderStyle { + std::shared_ptr<platform::graph::Brush> brush; + Thickness thickness; + CornerRadius corner_radius; +}; + class BorderRenderObject : public RenderObject { public: explicit BorderRenderObject(std::shared_ptr<platform::graph::Brush> brush); @@ -43,20 +51,30 @@ class BorderRenderObject : public RenderObject { void SetEnabled(bool enabled) { is_enabled_ = enabled; } std::shared_ptr<platform::graph::Brush> GetBrush() const { - return border_brush_; + return style_.brush; } void SetBrush(std::shared_ptr<platform::graph::Brush> new_brush) { - border_brush_ = std::move(new_brush); + style_.brush = std::move(new_brush); } - Thickness GetBorderWidth() const { return border_thickness_; } + Thickness GetBorderWidth() const { return style_.thickness; } + // Remember to call Refresh after set shape properties. void SetBorderWidth(const Thickness& thickness) { - border_thickness_ = thickness; + style_.thickness = thickness; } - CornerRadius GetCornerRadius() const { return corner_radius_; } + CornerRadius GetCornerRadius() const { return style_.corner_radius; } + // Remember to call Refresh after set shape properties. void SetCornerRadius(const CornerRadius& new_corner_radius) { - corner_radius_ = new_corner_radius; + style_.corner_radius = new_corner_radius; + } + + BorderStyle GetStyle() const { + return style_; + } + // Remember to call Refresh after set shape properties. + void SetStyle(BorderStyle newStyle) { + style_ = std::move(newStyle); } void Refresh() { RecreateGeometry(); } @@ -85,11 +103,11 @@ class BorderRenderObject : public RenderObject { private: bool is_enabled_ = false; - std::shared_ptr<platform::graph::Brush> border_brush_ = nullptr; - Thickness border_thickness_{}; - CornerRadius corner_radius_{}; + BorderStyle style_; + // The ring. Used for painting. std::shared_ptr<platform::graph::Geometry> geometry_ = nullptr; + // Area including border ring and inner area. Used for hit test. std::shared_ptr<platform::graph::Geometry> border_outer_geometry_ = nullptr; }; } // namespace cru::ui::render diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 6d6fc02d..62ae1775 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -1,6 +1,8 @@ file(GLOB CRU_UI_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/ui) add_library(cru_ui STATIC + routed_event_dispatch.hpp + content_control.cpp control.cpp layout_control.cpp diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 7563dc91..51e1937a 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -1,6 +1,10 @@ #include "cru/ui/control.hpp" +#include "cru/platform/native/basic_types.hpp" +#include "cru/ui/base.hpp" +#include "cru/ui/event/ui_event.hpp" #include "cru/ui/window.hpp" +#include "routed_event_dispatch.hpp" #include <cassert> @@ -10,7 +14,69 @@ void Control::_SetParent(Control* parent) { parent_ = parent; const auto new_parent = GetParent(); if (old_parent != new_parent) OnParentChanged(old_parent, new_parent); -} + + MouseDownEvent()->direct->AddHandler( + [this](event::MouseButtonEventArgs& args) { + switch (args.GetMouseButton()) { + case MouseButton::Left: + click_map_.left = true; + OnMouseClickBegin(MouseButton::Left); + break; + case MouseButton::Middle: + click_map_.middle = true; + OnMouseClickBegin(MouseButton::Middle); + break; + case MouseButton::Right: + click_map_.right = true; + OnMouseClickBegin(MouseButton::Right); + break; + } + }); + + MouseEnterEvent()->direct->AddHandler([this](event::MouseEventArgs&) { + this->is_mouse_over_ = true; + }); + + MouseLeaveEvent()->direct->AddHandler([this](event::MouseEventArgs&) { + this->is_mouse_over_ = false; + if (click_map_.left) { + OnMouseClickCancel(MouseButton::Left); + } + if (click_map_.middle) { + OnMouseClickCancel(MouseButton::Middle); + } + if (click_map_.right) { + OnMouseClickCancel(MouseButton::Right); + } + click_map_.left = click_map_.middle = click_map_.right = false; + }); + + MouseUpEvent()->direct->AddHandler([this](event::MouseButtonEventArgs& args) { + switch (args.GetMouseButton()) { + case MouseButton::Left: + if (click_map_.left) { + click_map_.left = false; + OnMouseClickEnd(MouseButton::Left); + DispatchEvent(this, &Control::MouseClickEvent, nullptr, args.GetPoint(), args.GetMouseButton()); + } + break; + case MouseButton::Middle: + if (click_map_.middle) { + click_map_.middle = false; + OnMouseClickEnd(MouseButton::Middle); + DispatchEvent(this, &Control::MouseClickEvent, nullptr, args.GetPoint(), args.GetMouseButton()); + } + break; + case MouseButton::Right: + if (click_map_.right) { + click_map_.right = false; + OnMouseClickEnd(MouseButton::Right); + DispatchEvent(this, &Control::MouseClickEvent, nullptr, args.GetPoint(), args.GetMouseButton()); + } + break; + } + }); +} // namespace cru::ui void Control::_SetDescendantWindow(Window* window) { if (window == nullptr && window_ == nullptr) return; @@ -40,8 +106,7 @@ void Control::TraverseDescendants( void Control::_TraverseDescendants( Control* control, const std::function<void(Control*)>& predicate) { predicate(control); - for (auto c : control->GetChildren()) - _TraverseDescendants(c, predicate); + for (auto c : control->GetChildren()) _TraverseDescendants(c, predicate); } bool Control::RequestFocus() { auto window = GetWindow(); @@ -66,4 +131,6 @@ void Control::OnDetachToWindow(Window* window) {} void Control::OnMouseClickBegin(platform::native::MouseButton button) {} void Control::OnMouseClickEnd(platform::native::MouseButton button) {} + +void Control::OnMouseClickCancel(platform::native::MouseButton button) {} } // namespace cru::ui diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp index 0ac65d26..2228343c 100644 --- a/src/ui/controls/button.cpp +++ b/src/ui/controls/button.cpp @@ -23,4 +23,18 @@ void Button::OnChildChanged(Control* old_child, Control* new_child) { if (new_child != nullptr) render_object_->AddChild(new_child->GetRenderObject(), 0); } + +void Button::OnMouseClickBegin(platform::native::MouseButton button) { + if (button & trigger_button_) { + SetState(ButtonState::Press); + //TODO! + } +} + +void Button::OnMouseClickEnd(platform::native::MouseButton button) { + if (button & trigger_button_) { + SetState(ButtonState::Normal); + //TODO! + } +} } // namespace cru::ui::controls diff --git a/src/ui/render/border_render_object.cpp b/src/ui/render/border_render_object.cpp index 16d2f1ea..1bec3e0b 100644 --- a/src/ui/render/border_render_object.cpp +++ b/src/ui/render/border_render_object.cpp @@ -12,12 +12,12 @@ namespace cru::ui::render { BorderRenderObject::BorderRenderObject( std::shared_ptr<platform::graph::Brush> brush) { assert(brush); - this->border_brush_ = std::move(brush); + this->style_.brush = std::move(brush); RecreateGeometry(); } void BorderRenderObject::Draw(platform::graph::Painter* painter) { - painter->FillGeometry(geometry_.get(), border_brush_.get()); + painter->FillGeometry(geometry_.get(), style_.brush.get()); if (const auto child = GetChild()) { auto offset = child->GetOffset(); platform::graph::util::WithTransform( @@ -69,8 +69,8 @@ void BorderRenderObject::OnMeasureCore(const Size& available_size) { margin.GetVerticalTotal() + padding.GetVerticalTotal()}; if (is_enabled_) { - margin_border_padding_size.width += border_thickness_.GetHorizontalTotal(); - margin_border_padding_size.height += border_thickness_.GetVerticalTotal(); + margin_border_padding_size.width += style_.thickness.GetHorizontalTotal(); + margin_border_padding_size.height += style_.thickness.GetVerticalTotal(); } auto coerced_margin_border_padding_size = margin_border_padding_size; @@ -104,8 +104,8 @@ void BorderRenderObject::OnLayoutCore(const Rect& rect) { margin.GetVerticalTotal() + padding.GetVerticalTotal()}; if (is_enabled_) { - margin_border_padding_size.width += border_thickness_.GetHorizontalTotal(); - margin_border_padding_size.height += border_thickness_.GetVerticalTotal(); + margin_border_padding_size.width += style_.thickness.GetHorizontalTotal(); + margin_border_padding_size.height += style_.thickness.GetVerticalTotal(); } const auto content_available_size = @@ -121,14 +121,13 @@ void BorderRenderObject::OnLayoutCore(const Rect& rect) { if (coerced_content_available_size.height < 0) { platform::DebugMessage( L"Layout: vertical length of padding, border and margin is bigger " - L"than " - L"available length."); + L"than available length."); coerced_content_available_size.height = 0; } OnLayoutContent(Rect{ - margin.left + (is_enabled_ ? border_thickness_.left : 0) + padding.left, - margin.top + (is_enabled_ ? border_thickness_.top : 0) + padding.top, + margin.left + (is_enabled_ ? style_.thickness.left : 0) + padding.left, + margin.top + (is_enabled_ ? style_.thickness.top : 0) + padding.top, coerced_content_available_size.width, coerced_content_available_size.height}); } @@ -184,14 +183,14 @@ void BorderRenderObject::RecreateGeometry() { const auto graph_factory = platform::graph::GraphFactory::GetInstance(); std::unique_ptr<platform::graph::GeometryBuilder> builder{ graph_factory->CreateGeometryBuilder()}; - f(builder.get(), outer_rect, corner_radius_); + f(builder.get(), outer_rect, style_.corner_radius); border_outer_geometry_.reset(builder->Build()); builder.reset(); - const Rect inner_rect = outer_rect.Shrink(border_thickness_); + const Rect inner_rect = outer_rect.Shrink(style_.thickness); builder.reset(graph_factory->CreateGeometryBuilder()); - f(builder.get(), outer_rect, corner_radius_); - f(builder.get(), inner_rect, corner_radius_); + f(builder.get(), outer_rect, style_.corner_radius); + f(builder.get(), inner_rect, style_.corner_radius); geometry_.reset(builder->Build()); builder.reset(); } diff --git a/src/ui/routed_event_dispatch.hpp b/src/ui/routed_event_dispatch.hpp new file mode 100644 index 00000000..3427441b --- /dev/null +++ b/src/ui/routed_event_dispatch.hpp @@ -0,0 +1,60 @@ +#pragma once +#include "cru/ui/control.hpp" + +namespace cru::ui { +// 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, + event::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)...); + static_cast<Event<EventArgs>*>(((*i)->*event_ptr)()->tunnel.get()) + ->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)...); + static_cast<Event<EventArgs>*>((i->*event_ptr)()->bubble.get()) + ->Raise(event_args); + if (event_args.IsHandled()) break; + } + } + + // direct + for (auto i : receive_list) { + EventArgs event_args(i, original_sender, std::forward<Args>(args)...); + static_cast<Event<EventArgs>*>((i->*event_ptr)()->direct.get()) + ->Raise(event_args); + } +} +} // namespace cru::ui diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 9eabc4a6..e17d603c 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -4,64 +4,12 @@ #include "cru/platform/native/native_window.hpp" #include "cru/platform/native/ui_applicaition.hpp" #include "cru/ui/render/window_render_object.hpp" +#include "routed_event_dispatch.hpp" #include <cassert> namespace cru::ui { namespace { -// 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, - event::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); - } -} - std::list<Control*> GetAncestorList(Control* control) { std::list<Control*> l; while (control != nullptr) { @@ -157,7 +105,7 @@ void Window::InvalidateLayout() { window->Relayout(); window->need_layout_ = false; } - }); + }); need_layout_ = true; } } diff --git a/tools/win_build.py b/tools/win_build.py index ab1c7107..d818024d 100644 --- a/tools/win_build.py +++ b/tools/win_build.py @@ -17,7 +17,7 @@ args = parser.parse_args() project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - +# this is not used when generator is Visual Studio def init_vc_environment(arch): arch_bat_map = { 'x86': 'vcvarsamd64_x86', |