59 size_t session_id,
const std::string& active_category,
60 const std::vector<std::string>& all_categories,
61 const std::unordered_set<std::string>& active_editor_categories,
62 std::function<
bool()> has_rom) {
65 const ImGuiViewport* viewport = ImGui::GetMainViewport();
68 const float viewport_height =
69 std::max(0.0f, viewport->WorkSize.y - top_inset - safe_area.bottom);
72 constexpr ImGuiWindowFlags kExtraFlags =
73 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoFocusOnAppearing |
74 ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoBringToFrontOnFocus;
78 ImVec2(viewport->WorkPos.x, viewport->WorkPos.y + top_inset),
79 ImVec2(bar_width, viewport_height),
82 .padding = {0.0f, 8.0f},
83 .spacing = {0.0f, 8.0f},
91 "Global Search (Ctrl+Shift+F)",
false,
92 ImVec4(0, 0, 0, 0),
"activity_bar",
99 ImVec2 sep_p1 = ImGui::GetCursorScreenPos();
102 ImGui::GetWindowDrawList()->AddLine(
108 bool rom_loaded = has_rom ? has_rom() :
false;
111 for (
const auto& cat : all_categories) {
115 bool is_selected = (cat == active_category);
117 bool has_active_editor = active_editor_categories.count(cat) > 0;
120 bool category_enabled =
121 rom_loaded || (cat ==
"Emulator") || (cat ==
"Agent");
125 ImVec4 cat_color(cat_theme.r, cat_theme.g, cat_theme.b, cat_theme.a);
126 ImVec4 glow_color(cat_theme.glow_r, cat_theme.glow_g, cat_theme.glow_b,
130 if (is_selected && category_enabled && panel_expanded) {
131 ImVec2 pos = ImGui::GetCursorScreenPos();
134 ImVec4 outer_glow = glow_color;
135 outer_glow.w = 0.15f;
136 ImGui::GetWindowDrawList()->AddRectFilled(
137 ImVec2(pos.x - 1.0f, pos.y - 1.0f),
138 ImVec2(pos.x + 49.0f, pos.y + 41.0f),
139 ImGui::ColorConvertFloat4ToU32(outer_glow), 4.0f);
142 ImVec4 highlight = glow_color;
144 ImGui::GetWindowDrawList()->AddRectFilled(
145 pos, ImVec2(pos.x + 48.0f, pos.y + 40.0f),
146 ImGui::ColorConvertFloat4ToU32(highlight), 2.0f);
149 ImGui::GetWindowDrawList()->AddRectFilled(
150 pos, ImVec2(pos.x + 4.0f, pos.y + 40.0f),
151 ImGui::ColorConvertFloat4ToU32(cat_color));
157 if (is_selected && category_enabled && !panel_expanded) {
158 ImVec2 pos = ImGui::GetCursorScreenPos();
159 ImVec4 highlight = glow_color;
161 ImGui::GetWindowDrawList()->AddRectFilled(
162 pos, ImVec2(pos.x + 48.0f, pos.y + 40.0f),
163 ImGui::ColorConvertFloat4ToU32(highlight), 2.0f);
164 ImVec4 accent = cat_color;
166 ImGui::GetWindowDrawList()->AddRectFilled(
167 pos, ImVec2(pos.x + 3.0f, pos.y + 40.0f),
168 ImGui::ColorConvertFloat4ToU32(accent));
172 ImVec4 icon_color = cat_color;
173 if (!category_enabled) {
174 ImGui::BeginDisabled();
177 nullptr, is_selected, icon_color,
178 "activity_bar", cat.c_str())) {
179 if (category_enabled) {
180 if (cat == active_category && panel_expanded) {
190 if (!category_enabled) {
191 ImGui::EndDisabled();
195 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
196 ImGui::BeginTooltip();
197 ImGui::Text(
"%s %s", icon.c_str(), cat.c_str());
198 if (!category_enabled) {
201 }
else if (has_active_editor) {
213 ImGui::SetCursorPosY(viewport_height - 48.0f);
216 nullptr,
false, ImVec4(0, 0, 0, 0),
217 "activity_bar",
"more_actions")) {
218 ImGui::OpenPopup(
"ActivityBarMoreMenu");
221 if (ImGui::BeginPopup(
"ActivityBarMoreMenu")) {
236 if (ImGui::MenuItem(
"Reset Layout")) {
245 std::function<
bool()> has_rom) {
248 const ImGuiViewport* viewport = ImGui::GetMainViewport();
250 const float panel_width =
255 const float panel_height =
256 std::max(0.0f, viewport->WorkSize.y - top_inset - safe_area.bottom);
260 ImVec2(viewport->WorkPos.x + bar_width, viewport->WorkPos.y + top_inset),
261 ImVec2(panel_width, panel_height),
263 .padding = {8.0f, 8.0f},
266 ImGuiWindowFlags_NoFocusOnAppearing);
270 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
271 ImGui::Text(
"%s", category.c_str());
275 float avail_width = ImGui::GetContentRegionAvail().x;
277 ImGui::SameLine(ImGui::GetCursorPosX() + avail_width - chrome_icon_size.x);
279 "Collapse Panel",
false, ImVec4(0, 0, 0, 0),
280 "activity_bar",
"collapse_side_panel")) {
288 static char sidebar_search[256] =
"";
290 const float standard_spacing =
292 const float compact_spacing = std::max(4.0f, standard_spacing * 0.75f);
293 const float search_spacing = compact_spacing;
294 const float search_width =
295 std::max(140.0f, ImGui::GetContentRegionAvail().x -
296 search_button_size.x - search_spacing);
297 ImGui::SetNextItemWidth(search_width);
298 ImGui::InputTextWithHint(
"##SidebarSearch",
ICON_MD_SEARCH " Filter...",
299 sidebar_search,
sizeof(sidebar_search));
300 ImGui::SameLine(0.0f, search_spacing);
301 const bool filter_empty = sidebar_search[0] ==
'\0';
303 ImGui::BeginDisabled();
306 "Clear filter",
false,
308 "clear_sidebar_filter")) {
309 sidebar_search[0] =
'\0';
312 ImGui::EndDisabled();
315 const auto is_dungeon_panel_mode_card =
316 [](
const std::string& panel_id) ->
bool {
317 const bool is_room_window = panel_id.rfind(
"dungeon.room_", 0) == 0;
318 return panel_id ==
"dungeon.room_selector" ||
319 panel_id ==
"dungeon.room_matrix" || is_room_window;
321 auto read_dungeon_workbench_mode = [&]() ->
bool {
322 if (category !=
"Dungeon") {
330 bool dungeon_workbench_mode = read_dungeon_workbench_mode();
332 auto switch_to_dungeon_workbench_mode = [&]() ->
bool {
333 if (category !=
"Dungeon") {
336 if (dungeon_workbench_mode) {
342 dungeon_workbench_mode =
true;
346 for (
const auto& descriptor :
348 const std::string& panel_id = descriptor.card_id;
349 if (panel_id ==
"dungeon.workbench") {
355 if (is_dungeon_panel_mode_card(panel_id)) {
359 dungeon_workbench_mode = read_dungeon_workbench_mode();
360 return dungeon_workbench_mode;
363 auto switch_to_dungeon_panel_mode = [&]() ->
bool {
364 if (category !=
"Dungeon") {
367 if (!dungeon_workbench_mode) {
373 dungeon_workbench_mode =
false;
379 dungeon_workbench_mode = read_dungeon_workbench_mode();
380 return !dungeon_workbench_mode;
383 auto ensure_dungeon_panel_mode_for_card =
384 [&](
const std::string& panel_id) ->
bool {
385 if (category !=
"Dungeon" || !dungeon_workbench_mode ||
386 !is_dungeon_panel_mode_card(panel_id)) {
389 return switch_to_dungeon_panel_mode();
392 if (category ==
"Dungeon") {
397 const float workflow_gap = compact_spacing;
398 const float workflow_min_button_width = 96.0f;
399 const float workflow_available_width =
400 std::max(1.0f, ImGui::GetContentRegionAvail().x);
401 const bool stack_workflow_buttons =
402 workflow_available_width <=
403 (workflow_min_button_width * 2.0f + workflow_gap);
404 const float workflow_button_width =
405 stack_workflow_buttons
406 ? workflow_available_width
407 : std::max(workflow_min_button_width,
408 (workflow_available_width - workflow_gap) * 0.5f);
409 const float workflow_button_height =
411 auto draw_workflow_button =
412 [&](
const char* id,
const char* icon,
const char* label,
bool active,
413 const char* tooltip,
const ImVec2& button_size) ->
bool {
418 {{ImGuiCol_Button, active ? active_bg : inactive_bg},
419 {ImGuiCol_ButtonHovered, active ? active_bg : inactive_hover},
420 {ImGuiCol_ButtonActive, active ? active_bg : inactive_hover}});
421 const std::string button_label =
422 absl::StrFormat(
"%s %s##%s", icon, label,
id);
423 const bool clicked = ImGui::Button(button_label.c_str(), button_size);
424 if (ImGui::IsItemHovered() && tooltip && *tooltip) {
425 ImGui::SetTooltip(
"%s", tooltip);
429 const ImVec2 workflow_button_size(workflow_button_width,
430 workflow_button_height);
432 if (draw_workflow_button(
434 dungeon_workbench_mode,
435 "Workbench mode: integrated room browser + inspector",
436 workflow_button_size)) {
437 switch_to_dungeon_workbench_mode();
439 if (!stack_workflow_buttons) {
440 ImGui::SameLine(0.0f, workflow_gap);
442 if (draw_workflow_button(
444 !dungeon_workbench_mode,
445 "Panel mode: standalone Room List + Room Matrix + room windows",
446 workflow_button_size)) {
447 switch_to_dungeon_panel_mode();
457 const bool rom_loaded = has_rom ? has_rom() :
true;
458 const bool disable_cards = !rom_loaded && category !=
"Emulator";
460 const auto category_cards =
462 int visible_cards_in_category = 0;
463 for (
const auto& category_card : category_cards) {
464 if (category_card.visibility_flag && *category_card.visibility_flag) {
465 ++visible_cards_in_category;
469 ImGui::TextDisabled(
"%d / %d visible", visible_cards_in_category,
470 static_cast<int>(category_cards.size()));
473 const float action_gap = compact_spacing;
474 const float action_min_button_width = 84.0f;
475 const float action_available_width =
476 std::max(1.0f, ImGui::GetContentRegionAvail().x);
477 const bool stack_action_buttons =
478 action_available_width <=
479 (action_min_button_width * 3.0f + (action_gap * 2.0f));
480 const float action_button_width =
482 ? action_available_width
483 : std::max(action_min_button_width,
484 (action_available_width - (action_gap * 2.0f)) / 3.0f);
485 const float action_button_height =
487 auto draw_action_button = [&](
const char* id,
const char* icon,
488 const char* label,
const char* tooltip,
489 const ImVec2& button_size) ->
bool {
490 const std::string button_label =
491 absl::StrFormat(
"%s %s##%s", icon, label,
id);
492 const bool clicked = ImGui::Button(button_label.c_str(), button_size);
493 if (ImGui::IsItemHovered() && tooltip && *tooltip) {
494 ImGui::SetTooltip(
"%s", tooltip);
498 const ImVec2 action_button_size(action_button_width, action_button_height);
500 if (draw_action_button(
"open_panel_browser",
ICON_MD_APPS,
"Browser",
501 "Open Panel Browser", action_button_size)) {
504 if (!stack_action_buttons) {
505 ImGui::SameLine(0.0f, action_gap);
508 const bool bulk_actions_enabled =
509 !disable_cards && !(category ==
"Dungeon" && dungeon_workbench_mode);
510 bool bulk_action_hovered =
false;
511 if (!bulk_actions_enabled) {
512 ImGui::BeginDisabled();
515 "Show all panels in this category",
516 action_button_size)) {
519 if (!stack_action_buttons) {
520 ImGui::SameLine(0.0f, action_gap);
522 if (!bulk_actions_enabled &&
523 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
524 bulk_action_hovered =
true;
527 "Hide",
"Hide all panels in this category",
528 action_button_size)) {
531 if (!bulk_actions_enabled) {
532 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
533 bulk_action_hovered =
true;
535 if (bulk_action_hovered && category ==
"Dungeon" &&
536 dungeon_workbench_mode) {
538 "Switch to Panel workflow to bulk-manage room panels.");
540 ImGui::EndDisabled();
547 " Open a ROM to enable this category");
552 ImGui::BeginDisabled();
557 const ImVec4 disabled_text =
558 ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
559 auto panel_text_color = [&](
bool visible) -> ImVec4 {
561 return disabled_text;
565 const float pin_button_side =
567 const ImVec2 pin_button_size(pin_button_side, pin_button_side);
568 auto draw_pin_toggle_button = [&](
const std::string& widget_id,
569 bool pinned) ->
bool {
570 ImGui::PushID(widget_id.c_str());
576 pinned ?
"Unpin panel" :
"Pin panel", pinned, pin_col,
"activity_bar",
583 bool pinned_section_open =
false;
584 if (sidebar_search[0] ==
'\0' && !pinned_cards.empty()) {
585 bool has_pinned_in_category =
false;
586 for (
const auto& card_id : pinned_cards) {
589 if (card && card->category == category) {
590 has_pinned_in_category =
true;
595 if (has_pinned_in_category) {
596 pinned_section_open = ImGui::CollapsingHeader(
598 if (pinned_section_open) {
599 for (
const auto& card_id : pinned_cards) {
602 if (!card || card->category != category)
609 if (draw_pin_toggle_button(
"pin_" + card->card_id,
true)) {
613 ImGui::SameLine(0.0f, compact_spacing);
616 std::string label = absl::StrFormat(
"%s %s", card->icon.c_str(),
617 card->display_name.c_str());
619 (std::string(
"pinned_select_") + card->card_id).c_str());
622 panel_text_color(visible));
623 ImVec2 item_size(ImGui::GetContentRegionAvail().x,
625 if (ImGui::Selectable(label.c_str(), visible,
626 ImGuiSelectableFlags_None, item_size)) {
627 const bool switched_mode =
628 ensure_dungeon_panel_mode_for_card(card->card_id);
637 card->visibility_flag ? *card->visibility_flag :
false;
640 const std::string window_name =
642 if (!window_name.empty()) {
643 ImGui::SetWindowFocus(window_name.c_str());
663 false, ImGuiWindowFlags_None);
664 if (panel_content_open) {
665 for (
const auto& card : cards) {
667 if (sidebar_search[0] !=
'\0') {
668 std::string search_str = sidebar_search;
669 std::string card_name = card.display_name;
670 std::transform(search_str.begin(), search_str.end(),
671 search_str.begin(), ::tolower);
672 std::transform(card_name.begin(), card_name.end(), card_name.begin(),
674 if (card_name.find(search_str) == std::string::npos) {
681 if (pinned_section_open && is_pinned) {
685 bool visible = card.visibility_flag ? *card.visibility_flag :
false;
688 if (draw_pin_toggle_button(
"pin_" + card.card_id, is_pinned)) {
691 ImGui::SameLine(0.0f, compact_spacing);
694 std::string label = absl::StrFormat(
"%s %s", card.icon.c_str(),
695 card.display_name.c_str());
696 ImGui::PushID((std::string(
"panel_select_") + card.card_id).c_str());
699 panel_text_color(visible));
700 ImVec2 item_size(ImGui::GetContentRegionAvail().x, pin_button_size.y);
701 if (ImGui::Selectable(label.c_str(), visible,
702 ImGuiSelectableFlags_None, item_size)) {
703 const bool switched_mode =
704 ensure_dungeon_panel_mode_for_card(card.card_id);
713 card.visibility_flag ? *card.visibility_flag :
false;
717 const std::string window_name =
719 if (!window_name.empty()) {
720 ImGui::SetWindowFocus(window_name.c_str());
728 if (ImGui::IsItemHovered() && !card.shortcut_hint.empty()) {
729 ImGui::SetTooltip(
"%s", card.shortcut_hint.c_str());
736 ImGui::EndDisabled();
740 const float handle_width = 6.0f;
741 const ImVec2 panel_pos = ImGui::GetWindowPos();
742 const float panel_draw_height = ImGui::GetWindowHeight();
743 ImGui::SetCursorScreenPos(
744 ImVec2(panel_pos.x + panel_width - handle_width * 0.5f, panel_pos.y));
745 ImGui::InvisibleButton(
"##SidePanelResizeHandle",
746 ImVec2(handle_width, panel_draw_height));
747 const bool handle_hovered = ImGui::IsItemHovered();
748 const bool handle_active = ImGui::IsItemActive();
749 if (handle_hovered || handle_active) {
750 ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
752 if (handle_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
756 const float new_width = panel_width + ImGui::GetIO().MouseDelta.x;
764 handle_color.w = handle_active ? 0.95f : (handle_hovered ? 0.72f : 0.35f);
765 ImGui::GetWindowDrawList()->AddLine(
766 ImVec2(panel_pos.x + panel_width - 1.0f, panel_pos.y),
767 ImVec2(panel_pos.x + panel_width - 1.0f,
768 panel_pos.y + panel_draw_height),
769 ImGui::GetColorU32(handle_color), handle_active ? 2.0f : 1.0f);
775 const ImGuiViewport* viewport = ImGui::GetMainViewport();
776 ImVec2 max_window_size(1600.0f, 1000.0f);
777 ImVec2 default_window_size(1080.0f, 700.0f);
779 max_window_size = ImVec2(std::max(760.0f, viewport->WorkSize.x * 0.95f),
780 std::max(520.0f, viewport->WorkSize.y * 0.95f));
781 default_window_size = ImVec2(
782 std::clamp(viewport->WorkSize.x * 0.72f, 880.0f, max_window_size.x),
783 std::clamp(viewport->WorkSize.y * 0.76f, 600.0f, max_window_size.y));
784 const ImVec2 center(viewport->WorkPos.x + viewport->WorkSize.x * 0.5f,
785 viewport->WorkPos.y + viewport->WorkSize.y * 0.5f);
786 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
789 ImGui::SetNextWindowSize(default_window_size, ImGuiCond_Appearing);
790 ImGui::SetNextWindowSizeConstraints(ImVec2(780, 520), max_window_size);
794 p_open, ImGuiWindowFlags_NoDocking)) {
795 static char search_filter[256] =
"";
796 static std::string category_filter =
"All";
798 std::vector<std::string> categories =
800 std::sort(categories.begin(), categories.end());
801 if (category_filter !=
"All" &&
802 std::find(categories.begin(), categories.end(), category_filter) ==
804 category_filter =
"All";
808 auto count_cards = [&](
const std::string& category,
809 bool visible_only) ->
int {
811 for (
const auto& card_id : all_cards) {
817 if (category !=
"All" && card->category != category) {
821 if (!visible_only || visible) {
828 ImGui::SetNextItemWidth(
829 std::max(280.0f, ImGui::GetContentRegionAvail().x * 0.45f));
830 ImGui::InputTextWithHint(
833 search_filter,
sizeof(search_filter));
836 search_filter[0] =
'\0';
839 if (category_filter ==
"All") {
859 const float content_height = ImGui::GetContentRegionAvail().y;
860 const float max_sidebar_width =
861 std::max(220.0f, ImGui::GetContentRegionAvail().x * 0.50f);
862 float category_sidebar_width =
866 if (ImGui::BeginChild(
"##PanelBrowserCategories",
867 ImVec2(category_sidebar_width, content_height),
869 const int visible_total = count_cards(
"All",
true);
870 std::string all_label =
872 visible_total,
static_cast<int>(all_cards.size()));
873 if (ImGui::Selectable(all_label.c_str(), category_filter ==
"All")) {
874 category_filter =
"All";
878 for (
const auto& cat : categories) {
879 const int category_total = count_cards(cat,
false);
880 if (category_total <= 0) {
883 const int visible_in_category = count_cards(cat,
true);
886 absl::StrFormat(
"%s %s (%d/%d)", icon.c_str(), cat.c_str(),
887 visible_in_category, category_total);
888 if (ImGui::Selectable(label.c_str(), category_filter == cat)) {
889 category_filter = cat;
895 ImGui::SameLine(0.0f, 0.0f);
897 const float splitter_width = 6.0f;
898 const ImVec2 splitter_pos = ImGui::GetCursorScreenPos();
899 ImGui::InvisibleButton(
"##PanelBrowserSplitter",
900 ImVec2(splitter_width, content_height));
901 const bool splitter_hovered = ImGui::IsItemHovered();
902 const bool splitter_active = ImGui::IsItemActive();
903 if (splitter_hovered || splitter_active) {
904 ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
906 if (splitter_hovered &&
907 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
910 category_sidebar_width =
914 if (splitter_active) {
915 category_sidebar_width =
916 std::clamp(category_sidebar_width + ImGui::GetIO().MouseDelta.x,
917 220.0f, max_sidebar_width);
919 ImGui::SetTooltip(
"Width: %.0f px", category_sidebar_width);
924 splitter_active ? 0.95f : (splitter_hovered ? 0.72f : 0.35f);
925 ImGui::GetWindowDrawList()->AddLine(
926 ImVec2(splitter_pos.x + splitter_width * 0.5f, splitter_pos.y),
927 ImVec2(splitter_pos.x + splitter_width * 0.5f,
928 splitter_pos.y + content_height),
929 ImGui::GetColorU32(splitter_color), splitter_active ? 2.0f : 1.0f);
931 ImGui::SameLine(0.0f, 0.0f);
933 if (ImGui::BeginChild(
"##PanelBrowserTable", ImVec2(0, content_height),
935 if (ImGui::BeginTable(
"##PanelTable", 5,
936 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
937 ImGuiTableFlags_Borders |
938 ImGuiTableFlags_Resizable)) {
939 ImGui::TableSetupColumn(
"Visible", ImGuiTableColumnFlags_WidthFixed,
941 ImGui::TableSetupColumn(
"Pin", ImGuiTableColumnFlags_WidthFixed, 36);
942 ImGui::TableSetupColumn(
"Name", ImGuiTableColumnFlags_WidthStretch);
943 ImGui::TableSetupColumn(
"Category", ImGuiTableColumnFlags_WidthFixed,
945 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthFixed,
947 ImGui::TableHeadersRow();
950 (category_filter ==
"All") ? all_cards : std::vector<std::string>{};
951 if (category_filter !=
"All") {
952 auto category_cards =
954 cards.reserve(category_cards.size());
955 for (
const auto& card : category_cards) {
956 cards.push_back(card.card_id);
960 for (
const auto& card_id : cards) {
967 std::string search_str = search_filter;
968 if (!search_str.empty()) {
970 std::transform(card_lower.begin(), card_lower.end(),
971 card_lower.begin(), [](
unsigned char c) {
972 return static_cast<char>(std::tolower(c));
974 std::transform(search_str.begin(), search_str.end(),
975 search_str.begin(), [](
unsigned char c) {
976 return static_cast<char>(std::tolower(c));
978 if (card_lower.find(search_str) == std::string::npos) {
983 ImGui::TableNextRow();
985 ImGui::TableNextColumn();
986 if (card->visibility_flag) {
987 bool visible = *card->visibility_flag;
989 absl::StrFormat(
"##vis_%s", card->card_id.c_str()).c_str(),
995 ImGui::TableNextColumn();
997 const ImVec4 pin_color =
999 const float pin_side =
1002 absl::StrFormat(
"browser_pin_%s", card->card_id).c_str());
1005 ImVec2(pin_side, pin_side),
1006 is_pinned ?
"Unpin panel" :
"Pin panel", is_pinned, pin_color,
1007 "panel_browser", card->card_id.c_str())) {
1013 ImGui::TableNextColumn();
1014 ImGui::Text(
"%s %s", card->icon.c_str(), card->display_name.c_str());
1015 if (ImGui::IsItemHovered() &&
1016 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
1018 const std::string window_name =
1020 if (!window_name.empty()) {
1021 ImGui::SetWindowFocus(window_name.c_str());
1025 ImGui::TableNextColumn();
1026 ImGui::TextUnformatted(card->category.c_str());
1028 ImGui::TableNextColumn();
1029 if (card->shortcut_hint.empty()) {
1030 ImGui::TextDisabled(
"-");
1032 ImGui::TextDisabled(
"%s", card->shortcut_hint.c_str());