yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
activity_bar.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cctype>
5#include <cstddef>
6#include <functional>
7#include <string>
8#include <unordered_set>
9#include <vector>
10
11#include "absl/strings/str_format.h"
13#include "app/gui/core/icons.h"
16#include "core/color.h"
17#include "imgui/imgui.h"
18
19namespace yaze {
20namespace editor {
21
23 : panel_manager_(panel_manager) {}
24
26 size_t session_id, const std::string& active_category,
27 const std::vector<std::string>& all_categories,
28 const std::unordered_set<std::string>& active_editor_categories,
29 std::function<bool()> has_rom) {
31 return;
32
33 DrawActivityBarStrip(session_id, active_category, all_categories,
34 active_editor_categories, has_rom);
35
37 DrawSidePanel(session_id, active_category, has_rom);
38 }
39}
40
42 size_t session_id, const std::string& active_category,
43 const std::vector<std::string>& all_categories,
44 const std::unordered_set<std::string>& active_editor_categories,
45 std::function<bool()> has_rom) {
46
47 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
48 const ImGuiViewport* viewport = ImGui::GetMainViewport();
49 const float viewport_height = viewport->WorkSize.y;
50 const float bar_width = 48.0f; // Fixed width for Activity Bar
51
52 // Position on left edge, full height
53 ImGui::SetNextWindowPos(ImVec2(viewport->WorkPos.x, viewport->WorkPos.y));
54 ImGui::SetNextWindowSize(ImVec2(bar_width, viewport_height));
55
56 ImVec4 bar_bg = gui::ConvertColorToImVec4(theme.surface);
57 ImVec4 bar_border = gui::ConvertColorToImVec4(theme.text_disabled);
58
59 ImGuiWindowFlags flags =
60 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
61 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
62 ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoScrollbar |
63 ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNavFocus |
64 ImGuiWindowFlags_NoBringToFrontOnFocus;
65
66 ImGui::PushStyleColor(ImGuiCol_WindowBg, bar_bg);
67 ImGui::PushStyleColor(ImGuiCol_Border, bar_border);
68 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 8.0f));
69 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,
70 ImVec2(0.0f, 8.0f)); // Increased spacing
71 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
72
73 if (ImGui::Begin("##ActivityBar", nullptr, flags)) {
74
75 // Global Search / Command Palette at top
76 if (gui::TransparentIconButton(ICON_MD_SEARCH, ImVec2(48.0f, 40.0f),
77 "Global Search (Ctrl+Shift+F)", false)) {
79 }
80
81 // Separator
82 ImGui::Spacing();
83 ImVec2 sep_p1 = ImGui::GetCursorScreenPos();
84 ImVec2 sep_p2 = ImVec2(sep_p1.x + 48.0f, sep_p1.y);
85 ImGui::GetWindowDrawList()->AddLine(
86 sep_p1, sep_p2,
87 ImGui::ColorConvertFloat4ToU32(gui::ConvertColorToImVec4(theme.border)),
88 1.0f);
89 ImGui::Spacing();
90
91 bool rom_loaded = has_rom ? has_rom() : false;
92
93 // Draw ALL editor categories (not just active ones)
94 for (const auto& cat : all_categories) {
95 bool is_selected =
96 (cat == active_category) && panel_manager_.IsPanelExpanded();
97 bool has_active_editor = active_editor_categories.count(cat) > 0;
98
99 // Emulator is always available, others require ROM
100 bool category_enabled = rom_loaded || (cat == "Emulator");
101
102 // Get category-specific theme colors for expressive appearance
103 auto cat_theme = PanelManager::GetCategoryTheme(cat);
104 ImVec4 cat_color(cat_theme.r, cat_theme.g, cat_theme.b, cat_theme.a);
105 ImVec4 glow_color(cat_theme.glow_r, cat_theme.glow_g, cat_theme.glow_b,
106 1.0f);
107
108 // Active Indicator with category-specific colors
109 if (is_selected && category_enabled) {
110 ImVec2 pos = ImGui::GetCursorScreenPos();
111
112 // Outer glow shadow (subtle, category color at 15% opacity)
113 ImVec4 outer_glow = glow_color;
114 outer_glow.w = 0.15f;
115 ImGui::GetWindowDrawList()->AddRectFilled(
116 ImVec2(pos.x - 1.0f, pos.y - 1.0f),
117 ImVec2(pos.x + 49.0f, pos.y + 41.0f),
118 ImGui::ColorConvertFloat4ToU32(outer_glow), 4.0f);
119
120 // Background highlight (category glow at 30% opacity)
121 ImVec4 highlight = glow_color;
122 highlight.w = 0.30f;
123 ImGui::GetWindowDrawList()->AddRectFilled(
124 pos, ImVec2(pos.x + 48.0f, pos.y + 40.0f),
125 ImGui::ColorConvertFloat4ToU32(highlight), 2.0f);
126
127 // Left accent border (4px wide, category-specific color)
128 ImGui::GetWindowDrawList()->AddRectFilled(
129 pos, ImVec2(pos.x + 4.0f, pos.y + 40.0f),
130 ImGui::ColorConvertFloat4ToU32(cat_color));
131 }
132
133 std::string icon = PanelManager::GetCategoryIcon(cat);
134
135 // Use ThemedWidgets with category-specific color when active
136 ImVec4 icon_color =
137 is_selected ? cat_color : ImVec4(0, 0, 0, 0); // 0 = use default
138 if (gui::TransparentIconButton(icon.c_str(), ImVec2(48.0f, 40.0f),
139 nullptr, is_selected, icon_color)) {
140 if (category_enabled) {
141 if (cat == active_category && panel_manager_.IsPanelExpanded()) {
143 } else {
146 // Notify that a category was selected (dismisses dashboard)
148 }
149 }
150 }
151
152 // Tooltip with status information
153 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
154 ImGui::BeginTooltip();
155 ImGui::Text("%s %s", icon.c_str(), cat.c_str());
156 if (!category_enabled) {
157 ImGui::TextColored(gui::ConvertColorToImVec4(theme.warning),
158 "Open ROM required");
159 } else if (has_active_editor) {
160 ImGui::PushStyleColor(ImGuiCol_Text,
161 gui::ConvertColorToImVec4(theme.success));
162 ImGui::TextUnformatted("Editor open");
163 ImGui::PopStyleColor();
164 } else {
165 ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextSecondaryVec4());
166 ImGui::TextUnformatted("Click to view panels");
167 ImGui::PopStyleColor();
168 }
169 ImGui::EndTooltip();
170 }
171 }
172 }
173
174 // Draw "More Actions" button at the bottom
175 ImGui::SetCursorPosY(viewport_height - 48.0f);
176
177 if (gui::TransparentIconButton(ICON_MD_MORE_HORIZ, ImVec2(48.0f, 48.0f))) {
178 ImGui::OpenPopup("ActivityBarMoreMenu");
179 }
180
181 if (ImGui::BeginPopup("ActivityBarMoreMenu")) {
182 if (ImGui::MenuItem(ICON_MD_TERMINAL " Command Palette")) {
184 }
185 if (ImGui::MenuItem(ICON_MD_KEYBOARD " Keyboard Shortcuts")) {
187 }
188 ImGui::Separator();
189 if (ImGui::MenuItem(ICON_MD_FOLDER_OPEN " Open ROM")) {
191 }
192 if (ImGui::MenuItem(ICON_MD_SETTINGS " Settings")) {
194 }
195 ImGui::Separator();
196 if (ImGui::MenuItem("Reset Layout")) {
197 // TODO: Implement layout reset
198 }
199 ImGui::EndPopup();
200 }
201
202 ImGui::End();
203
204 ImGui::PopStyleVar(3);
205 ImGui::PopStyleColor(2);
206}
207
208void ActivityBar::DrawSidePanel(size_t session_id, const std::string& category,
209 std::function<bool()> has_rom) {
210
211 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
212 const ImGuiViewport* viewport = ImGui::GetMainViewport();
213 const float bar_width = PanelManager::GetSidebarWidth();
214 const float panel_width =
215 PanelManager::GetSidePanelWidthForViewport(viewport->WorkSize.x);
216
217 ImGui::SetNextWindowPos(
218 ImVec2(viewport->WorkPos.x + bar_width, viewport->WorkPos.y));
219 ImGui::SetNextWindowSize(ImVec2(panel_width, viewport->WorkSize.y));
220
221 ImVec4 panel_bg = gui::ConvertColorToImVec4(theme.surface);
222
223 ImGuiWindowFlags flags =
224 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
225 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
226 ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing;
227
228 ImGui::PushStyleColor(ImGuiCol_WindowBg, panel_bg);
229 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
230 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); // Right border
231 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,
232 ImVec2(12.0f, 12.0f)); // Consistent padding
233
234 if (ImGui::Begin("##SidePanel", nullptr, flags)) {
235 // Header
236 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); // Use default font
237 ImGui::Text("%s", category.c_str());
238 ImGui::PopFont();
239
240 // Header Buttons (Right Aligned)
241 float avail_width = ImGui::GetContentRegionAvail().x;
242 float button_size = 28.0f;
243 float spacing = 4.0f;
244 float current_x = ImGui::GetCursorPosX() + avail_width - button_size;
245
246 // Collapse Button (rightmost)
247 ImGui::SameLine(current_x);
248 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 4.0f);
249 if (ImGui::Button(ICON_MD_KEYBOARD_DOUBLE_ARROW_LEFT,
250 ImVec2(button_size, button_size))) {
252 }
253 if (ImGui::IsItemHovered()) {
254 ImGui::SetTooltip("Collapse Panel");
255 }
256
257 // Close All Panels Button
258 current_x -= (button_size + spacing);
259 ImGui::SameLine(current_x);
260 if (ImGui::Button(ICON_MD_CLOSE_FULLSCREEN,
261 ImVec2(button_size, button_size))) {
262 panel_manager_.HideAllPanelsInCategory(session_id, category);
263 }
264 if (ImGui::IsItemHovered()) {
265 ImGui::SetTooltip("Close All Panels");
266 }
267
268 // Expand All Panels Button
269 current_x -= (button_size + spacing);
270 ImGui::SameLine(current_x);
271 if (ImGui::Button(ICON_MD_OPEN_IN_FULL, ImVec2(button_size, button_size))) {
272 panel_manager_.ShowAllPanelsInCategory(session_id, category);
273 }
274 if (ImGui::IsItemHovered()) {
275 ImGui::SetTooltip("Show All Panels");
276 }
277
278 ImGui::Spacing();
279 ImGui::Separator();
280 ImGui::Spacing();
281
282 // Search Bar
283 static char sidebar_search[256] = "";
284 ImGui::SetNextItemWidth(-1);
285 ImGui::InputTextWithHint("##SidebarSearch", ICON_MD_SEARCH " Filter...",
286 sidebar_search, sizeof(sidebar_search));
287 ImGui::Spacing();
288
289 // Disable non-emulator categories when no ROM is loaded
290 const bool rom_loaded = has_rom ? has_rom() : true;
291 const bool disable_cards = !rom_loaded && category != "Emulator";
292 if (disable_cards) {
293 ImGui::TextUnformatted(ICON_MD_FOLDER_OPEN
294 " Open a ROM to enable this category");
295 ImGui::Spacing();
296 }
297
298 if (disable_cards) {
299 ImGui::BeginDisabled();
300 }
301
302 // Get pinned and recent panels
303 const auto pinned_cards = panel_manager_.GetPinnedPanels();
304 const auto& recent_cards = panel_manager_.GetRecentPanels();
305
306 // --- Pinned Section (panels that persist across editors) ---
307 if (sidebar_search[0] == '\0' && !pinned_cards.empty()) {
308 bool has_pinned_in_category = false;
309 for (const auto& card_id : pinned_cards) {
310 const auto* card =
311 panel_manager_.GetPanelDescriptor(session_id, card_id);
312 if (card && card->category == category) {
313 has_pinned_in_category = true;
314 break;
315 }
316 }
317
318 if (has_pinned_in_category) {
319 if (ImGui::CollapsingHeader(ICON_MD_PUSH_PIN " Pinned",
320 ImGuiTreeNodeFlags_DefaultOpen)) {
321 for (const auto& card_id : pinned_cards) {
322 const auto* card =
323 panel_manager_.GetPanelDescriptor(session_id, card_id);
324 if (!card || card->category != category)
325 continue;
326
327 bool visible =
328 card->visibility_flag ? *card->visibility_flag : false;
329
330 // Unpin button
331 ImGui::PushStyleColor(ImGuiCol_Text,
332 gui::ConvertColorToImVec4(theme.primary));
333 if (ImGui::SmallButton(
334 (std::string(ICON_MD_PUSH_PIN "##pin_") + card->card_id)
335 .c_str())) {
336 panel_manager_.SetPanelPinned(card->card_id, false);
337 }
338 ImGui::PopStyleColor();
339 if (ImGui::IsItemHovered()) {
340 ImGui::SetTooltip("Unpin panel");
341 }
342
343 ImGui::SameLine();
344
345 // Panel Item
346 std::string label = absl::StrFormat("%s %s", card->icon.c_str(),
347 card->display_name.c_str());
348 if (ImGui::Selectable(label.c_str(), visible)) {
349 panel_manager_.TogglePanel(session_id, card->card_id);
350
351 bool new_visible =
352 card->visibility_flag ? *card->visibility_flag : false;
353 if (new_visible) {
354 panel_manager_.TriggerPanelClicked(card->category);
355 ImGui::SetWindowFocus(card->GetWindowTitle().c_str());
356 }
357 }
358 }
359 ImGui::Spacing();
360 ImGui::Separator();
361 ImGui::Spacing();
362 }
363 }
364 }
365
366 // --- Recent Section ---
367 if (sidebar_search[0] == '\0' && !recent_cards.empty()) {
368 bool has_recents_in_category = false;
369 for (const auto& card_id : recent_cards) {
370 const auto* card =
371 panel_manager_.GetPanelDescriptor(session_id, card_id);
372 if (card && card->category == category) {
373 has_recents_in_category = true;
374 break;
375 }
376 }
377
378 if (has_recents_in_category) {
379 if (ImGui::CollapsingHeader(ICON_MD_HISTORY " Recent",
380 ImGuiTreeNodeFlags_DefaultOpen)) {
381 for (const auto& card_id : recent_cards) {
382 const auto* card =
383 panel_manager_.GetPanelDescriptor(session_id, card_id);
384 if (!card || card->category != category)
385 continue;
386
387 bool visible =
388 card->visibility_flag ? *card->visibility_flag : false;
389
390 // Pin Toggle Button
391 bool is_pinned = panel_manager_.IsPanelPinned(card->card_id);
392 ImGui::PushID((std::string("recent_") + card->card_id).c_str());
393 if (is_pinned) {
394 ImGui::PushStyleColor(ImGuiCol_Text,
395 gui::ConvertColorToImVec4(theme.primary));
396 if (ImGui::SmallButton(ICON_MD_PUSH_PIN)) {
397 panel_manager_.SetPanelPinned(card->card_id, false);
398 }
399 ImGui::PopStyleColor();
400 } else {
401 ImGui::PushStyleColor(ImGuiCol_Text, gui::ConvertColorToImVec4(
402 theme.text_disabled));
403 if (ImGui::SmallButton(ICON_MD_PUSH_PIN)) {
404 panel_manager_.SetPanelPinned(card->card_id, true);
405 }
406 ImGui::PopStyleColor();
407 }
408 ImGui::PopID();
409 ImGui::SameLine();
410
411 // Panel Item
412 std::string label = absl::StrFormat("%s %s", card->icon.c_str(),
413 card->display_name.c_str());
414 if (ImGui::Selectable(label.c_str(), visible)) {
415 panel_manager_.TogglePanel(session_id, card->card_id);
416
417 bool new_visible =
418 card->visibility_flag ? *card->visibility_flag : false;
419 if (new_visible) {
420 panel_manager_.AddToRecent(card->card_id); // Move to top
421 panel_manager_.TriggerPanelClicked(card->category);
422 ImGui::SetWindowFocus(card->GetWindowTitle().c_str());
423 }
424 }
425 }
426 ImGui::Spacing();
427 ImGui::Separator();
428 ImGui::Spacing();
429 }
430 }
431 }
432
433 // Content - Reusing GetPanelsInCategory logic
434 auto cards = panel_manager_.GetPanelsInCategory(session_id, category);
435
436 // Calculate available height for cards vs file browser
437 float available_height = ImGui::GetContentRegionAvail().y;
438 bool has_file_browser = panel_manager_.HasFileBrowser(category);
439 float cards_height =
440 has_file_browser ? available_height * 0.4f : available_height;
441 float file_browser_height = available_height - cards_height - 30.0f;
442
443 // Panels section
444 ImGui::BeginChild("##PanelContent", ImVec2(0, cards_height), false,
445 ImGuiWindowFlags_None);
446 for (const auto& card : cards) {
447 // Apply search filter
448 if (sidebar_search[0] != '\0') {
449 std::string search_str = sidebar_search;
450 std::string card_name = card.display_name;
451 std::transform(search_str.begin(), search_str.end(), search_str.begin(),
452 ::tolower);
453 std::transform(card_name.begin(), card_name.end(), card_name.begin(),
454 ::tolower);
455 if (card_name.find(search_str) == std::string::npos) {
456 continue;
457 }
458 }
459
460 bool visible = card.visibility_flag ? *card.visibility_flag : false;
461
462 // Pin Toggle Button (replaces favorites - more useful for panel management)
463 // Use active session to avoid potential session ID issues
464 bool is_pinned = panel_manager_.IsPanelPinned(card.card_id);
465 ImGui::PushID(card.card_id.c_str());
466 if (is_pinned) {
467 ImGui::PushStyleColor(ImGuiCol_Text,
468 gui::ConvertColorToImVec4(theme.primary));
469 if (ImGui::SmallButton(ICON_MD_PUSH_PIN)) {
470 panel_manager_.SetPanelPinned(card.card_id, false);
471 }
472 ImGui::PopStyleColor();
473 if (ImGui::IsItemHovered()) {
474 ImGui::SetTooltip("Unpin - panel will hide when switching editors");
475 }
476 } else {
477 ImGui::PushStyleColor(ImGuiCol_Text,
478 gui::ConvertColorToImVec4(theme.text_disabled));
479 if (ImGui::SmallButton(ICON_MD_PUSH_PIN)) {
480 panel_manager_.SetPanelPinned(card.card_id, true);
481 }
482 ImGui::PopStyleColor();
483 if (ImGui::IsItemHovered()) {
484 ImGui::SetTooltip("Pin - keep visible across all editors");
485 }
486 }
487 ImGui::PopID();
488 ImGui::SameLine();
489
490 // Panel Item with Icon
491 std::string label = absl::StrFormat("%s %s", card.icon.c_str(),
492 card.display_name.c_str());
493 if (ImGui::Selectable(label.c_str(), visible)) {
494 // Toggle visibility
495 panel_manager_.TogglePanel(session_id, card.card_id);
496
497 // Get the new visibility state after toggle
498 bool new_visible = card.visibility_flag ? *card.visibility_flag : false;
499
500 if (new_visible) {
501 panel_manager_.AddToRecent(card.card_id); // Track recent
502
503 // Panel was just shown - activate the associated editor
504 panel_manager_.TriggerPanelClicked(card.category);
505
506 // Focus the card window so it comes to front
507 std::string window_title = card.GetWindowTitle();
508 ImGui::SetWindowFocus(window_title.c_str());
509 }
510 }
511
512 // Shortcut hint on hover
513 if (ImGui::IsItemHovered() && !card.shortcut_hint.empty()) {
514 ImGui::SetTooltip("%s", card.shortcut_hint.c_str());
515 }
516 }
517 ImGui::EndChild();
518
519 // File browser section (if enabled for this category)
520 if (has_file_browser) {
521 ImGui::Spacing();
522 ImGui::Separator();
523
524 // Collapsible header for file browser
525 ImGui::PushStyleColor(ImGuiCol_Header,
527 ImGui::PushStyleColor(ImGuiCol_HeaderHovered,
529 bool files_expanded = ImGui::CollapsingHeader(
530 ICON_MD_FOLDER " Files", ImGuiTreeNodeFlags_DefaultOpen);
531 ImGui::PopStyleColor(2);
532
533 if (files_expanded) {
534 ImGui::BeginChild("##FileBrowser", ImVec2(0, file_browser_height),
535 false, ImGuiWindowFlags_None);
536 auto* browser = panel_manager_.GetFileBrowser(category);
537 if (browser) {
538 browser->DrawCompact();
539 }
540 ImGui::EndChild();
541 }
542 }
543
544 if (disable_cards) {
545 ImGui::EndDisabled();
546 }
547 }
548 ImGui::End();
549
550 ImGui::PopStyleVar(3);
551 ImGui::PopStyleColor(1);
552}
553
554void ActivityBar::DrawPanelBrowser(size_t session_id, bool* p_open) {
555 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
556
557 if (ImGui::Begin(
558 absl::StrFormat("%s Panel Browser", ICON_MD_DASHBOARD).c_str(),
559 p_open)) {
560 static char search_filter[256] = "";
561 static std::string category_filter = "All";
562
563 // Search bar
564 ImGui::SetNextItemWidth(300);
565 ImGui::InputTextWithHint(
566 "##Search",
567 absl::StrFormat("%s Search panels...", ICON_MD_SEARCH).c_str(),
568 search_filter, sizeof(search_filter));
569
570 ImGui::SameLine();
571
572 // Category filter
573 if (ImGui::BeginCombo("##CategoryFilter", category_filter.c_str())) {
574 if (ImGui::Selectable("All", category_filter == "All")) {
575 category_filter = "All";
576 }
577
578 auto categories = panel_manager_.GetAllCategories(session_id);
579 for (const auto& cat : categories) {
580 if (ImGui::Selectable(cat.c_str(), category_filter == cat)) {
581 category_filter = cat;
582 }
583 }
584 ImGui::EndCombo();
585 }
586
587 ImGui::Separator();
588
589 // Panel table
590 if (ImGui::BeginTable("##PanelTable", 4,
591 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
592 ImGuiTableFlags_Borders)) {
593 ImGui::TableSetupColumn("Visible", ImGuiTableColumnFlags_WidthFixed, 60);
594 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
595 ImGui::TableSetupColumn("Category", ImGuiTableColumnFlags_WidthFixed,
596 120);
597 ImGui::TableSetupColumn("Shortcut", ImGuiTableColumnFlags_WidthFixed,
598 100);
599 ImGui::TableHeadersRow();
600
601 auto cards = (category_filter == "All")
603 : std::vector<std::string>{};
604
605 if (category_filter != "All") {
606 auto cat_cards =
607 panel_manager_.GetPanelsInCategory(session_id, category_filter);
608 for (const auto& card : cat_cards) {
609 cards.push_back(card.card_id);
610 }
611 }
612
613 for (const auto& card_id : cards) {
614 const auto* card =
615 panel_manager_.GetPanelDescriptor(session_id, card_id);
616 if (!card)
617 continue;
618
619 // Apply search filter
620 std::string search_str = search_filter;
621 if (!search_str.empty()) {
622 std::string card_lower = card->display_name;
623 std::transform(card_lower.begin(), card_lower.end(),
624 card_lower.begin(), ::tolower);
625 std::transform(search_str.begin(), search_str.end(),
626 search_str.begin(), ::tolower);
627 if (card_lower.find(search_str) == std::string::npos) {
628 continue;
629 }
630 }
631
632 ImGui::TableNextRow();
633
634 // Visibility toggle
635 ImGui::TableNextColumn();
636 if (card->visibility_flag) {
637 bool visible = *card->visibility_flag;
638 if (ImGui::Checkbox(
639 absl::StrFormat("##vis_%s", card->card_id.c_str()).c_str(),
640 &visible)) {
641 panel_manager_.TogglePanel(session_id, card->card_id);
642 // Note: TogglePanel handles callbacks
643 }
644 }
645
646 // Name with icon
647 ImGui::TableNextColumn();
648 ImGui::Text("%s %s", card->icon.c_str(), card->display_name.c_str());
649
650 // Category
651 ImGui::TableNextColumn();
652 ImGui::Text("%s", card->category.c_str());
653
654 // Shortcut
655 ImGui::TableNextColumn();
656 ImGui::TextDisabled("%s", card->shortcut_hint.c_str());
657 }
658
659 ImGui::EndTable();
660 }
661 }
662 ImGui::End();
663}
664
665} // namespace editor
666} // namespace yaze
void DrawPanelBrowser(size_t session_id, bool *p_open)
void DrawSidePanel(size_t session_id, const std::string &category, std::function< bool()> has_rom)
void Render(size_t session_id, const std::string &active_category, const std::vector< std::string > &all_categories, const std::unordered_set< std::string > &active_editor_categories, std::function< bool()> has_rom)
void DrawActivityBarStrip(size_t session_id, const std::string &active_category, const std::vector< std::string > &all_categories, const std::unordered_set< std::string > &active_editor_categories, std::function< bool()> has_rom)
PanelManager & panel_manager_
ActivityBar(PanelManager &panel_manager)
void DrawCompact()
Draw a compact version for narrow sidebars.
Central registry for all editor cards with session awareness and dependency injection.
std::vector< std::string > GetAllCategories(size_t session_id) const
void AddToRecent(const std::string &card_id)
void TriggerCategorySelected(const std::string &category)
std::vector< std::string > GetPinnedPanels(size_t session_id) const
bool TogglePanel(size_t session_id, const std::string &base_card_id)
const PanelDescriptor * GetPanelDescriptor(size_t session_id, const std::string &base_card_id) const
void TriggerPanelClicked(const std::string &category)
std::vector< std::string > GetPanelsInSession(size_t session_id) const
bool HasFileBrowser(const std::string &category) const
static float GetSidePanelWidthForViewport(float viewport_width)
std::vector< PanelDescriptor > GetPanelsInCategory(size_t session_id, const std::string &category) const
static CategoryTheme GetCategoryTheme(const std::string &category)
void SetPanelExpanded(bool expanded)
static constexpr float GetSidebarWidth()
const std::vector< std::string > & GetRecentPanels() const
void ShowAllPanelsInCategory(size_t session_id, const std::string &category)
static std::string GetCategoryIcon(const std::string &category)
bool IsPanelPinned(size_t session_id, const std::string &base_card_id) const
FileBrowser * GetFileBrowser(const std::string &category)
void SetActiveCategory(const std::string &category)
void SetPanelPinned(size_t session_id, const std::string &base_card_id, bool pinned)
void HideAllPanelsInCategory(size_t session_id, const std::string &category)
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define ICON_MD_FOLDER_OPEN
Definition icons.h:813
#define ICON_MD_SETTINGS
Definition icons.h:1699
#define ICON_MD_SEARCH
Definition icons.h:1673
#define ICON_MD_OPEN_IN_FULL
Definition icons.h:1353
#define ICON_MD_MORE_HORIZ
Definition icons.h:1241
#define ICON_MD_KEYBOARD_DOUBLE_ARROW_LEFT
Definition icons.h:1041
#define ICON_MD_CLOSE_FULLSCREEN
Definition icons.h:419
#define ICON_MD_KEYBOARD
Definition icons.h:1028
#define ICON_MD_TERMINAL
Definition icons.h:1951
#define ICON_MD_DASHBOARD
Definition icons.h:517
#define ICON_MD_FOLDER
Definition icons.h:809
#define ICON_MD_PUSH_PIN
Definition icons.h:1529
#define ICON_MD_HISTORY
Definition icons.h:946
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:23
bool TransparentIconButton(const char *icon, const ImVec2 &size, const char *tooltip, bool is_active, const ImVec4 &active_color)
Draw a transparent icon button (hover effect only).
ImVec4 GetSurfaceContainerHighestVec4()
ImVec4 GetTextSecondaryVec4()
ImVec4 GetSurfaceContainerHighVec4()