13#include "imgui/imgui.h"
26 {ImGuiKey_Tab,
"Tab"},
27 {ImGuiKey_LeftArrow,
"Left"},
28 {ImGuiKey_RightArrow,
"Right"},
29 {ImGuiKey_UpArrow,
"Up"},
30 {ImGuiKey_DownArrow,
"Down"},
31 {ImGuiKey_PageUp,
"PageUp"},
32 {ImGuiKey_PageDown,
"PageDown"},
33 {ImGuiKey_Home,
"Home"},
34 {ImGuiKey_End,
"End"},
35 {ImGuiKey_Insert,
"Insert"},
36 {ImGuiKey_Delete,
"Delete"},
37 {ImGuiKey_Backspace,
"Backspace"},
38 {ImGuiKey_Space,
"Space"},
39 {ImGuiKey_Enter,
"Enter"},
40 {ImGuiKey_Escape,
"Escape"},
86 {ImGuiKey_F10,
"F10"},
87 {ImGuiKey_F11,
"F11"},
88 {ImGuiKey_F12,
"F12"},
89 {ImGuiKey_Minus,
"-"},
90 {ImGuiKey_Equal,
"="},
91 {ImGuiKey_LeftBracket,
"["},
92 {ImGuiKey_RightBracket,
"]"},
93 {ImGuiKey_Backslash,
"\\"},
94 {ImGuiKey_Semicolon,
";"},
95 {ImGuiKey_Apostrophe,
"'"},
96 {ImGuiKey_Comma,
","},
97 {ImGuiKey_Period,
"."},
98 {ImGuiKey_Slash,
"/"},
99 {ImGuiKey_GraveAccent,
"`"},
104 if (entry.key ==
key) {
138 if (pressed_key !=
key)
return false;
155 const std::string& description,
156 ImGuiKey key,
bool ctrl,
bool shift,
157 bool alt,
const std::string& category,
159 std::function<
void()> action) {
182 it->second.enabled = enabled;
189 return ImGui::GetIO().WantTextInput;
199 const auto& io = ImGui::GetIO();
200 bool ctrl = io.KeyCtrl;
201 bool shift = io.KeyShift;
202 bool alt = io.KeyAlt;
206 if (ImGui::IsKeyPressed(ImGuiKey_Slash) && shift && !ctrl && !alt) {
211 }
else if (!ImGui::IsKeyPressed(ImGuiKey_Slash)) {
227 for (
const auto& [
id, shortcut] :
shortcuts_) {
228 if (!shortcut.enabled)
continue;
232 if (ImGui::IsKeyPressed(shortcut.key,
false)) {
233 if (shortcut.Matches(shortcut.key, ctrl, shift, alt)) {
234 if (shortcut.action) {
254 ImGuiIO& io = ImGui::GetIO();
255 ImGui::SetNextWindowPos(ImVec2(0, 0));
256 ImGui::SetNextWindowSize(io.DisplaySize);
257 ImGuiWindowFlags overlay_flags = ImGuiWindowFlags_NoTitleBar |
258 ImGuiWindowFlags_NoResize |
259 ImGuiWindowFlags_NoMove |
260 ImGuiWindowFlags_NoScrollbar |
261 ImGuiWindowFlags_NoSavedSettings |
262 ImGuiWindowFlags_NoBringToFrontOnFocus;
266 "##ShortcutOverlayBg",
267 {.bg = ImVec4(0.0f, 0.0f, 0.0f, 0.7f),
268 .padding = ImVec2(0, 0),
269 .border_size = 0.0f},
270 nullptr, overlay_flags);
273 if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0)) {
274 ImVec2 mouse = ImGui::GetMousePos();
275 ImVec2 modal_pos = ImVec2((io.DisplaySize.x - 600) * 0.5f,
276 (io.DisplaySize.y - 500) * 0.5f);
277 ImVec2 modal_size = ImVec2(600, 500);
279 if (mouse.x < modal_pos.x || mouse.x > modal_pos.x + modal_size.x ||
280 mouse.y < modal_pos.y || mouse.y > modal_pos.y + modal_size.y) {
293 ImGuiIO& io = ImGui::GetIO();
296 float modal_width = 600.0f;
297 float modal_height = 500.0f;
298 ImVec2 modal_pos((io.DisplaySize.x - modal_width) * 0.5f,
299 (io.DisplaySize.y - modal_height) * 0.5f);
301 ImGui::SetNextWindowPos(modal_pos);
302 ImGui::SetNextWindowSize(ImVec2(modal_width, modal_height));
305 ImGuiWindowFlags modal_flags = ImGuiWindowFlags_NoTitleBar |
306 ImGuiWindowFlags_NoResize |
307 ImGuiWindowFlags_NoMove |
308 ImGuiWindowFlags_NoCollapse |
309 ImGuiWindowFlags_NoSavedSettings;
315 .padding = ImVec2(20, 16),
318 nullptr, modal_flags);
322 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
326 ImGui::SameLine(modal_width - 60);
327 if (ImGui::SmallButton(
"X##CloseOverlay")) {
330 if (ImGui::IsItemHovered()) {
331 ImGui::SetTooltip(
"Close (Escape)");
338 ImGui::SetNextItemWidth(modal_width - 40);
340 StyleVarGuard frame_rounding(ImGuiStyleVar_FrameRounding, 4.0f);
341 ImGui::InputTextWithHint(
"##ShortcutSearch",
"Search shortcuts...",
354 ImGui::BeginChild(
"##ShortcutList", ImVec2(0, -30),
false,
355 ImGuiWindowFlags_AlwaysVerticalScrollbar);
358 std::map<std::string, std::vector<const Shortcut*>> shortcuts_by_category;
359 std::string filter_lower;
361 filter_lower +=
static_cast<char>(std::tolower(c));
364 for (
const auto& [
id, shortcut] :
shortcuts_) {
366 if (!filter_lower.empty()) {
367 std::string desc_lower;
368 for (
char c : shortcut.description) {
369 desc_lower +=
static_cast<char>(std::tolower(c));
371 std::string cat_lower;
372 for (
char c : shortcut.category) {
373 cat_lower +=
static_cast<char>(std::tolower(c));
375 std::string key_lower;
376 for (
char c : shortcut.GetDisplayString()) {
377 key_lower +=
static_cast<char>(std::tolower(c));
380 if (desc_lower.find(filter_lower) == std::string::npos &&
381 cat_lower.find(filter_lower) == std::string::npos &&
382 key_lower.find(filter_lower) == std::string::npos) {
387 shortcuts_by_category[shortcut.category].push_back(&shortcut);
392 auto it = shortcuts_by_category.find(category);
393 if (it != shortcuts_by_category.end() && !it->second.empty()) {
399 for (
const auto& [category, shortcuts] : shortcuts_by_category) {
400 bool in_order =
false;
402 if (ordered == category) {
407 if (!in_order && !shortcuts.empty()) {
416 ImGui::TextDisabled(
"Press ? to toggle | Escape to close");
421 const std::string& category,
422 const std::vector<const Shortcut*>& shortcuts) {
428 {ImGuiCol_Header, header_bg},
429 {ImGuiCol_HeaderHovered,
430 ImVec4(header_bg.x + 0.05f, header_bg.y + 0.05f,
431 header_bg.z + 0.05f, 1.0f)},
434 bool is_open = ImGui::CollapsingHeader(
435 category.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
438 ImGui::Indent(10.0f);
441 if (ImGui::BeginTable(
"##ShortcutTable", 3,
442 ImGuiTableFlags_SizingStretchProp |
443 ImGuiTableFlags_RowBg)) {
444 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthFixed, 120.0f);
445 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch);
446 ImGui::TableSetupColumn(
"Context", ImGuiTableColumnFlags_WidthFixed, 80.0f);
448 for (
const auto* shortcut : shortcuts) {
455 ImGui::Unindent(10.0f);
463 ImGui::TableNextRow();
466 ImGui::TableNextColumn();
471 {ImGuiCol_Button, is_active ? ImVec4(0.2f, 0.3f, 0.4f, 0.8f)
472 : ImVec4(0.15f, 0.15f, 0.15f, 0.6f)},
473 {ImGuiCol_ButtonHovered, is_active ? ImVec4(0.25f, 0.35f, 0.45f, 0.9f)
474 : ImVec4(0.2f, 0.2f, 0.2f, 0.7f)},
477 {ImGuiStyleVar_FrameRounding, 4.0f},
478 {ImGuiStyleVar_FramePadding, ImVec2(6, 2)},
482 ImGui::SmallButton(display.c_str());
485 ImGui::TableNextColumn();
488 ImGui::TextColored(text_color,
"%s", shortcut.
description.c_str());
491 ImGui::TableNextColumn();
506 const std::string& category)
const {
507 std::vector<const Shortcut*> result;
508 for (
const auto& [
id, shortcut] :
shortcuts_) {
509 if (shortcut.category == category) {
510 result.push_back(&shortcut);
517 std::vector<const Shortcut*> result;
518 for (
const auto& [
id, shortcut] :
shortcuts_) {
520 result.push_back(&shortcut);
527 std::vector<std::string> result;
528 for (
const auto& [
id, shortcut] :
shortcuts_) {
530 for (
const auto& cat : result) {
531 if (cat == shortcut.category) {
537 result.push_back(shortcut.category);
544 std::function<
void()> open_callback,
545 std::function<
void()> save_callback,
546 std::function<
void()> save_as_callback,
547 std::function<
void()> close_callback,
548 std::function<
void()> undo_callback,
549 std::function<
void()> redo_callback,
550 std::function<
void()> copy_callback,
551 std::function<
void()> paste_callback,
552 std::function<
void()> cut_callback,
553 std::function<
void()> find_callback) {
568 if (save_as_callback) {
574 if (close_callback) {
604 if (paste_callback) {
732 if (editor_name ==
"Assembly" || editor_name ==
"Code")
Manages keyboard shortcuts and provides an overlay UI.
void SetShortcutEnabled(const std::string &id, bool enabled)
void UnregisterShortcut(const std::string &id)
std::vector< std::string > category_order_
std::vector< std::string > GetCategories() const
std::map< std::string, Shortcut > shortcuts_
void DrawShortcutRow(const Shortcut &shortcut)
bool toggle_key_was_pressed_
std::vector< const Shortcut * > GetContextShortcuts() const
static bool IsTextInputActive()
void DrawOverlayContent()
std::vector< const Shortcut * > GetShortcutsInCategory(const std::string &category) const
static KeyboardShortcuts & Get()
void DrawCategorySection(const std::string &category, const std::vector< const Shortcut * > &shortcuts)
void RegisterShortcut(const Shortcut &shortcut)
ShortcutContext current_context_
void RegisterDefaultShortcuts(std::function< void()> open_callback, std::function< void()> save_callback, std::function< void()> save_as_callback, std::function< void()> close_callback, std::function< void()> undo_callback, std::function< void()> redo_callback, std::function< void()> copy_callback, std::function< void()> paste_callback, std::function< void()> cut_callback, std::function< void()> find_callback)
bool IsShortcutActiveInContext(const Shortcut &shortcut) const
RAII guard for ImGui style colors.
RAII guard for ImGui style vars.
RAII compound guard for window-level style setup.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
const char * GetLocalKeyName(ImGuiKey key)
constexpr struct yaze::gui::anonymous_namespace{keyboard_shortcuts.cc}::@1 kLocalKeyNames[]
const char * GetCtrlDisplayName()
Get the display name for the primary modifier key.
ImVec4 ConvertColorToImVec4(const Color &color)
const char * ShortcutContextToString(ShortcutContext context)
Convert ShortcutContext to display string.
ShortcutContext EditorNameToContext(const std::string &editor_name)
Convert editor type name to ShortcutContext.
const char * GetKeyName(ImGuiKey key)
Get the ImGui key name as a string.
ShortcutContext
Defines the context in which a shortcut is active.
const char * GetAltDisplayName()
Get the display name for the secondary modifier key.
Represents a keyboard shortcut with its associated action.
std::string GetDisplayString() const
std::function< void()> action
bool Matches(ImGuiKey pressed_key, bool ctrl, bool shift, bool alt) const