| 1 | using CascadeIDE.Contracts; |
| 2 | using CascadeIDE.Models; |
| 3 | |
| 4 | namespace CascadeIDE.Features.WorkspaceNavigation.Application; |
| 5 | |
| 6 | /// <summary> |
| 7 | /// Проекция UI для панели карты намерений (PFD): видимость list/graph и вспомогательные строки без привязки к ViewModel. |
| 8 | /// </summary> |
| 9 | [PresentationProjection] |
| 10 | public static class CodeNavigationMapPresentationProjection |
| 11 | { |
| 12 | private static readonly string[] PresentationViewCycleOrder = ["list", "graph", "both"]; |
| 13 | |
| 14 | /// <summary>Список related на странице MFD (вкладка RelatedFiles), не в колонке PFD.</summary> |
| 15 | public const bool ShowCodeNavigationMapListOnPfd = false; |
| 16 | |
| 17 | /// <summary>Строка сводки настроек карты для HUD (без ComboBox).</summary> |
| 18 | public static string SettingsSummaryLine( |
| 19 | string presentationView, |
| 20 | string mapLevel, |
| 21 | string detailLevelRaw, |
| 22 | string relatedGraphLayoutRaw, |
| 23 | string controlFlowMainAxisRaw) => |
| 24 | $"Вид: {presentationView} · уровень: {mapLevel} · укладка: {CodeNavigationMapRelatedGraphLayoutKind.Normalize(relatedGraphLayoutRaw)} · CF ось: {CodeNavigationMapControlFlowMainAxisKind.Normalize(controlFlowMainAxisRaw)} · детализация: {detailLevelRaw.Trim()} · палитра / MCP"; |
| 25 | |
| 26 | /// <summary>Цикл укладки related-files: radial → top_down → bottom_up.</summary> |
| 27 | public static string NextRelatedGraphLayoutAfter(string current) => |
| 28 | CodeNavigationMapRelatedGraphLayoutKind.Normalize(current) switch |
| 29 | { |
| 30 | CodeNavigationMapRelatedGraphLayoutKind.Radial => CodeNavigationMapRelatedGraphLayoutKind.TopDown, |
| 31 | CodeNavigationMapRelatedGraphLayoutKind.TopDown => CodeNavigationMapRelatedGraphLayoutKind.BottomUp, |
| 32 | _ => CodeNavigationMapRelatedGraphLayoutKind.Radial |
| 33 | }; |
| 34 | |
| 35 | /// <summary>Следующий <see cref="CodeNavigationMapSettings.NormalizeView"/> после текущего: list → graph → both → list.</summary> |
| 36 | public static string NextPresentationViewAfter(string currentPresentationView) |
| 37 | { |
| 38 | var cur = CodeNavigationMapSettings.NormalizeView(currentPresentationView); |
| 39 | var i = Array.IndexOf(PresentationViewCycleOrder, cur); |
| 40 | if (i < 0) |
| 41 | i = 0; |
| 42 | return PresentationViewCycleOrder[(i + 1) % PresentationViewCycleOrder.Length]; |
| 43 | } |
| 44 | |
| 45 | /// <summary>Следующий нормализованный depth: file ↔ controlFlow.</summary> |
| 46 | public static string ToggledMapLevel(string currentDepth) |
| 47 | { |
| 48 | var n = CodeNavigationMapLevelKind.Normalize(currentDepth); |
| 49 | return string.Equals(n, CodeNavigationMapLevelKind.File, StringComparison.Ordinal) |
| 50 | ? CodeNavigationMapLevelKind.ControlFlow |
| 51 | : CodeNavigationMapLevelKind.File; |
| 52 | } |
| 53 | |
| 54 | /// <summary>Цикл детализации glance → normal → inspect → glance для <c>[code_navigation_map]</c>.</summary> |
| 55 | public static (CodeNavigationMapDetailLevel Detail, string TomlDetailLevel) NextDetailCycle(CodeNavigationMapDetailLevel currentNormalized) |
| 56 | { |
| 57 | var next = currentNormalized switch |
| 58 | { |
| 59 | CodeNavigationMapDetailLevel.Glance => CodeNavigationMapDetailLevel.Normal, |
| 60 | CodeNavigationMapDetailLevel.Normal => CodeNavigationMapDetailLevel.Inspect, |
| 61 | CodeNavigationMapDetailLevel.Inspect => CodeNavigationMapDetailLevel.Glance, |
| 62 | _ => CodeNavigationMapDetailLevel.Normal |
| 63 | }; |
| 64 | var toml = next switch |
| 65 | { |
| 66 | CodeNavigationMapDetailLevel.Glance => "glance", |
| 67 | CodeNavigationMapDetailLevel.Normal => "normal", |
| 68 | CodeNavigationMapDetailLevel.Inspect => "inspect", |
| 69 | _ => "normal" |
| 70 | }; |
| 71 | return (next, toml); |
| 72 | } |
| 73 | |
| 74 | public static bool ShowCodeNavigationMapList(string presentationView) => |
| 75 | CodeNavigationMapSettings.ViewWantsList(presentationView); |
| 76 | |
| 77 | /// <summary> |
| 78 | /// Граф на PFD: для <c>controlFlow</c> всегда виден (основной продукт уровня), для <c>file</c> — по <c>view</c>. |
| 79 | /// </summary> |
| 80 | public static bool ShowCodeNavigationMapGraph(string presentationView, string mapLevel) => |
| 81 | string.Equals( |
| 82 | CodeNavigationMapLevelKind.Normalize(mapLevel), |
| 83 | CodeNavigationMapLevelKind.ControlFlow, |
| 84 | StringComparison.Ordinal) |
| 85 | || CodeNavigationMapSettings.ViewWantsGraph(presentationView); |
| 86 | |
| 87 | /// <summary>Нужна ли нижняя строка под список на PFD (политика: список только в MFD — всегда false).</summary> |
| 88 | public static bool ListAreaRowUsesStar(bool showList, bool showListOnPfd) => showList && showListOnPfd; |
| 89 | |
| 90 | public static bool ShowCodeNavigationMapGraphClickHint(bool showGraph, string codeNavigationMapLevel, string presentationView) |
| 91 | { |
| 92 | if (!showGraph) |
| 93 | return false; |
| 94 | if (CodeNavigationMapSettings.NormalizeView(presentationView) == "list") |
| 95 | return false; |
| 96 | return string.Equals( |
| 97 | CodeNavigationMapLevelKind.Normalize(codeNavigationMapLevel), |
| 98 | CodeNavigationMapLevelKind.File, |
| 99 | StringComparison.OrdinalIgnoreCase); |
| 100 | } |
| 101 | |
| 102 | public static string WorkspaceNavigationMapRelatedBadge(int relatedCount) => relatedCount switch |
| 103 | { |
| 104 | 0 => "", |
| 105 | 1 => "1 связь", |
| 106 | _ => $"{relatedCount} связей" |
| 107 | }; |
| 108 | |
| 109 | public static bool WorkspaceNavigationMapHasRelated(int relatedCount, int? graphSceneNodeCount) => |
| 110 | relatedCount > 0 || graphSceneNodeCount > 1; |
| 111 | } |
| 112 | |