Forge
csharpdeeb25a2
1#nullable enable
2using Avalonia;
3using CascadeIDE.Cockpit.Graph.Layout;
4using CascadeIDE.Models;
5
6namespace CascadeIDE.ViewModels;
7
8/// <summary>Какой доменный граф рисуем на мини-карте: CFG vs связанные файлы (ADR 0067).</summary>
9public enum CodeNavigationMapGraphPresentationKind
10{
11 /// <summary>Control flow / CFG (полётный план по коду).</summary>
12 CodeControlFlow = 0,
13
14 /// <summary>Якорь и связанные файлы проекта (звезда / workspace).</summary>
15 WorkspaceRelatedFiles = 1
16}
17
18/// <summary>Как смонтирован блок легенды (номера шагов / ключи фигур) относительно графа control-flow — на уровне блока, а не пиксельной «подтяжки».</summary>
19public enum CodeNavigationMapLegendBlockPlacement
20{
21 /// <summary>Колонка справа от графа, текст — в оставшейся ширине (классический split).</summary>
22 BesideGraph = 0,
23
24 /// <summary>Блок под графом, с выравниванием слева на всю ширину вьюпорта.</summary>
25 BelowGraph = 1
26}
27
28/// <summary>Сцена мини-карты навигации по коду (узлы с центром в логических пикселях контрола).</summary>
29public sealed class CodeNavigationMapGraphSceneVm
30{
31 public required IReadOnlyList<CodeNavigationMapGraphNodeLayout> Nodes { get; init; }
32 public required IReadOnlyList<CodeNavigationMapGraphEdgeLayout> Edges { get; init; }
33
34 /// <summary>Визуальный язык сцены; Render — <see cref="CascadeIDE.Views.SkiaKit.Graph.SkiaGraphVisualTheme.ForPresentation"/>.</summary>
35 public CodeNavigationMapGraphPresentationKind Presentation { get; init; } = CodeNavigationMapGraphPresentationKind.CodeControlFlow;
36 public IReadOnlyList<CodeNavigationMapLegendEntry> Legend { get; init; } = [];
37 /// <summary>Резервировать колонку под легенду (номера шагов и/или обозначения фигур).</summary>
38 public bool UseLegendColumn { get; init; }
39 /// <summary>Показать в легенде расшифровку: ромб — условие.</summary>
40 public bool ShowLegendConditionKey { get; init; }
41 /// <summary>Показать в легенде расшифровку: круг со стрелкой — return.</summary>
42 public bool ShowLegendReturnKey { get; init; }
43 /// <summary>Показать в легенде расшифровку: обработчик исключений (catch) / ребро ExceptionFlow.</summary>
44 public bool ShowLegendExceptionFlowKey { get; init; }
45 /// <summary>Показать в легенде стили рёбер: сплошная / пунктир (условие, multibranch, loop).</summary>
46 public bool ShowLegendEdgeStyleKey { get; init; }
47 /// <summary>Левая граница колонки легенды (X); если легенды нет — равна ширине области (не рисуем). При <see cref="LegendPlacement"/> = <see cref="CodeNavigationMapLegendBlockPlacement.BelowGraph"/> — левый отступ текста (как у графа).</summary>
48 public double LegendColumnLeft { get; init; } = double.PositiveInfinity;
49
50 /// <summary>Кладка легенды: рядом с графом или снизу (control-flow; для звёзд не используется).</summary>
51 public CodeNavigationMapLegendBlockPlacement LegendPlacement { get; init; } = CodeNavigationMapLegendBlockPlacement.BesideGraph;
52
53 /// <summary>
54 /// Y начала блока легенды при <see cref="LegendPlacement"/> = <see cref="CodeNavigationMapLegendBlockPlacement.BelowGraph"/>;
55 /// иначе не используется.
56 /// </summary>
57 public double LegendBlockTopY { get; init; }
58 public IReadOnlySet<string> HighlightedNodeIds { get; init; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
59 public IReadOnlySet<string> HighlightedEdgeKeys { get; init; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
60
61 /// <summary>Номера шагов на узлах (без колонки легенды).</summary>
62 public bool ShowNodeLegendGlyphs { get; init; }
63
64 /// <summary><c>radial</c> | <c>top_down</c> | <c>bottom_up</c> (related-files).</summary>
65 public string RelatedFilesLayout { get; init; } = CodeNavigationMapRelatedGraphLayoutKind.Radial;
66
67 /// <summary>Главная ось потока после укладки CF — для подписей узлов и согласованности VM↔layout (ADR 0056).</summary>
68 public GraphControlFlowMainAxis ControlFlowMainAxis { get; init; } = GraphControlFlowMainAxis.Vertical;
69
70 /// <summary>
71 /// Размер шрифта боковых подписей узлов (call_step), согласованный с укладкой; null — <see cref="CascadeIDE.Cockpit.Graph.Layout.GraphRenderInvariants.MinSideLabelFontSize"/> при отрисовке.
72 /// </summary>
73 public double? SideLabelFontSizePx { get; init; }
74
75 /// <summary>Ширина viewport при укладке (для hit-test при расхождении с <c>Bounds</c>).</summary>
76 public double LayoutViewportWidth { get; init; }
77
78 /// <summary>Высота viewport при укладке (для hit-test при расхождении с <c>Bounds</c>).</summary>
79 public double LayoutViewportHeight { get; init; }
80
81 public bool IsEmpty => Nodes.Count == 0;
82}
83
84/// <summary>Строка легенды control flow: номер ↔ одна строка кода/предиката.</summary>
85public sealed class CodeNavigationMapLegendEntry
86{
87 public int Index { get; init; }
88 public required string Text { get; init; }
89}
90
91public enum CodeNavigationMapNodeShape
92{
93 /// <summary>Обычный шаг (круг).</summary>
94 Circle,
95
96 /// <summary>Условие / ветвление в CFG; на карте — ромб (не имя геометрии в API).</summary>
97 Condition,
98
99 /// <summary>Файловая карточка / узел related-files (прямоугольник с подписью внутри).</summary>
100 Rectangle
101}
102
103public sealed class CodeNavigationMapGraphNodeLayout
104{
105 public required string Id { get; init; }
106 public required string Kind { get; init; }
107 public required string FullPath { get; init; }
108 public required string Label { get; init; }
109 public required Point Center { get; init; }
110 public required double Radius { get; init; }
111 public required bool IsAnchor { get; init; }
112 public CodeNavigationMapNodeShape Shape { get; init; } = CodeNavigationMapNodeShape.Circle;
113 public int? LegendIndex { get; init; }
114 public string? LegendLine { get; init; }
115 public int? LineStart { get; init; }
116 public int? LineEnd { get; init; }
117
118 /// <summary>Группа тела цикла (овал регион + loop edges); см. <see cref="GraphLayoutNode.LoopGroupId"/>.</summary>
119 public int? LoopGroupId { get; init; }
120}
121
122public sealed class CodeNavigationMapGraphEdgeLayout
123{
124 public required string FromNodeId { get; init; }
125 public required string ToNodeId { get; init; }
126 public required Point From { get; init; }
127 public required Point To { get; init; }
128 public required double ToRadius { get; init; }
129 public string? Kind { get; init; }
130 public string? RelatedKind { get; init; }
131 public string? BranchLabel { get; init; }
132
133 public string Key => $"{FromNodeId}->{ToNodeId}";
134}
135
View only · write via MCP/CIDE