1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include "cru/ui/helper/ShortcutHub.hpp"
#include "cru/common/Logger.hpp"
#include "cru/ui/DebugFlags.hpp"
#include "cru/ui/controls/Control.hpp"
#include <algorithm>
#include <functional>
#include <iterator>
#include <optional>
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<ShortcutInfo> ShortcutHub::GetAllShortcuts() const {
std::vector<ShortcutInfo> result;
for (const auto& pair : map_) {
std::copy(pair.second.cbegin(), pair.second.cend(),
std::back_inserter(result));
}
return result;
}
std::optional<ShortcutInfo> 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<ShortcutInfo>& 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
|