198 const auto& io = ImGui::GetIO();
199 bool ctrl = io.KeyCtrl;
200 bool shift = io.KeyShift;
201 bool alt = io.KeyAlt;
205 if (ImGui::IsKeyPressed(ImGuiKey_Slash) && shift && !ctrl && !alt) {
210 }
else if (!ImGui::IsKeyPressed(ImGuiKey_Slash)) {
226 for (
const auto& [
id, shortcut] :
shortcuts_) {
227 if (!shortcut.enabled)
continue;
231 if (ImGui::IsKeyPressed(shortcut.key,
false)) {
232 if (shortcut.Matches(shortcut.key, ctrl, shift, alt)) {
233 if (shortcut.action) {
255 ImGuiIO& io = ImGui::GetIO();
256 ImGui::SetNextWindowPos(ImVec2(0, 0));
257 ImGui::SetNextWindowSize(io.DisplaySize);
258 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.7f));
259 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
260 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
262 ImGuiWindowFlags overlay_flags = ImGuiWindowFlags_NoTitleBar |
263 ImGuiWindowFlags_NoResize |
264 ImGuiWindowFlags_NoMove |
265 ImGuiWindowFlags_NoScrollbar |
266 ImGuiWindowFlags_NoSavedSettings |
267 ImGuiWindowFlags_NoBringToFrontOnFocus;
269 if (ImGui::Begin(
"##ShortcutOverlayBg",
nullptr, overlay_flags)) {
271 if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0)) {
272 ImVec2 mouse = ImGui::GetMousePos();
274 ImVec2((io.DisplaySize.x - 600) * 0.5f, (io.DisplaySize.y - 500) * 0.5f);
275 ImVec2 modal_size = ImVec2(600, 500);
277 if (mouse.x < modal_pos.x || mouse.x > modal_pos.x + modal_size.x ||
278 mouse.y < modal_pos.y || mouse.y > modal_pos.y + modal_size.y) {
284 ImGui::PopStyleVar(2);
285 ImGui::PopStyleColor();
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));
307 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f);
308 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 16));
309 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
311 ImGuiWindowFlags modal_flags = ImGuiWindowFlags_NoTitleBar |
312 ImGuiWindowFlags_NoResize |
313 ImGuiWindowFlags_NoMove |
314 ImGuiWindowFlags_NoCollapse |
315 ImGuiWindowFlags_NoSavedSettings;
317 if (ImGui::Begin(
"##ShortcutOverlay",
nullptr, modal_flags)) {
319 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
323 ImGui::SameLine(modal_width - 60);
324 if (ImGui::SmallButton(
"X##CloseOverlay")) {
327 if (ImGui::IsItemHovered()) {
328 ImGui::SetTooltip(
"Close (Escape)");
335 ImGui::SetNextItemWidth(modal_width - 40);
336 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
337 ImGui::InputTextWithHint(
"##ShortcutSearch",
"Search shortcuts...",
339 ImGui::PopStyleVar();
350 ImGui::BeginChild(
"##ShortcutList", ImVec2(0, -30),
false,
351 ImGuiWindowFlags_AlwaysVerticalScrollbar);
354 std::map<std::string, std::vector<const Shortcut*>> shortcuts_by_category;
355 std::string filter_lower;
357 filter_lower +=
static_cast<char>(std::tolower(c));
360 for (
const auto& [
id, shortcut] :
shortcuts_) {
362 if (!filter_lower.empty()) {
363 std::string desc_lower;
364 for (
char c : shortcut.description) {
365 desc_lower +=
static_cast<char>(std::tolower(c));
367 std::string cat_lower;
368 for (
char c : shortcut.category) {
369 cat_lower +=
static_cast<char>(std::tolower(c));
371 std::string key_lower;
372 for (
char c : shortcut.GetDisplayString()) {
373 key_lower +=
static_cast<char>(std::tolower(c));
376 if (desc_lower.find(filter_lower) == std::string::npos &&
377 cat_lower.find(filter_lower) == std::string::npos &&
378 key_lower.find(filter_lower) == std::string::npos) {
383 shortcuts_by_category[shortcut.category].push_back(&shortcut);
388 auto it = shortcuts_by_category.find(category);
389 if (it != shortcuts_by_category.end() && !it->second.empty()) {
395 for (
const auto& [category, shortcuts] : shortcuts_by_category) {
396 bool in_order =
false;
398 if (ordered == category) {
403 if (!in_order && !shortcuts.empty()) {
412 ImGui::TextDisabled(
"Press ? to toggle | Escape to close");
416 ImGui::PopStyleVar(3);
417 ImGui::PopStyleColor(2);
421 const std::string& category,
422 const std::vector<const Shortcut*>& shortcuts) {
427 ImGui::PushStyleColor(ImGuiCol_Header, header_bg);
428 ImGui::PushStyleColor(ImGuiCol_HeaderHovered,
429 ImVec4(header_bg.x + 0.05f,
431 header_bg.z + 0.05f, 1.0f));
433 bool is_open = ImGui::CollapsingHeader(
434 category.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
436 ImGui::PopStyleColor(2);
439 ImGui::Indent(10.0f);
442 if (ImGui::BeginTable(
"##ShortcutTable", 3,
443 ImGuiTableFlags_SizingStretchProp |
444 ImGuiTableFlags_RowBg)) {
445 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthFixed, 120.0f);
446 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch);
447 ImGui::TableSetupColumn(
"Context", ImGuiTableColumnFlags_WidthFixed, 80.0f);
449 for (
const auto* shortcut : shortcuts) {
456 ImGui::Unindent(10.0f);
464 ImGui::TableNextRow();
467 ImGui::TableNextColumn();
471 ImGui::PushStyleColor(ImGuiCol_Button,
472 is_active ? ImVec4(0.2f, 0.3f, 0.4f, 0.8f)
473 : ImVec4(0.15f, 0.15f, 0.15f, 0.6f));
474 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
475 is_active ? ImVec4(0.25f, 0.35f, 0.45f, 0.9f)
476 : ImVec4(0.2f, 0.2f, 0.2f, 0.7f));
477 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
478 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6, 2));
481 ImGui::SmallButton(display.c_str());
483 ImGui::PopStyleVar(2);
484 ImGui::PopStyleColor(2);
487 ImGui::TableNextColumn();
490 ImGui::TextColored(text_color,
"%s", shortcut.
description.c_str());
493 ImGui::TableNextColumn();
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)