diff options
-rw-r--r-- | include/cru/common/event.hpp | 56 | ||||
-rw-r--r-- | include/cru/platform/native_window.hpp | 8 | ||||
-rw-r--r-- | include/cru/platform/painter.hpp | 1 | ||||
-rw-r--r-- | include/cru/platform/win/win_native_window.hpp | 16 | ||||
-rw-r--r-- | include/cru/platform/win/win_painter.hpp | 1 | ||||
-rw-r--r-- | include/cru/ui/window.hpp | 23 | ||||
-rw-r--r-- | src/platform_win/win_native_window.cpp | 6 | ||||
-rw-r--r-- | src/platform_win/win_painter.cpp | 5 | ||||
-rw-r--r-- | src/ui/window.cpp | 146 |
9 files changed, 117 insertions, 145 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index ce014fb8..52d75a7b 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -3,33 +3,65 @@ #include <functional> #include <map> +#include <memory> #include <utility> namespace cru { +using EventHandlerRevoker = std::function<void()>; + // A non-copyable non-movable Event class. // It stores a list of event handlers. template <typename... TArgs> class Event { + private: + using EventResolver = std::function<Event*()>; + class EventHandlerRevokerImpl { + public: + EventHandlerRevokerImpl(const std::shared_ptr<EventResolver>& resolver, + long token) + : resolver_(resolver), token_(token) {} + EventHandlerRevokerImpl(const EventHandlerRevokerImpl& other) = default; + EventHandlerRevokerImpl(EventHandlerRevokerImpl&& other) = default; + EventHandlerRevokerImpl& operator=(EventHandlerRevokerImpl&& other) = + default; + EventHandlerRevokerImpl& operator=(EventHandlerRevokerImpl&& other) = + default; + ~EventHandlerRevokerImpl() = default; + + void operator()() { + const auto true_resolver = resolver_.lock(); + if (true_resolver) { + true_resolver()->RemoveHandler(token_); + } + } + + private: + std::weak_ptr<EventResolver> resolver_; + long token_; + }; + public: using EventHandler = std::function<void(TArgs...)>; - using EventHandlerToken = long; - Event() = default; + Event() + : event_resolver_(new std::function<Event*()>([this] { return this; })) {} Event(const Event&) = delete; Event& operator=(const Event&) = delete; Event(Event&&) = delete; Event& operator=(Event&&) = delete; ~Event() = default; - EventHandlerToken AddHandler(const EventHandler& handler) { + EventHandlerRevoker AddHandler(const EventHandler& handler) { const auto token = current_token_++; handlers_.emplace(token, handler); - return token; + return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token)); } - void RemoveHandler(const EventHandlerToken token) { - auto find_result = handlers_.find(token); - if (find_result != handlers_.cend()) handlers_.erase(find_result); + template <typename... Args> + EventHandlerRevoker AddHandler(Args&& args...) { + const auto token = current_token_++; + handlers_.emplace(token, EventHandler(std::forward<Args>(args)...)); + return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token)); } template <typename... Args> @@ -39,8 +71,14 @@ class Event { } private: - std::map<EventHandlerToken, EventHandler> handlers_; + void RemoveHandler(const long token) { + auto find_result = handlers_.find(token); + if (find_result != handlers_.cend()) handlers_.erase(find_result); + } - EventHandlerToken current_token_ = 0; + private: + std::map<long, EventHandler> handlers_{}; + long current_token_ = 0; + std::shared_ptr<EventResolver> event_resolver_; }; } // namespace cru diff --git a/include/cru/platform/native_window.hpp b/include/cru/platform/native_window.hpp index 2daf4870..f68fd3a4 100644 --- a/include/cru/platform/native_window.hpp +++ b/include/cru/platform/native_window.hpp @@ -35,13 +35,13 @@ struct NativeWindow : public virtual Interface { virtual Painter* BeginPaint() = 0; virtual Event<>* DestroyEvent() = 0; - virtual Event<ui::Size>* ResizeEvent() = 0; + virtual Event<const ui::Size&>* ResizeEvent() = 0; virtual Event<>* PaintEvent() = 0; virtual Event<bool>* FocusEvent() = 0; virtual Event<bool>* MouseEnterLeaveEvent() = 0; - virtual Event<ui::Point>* MouseMoveEvent() = 0; - virtual Event<MouseButton, ui::Point>* MouseDownEvent() = 0; - virtual Event<MouseButton, ui::Point>* MouseUpEvent() = 0; + virtual Event<const ui::Point&>* MouseMoveEvent() = 0; + virtual Event<MouseButton, const ui::Point&>* MouseDownEvent() = 0; + virtual Event<MouseButton, const ui::Point&>* MouseUpEvent() = 0; virtual Event<int>* KeyDownEvent() = 0; virtual Event<int>* KeyUpEvent() = 0; }; diff --git a/include/cru/platform/painter.hpp b/include/cru/platform/painter.hpp index 7310bc5c..eaaf61f9 100644 --- a/include/cru/platform/painter.hpp +++ b/include/cru/platform/painter.hpp @@ -12,6 +12,7 @@ struct TextLayout; struct Painter : virtual Interface { virtual Matrix GetTransform() = 0; virtual void SetTransform(const Matrix& matrix) = 0; + virtual void Clear(const ui::Color& color) = 0; virtual void StrokeRectangle(const ui::Rect& rectangle, Brush* brush, float width) = 0; virtual void FillRectangle(const ui::Rect& rectangle, Brush* brush) = 0; diff --git a/include/cru/platform/win/win_native_window.hpp b/include/cru/platform/win/win_native_window.hpp index ae19c9f3..7b93fd5c 100644 --- a/include/cru/platform/win/win_native_window.hpp +++ b/include/cru/platform/win/win_native_window.hpp @@ -47,17 +47,17 @@ class WinNativeWindow : public Object, public virtual NativeWindow { Painter* BeginPaint() override; Event<>* DestroyEvent() override { return &destroy_event_; } - Event<ui::Size>* ResizeEvent() override { return &resize_event_; } + Event<const ui::Size&>* ResizeEvent() override { return &resize_event_; } Event<>* PaintEvent() override { return &paint_event_; } Event<bool>* FocusEvent() override { return &focus_event_; } Event<bool>* MouseEnterLeaveEvent() override { return &mouse_enter_leave_event_; } - Event<ui::Point>* MouseMoveEvent() override { return &mouse_move_event_; } - Event<MouseButton, ui::Point>* MouseDownEvent() override { + Event<const ui::Point&>* MouseMoveEvent() override { return &mouse_move_event_; } + Event<MouseButton, const ui::Point&>* MouseDownEvent() override { return &mouse_down_event_; } - Event<MouseButton, ui::Point>* MouseUpEvent() override { + Event<MouseButton, const ui::Point&>* MouseUpEvent() override { return &mouse_up_event_; } Event<int>* KeyDownEvent() override { return &key_down_event_; } @@ -117,13 +117,13 @@ class WinNativeWindow : public Object, public virtual NativeWindow { std::shared_ptr<WindowRenderTarget> window_render_target_; Event<> destroy_event_; - Event<ui::Size> resize_event_; + Event<const ui::Size&> resize_event_; Event<> paint_event_; Event<bool> focus_event_; Event<bool> mouse_enter_leave_event_; - Event<ui::Point> mouse_move_event_; - Event<MouseButton, ui::Point> mouse_down_event_; - Event<MouseButton, ui::Point> mouse_up_event_; + Event<const ui::Point&> mouse_move_event_; + Event<MouseButton, const ui::Point&> mouse_down_event_; + Event<MouseButton, const ui::Point&> mouse_up_event_; Event<int> key_down_event_; Event<int> key_up_event_; diff --git a/include/cru/platform/win/win_painter.hpp b/include/cru/platform/win/win_painter.hpp index dfb981d5..3c37ccb2 100644 --- a/include/cru/platform/win/win_painter.hpp +++ b/include/cru/platform/win/win_painter.hpp @@ -17,6 +17,7 @@ class WinPainter : public Object, public virtual Painter { Matrix GetTransform() override; void SetTransform(const Matrix& matrix) override; + void Clear(const ui::Color& color) override; void StrokeRectangle(const ui::Rect& rectangle, Brush* brush, float width) override; void FillRectangle(const ui::Rect& rectangle, Brush* brush) override; diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp index 043aae35..f0c790be 100644 --- a/include/cru/ui/window.hpp +++ b/include/cru/ui/window.hpp @@ -60,23 +60,18 @@ class Window final : public ContentControl { void OnNativeDestroy(); void OnNativePaint(); - void OnNativeResize(float new_width, float new_height); + void OnNativeResize(const Size& size); - void OnSetFocusInternal(); - void OnKillFocusInternal(); + void OnNativeFocus(bool focus); - void OnMouseMoveInternal(POINT point); - void OnMouseLeaveInternal(); - void OnMouseDownInternal(MouseButton button, POINT point); - void OnMouseUpInternal(MouseButton button, POINT point); + void OnNativeMouseMove(const Point& point); + void OnNativeMouseLeave(); + void OnNativeMouseDown(platform::MouseButton button, const Point& point); + void OnNativeMouseUp(platform::MouseButton button, const Point& point); - void OnMouseWheelInternal(short delta, POINT point); - void OnKeyDownInternal(int virtual_code); - void OnKeyUpInternal(int virtual_code); - void OnCharInternal(wchar_t c); + void OnNativeKeyDown(int virtual_code); + void OnNativeKeyUp(int virtual_code); - void OnActivatedInternal(); - void OnDeactivatedInternal(); //*************** region: event dispatcher helper *************** @@ -86,7 +81,7 @@ class Window final : public ContentControl { private: platform::NativeWindow* native_window_; - std::vector<EventHandlerToken> revoke_tokens_; + std::vector<EventHandlerRevoker> event_revokers_; std::shared_ptr<render::WindowRenderObject> render_object_; diff --git a/src/platform_win/win_native_window.cpp b/src/platform_win/win_native_window.cpp index ae740205..12c25674 100644 --- a/src/platform_win/win_native_window.cpp +++ b/src/platform_win/win_native_window.cpp @@ -4,6 +4,7 @@ #include "cru/platform/win/win_application.hpp" #include "cru/platform/win/win_painter.hpp" #include "cru/platform/win/window_class.hpp" +#include "cru/platform/win/window_render_target.hpp" #include "dpi_util.hpp" #include "window_manager.hpp" @@ -258,10 +259,11 @@ void WinNativeWindow::OnPaintInternal() { void WinNativeWindow::OnResizeInternal(const int new_width, const int new_height) { - // render_target_->ResizeBuffer(new_width, new_height); - if (!(new_width == 0 && new_height == 0)) + if (!(new_width == 0 && new_height == 0)) { + window_render_target_->ResizeBuffer(new_width, new_height); resize_event_.Raise( ui::Size{PixelToDipX(new_width), PixelToDipY(new_height)}); + } } void WinNativeWindow::OnSetFocusInternal() { diff --git a/src/platform_win/win_painter.cpp b/src/platform_win/win_painter.cpp index b648f97d..6ce5f4de 100644 --- a/src/platform_win/win_painter.cpp +++ b/src/platform_win/win_painter.cpp @@ -40,6 +40,11 @@ void WinPainter::SetTransform(const Matrix& matrix) { render_target_->SetTransform(util::Convert(matrix)); } +void WinPainter::Clear(const ui::Color& color) { + assert(!IsDisposed()); + render_target_->Clear(util::Convert(color)); +} + void WinPainter::StrokeRectangle(const ui::Rect& rectangle, Brush* brush, float width) { assert(!IsDisposed()); diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 1065a3fb..bad704ae 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -1,8 +1,9 @@ #include "cru/ui/window.hpp" -#include "cru/ui/render/window_render_object.hpp" -#include "cru/platform/ui_applicaition.hpp" #include "cru/platform/native_window.hpp" +#include "cru/platform/painter.hpp" +#include "cru/platform/ui_applicaition.hpp" +#include "cru/ui/render/window_render_object.hpp" #include <cassert> @@ -97,10 +98,16 @@ Window* Window::CreateOverlapped() { return new Window(tag_overlapped_constructor{}); } - Window::Window(tag_overlapped_constructor) { - native_window_ = platform::UiApplication::GetInstance()->CreateWindow(nullptr); + native_window_ = + platform::UiApplication::GetInstance()->CreateWindow(nullptr); render_object_.reset(new render::WindowRenderObject(this)); + + event_revokers_.push_back(native_window_->DestroyEvent()->AddHandler( + this, Window::OnNativeDestroy)); + event_revokers_.push_back( + native_window_->PaintEvent()->AddHandler(this, Window::OnNativePaint)); + //TODO } Window::~Window() { @@ -143,135 +150,58 @@ Control* Window::HitTest(const Point& point) { void Window::OnNativeDestroy() { delete this; } void Window::OnNativePaint() { - render_target_->SetAsTarget(); - - auto device_context = - render_target_->GetGraphManager()->GetD2D1DeviceContext(); - device_context->BeginDraw(); - // Clear the background. - device_context->Clear(D2D1::ColorF(D2D1::ColorF::White)); - render_object_->Draw(device_context); - ThrowIfFailed(device_context->EndDraw(), "Failed to draw window."); - render_target_->Present(); - - ValidateRect(hwnd_, nullptr); -} - -void Window::OnResizeInternal(const int new_width, const int new_height) { - render_target_->ResizeBuffer(new_width, new_height); - if (!(new_width == 0 && new_height == 0)) render_object_->MeasureAndLayout(); + const auto painter = + std::make_unique<platform::Painter>(native_window_->BeginPaint()); + render_object_->Draw(painter.get()); + painter->EndDraw(); } -void Window::OnSetFocusInternal() { - window_focus_ = true; - DispatchEvent(focus_control_, &Control::GainFocusEvent, nullptr, true); +void Window::OnNativeResize(const Size& size) { + render_object_->MeasureAndLayout(); } -void Window::OnKillFocusInternal() { - window_focus_ = false; - DispatchEvent(focus_control_, &Control::LoseFocusEvent, nullptr, true); +void Window::OnNativeFocus(bool focus) { + focus + ? DispatchEvent(focus_control_, &Control::GainFocusEvent, nullptr, true) + : DispatchEvent(focus_control_, &Control::LoseFocusEvent, nullptr, true); } -void Window::OnMouseMoveInternal(const POINT point) { - const auto dip_point = PiToDip(point); - - // when mouse was previous outside the window - if (mouse_hover_control_ == nullptr) { - // invoke TrackMouseEvent to have WM_MOUSELEAVE sent. - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof tme; - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd_; - - TrackMouseEvent(&tme); - } - +void Window::OnNativeMouseMove(const Point& point) { // Find the first control that hit test succeed. - const auto new_control_mouse_hover = HitTest(dip_point); + const auto new_control_mouse_hover = HitTest(point); const auto old_control_mouse_hover = mouse_hover_control_; mouse_hover_control_ = new_control_mouse_hover; - if (mouse_capture_control_) // if mouse is captured - { - DispatchEvent(mouse_capture_control_, &Control::MouseMoveEvent, nullptr, - dip_point); - } else { - DispatchMouseHoverControlChangeEvent(old_control_mouse_hover, - new_control_mouse_hover, dip_point); - DispatchEvent(new_control_mouse_hover, &Control::MouseMoveEvent, nullptr, - dip_point); - } + DispatchMouseHoverControlChangeEvent(old_control_mouse_hover, + new_control_mouse_hover, point); + DispatchEvent(new_control_mouse_hover, &Control::MouseMoveEvent, nullptr, + point); } -void Window::OnMouseLeaveInternal() { +void Window::OnNativeMouseLeave() { DispatchEvent(mouse_hover_control_, &Control::MouseLeaveEvent, nullptr); mouse_hover_control_ = nullptr; } -void Window::OnMouseDownInternal(MouseButton button, POINT point) { - const auto dip_point = PiToDip(point); - - Control* control; - - if (mouse_capture_control_) - control = mouse_capture_control_; - else - control = HitTest(dip_point); - - DispatchEvent(control, &Control::MouseDownEvent, nullptr, dip_point, - button); +void Window::OnNativeMouseDown(platform::MouseButton button, + const Point& point) { + Control* control = HitTest(point); + DispatchEvent(control, &Control::MouseDownEvent, nullptr, point, button); } -void Window::OnMouseUpInternal(MouseButton button, POINT point) { - const auto dip_point = PiToDip(point); - - Control* control; - - if (mouse_capture_control_) - control = mouse_capture_control_; - else - control = HitTest(dip_point); - - DispatchEvent(control, &Control::MouseUpEvent, nullptr, dip_point, button); +void Window::OnNativeMouseUp(platform::MouseButton button, const Point& point) { + Control* control = HitTest(point); + DispatchEvent(control, &Control::MouseUpEvent, nullptr, point, button); } -void Window::OnMouseWheelInternal(short delta, POINT point) { - const auto dip_point = PiToDip(point); - - Control* control; - - if (mouse_capture_control_) - control = mouse_capture_control_; - else - control = HitTest(dip_point); - - DispatchEvent(control, &Control::MouseWheelEvent, nullptr, dip_point, - static_cast<float>(delta)); +void Window::OnNativeKeyDown(int virtual_code) { + DispatchEvent(focus_control_, &Control::KeyDownEvent, nullptr, virtual_code); } -void Window::OnKeyDownInternal(int virtual_code) { - DispatchEvent(focus_control_, &Control::KeyDownEvent, nullptr, - virtual_code); -} - -void Window::OnKeyUpInternal(int virtual_code) { +void Window::OnNativeKeyUp(int virtual_code) { DispatchEvent(focus_control_, &Control::KeyUpEvent, nullptr, virtual_code); } -void Window::OnCharInternal(wchar_t c) { - DispatchEvent(focus_control_, &Control::CharEvent, nullptr, c); -} - -void Window::OnActivatedInternal() { - events::UiEventArgs args(this, this); - activated_event_.Raise(args); -} - -void Window::OnDeactivatedInternal() { - events::UiEventArgs args(this, this); - deactivated_event_.Raise(args); -} - void Window::DispatchMouseHoverControlChangeEvent(Control* old_control, Control* new_control, const Point& point) { |