464 const std::string& category,
465 const std::vector<std::string>& active_categories,
466 std::function<
void(
const std::string&)> on_category_switch,
467 std::function<
void()> on_collapse) {
474 ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetFrameHeight()));
475 ImGui::SetNextWindowSize(ImVec2(sidebar_width, -1));
477 ImGuiWindowFlags sidebar_flags =
478 ImGuiWindowFlags_NoTitleBar |
479 ImGuiWindowFlags_NoResize |
480 ImGuiWindowFlags_NoMove |
481 ImGuiWindowFlags_NoCollapse |
482 ImGuiWindowFlags_NoDocking |
483 ImGuiWindowFlags_NoScrollbar |
484 ImGuiWindowFlags_NoScrollWithMouse |
485 ImGuiWindowFlags_NoFocusOnAppearing |
486 ImGuiWindowFlags_NoNavFocus;
489 ImVec4 sidebar_bg = ImVec4(0.18f, 0.18f, 0.20f, 1.0f);
490 ImVec4 sidebar_border = ImVec4(0.4f, 0.4f, 0.45f, 1.0f);
492 ImGui::PushStyleColor(ImGuiCol_WindowBg, sidebar_bg);
493 ImGui::PushStyleColor(ImGuiCol_Border, sidebar_border);
494 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4.0f, 8.0f));
495 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 6.0f));
496 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 2.0f);
498 if (ImGui::Begin(
"##EditorCardSidebar",
nullptr, sidebar_flags)) {
500 if (active_categories.size() > 1) {
504 for (
const auto& cat : active_categories) {
505 bool is_current = (cat == category);
509 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(accent.x, accent.y, accent.z, 0.8f));
510 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(accent.x, accent.y, accent.z, 1.0f));
512 ImGui::PushStyleColor(ImGuiCol_Button, inactive);
517 std::string btn_label = cat.empty() ?
"?" : std::string(1, cat[0]);
518 if (ImGui::Button(btn_label.c_str(), ImVec2(40.0f, 32.0f))) {
520 if (on_category_switch) {
521 on_category_switch(cat);
527 ImGui::PopStyleColor(2);
529 if (ImGui::IsItemHovered()) {
530 ImGui::SetTooltip(
"%s Editor\nClick to switch", cat.c_str());
534 ImGui::Dummy(ImVec2(0, 2.0f));
543 if (!cards.empty()) {
548 if (!cards.empty()) {
550 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(
551 error_color.x * 0.6f, error_color.y * 0.6f, error_color.z * 0.6f, 0.9f));
552 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, error_color);
553 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(
554 error_color.x * 1.2f, error_color.y * 1.2f, error_color.z * 1.2f, 1.0f));
560 ImGui::PopStyleColor(3);
562 if (ImGui::IsItemHovered()) {
563 ImGui::SetTooltip(
"Close All %s Cards", category.c_str());
568 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(
569 success_color.x * 0.6f, success_color.y * 0.6f, success_color.z * 0.6f, 0.7f));
570 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, success_color);
571 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(
572 success_color.x * 1.2f, success_color.y * 1.2f, success_color.z * 1.2f, 1.0f));
578 ImGui::PopStyleColor(3);
580 if (ImGui::IsItemHovered()) {
581 ImGui::SetTooltip(
"Show All %s Cards", category.c_str());
584 ImGui::Dummy(ImVec2(0, 2.0f));
590 for (
const auto& card : cards) {
591 ImGui::PushID(card.card_id.c_str());
593 bool is_active = card.visibility_flag && *card.visibility_flag;
597 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(
598 accent_color.x, accent_color.y, accent_color.z, 0.5f));
599 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(
600 accent_color.x, accent_color.y, accent_color.z, 0.7f));
601 ImGui::PushStyleColor(ImGuiCol_ButtonActive, accent_color);
603 ImGui::PushStyleColor(ImGuiCol_Button, button_bg);
609 if (ImGui::Button(card.icon.c_str(), ImVec2(40.0f, 40.0f))) {
614 ImGui::PopStyleColor(3);
617 if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
620 ImGui::SetTooltip(
"%s\n%s", card.display_name.c_str(),
621 card.shortcut_hint.empty() ?
"" : card.shortcut_hint.c_str());
630 ImGui::Dummy(ImVec2(0, 10.0f));
635 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.2f, 0.22f, 0.9f));
636 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.3f, 0.32f, 1.0f));
637 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.25f, 0.25f, 0.27f, 1.0f));
643 ImGui::PopStyleColor(3);
645 if (ImGui::IsItemHovered()) {
646 ImGui::SetTooltip(
"Hide Sidebar\nCtrl+B");
652 ImGui::PopStyleVar(3);
653 ImGui::PopStyleColor(2);
699 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
704 static char search_filter[256] =
"";
705 static std::string category_filter =
"All";
708 ImGui::SetNextItemWidth(300);
709 ImGui::InputTextWithHint(
"##Search", absl::StrFormat(
"%s Search cards...",
711 search_filter,
sizeof(search_filter));
716 if (ImGui::BeginCombo(
"##CategoryFilter", category_filter.c_str())) {
717 if (ImGui::Selectable(
"All", category_filter ==
"All")) {
718 category_filter =
"All";
722 for (
const auto& cat : categories) {
723 if (ImGui::Selectable(cat.c_str(), category_filter == cat)) {
724 category_filter = cat;
733 if (ImGui::BeginTable(
"##CardTable", 4,
734 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
735 ImGuiTableFlags_Borders)) {
737 ImGui::TableSetupColumn(
"Visible", ImGuiTableColumnFlags_WidthFixed, 60);
738 ImGui::TableSetupColumn(
"Name", ImGuiTableColumnFlags_WidthStretch);
739 ImGui::TableSetupColumn(
"Category", ImGuiTableColumnFlags_WidthFixed, 120);
740 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthFixed, 100);
741 ImGui::TableHeadersRow();
743 auto cards = (category_filter ==
"All")
745 : std::vector<std::string>{};
747 if (category_filter !=
"All") {
749 for (
const auto& card : cat_cards) {
750 cards.push_back(card.card_id);
754 for (
const auto& card_id : cards) {
755 auto card_it =
cards_.find(card_id);
756 if (card_it ==
cards_.end())
continue;
758 const auto& card = card_it->second;
761 std::string search_str = search_filter;
762 if (!search_str.empty()) {
763 std::string card_lower = card.display_name;
764 std::transform(card_lower.begin(), card_lower.end(), card_lower.begin(), ::tolower);
765 std::transform(search_str.begin(), search_str.end(), search_str.begin(), ::tolower);
766 if (card_lower.find(search_str) == std::string::npos) {
771 ImGui::TableNextRow();
774 ImGui::TableNextColumn();
775 if (card.visibility_flag) {
776 bool visible = *card.visibility_flag;
777 if (ImGui::Checkbox(absl::StrFormat(
"##vis_%s", card.card_id.c_str()).c_str(),
779 *card.visibility_flag = visible;
780 if (visible && card.on_show) {
782 }
else if (!visible && card.on_hide) {
789 ImGui::TableNextColumn();
790 ImGui::Text(
"%s %s", card.icon.c_str(), card.display_name.c_str());
793 ImGui::TableNextColumn();
794 ImGui::Text(
"%s", card.category.c_str());
797 ImGui::TableNextColumn();
798 ImGui::TextDisabled(
"%s", card.shortcut_hint.c_str());