From fde24556042b76863bdec34dcc213cb7298f68f9 Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 28 Oct 2020 16:17:20 +0800 Subject: ... --- include/cru/platform/native/Keyboard.hpp | 5 ++ include/cru/ui/ShortcutHub.hpp | 12 +++ src/platform/native/CMakeLists.txt | 1 + src/platform/native/Keyboard.cpp | 142 +++++++++++++++++++++++++++++++ src/ui/ShortcutHub.cpp | 62 ++++++++++++++ 5 files changed, 222 insertions(+) create mode 100644 src/platform/native/Keyboard.cpp diff --git a/include/cru/platform/native/Keyboard.hpp b/include/cru/platform/native/Keyboard.hpp index 83c61bcc..8f53c5d6 100644 --- a/include/cru/platform/native/Keyboard.hpp +++ b/include/cru/platform/native/Keyboard.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include "cru/common/Bitmask.hpp" namespace cru::platform::native { @@ -117,4 +118,8 @@ struct KeyModifiers { static constexpr KeyModifier ctrl{0b10}; static constexpr KeyModifier alt{0b100}; }; + +std::u16string_view ToString(KeyCode key_code); +std::u16string ToString(KeyModifier key_modifier, + std::u16string_view separator = u"+"); } // namespace cru::platform::native diff --git a/include/cru/ui/ShortcutHub.hpp b/include/cru/ui/ShortcutHub.hpp index 7557b758..a1dfcb7d 100644 --- a/include/cru/ui/ShortcutHub.hpp +++ b/include/cru/ui/ShortcutHub.hpp @@ -4,6 +4,7 @@ #include "cru/common/Base.hpp" #include "cru/common/Event.hpp" #include "cru/platform/native/Keyboard.hpp" +#include "cru/ui/UiEvent.hpp" #include #include @@ -43,6 +44,14 @@ class ShortcutKeyBind { return !this->operator==(other); } + std::u16string ToString() { + std::u16string result = u"("; + result += platform::native::ToString(modifier_); + result += u")"; + result += platform::native::ToString(key_); + return result; + } + private: platform::native::KeyCode key_; platform::native::KeyModifier modifier_; @@ -94,6 +103,9 @@ class ShortcutHub : public Object { void Install(Control* control); void Uninstall(); + private: + void OnKeyDown(event::KeyEventArgs& event); + private: std::unordered_map> map_; diff --git a/src/platform/native/CMakeLists.txt b/src/platform/native/CMakeLists.txt index c68a0958..3fe4370a 100644 --- a/src/platform/native/CMakeLists.txt +++ b/src/platform/native/CMakeLists.txt @@ -1,5 +1,6 @@ set(CRU_PLATFORM_NATIVE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/native) add_library(cru_platform_native STATIC + Keyboard.cpp UiApplication.cpp ) target_sources(cru_platform_native PUBLIC diff --git a/src/platform/native/Keyboard.cpp b/src/platform/native/Keyboard.cpp new file mode 100644 index 00000000..dd0e8f23 --- /dev/null +++ b/src/platform/native/Keyboard.cpp @@ -0,0 +1,142 @@ +#include "cru/platform/native/Keyboard.hpp" + +#include +#include +#include + +namespace cru::platform::native { +constexpr std::array(KeyCode::NumPad9) + 1> + key_code_string_list{u"Unknown", + u"LeftButton", + u"MiddleButton", + u"RightButton", + u"Escape", + u"F1", + u"F2", + u"F3", + u"F4", + u"F5", + u"F6", + u"F7", + u"F8", + u"F9", + u"F10", + u"F11", + u"F12", + u"N0", + u"N1", + u"N2", + u"N3", + u"N4", + u"N5", + u"N6", + u"N7", + u"N8", + u"N9", + u"A", + u"B", + u"C", + u"D", + u"E", + u"F", + u"G", + u"H", + u"I", + u"J", + u"K", + u"L", + u"M", + u"N", + u"O", + u"P", + u"Q", + u"R", + u"S", + u"T", + u"U", + u"V", + u"W", + u"X", + u"Y", + u"Z", + u"GraveAccent", + u"Tab", + u"CapsLock", + u"LeftShift", + u"LeftCtrl", + u"LeftSuper", + u"LeftAlt", + u"Minus", + u"Equal", + u"Backspace", + u"LeftSquareBracket", + u"RightSquareBracket", + u"BackSlash", + u"Semicolon", + u"Quote", + u"Comma", + u"Period", + u"Slash", + u"RightShift", + u"RightCtrl", + u"RightSuper", + u"RightAlt", + u"Insert", + u"Delete", + u"Home", + u"End", + u"PageUp", + u"PageDown", + u"Up", + u"Left", + u"Down", + u"Right", + u"PrintScreen", + u"ScrollLock", + u"Pause", + u"NumPad0", + u"NumPad1", + u"NumPad2", + u"NumPad3", + u"NumPad4", + u"NumPad5", + u"NumPad6", + u"NumPad7", + u"NumPad8", + u"NumPad9"}; + +std::u16string_view ToString(KeyCode key_code) { + if (static_cast(key_code) < 0 || + static_cast(key_code) >= + static_cast(key_code_string_list.size())) + return u"UNKNOWN_KEYCODENAME"; + + return key_code_string_list[static_cast(key_code)]; +} + +std::u16string ToString(KeyModifier key_modifier, + std::u16string_view separator) { + std::vector list; + if (key_modifier & KeyModifiers::shift) { + list.push_back(u"Shift"); + } + + if (key_modifier & KeyModifiers::ctrl) { + list.push_back(u"Ctrl"); + } + + if (key_modifier & KeyModifiers::alt) { + list.push_back(u"Shift"); + } + + if (list.empty()) return u""; + std::u16string result = list.front(); + for (auto iter = list.cbegin() + 1; iter != list.cend(); ++iter) { + result += separator; + result += *iter; + } + + return result; +} +} // namespace cru::platform::native diff --git a/src/ui/ShortcutHub.cpp b/src/ui/ShortcutHub.cpp index e5847f8c..145cfa87 100644 --- a/src/ui/ShortcutHub.cpp +++ b/src/ui/ShortcutHub.cpp @@ -1,5 +1,11 @@ #include "cru/ui/ShortcutHub.hpp" + +#include "cru/common/Logger.hpp" +#include "cru/ui/Control.hpp" +#include "cru/ui/DebugFlags.hpp" + #include +#include #include #include @@ -55,4 +61,60 @@ const std::vector& ShortcutHub::GetShortcutByKeyBind( 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 -- cgit v1.2.3