From 2188845a7acffa653015a1000139ec0a9a3984bc Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 8 Nov 2020 17:45:41 +0800 Subject: ... --- src/ui/CMakeLists.txt | 32 +++---- src/ui/ClickDetector.cpp | 131 --------------------------- src/ui/ContentControl.cpp | 27 ------ src/ui/Control.cpp | 157 --------------------------------- src/ui/LayoutControl.cpp | 6 -- src/ui/NoChildControl.cpp | 3 - src/ui/ShortcutHub.cpp | 120 ------------------------- src/ui/UiEvent.cpp | 10 --- src/ui/Window.cpp | 32 ------- src/ui/controls/Button.cpp | 17 ++-- src/ui/controls/ContentControl.cpp | 25 ++++++ src/ui/controls/Control.cpp | 157 +++++++++++++++++++++++++++++++++ src/ui/controls/LayoutControl.cpp | 3 + src/ui/controls/NoChildControl.cpp | 3 + src/ui/controls/TextControlService.hpp | 8 +- src/ui/controls/Window.cpp | 32 +++++++ src/ui/events/UiEvent.cpp | 10 +++ src/ui/helper/ClickDetector.cpp | 131 +++++++++++++++++++++++++++ src/ui/helper/ShortcutHub.cpp | 120 +++++++++++++++++++++++++ src/ui/host/RoutedEventDispatch.hpp | 14 +-- src/ui/host/WindowHost.cpp | 83 ++++++++--------- src/win/gui/UiApplication.cpp | 12 ++- 22 files changed, 567 insertions(+), 566 deletions(-) delete mode 100644 src/ui/ClickDetector.cpp delete mode 100644 src/ui/ContentControl.cpp delete mode 100644 src/ui/Control.cpp delete mode 100644 src/ui/LayoutControl.cpp delete mode 100644 src/ui/NoChildControl.cpp delete mode 100644 src/ui/ShortcutHub.cpp delete mode 100644 src/ui/UiEvent.cpp delete mode 100644 src/ui/Window.cpp create mode 100644 src/ui/controls/ContentControl.cpp create mode 100644 src/ui/controls/Control.cpp create mode 100644 src/ui/controls/LayoutControl.cpp create mode 100644 src/ui/controls/NoChildControl.cpp create mode 100644 src/ui/controls/Window.cpp create mode 100644 src/ui/events/UiEvent.cpp create mode 100644 src/ui/helper/ClickDetector.cpp create mode 100644 src/ui/helper/ShortcutHub.cpp (limited to 'src') diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 449fb4d9..2f0eb10d 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -4,23 +4,23 @@ add_library(cru_ui STATIC Helper.hpp host/RoutedEventDispatch.hpp - ClickDetector.cpp - ContentControl.cpp - Control.cpp Helper.cpp - LayoutControl.cpp - NoChildControl.cpp - ShortcutHub.cpp - UiEvent.cpp UiManager.cpp - Window.cpp controls/Button.cpp controls/Container.cpp + controls/ContentControl.cpp + controls/Control.cpp controls/FlexLayout.cpp + controls/LayoutControl.cpp + controls/NoChildControl.cpp controls/StackLayout.cpp controls/TextBlock.cpp controls/TextBox.cpp controls/TextControlService.hpp + controls/Window.cpp + events/UiEvent.cpp + helper/ClickDetector.cpp + helper/ShortcutHub.cpp host/LayoutPaintCycler.cpp host/WindowHost.cpp render/BorderRenderObject.cpp @@ -34,23 +34,23 @@ add_library(cru_ui STATIC ) target_sources(cru_ui PUBLIC ${CRU_UI_INCLUDE_DIR}/Base.hpp - ${CRU_UI_INCLUDE_DIR}/ClickDetector.hpp - ${CRU_UI_INCLUDE_DIR}/ContentControl.hpp - ${CRU_UI_INCLUDE_DIR}/Control.hpp ${CRU_UI_INCLUDE_DIR}/DebugFlags.hpp - ${CRU_UI_INCLUDE_DIR}/LayoutControl.hpp - ${CRU_UI_INCLUDE_DIR}/NoChildControl.hpp - ${CRU_UI_INCLUDE_DIR}/ShortcutHub.hpp - ${CRU_UI_INCLUDE_DIR}/UiEvent.hpp ${CRU_UI_INCLUDE_DIR}/UiManager.hpp - ${CRU_UI_INCLUDE_DIR}/Window.hpp ${CRU_UI_INCLUDE_DIR}/controls/Base.hpp ${CRU_UI_INCLUDE_DIR}/controls/Button.hpp ${CRU_UI_INCLUDE_DIR}/controls/Container.hpp + ${CRU_UI_INCLUDE_DIR}/controls/ContentControl.hpp + ${CRU_UI_INCLUDE_DIR}/controls/Control.hpp ${CRU_UI_INCLUDE_DIR}/controls/FlexLayout.hpp + ${CRU_UI_INCLUDE_DIR}/controls/LayoutControl.hpp + ${CRU_UI_INCLUDE_DIR}/controls/NoChildControl.hpp ${CRU_UI_INCLUDE_DIR}/controls/StackLayout.hpp ${CRU_UI_INCLUDE_DIR}/controls/TextBox.hpp ${CRU_UI_INCLUDE_DIR}/controls/TextBlock.hpp + ${CRU_UI_INCLUDE_DIR}/controls/Window.hpp + ${CRU_UI_INCLUDE_DIR}/events/UiEvent.hpp + ${CRU_UI_INCLUDE_DIR}/helper/ClickDetector.hpp + ${CRU_UI_INCLUDE_DIR}/helper/ShortcutHub.hpp ${CRU_UI_INCLUDE_DIR}/host/LayoutPaintCycler.hpp ${CRU_UI_INCLUDE_DIR}/host/WindowHost.hpp ${CRU_UI_INCLUDE_DIR}/render/Base.hpp diff --git a/src/ui/ClickDetector.cpp b/src/ui/ClickDetector.cpp deleted file mode 100644 index 09f208cd..00000000 --- a/src/ui/ClickDetector.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "cru/ui/ClickDetector.hpp" - -#include "cru/common/Logger.hpp" - -#include - -namespace cru::ui { -ClickDetector::ClickDetector(Control* control) { - Expects(control); - control_ = control; - - event_rovoker_guards_.push_back( - EventRevokerGuard(control->MouseEnterEvent()->Direct()->AddHandler( - [this](event::MouseEventArgs&) { - if (this->enable_) { - if (this->state_ == ClickState::PressInactive) { - if ((this->button_ & this->trigger_button_)) { - this->SetState(ClickState::Press); - } - } else { - this->SetState(ClickState::Hover); - } - } - }))); - - event_rovoker_guards_.push_back( - EventRevokerGuard(control->MouseLeaveEvent()->Direct()->AddHandler( - [this](event::MouseEventArgs&) { - if (this->enable_) { - if (this->state_ == ClickState::Press) { - if ((this->button_ & this->trigger_button_)) { - this->SetState(ClickState::PressInactive); - } - } else { - this->SetState(ClickState::None); - } - } - }))); - - event_rovoker_guards_.push_back( - EventRevokerGuard(control->MouseDownEvent()->Direct()->AddHandler( - [this](event::MouseButtonEventArgs& args) { - const auto button = args.GetButton(); - if (this->enable_ && (button & this->trigger_button_) && - this->state_ == ClickState::Hover) { - if (!this->control_->CaptureMouse()) { - log::TagDebug(log_tag, - u"Failed to capture mouse when begin click."); - return; - } - this->down_point_ = args.GetPoint(); - this->button_ = button; - this->SetState(ClickState::Press); - } - }))); - - event_rovoker_guards_.push_back( - EventRevokerGuard(control->MouseUpEvent()->Direct()->AddHandler( - [this](event::MouseButtonEventArgs& args) { - const auto button = args.GetButton(); - if (this->enable_ && (button & this->trigger_button_) && - button == button_) { - if (this->state_ == ClickState::Press) { - this->SetState(ClickState::Hover); - this->event_.Raise(ClickEventArgs{this->control_, - this->down_point_, - args.GetPoint(), button}); - this->control_->ReleaseMouse(); - } else if (this->state_ == ClickState::PressInactive) { - this->SetState(ClickState::None); - this->control_->ReleaseMouse(); - } - } - }))); -} // namespace cru::ui - -void ClickDetector::SetEnabled(bool enable) { - if (enable == enable_) { - return; - } - - enable_ = enable; - if (enable) { - SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None); - } else { - if (state_ == ClickState::Press || state_ == ClickState::PressInactive) { - SetState(ClickState::None); - control_->ReleaseMouse(); - } else if (state_ == ClickState::Hover) { - SetState(ClickState::None); - } - } -} - -void ClickDetector::SetTriggerButton(MouseButton trigger_button) { - if (trigger_button == trigger_button_) { - return; - } - - trigger_button_ = trigger_button; - if ((state_ == ClickState::Press || state_ == ClickState::PressInactive) && - !(button_ & trigger_button)) { - SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None); - control_->ReleaseMouse(); - } -} - -void ClickDetector::SetState(ClickState state) { -#ifdef CRU_DEBUG - auto to_string = [](ClickState state) -> std::u16string_view { - switch (state) { - case ClickState::None: - return u"None"; - case ClickState::Hover: - return u"Hover"; - case ClickState::Press: - return u"Press"; - case ClickState::PressInactive: - return u"PressInvactive"; - default: - UnreachableCode(); - } - }; - log::TagDebug(log_tag, u"Click state changed, new state: {}.", - to_string(state)); -#endif - - state_ = state; - state_change_event_.Raise(state); -} -} // namespace cru::ui diff --git a/src/ui/ContentControl.cpp b/src/ui/ContentControl.cpp deleted file mode 100644 index 19b1b06f..00000000 --- a/src/ui/ContentControl.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "cru/ui/ContentControl.hpp" - -#include "cru/ui/Window.hpp" - -namespace cru::ui { -Control* ContentControl::GetChild() const { - if (GetChildren().empty()) return nullptr; - return GetChildren()[0]; -} - -void ContentControl::SetChild(Control* child) { - Control* old_child = nullptr; - if (!GetChildren().empty()) { - old_child = GetChildren()[0]; - this->RemoveChild(0); - } - if (child) { - this->AddChild(child, 0); - } - OnChildChanged(old_child, child); -} - -void ContentControl::OnChildChanged(Control* old_child, Control* new_child) { - CRU_UNUSED(old_child) - CRU_UNUSED(new_child) -} -} // namespace cru::ui diff --git a/src/ui/Control.cpp b/src/ui/Control.cpp deleted file mode 100644 index 23a3cef2..00000000 --- a/src/ui/Control.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "cru/ui/Control.hpp" - -#include "cru/common/Base.hpp" -#include "cru/platform/gui/Cursor.hpp" -#include "cru/platform/gui/UiApplication.hpp" -#include "cru/ui/Base.hpp" -#include "cru/ui/host/WindowHost.hpp" -#include "cru/ui/render/RenderObject.hpp" - -#include - -namespace cru::ui { -using platform::gui::ICursor; -using platform::gui::IUiApplication; -using platform::gui::SystemCursorType; - -Control::Control() { - MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) { - this->is_mouse_over_ = true; - this->OnMouseHoverChange(true); - }); - - MouseLeaveEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) { - this->is_mouse_over_ = false; - this->OnMouseHoverChange(true); - }); -} - -Control::~Control() { - for (const auto child : children_) delete child; -} - -host::WindowHost* Control::GetWindowHost() const { return window_host_; } - -void Control::TraverseDescendants( - const std::function& predicate) { - predicate(this); - for (auto c : GetChildren()) c->TraverseDescendants(predicate); -} - -bool Control::HasFocus() { - auto host = GetWindowHost(); - if (host == nullptr) return false; - - return host->GetFocusControl() == this; -} - -bool Control::CaptureMouse() { - auto host = GetWindowHost(); - if (host == nullptr) return false; - - return host->CaptureMouseFor(this); -} - -void Control::SetFocus() { - auto host = GetWindowHost(); - if (host == nullptr) return; - - host->SetFocusControl(this); -} - -bool Control::ReleaseMouse() { - auto host = GetWindowHost(); - if (host == nullptr) return false; - - return host->CaptureMouseFor(nullptr); -} - -bool Control::IsMouseCaptured() { - auto host = GetWindowHost(); - if (host == nullptr) return false; - - return host->GetMouseCaptureControl() == this; -} - -std::shared_ptr Control::GetCursor() { return cursor_; } - -std::shared_ptr Control::GetInheritedCursor() { - Control* control = this; - while (control != nullptr) { - const auto cursor = control->GetCursor(); - if (cursor != nullptr) return cursor; - control = control->GetParent(); - } - return IUiApplication::GetInstance()->GetCursorManager()->GetSystemCursor( - SystemCursorType::Arrow); -} - -void Control::SetCursor(std::shared_ptr cursor) { - cursor_ = std::move(cursor); - const auto host = GetWindowHost(); - if (host != nullptr) { - host->UpdateCursor(); - } -} - -void Control::AddChild(Control* control, const Index position) { - Expects(control->GetParent() == - nullptr); // The control already has a parent. - Expects(position >= 0); - Expects(position <= static_cast( - children_.size())); // The position is out of range. - - children_.insert(children_.cbegin() + position, control); - - const auto old_parent = control->parent_; - control->parent_ = this; - - OnAddChild(control, position); - control->OnParentChanged(old_parent, this); - - if (window_host_) - control->TraverseDescendants([this](Control* control) { - control->window_host_ = window_host_; - control->OnAttachToHost(window_host_); - }); -} - -void Control::RemoveChild(const Index position) { - Expects(position >= 0); - Expects(position < static_cast( - children_.size())); // The position is out of range. - - const auto i = children_.cbegin() + position; - const auto control = *i; - - children_.erase(i); - control->parent_ = nullptr; - - OnRemoveChild(control, position); - control->OnParentChanged(this, nullptr); - - if (window_host_) - control->TraverseDescendants([this](Control* control) { - control->window_host_ = nullptr; - control->OnDetachFromHost(window_host_); - }); -} - -void Control::OnAddChild(Control* child, Index position) { - CRU_UNUSED(child) - CRU_UNUSED(position) -} -void Control::OnRemoveChild(Control* child, Index position) { - CRU_UNUSED(child) - CRU_UNUSED(position) -} - -void Control::OnParentChanged(Control* old_parent, Control* new_parent) { - CRU_UNUSED(old_parent) - CRU_UNUSED(new_parent) -} - -void Control::OnAttachToHost(host::WindowHost* host) { CRU_UNUSED(host) } - -void Control::OnDetachFromHost(host::WindowHost* host) { CRU_UNUSED(host) } -} // namespace cru::ui diff --git a/src/ui/LayoutControl.cpp b/src/ui/LayoutControl.cpp deleted file mode 100644 index 351026f9..00000000 --- a/src/ui/LayoutControl.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "cru/ui/LayoutControl.hpp" - -#include "cru/ui/Window.hpp" - -namespace cru::ui { -} // namespace cru::ui diff --git a/src/ui/NoChildControl.cpp b/src/ui/NoChildControl.cpp deleted file mode 100644 index 8adbe3bc..00000000 --- a/src/ui/NoChildControl.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "cru/ui/NoChildControl.hpp" - -namespace cru::ui {} diff --git a/src/ui/ShortcutHub.cpp b/src/ui/ShortcutHub.cpp deleted file mode 100644 index c9ce6cdd..00000000 --- a/src/ui/ShortcutHub.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "cru/ui/ShortcutHub.hpp" - -#include "cru/common/Logger.hpp" -#include "cru/ui/Control.hpp" -#include "cru/ui/DebugFlags.hpp" - -#include -#include -#include -#include - -namespace cru::ui { -int ShortcutHub::RegisterShortcut(Shortcut shortcut) { - const int id = current_id_++; - map_[shortcut.key_bind].push_back({id, std::move(shortcut.name), - shortcut.key_bind, - std::move(shortcut.handler)}); - return id; -} - -void ShortcutHub::UnregisterShortcut(int id) { - if (id <= 0) return; - for (auto& pair : map_) { - auto& list = pair.second; - auto result = - std::find_if(list.cbegin(), list.cend(), - [id](const ShortcutInfo& info) { return info.id == id; }); - if (result != list.cend()) { - list.erase(result); - } - } -} - -std::vector ShortcutHub::GetAllShortcuts() const { - std::vector result; - - for (const auto& pair : map_) { - std::copy(pair.second.cbegin(), pair.second.cend(), - std::back_inserter(result)); - } - - return result; -} - -std::optional ShortcutHub::GetShortcut(int id) const { - for (auto& pair : map_) { - auto& list = pair.second; - auto result = - std::find_if(list.cbegin(), list.cend(), - [id](const ShortcutInfo& info) { return info.id == id; }); - if (result != list.cend()) { - return *result; - } - } - return std::nullopt; -} - -const std::vector& ShortcutHub::GetShortcutByKeyBind( - const ShortcutKeyBind& key_bind) const { - auto result = map_.find(key_bind); - if (result != map_.cend()) return result->second; - return empty_list_; -} - -void ShortcutHub::Install(Control* control) { - if (!event_guard_.IsEmpty()) { - log::Error(u"Shortcut hub is already installed. Failed to install."); - return; - } - - event_guard_ += control->KeyDownEvent()->Bubble()->AddHandler( - std::bind(&ShortcutHub::OnKeyDown, this, std::placeholders::_1)); -} - -void ShortcutHub::Uninstall() { - if (event_guard_.IsEmpty()) { - log::Warn(u"Shortcut hub is not installed. Failed to uninstall."); - return; - } - - event_guard_.Clear(); -} - -void ShortcutHub::OnKeyDown(event::KeyEventArgs& event) { - ShortcutKeyBind key_bind(event.GetKeyCode(), event.GetKeyModifier()); - const auto& shortcut_list = this->GetShortcutByKeyBind(key_bind); - - if constexpr (debug_flags::shortcut) { - if (shortcut_list.empty()) { - log::Debug(u"No shortcut for key bind {}.", key_bind.ToString()); - } - log::Debug(u"Begin to handle shortcut for key bind {}.", - key_bind.ToString()); - } - - for (const auto& shortcut : shortcut_list) { - auto is_handled = shortcut.handler(); - if (is_handled) { - if constexpr (debug_flags::shortcut) { - log::Debug(u"Handle {} handled it.", shortcut.name); - } - - event.SetHandled(); - - break; - } else { - if constexpr (debug_flags::shortcut) { - log::Debug(u"Handle {} disdn't handle it.", shortcut.name); - } - } - } - - if constexpr (debug_flags::shortcut) { - if (!shortcut_list.empty()) { - log::Debug(u"End handling shortcut for key bind {}.", - key_bind.ToString()); - } - } -} -} // namespace cru::ui diff --git a/src/ui/UiEvent.cpp b/src/ui/UiEvent.cpp deleted file mode 100644 index 74dd54dc..00000000 --- a/src/ui/UiEvent.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "cru/ui/UiEvent.hpp" - -#include "cru/ui/render/RenderObject.hpp" - -namespace cru::ui::event { -Point MouseEventArgs::GetPointToContent( - render::RenderObject* render_object) const { - return render_object->FromRootToContent(GetPoint()); -} -} // namespace cru::ui::event diff --git a/src/ui/Window.cpp b/src/ui/Window.cpp deleted file mode 100644 index c49140a4..00000000 --- a/src/ui/Window.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "cru/ui/Window.hpp" - -#include "cru/common/Base.hpp" -#include "cru/ui/host/WindowHost.hpp" -#include "cru/ui/render/Base.hpp" -#include "cru/ui/render/StackLayoutRenderObject.hpp" - -namespace cru::ui { -Window* Window::CreateOverlapped() { return new Window(); } - -Window::Window() : render_object_(new render::StackLayoutRenderObject()) { - render_object_->SetAttachedControl(this); - window_host_ = std::make_unique(this); -} - -Window::~Window() {} - -std::u16string_view Window::GetControlType() const { return control_type; } - -render::RenderObject* Window::GetRenderObject() const { - return render_object_.get(); -} - -void Window::OnAddChild(Control* child, Index position) { - render_object_->AddChild(child->GetRenderObject(), position); -} - -void Window::OnRemoveChild(Control* child, Index position) { - CRU_UNUSED(child); - render_object_->RemoveChild(position); -} -} // namespace cru::ui diff --git a/src/ui/controls/Button.cpp b/src/ui/controls/Button.cpp index 5f7ed143..b7407ec2 100644 --- a/src/ui/controls/Button.cpp +++ b/src/ui/controls/Button.cpp @@ -5,9 +5,9 @@ #include "cru/platform/graphics/Brush.hpp" #include "cru/platform/gui/Cursor.hpp" #include "cru/platform/gui/UiApplication.hpp" -#include "cru/ui/render/BorderRenderObject.hpp" #include "cru/ui/UiManager.hpp" -#include "cru/ui/Window.hpp" +#include "cru/ui/helper/ClickDetector.hpp" +#include "cru/ui/render/BorderRenderObject.hpp" namespace cru::ui::controls { using cru::platform::gui::SystemCursorType; @@ -21,8 +21,7 @@ void Set(render::BorderRenderObject* o, const ButtonStateStyle& s) { o->SetBackgroundBrush(s.background_brush); } -std::shared_ptr GetSystemCursor( - SystemCursorType type) { +std::shared_ptr GetSystemCursor(SystemCursorType type) { return GetUiApplication()->GetCursorManager()->GetSystemCursor(type); } } // namespace @@ -36,21 +35,21 @@ Button::Button() : click_detector_(this) { render_object_->SetBorderEnabled(true); click_detector_.StateChangeEvent()->AddHandler( - [this](const ClickState& state) { + [this](const helper::ClickState& state) { switch (state) { - case ClickState::None: + case helper::ClickState::None: Set(render_object_.get(), style_.normal); SetCursor(GetSystemCursor(SystemCursorType::Arrow)); break; - case ClickState::Hover: + case helper::ClickState::Hover: Set(render_object_.get(), style_.hover); SetCursor(GetSystemCursor(SystemCursorType::Hand)); break; - case ClickState::Press: + case helper::ClickState::Press: Set(render_object_.get(), style_.press); SetCursor(GetSystemCursor(SystemCursorType::Hand)); break; - case ClickState::PressInactive: + case helper::ClickState::PressInactive: Set(render_object_.get(), style_.press_cancel); SetCursor(GetSystemCursor(SystemCursorType::Arrow)); break; diff --git a/src/ui/controls/ContentControl.cpp b/src/ui/controls/ContentControl.cpp new file mode 100644 index 00000000..653882c0 --- /dev/null +++ b/src/ui/controls/ContentControl.cpp @@ -0,0 +1,25 @@ +#include "cru/ui/controls/ContentControl.hpp" + +namespace cru::ui::controls { +Control* ContentControl::GetChild() const { + if (GetChildren().empty()) return nullptr; + return GetChildren()[0]; +} + +void ContentControl::SetChild(Control* child) { + Control* old_child = nullptr; + if (!GetChildren().empty()) { + old_child = GetChildren()[0]; + this->RemoveChild(0); + } + if (child) { + this->AddChild(child, 0); + } + OnChildChanged(old_child, child); +} + +void ContentControl::OnChildChanged(Control* old_child, Control* new_child) { + CRU_UNUSED(old_child) + CRU_UNUSED(new_child) +} +} // namespace cru::ui::controls diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp new file mode 100644 index 00000000..c1316a62 --- /dev/null +++ b/src/ui/controls/Control.cpp @@ -0,0 +1,157 @@ +#include "cru/ui/controls/Control.hpp" + +#include "cru/common/Base.hpp" +#include "cru/platform/gui/Cursor.hpp" +#include "cru/platform/gui/UiApplication.hpp" +#include "cru/ui/Base.hpp" +#include "cru/ui/host/WindowHost.hpp" +#include "cru/ui/render/RenderObject.hpp" + +#include + +namespace cru::ui::controls { +using platform::gui::ICursor; +using platform::gui::IUiApplication; +using platform::gui::SystemCursorType; + +Control::Control() { + MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) { + this->is_mouse_over_ = true; + this->OnMouseHoverChange(true); + }); + + MouseLeaveEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) { + this->is_mouse_over_ = false; + this->OnMouseHoverChange(true); + }); +} + +Control::~Control() { + for (const auto child : children_) delete child; +} + +host::WindowHost* Control::GetWindowHost() const { return window_host_; } + +void Control::TraverseDescendants( + const std::function& predicate) { + predicate(this); + for (auto c : GetChildren()) c->TraverseDescendants(predicate); +} + +bool Control::HasFocus() { + auto host = GetWindowHost(); + if (host == nullptr) return false; + + return host->GetFocusControl() == this; +} + +bool Control::CaptureMouse() { + auto host = GetWindowHost(); + if (host == nullptr) return false; + + return host->CaptureMouseFor(this); +} + +void Control::SetFocus() { + auto host = GetWindowHost(); + if (host == nullptr) return; + + host->SetFocusControl(this); +} + +bool Control::ReleaseMouse() { + auto host = GetWindowHost(); + if (host == nullptr) return false; + + return host->CaptureMouseFor(nullptr); +} + +bool Control::IsMouseCaptured() { + auto host = GetWindowHost(); + if (host == nullptr) return false; + + return host->GetMouseCaptureControl() == this; +} + +std::shared_ptr Control::GetCursor() { return cursor_; } + +std::shared_ptr Control::GetInheritedCursor() { + Control* control = this; + while (control != nullptr) { + const auto cursor = control->GetCursor(); + if (cursor != nullptr) return cursor; + control = control->GetParent(); + } + return IUiApplication::GetInstance()->GetCursorManager()->GetSystemCursor( + SystemCursorType::Arrow); +} + +void Control::SetCursor(std::shared_ptr cursor) { + cursor_ = std::move(cursor); + const auto host = GetWindowHost(); + if (host != nullptr) { + host->UpdateCursor(); + } +} + +void Control::AddChild(Control* control, const Index position) { + Expects(control->GetParent() == + nullptr); // The control already has a parent. + Expects(position >= 0); + Expects(position <= static_cast( + children_.size())); // The position is out of range. + + children_.insert(children_.cbegin() + position, control); + + const auto old_parent = control->parent_; + control->parent_ = this; + + OnAddChild(control, position); + control->OnParentChanged(old_parent, this); + + if (window_host_) + control->TraverseDescendants([this](Control* control) { + control->window_host_ = window_host_; + control->OnAttachToHost(window_host_); + }); +} + +void Control::RemoveChild(const Index position) { + Expects(position >= 0); + Expects(position < static_cast( + children_.size())); // The position is out of range. + + const auto i = children_.cbegin() + position; + const auto control = *i; + + children_.erase(i); + control->parent_ = nullptr; + + OnRemoveChild(control, position); + control->OnParentChanged(this, nullptr); + + if (window_host_) + control->TraverseDescendants([this](Control* control) { + control->window_host_ = nullptr; + control->OnDetachFromHost(window_host_); + }); +} + +void Control::OnAddChild(Control* child, Index position) { + CRU_UNUSED(child) + CRU_UNUSED(position) +} +void Control::OnRemoveChild(Control* child, Index position) { + CRU_UNUSED(child) + CRU_UNUSED(position) +} + +void Control::OnParentChanged(Control* old_parent, Control* new_parent) { + CRU_UNUSED(old_parent) + CRU_UNUSED(new_parent) +} + +void Control::OnAttachToHost(host::WindowHost* host) { CRU_UNUSED(host) } + +void Control::OnDetachFromHost(host::WindowHost* host) { CRU_UNUSED(host) } +} // namespace cru::ui::controls diff --git a/src/ui/controls/LayoutControl.cpp b/src/ui/controls/LayoutControl.cpp new file mode 100644 index 00000000..85417beb --- /dev/null +++ b/src/ui/controls/LayoutControl.cpp @@ -0,0 +1,3 @@ +#include "cru/ui/controls/LayoutControl.hpp" + +namespace cru::ui::controls {} diff --git a/src/ui/controls/NoChildControl.cpp b/src/ui/controls/NoChildControl.cpp new file mode 100644 index 00000000..c62c5819 --- /dev/null +++ b/src/ui/controls/NoChildControl.cpp @@ -0,0 +1,3 @@ +#include "cru/ui/controls/NoChildControl.hpp" + +namespace cru::ui::controls {} diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp index a7e4e440..8ad95dec 100644 --- a/src/ui/controls/TextControlService.hpp +++ b/src/ui/controls/TextControlService.hpp @@ -8,10 +8,10 @@ #include "cru/platform/gui/UiApplication.hpp" #include "cru/platform/gui/Window.hpp" #include "cru/ui/Base.hpp" -#include "cru/ui/Control.hpp" #include "cru/ui/DebugFlags.hpp" -#include "cru/ui/ShortcutHub.hpp" -#include "cru/ui/UiEvent.hpp" +#include "cru/ui/controls/Control.hpp" +#include "cru/ui/events/UiEvent.hpp" +#include "cru/ui/helper/ShortcutHub.hpp" #include "cru/ui/host/WindowHost.hpp" #include "cru/ui/render/CanvasRenderObject.hpp" #include "cru/ui/render/ScrollRenderObject.hpp" @@ -472,7 +472,7 @@ class TextControlService : public Object { platform::gui::TimerAutoCanceler caret_timer_canceler_; int caret_blink_duration_ = k_default_caret_blink_duration; - ShortcutHub shortcut_hub_; + helper::ShortcutHub shortcut_hub_; // nullopt means not selecting std::optional select_down_button_; diff --git a/src/ui/controls/Window.cpp b/src/ui/controls/Window.cpp new file mode 100644 index 00000000..7ce40dfe --- /dev/null +++ b/src/ui/controls/Window.cpp @@ -0,0 +1,32 @@ +#include "cru/ui/controls/Window.hpp" + +#include "cru/common/Base.hpp" +#include "cru/ui/host/WindowHost.hpp" +#include "cru/ui/render/Base.hpp" +#include "cru/ui/render/StackLayoutRenderObject.hpp" + +namespace cru::ui::controls { +Window* Window::CreateOverlapped() { return new Window(); } + +Window::Window() : render_object_(new render::StackLayoutRenderObject()) { + render_object_->SetAttachedControl(this); + window_host_ = std::make_unique(this); +} + +Window::~Window() {} + +std::u16string_view Window::GetControlType() const { return control_type; } + +render::RenderObject* Window::GetRenderObject() const { + return render_object_.get(); +} + +void Window::OnAddChild(Control* child, Index position) { + render_object_->AddChild(child->GetRenderObject(), position); +} + +void Window::OnRemoveChild(Control* child, Index position) { + CRU_UNUSED(child); + render_object_->RemoveChild(position); +} +} // namespace cru::ui::controls diff --git a/src/ui/events/UiEvent.cpp b/src/ui/events/UiEvent.cpp new file mode 100644 index 00000000..b35f15a7 --- /dev/null +++ b/src/ui/events/UiEvent.cpp @@ -0,0 +1,10 @@ +#include "cru/ui/events/UiEvent.hpp" + +#include "cru/ui/render/RenderObject.hpp" + +namespace cru::ui::event { +Point MouseEventArgs::GetPointToContent( + render::RenderObject* render_object) const { + return render_object->FromRootToContent(GetPoint()); +} +} // namespace cru::ui::event diff --git a/src/ui/helper/ClickDetector.cpp b/src/ui/helper/ClickDetector.cpp new file mode 100644 index 00000000..4059f890 --- /dev/null +++ b/src/ui/helper/ClickDetector.cpp @@ -0,0 +1,131 @@ +#include "cru/ui/helper/ClickDetector.hpp" + +#include "cru/common/Logger.hpp" + +#include + +namespace cru::ui::helper { +ClickDetector::ClickDetector(controls::Control* control) { + Expects(control); + control_ = control; + + event_rovoker_guards_.push_back( + EventRevokerGuard(control->MouseEnterEvent()->Direct()->AddHandler( + [this](event::MouseEventArgs&) { + if (this->enable_) { + if (this->state_ == ClickState::PressInactive) { + if ((this->button_ & this->trigger_button_)) { + this->SetState(ClickState::Press); + } + } else { + this->SetState(ClickState::Hover); + } + } + }))); + + event_rovoker_guards_.push_back( + EventRevokerGuard(control->MouseLeaveEvent()->Direct()->AddHandler( + [this](event::MouseEventArgs&) { + if (this->enable_) { + if (this->state_ == ClickState::Press) { + if ((this->button_ & this->trigger_button_)) { + this->SetState(ClickState::PressInactive); + } + } else { + this->SetState(ClickState::None); + } + } + }))); + + event_rovoker_guards_.push_back( + EventRevokerGuard(control->MouseDownEvent()->Direct()->AddHandler( + [this](event::MouseButtonEventArgs& args) { + const auto button = args.GetButton(); + if (this->enable_ && (button & this->trigger_button_) && + this->state_ == ClickState::Hover) { + if (!this->control_->CaptureMouse()) { + log::TagDebug(log_tag, + u"Failed to capture mouse when begin click."); + return; + } + this->down_point_ = args.GetPoint(); + this->button_ = button; + this->SetState(ClickState::Press); + } + }))); + + event_rovoker_guards_.push_back( + EventRevokerGuard(control->MouseUpEvent()->Direct()->AddHandler( + [this](event::MouseButtonEventArgs& args) { + const auto button = args.GetButton(); + if (this->enable_ && (button & this->trigger_button_) && + button == button_) { + if (this->state_ == ClickState::Press) { + this->SetState(ClickState::Hover); + this->event_.Raise(ClickEventArgs{this->control_, + this->down_point_, + args.GetPoint(), button}); + this->control_->ReleaseMouse(); + } else if (this->state_ == ClickState::PressInactive) { + this->SetState(ClickState::None); + this->control_->ReleaseMouse(); + } + } + }))); +} // namespace cru::ui + +void ClickDetector::SetEnabled(bool enable) { + if (enable == enable_) { + return; + } + + enable_ = enable; + if (enable) { + SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None); + } else { + if (state_ == ClickState::Press || state_ == ClickState::PressInactive) { + SetState(ClickState::None); + control_->ReleaseMouse(); + } else if (state_ == ClickState::Hover) { + SetState(ClickState::None); + } + } +} + +void ClickDetector::SetTriggerButton(MouseButton trigger_button) { + if (trigger_button == trigger_button_) { + return; + } + + trigger_button_ = trigger_button; + if ((state_ == ClickState::Press || state_ == ClickState::PressInactive) && + !(button_ & trigger_button)) { + SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None); + control_->ReleaseMouse(); + } +} + +void ClickDetector::SetState(ClickState state) { +#ifdef CRU_DEBUG + auto to_string = [](ClickState state) -> std::u16string_view { + switch (state) { + case ClickState::None: + return u"None"; + case ClickState::Hover: + return u"Hover"; + case ClickState::Press: + return u"Press"; + case ClickState::PressInactive: + return u"PressInvactive"; + default: + UnreachableCode(); + } + }; + log::TagDebug(log_tag, u"Click state changed, new state: {}.", + to_string(state)); +#endif + + state_ = state; + state_change_event_.Raise(state); +} +} // namespace cru::ui::helper diff --git a/src/ui/helper/ShortcutHub.cpp b/src/ui/helper/ShortcutHub.cpp new file mode 100644 index 00000000..823072f2 --- /dev/null +++ b/src/ui/helper/ShortcutHub.cpp @@ -0,0 +1,120 @@ +#include "cru/ui/helper/ShortcutHub.hpp" + +#include "cru/common/Logger.hpp" +#include "cru/ui/DebugFlags.hpp" +#include "cru/ui/controls/Control.hpp" + +#include +#include +#include +#include + +namespace cru::ui::helper { +int ShortcutHub::RegisterShortcut(Shortcut shortcut) { + const int id = current_id_++; + map_[shortcut.key_bind].push_back({id, std::move(shortcut.name), + shortcut.key_bind, + std::move(shortcut.handler)}); + return id; +} + +void ShortcutHub::UnregisterShortcut(int id) { + if (id <= 0) return; + for (auto& pair : map_) { + auto& list = pair.second; + auto result = + std::find_if(list.cbegin(), list.cend(), + [id](const ShortcutInfo& info) { return info.id == id; }); + if (result != list.cend()) { + list.erase(result); + } + } +} + +std::vector ShortcutHub::GetAllShortcuts() const { + std::vector result; + + for (const auto& pair : map_) { + std::copy(pair.second.cbegin(), pair.second.cend(), + std::back_inserter(result)); + } + + return result; +} + +std::optional ShortcutHub::GetShortcut(int id) const { + for (auto& pair : map_) { + auto& list = pair.second; + auto result = + std::find_if(list.cbegin(), list.cend(), + [id](const ShortcutInfo& info) { return info.id == id; }); + if (result != list.cend()) { + return *result; + } + } + return std::nullopt; +} + +const std::vector& ShortcutHub::GetShortcutByKeyBind( + const ShortcutKeyBind& key_bind) const { + auto result = map_.find(key_bind); + if (result != map_.cend()) return result->second; + return empty_list_; +} + +void ShortcutHub::Install(controls::Control* control) { + if (!event_guard_.IsEmpty()) { + log::Error(u"Shortcut hub is already installed. Failed to install."); + return; + } + + event_guard_ += control->KeyDownEvent()->Bubble()->AddHandler( + std::bind(&ShortcutHub::OnKeyDown, this, std::placeholders::_1)); +} + +void ShortcutHub::Uninstall() { + if (event_guard_.IsEmpty()) { + log::Warn(u"Shortcut hub is not installed. Failed to uninstall."); + return; + } + + event_guard_.Clear(); +} + +void ShortcutHub::OnKeyDown(event::KeyEventArgs& event) { + ShortcutKeyBind key_bind(event.GetKeyCode(), event.GetKeyModifier()); + const auto& shortcut_list = this->GetShortcutByKeyBind(key_bind); + + if constexpr (debug_flags::shortcut) { + if (shortcut_list.empty()) { + log::Debug(u"No shortcut for key bind {}.", key_bind.ToString()); + } + log::Debug(u"Begin to handle shortcut for key bind {}.", + key_bind.ToString()); + } + + for (const auto& shortcut : shortcut_list) { + auto is_handled = shortcut.handler(); + if (is_handled) { + if constexpr (debug_flags::shortcut) { + log::Debug(u"Handle {} handled it.", shortcut.name); + } + + event.SetHandled(); + + break; + } else { + if constexpr (debug_flags::shortcut) { + log::Debug(u"Handle {} disdn't handle it.", shortcut.name); + } + } + } + + if constexpr (debug_flags::shortcut) { + if (!shortcut_list.empty()) { + log::Debug(u"End handling shortcut for key bind {}.", + key_bind.ToString()); + } + } +} +} // namespace cru::ui::helper diff --git a/src/ui/host/RoutedEventDispatch.hpp b/src/ui/host/RoutedEventDispatch.hpp index de94a598..52507fc7 100644 --- a/src/ui/host/RoutedEventDispatch.hpp +++ b/src/ui/host/RoutedEventDispatch.hpp @@ -1,8 +1,7 @@ #pragma once -#include "cru/ui/Control.hpp" - #include "cru/common/Logger.hpp" #include "cru/ui/DebugFlags.hpp" +#include "cru/ui/controls/Control.hpp" #include @@ -21,10 +20,11 @@ namespace cru::ui { // "original_sender", which is unchanged. And "args" will be perfectly forwarded // as the rest arguments. template -void DispatchEvent(const std::u16string_view& event_name, - Control* const original_sender, - event::RoutedEvent* (Control::*event_ptr)(), - Control* const last_receiver, Args&&... args) { +void DispatchEvent( + const std::u16string_view& event_name, + controls::Control* const original_sender, + event::RoutedEvent* (controls::Control::*event_ptr)(), + controls::Control* const last_receiver, Args&&... args) { CRU_UNUSED(event_name) if (original_sender == last_receiver) { @@ -36,7 +36,7 @@ void DispatchEvent(const std::u16string_view& event_name, return; } - std::vector receive_list; + std::vector receive_list; auto parent = original_sender; while (parent != last_receiver) { diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp index e04fdf31..1702c4ed 100644 --- a/src/ui/host/WindowHost.cpp +++ b/src/ui/host/WindowHost.cpp @@ -8,7 +8,7 @@ #include "cru/platform/gui/UiApplication.hpp" #include "cru/platform/gui/Window.hpp" #include "cru/ui/DebugFlags.hpp" -#include "cru/ui/Window.hpp" +#include "cru/ui/controls/Window.hpp" #include "cru/ui/host/LayoutPaintCycler.hpp" #include "cru/ui/render/MeasureRequirement.hpp" #include "cru/ui/render/RenderObject.hpp" @@ -43,7 +43,7 @@ CRU_DEFINE_EVENT_NAME(KeyUp) } // namespace event_names namespace { -bool IsAncestor(Control* control, Control* ancestor) { +bool IsAncestor(controls::Control* control, controls::Control* ancestor) { while (control != nullptr) { if (control == ancestor) return true; control = control->GetParent(); @@ -52,8 +52,8 @@ bool IsAncestor(Control* control, Control* ancestor) { } // Ancestor at last. -std::vector GetAncestorList(Control* control) { - std::vector l; +std::vector GetAncestorList(controls::Control* control) { + std::vector l; while (control != nullptr) { l.push_back(control); control = control->GetParent(); @@ -61,7 +61,8 @@ std::vector GetAncestorList(Control* control) { return l; } -Control* FindLowestCommonAncestor(Control* left, Control* right) { +controls::Control* FindLowestCommonAncestor(controls::Control* left, + controls::Control* right) { if (left == nullptr || right == nullptr) return nullptr; auto&& left_list = GetAncestorList(left); @@ -102,13 +103,13 @@ inline void BindNativeEvent( } } // namespace -WindowHost::WindowHost(Control* root_control) +WindowHost::WindowHost(controls::Control* root_control) : root_control_(root_control), focus_control_(root_control) { const auto ui_application = IUiApplication::GetInstance(); auto native_window = ui_application->CreateWindow(nullptr); native_window_ = native_window; - root_control_->TraverseDescendants([this](Control* control) { + root_control_->TraverseDescendants([this](controls::Control* control) { control->window_host_ = this; control->OnAttachToHost(this); }); @@ -195,9 +196,9 @@ void WindowHost::Repaint() { painter->EndDraw(); } -Control* WindowHost::GetFocusControl() { return focus_control_; } +controls::Control* WindowHost::GetFocusControl() { return focus_control_; } -void WindowHost::SetFocusControl(Control* control) { +void WindowHost::SetFocusControl(controls::Control* control) { if (focus_control_ == control) return; if (control == nullptr) control = root_control_; @@ -206,13 +207,13 @@ void WindowHost::SetFocusControl(Control* control) { focus_control_ = control; DispatchEvent(event_names::LoseFocus, old_focus_control, - &Control::LoseFocusEvent, nullptr, false); + &controls::Control::LoseFocusEvent, nullptr, false); - DispatchEvent(event_names::GainFocus, control, &Control::GainFocusEvent, - nullptr, false); + DispatchEvent(event_names::GainFocus, control, + &controls::Control::GainFocusEvent, nullptr, false); } -bool WindowHost::CaptureMouseFor(Control* control) { +bool WindowHost::CaptureMouseFor(controls::Control* control) { if (!native_window_) return false; if (control == mouse_captured_control_) return true; @@ -240,7 +241,7 @@ bool WindowHost::CaptureMouseFor(Control* control) { return true; } -Control* WindowHost::GetMouseCaptureControl() { +controls::Control* WindowHost::GetMouseCaptureControl() { return mouse_captured_control_; } @@ -275,9 +276,9 @@ void WindowHost::OnNativeFocus(INativeWindow* window, focus == platform::gui::FocusChangeType::Gain ? DispatchEvent(event_names::GainFocus, focus_control_, - &Control::GainFocusEvent, nullptr, true) + &controls::Control::GainFocusEvent, nullptr, true) : DispatchEvent(event_names::LoseFocus, focus_control_, - &Control::LoseFocusEvent, nullptr, true); + &controls::Control::LoseFocusEvent, nullptr, true); } void WindowHost::OnNativeMouseEnterLeave( @@ -286,7 +287,7 @@ void WindowHost::OnNativeMouseEnterLeave( if (type == platform::gui::MouseEnterLeaveType::Leave) { DispatchEvent(event_names::MouseLeave, mouse_hover_control_, - &Control::MouseLeaveEvent, nullptr); + &controls::Control::MouseLeaveEvent, nullptr); mouse_hover_control_ = nullptr; } } @@ -306,13 +307,14 @@ void WindowHost::OnNativeMouseMove(INativeWindow* window, const Point& point) { mouse_captured_control_); bool a = IsAncestor(o, n); if (a) { - DispatchEvent(event_names::MouseLeave, o, &Control::MouseLeaveEvent, n); + DispatchEvent(event_names::MouseLeave, o, + &controls::Control::MouseLeaveEvent, n); } else { - DispatchEvent(event_names::MouseEnter, n, &Control::MouseEnterEvent, o, - point); + DispatchEvent(event_names::MouseEnter, n, + &controls::Control::MouseEnterEvent, o, point); } DispatchEvent(event_names::MouseMove, mouse_captured_control_, - &Control::MouseMoveEvent, nullptr, point); + &controls::Control::MouseMoveEvent, nullptr, point); UpdateCursor(); return; } @@ -320,7 +322,7 @@ void WindowHost::OnNativeMouseMove(INativeWindow* window, const Point& point) { DispatchMouseHoverControlChangeEvent( old_mouse_hover_control, new_mouse_hover_control, point, false, false); DispatchEvent(event_names::MouseMove, new_mouse_hover_control, - &Control::MouseMoveEvent, nullptr, point); + &controls::Control::MouseMoveEvent, nullptr, point); UpdateCursor(); } @@ -329,10 +331,11 @@ void WindowHost::OnNativeMouseDown( const platform::gui::NativeMouseButtonEventArgs& args) { CRU_UNUSED(window) - Control* control = + controls::Control* control = mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point); - DispatchEvent(event_names::MouseDown, control, &Control::MouseDownEvent, - nullptr, args.point, args.button, args.modifier); + DispatchEvent(event_names::MouseDown, control, + &controls::Control::MouseDownEvent, nullptr, args.point, + args.button, args.modifier); } void WindowHost::OnNativeMouseUp( @@ -340,44 +343,44 @@ void WindowHost::OnNativeMouseUp( const platform::gui::NativeMouseButtonEventArgs& args) { CRU_UNUSED(window) - Control* control = + controls::Control* control = mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point); - DispatchEvent(event_names::MouseUp, control, &Control::MouseUpEvent, nullptr, - args.point, args.button, args.modifier); + DispatchEvent(event_names::MouseUp, control, &controls::Control::MouseUpEvent, + nullptr, args.point, args.button, args.modifier); } void WindowHost::OnNativeKeyDown( INativeWindow* window, const platform::gui::NativeKeyEventArgs& args) { CRU_UNUSED(window) - DispatchEvent(event_names::KeyDown, focus_control_, &Control::KeyDownEvent, - nullptr, args.key, args.modifier); + DispatchEvent(event_names::KeyDown, focus_control_, + &controls::Control::KeyDownEvent, nullptr, args.key, + args.modifier); } void WindowHost::OnNativeKeyUp(INativeWindow* window, const platform::gui::NativeKeyEventArgs& args) { CRU_UNUSED(window) - DispatchEvent(event_names::KeyUp, focus_control_, &Control::KeyUpEvent, - nullptr, args.key, args.modifier); + DispatchEvent(event_names::KeyUp, focus_control_, + &controls::Control::KeyUpEvent, nullptr, args.key, + args.modifier); } -void WindowHost::DispatchMouseHoverControlChangeEvent(Control* old_control, - Control* new_control, - const Point& point, - bool no_leave, - bool no_enter) { +void WindowHost::DispatchMouseHoverControlChangeEvent( + controls::Control* old_control, controls::Control* new_control, + const Point& point, bool no_leave, bool no_enter) { if (new_control != old_control) // if the mouse-hover-on control changed { const auto lowest_common_ancestor = FindLowestCommonAncestor(old_control, new_control); if (!no_leave && old_control != nullptr) DispatchEvent(event_names::MouseLeave, old_control, - &Control::MouseLeaveEvent, + &controls::Control::MouseLeaveEvent, lowest_common_ancestor); // dispatch mouse leave event. if (!no_enter && new_control != nullptr) { DispatchEvent(event_names::MouseEnter, new_control, - &Control::MouseEnterEvent, lowest_common_ancestor, + &controls::Control::MouseEnterEvent, lowest_common_ancestor, point); // dispatch mouse enter event. } } @@ -391,7 +394,7 @@ void WindowHost::UpdateCursor() { } } -Control* WindowHost::HitTest(const Point& point) { +controls::Control* WindowHost::HitTest(const Point& point) { const auto render_object = root_render_object_->HitTest(point); if (render_object) { const auto control = render_object->GetAttachedControl(); diff --git a/src/win/gui/UiApplication.cpp b/src/win/gui/UiApplication.cpp index 5041a6c0..f4541dd0 100644 --- a/src/win/gui/UiApplication.cpp +++ b/src/win/gui/UiApplication.cpp @@ -36,8 +36,8 @@ WinUiApplication::WinUiApplication() { log::Logger::GetInstance()->AddSource( std::make_unique<::cru::platform::win::WinStdOutLoggerSource>()); - graph_factory_ = - std::make_unique(); + graph_factory_ = std::make_unique< + cru::platform::graphics::win::direct::DirectGraphFactory>(); god_window_ = std::make_unique(this); timer_manager_ = std::make_unique(god_window_.get()); @@ -99,13 +99,17 @@ std::vector WinUiApplication::GetAllWindow() { return result; } -INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent) { +INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent, + CreateWindowFlag flag) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = CheckPlatform(parent, GetPlatformId()); } return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), - WS_OVERLAPPEDWINDOW, p); + flag & CreateWindowFlags::NoCaptionAndBorder + ? WS_POPUP + : WS_OVERLAPPEDWINDOW, + p); } cru::platform::graphics::IGraphFactory* WinUiApplication::GetGraphFactory() { -- cgit v1.2.3