Forge
csharpdeeb25a2
1using CascadeIDE.Cockpit;
2using CascadeIDE.Cockpit.Cds;
3using CascadeIDE.Cockpit.Channels.WorkspaceHealth;
4using CascadeIDE.Cockpit.ComputingUnits;
5using CascadeIDE.Cockpit.ComputingUnits.IdeHealth;
6using CascadeIDE.Cockpit.Composition;
7using CascadeIDE.Cockpit.Composition.HostSurface;
8using CascadeIDE.Cockpit.Composition.Shell;
9using CascadeIDE.Features.Agent.Environment;
10using CascadeIDE.Features.Shell.Application;
11using CascadeIDE.Features.UiChrome;
12using CascadeIDE.Models;
13
14namespace CascadeIDE.ViewModels;
15
16/// <summary>Вычисляемые свойства разметки, Workspace Health и видимости панелей (режимы UI).</summary>
17public partial class MainWindowViewModel
18{
19 /// <summary>Семейство текущего UI-режима (одна ось вместо булевых Is*Mode).</summary>
20 public UiModeFamily UiModeFamily => UiModeFamilyResolver.FromNormalizedMode(NormalizeUiMode(UiMode));
21
22 /// <summary>Настройки отображения для композиторов кабины (mount, Skia, instrument routing).</summary>
23 public DisplaySettings DisplaySettings => _settings.Display;
24
25 /// <summary>Заголовок главного окна (в Power — подпись «Autonomous Agent Cockpit»); из TOML — <c>main_window_title</c>.</summary>
26 public string WindowTitle =>
27 MainWindowPresentationSurfaceProjection.ResolveWindowTitle(NormalizeUiMode(UiMode));
28
29 /// <summary>Композитор: intent + CDS style → кадр хоста (колонки + инструменты слотов; ADR 0036 п.3, 0047).</summary>
30 private MainWindowHostSurfaceFrame HostSurfaceFrame =>
31 MainWindowPresentationSurfaceProjection.ComposeHostSurfaceFrame(
32 this,
33 NormalizeUiMode(UiMode),
34 CurrentMfdShellPage,
35 PrimaryWorkSurface);
36
37 private MainWindowShellSurfaceComposition ShellSurfaceComposition => HostSurfaceFrame.Shell;
38
39 /// <summary>Логические инструменты по слотам для главного окна; хост (Avalonia/Skia) сопоставляет <c>instrument_id</c> разметке.</summary>
40 public IReadOnlyList<CockpitInstrumentDescriptor> MainWindowHostSurfaceInstruments => HostSurfaceFrame.Instruments;
41
42 /// <summary>Ширина региона MFD в main grid (пиксели); 0 если колонка не выделяется (хост MFD и т.п.).</summary>
43 public int ChatPanelColumnPixelWidth =>
44 IsCompactPresentationTier
45 ? CompactRightChromeColumnPixelWidth
46 : ShellSurfaceComposition.MfdColumnPixelWidthInMainGrid;
47
48 /// <summary>Есть правая колонка MFD и сплиттер перед ней (ширина &gt; 0 в main).</summary>
49 public bool IsChatPanelColumnVisible =>
50 MainWindowPresentationSurfaceProjection.IsMainGridSplitColumnVisible(ChatPanelColumnPixelWidth);
51
52 /// <summary>
53 /// Какая топология размещения зон сейчас активна. Свойства <see cref="IsPfdColumnVisible"/> / <see cref="IsMfdColumnVisible"/>
54 /// имеют смысл только для <see cref="AttentionLayoutSurfaceKind.MainWindowDockedGrid"/>; иные варианты — ADR 0021 §13, 0017.
55 /// </summary>
56 public AttentionLayoutSurfaceKind ActiveAttentionLayoutSurface =>
57 AttentionLayoutSurfaceResolver.Resolve(
58 _suppressPfdColumnForPfdHostWindow,
59 _suppressMfdColumnForMfdHostWindow,
60 PresentationRequestsPfdHostWindow,
61 _presentationMfdHostTopology);
62
63 /// <summary>
64 /// Видна ли колонка <c>MainGrid</c> под левый якорь при <see cref="ActiveAttentionLayoutSurface"/> (в этой разметке — зона PFD).
65 /// Не путать с картой «панель → зона»: <see cref="AttentionZonePanelRuntime"/>, <c>docs/design/attention-zone-panel-playbook-v1.md</c>.
66 /// Ширина колонки совпадает с поверхностью PFD в main grid.
67 /// </summary>
68 public bool IsPfdColumnVisible =>
69 IsCompactPresentationTier
70 ? false
71 : ShellSurfaceComposition.PfdSurfaceVisible;
72
73 /// <summary>
74 /// Видна ли колонка <c>MainGrid</c> под правый якорь при <see cref="ActiveAttentionLayoutSurface"/> (в этой разметке — зона MFD).
75 /// Не путать с вкладками MFD или картой панелей — <see cref="AttentionZonePanelRuntime"/>; место в сетке совпадает с <see cref="IsChatPanelColumnVisible"/>.
76 /// </summary>
77 public bool IsMfdColumnVisible =>
78 IsCompactPresentationTier
79 ? IsCompactRightChromeColumnVisible
80 : ShellSurfaceComposition.MfdColumnVisibleInMainGrid;
81
82 /// <summary>Включён debug-overlay контуров зон (ручная валидация геометрии W2).</summary>
83 public bool ShowSkiaZoneGeometryOverlay => _settings.Display.Skia.ZoneGeometryOverlay;
84
85 public bool IsSkiaZoneGeometryOverlayPfdVisible =>
86 MainWindowPresentationCapabilitiesProjection.IsSkiaZoneGeometryOverlayPfdVisible(
87 ShowSkiaZoneGeometryOverlay,
88 IsPfdColumnVisible);
89
90 public bool IsSkiaZoneGeometryOverlayForwardVisible =>
91 MainWindowPresentationCapabilitiesProjection.IsSkiaZoneGeometryOverlayForwardVisible(
92 ShowSkiaZoneGeometryOverlay);
93
94 public bool IsSkiaZoneGeometryOverlayMfdVisible =>
95 MainWindowPresentationCapabilitiesProjection.IsSkiaZoneGeometryOverlayMfdVisible(
96 ShowSkiaZoneGeometryOverlay,
97 IsMfdColumnVisible);
98
99 /// <summary>Wave 3: включить отрисовку инструмента в Skia mount-слое зон P/F/M.</summary>
100 public bool UseSkiaInstrumentMount => _settings.Display.Skia.InstrumentMount;
101
102 /// <summary>Декларативный mount-style mount-инструмента (идёт из <c>[display.mount]</c>).</summary>
103 public string InstrumentMountStyle =>
104 MainWindowPresentationSurfaceProjection.InstrumentMountDisplayStyle(_settings.Display);
105
106 /// <summary>Резолв style для mount в слоте PFD с учётом registry-правил.</summary>
107 public string PfdInstrumentMountStyle =>
108 MainWindowPresentationSurfaceProjection.ResolveInstrumentMountStyleForSlot(
109 _instrumentMountPolicyResolver,
110 _settings.Display,
111 ActiveAttentionLayoutSurface,
112 "pfd",
113 CockpitStandardInstrumentIds.IdeHealthStatusV1);
114
115 /// <summary>Резолв style для mount в слоте MFD с учётом registry-правил.</summary>
116 public string MfdInstrumentMountStyle =>
117 MainWindowPresentationSurfaceProjection.ResolveInstrumentMountStyleForSlot(
118 _instrumentMountPolicyResolver,
119 _settings.Display,
120 ActiveAttentionLayoutSurface,
121 "mfd",
122 CockpitStandardInstrumentIds.IdeHealthStatusV1);
123 /// <summary>Полоса активной задачи / Task Cockpit — из <c>UiModes/&lt;id&gt;.toml</c> (<c>active_task_strip</c>); по умолчанию скрыто для семьи Debug.</summary>
124 public bool ShowTaskBar => UiModeCatalog.GetShowTaskBar(NormalizeUiMode(UiMode));
125
126 private UiModeCapabilities Capabilities =>
127 UiModeCatalog.GetCapabilities(NormalizeUiMode(UiMode));
128
129 public bool QuickActions => Capabilities.QuickActions;
130 public bool ShowAgentOperations => true;
131 /// <summary>В Focus справа показываем план и гейт, в Power — trace/safety; блок «операции» остаётся в Balanced.</summary>
132 public bool AgentOperationsPanel => Capabilities.AgentOperationsPanel;
133 public bool AgentTrace => Capabilities.AgentTrace;
134 public bool AutonomousAgentTelemetry => Capabilities.AutonomousAgentTelemetry;
135 /// <summary>Карточка уровня безопасности: в Power — safety.observe/confirm/autonomous; в Focus/Balanced — компактные кнопки (разметка в ChatPanelView).</summary>
136 public bool ShowSafetyControls => true;
137 public bool ShowTelemetryHiddenHint => UiModeGateSpecifications.ShowTelemetryHiddenHint.IsSatisfiedBy(
138 new UiModeGateContext(UiModeFamily, AutonomousAgentTelemetry, IsTerminalVisible, HasDebugSession));
139
140 /// <summary>
141 /// Дублирующая карточка IDE Health на вкладке «Терминал» в Power. Пока видна полоса <see cref="WorkspaceHealthStripView"/> под редактором —
142 /// false, чтобы DockPanel не отдавал высоту дублю и не схлопывал область вывода консоли.
143 /// </summary>
144 public bool IdeHealthOnTerminalTab =>
145 MainWindowPresentationCapabilitiesProjection.IdeHealthOnTerminalTab(Capabilities, ShowIdeHealthStrip);
146
147 /// <summary>Куда вести полосу IDE Health: нижняя полоса или страница зоны — из capabilities (<c>ide_health_surface</c>).</summary>
148 public IdeHealthUiSurface IdeHealthStripSurface => Capabilities.IdeHealthSurface;
149
150 /// <summary>Форма представления канала IDE Health на оси <see cref="ContentRepresentation"/> (ADR 0063).</summary>
151 public ContentRepresentation IdeHealthContentRepresentation => Capabilities.IdeHealthContentRepresentation;
152
153 /// <summary>Полоска build/tests/debug/git — при <c>ide_health_strip</c> и <c>bottom_strip</c>; рисуется в <see cref="Views.WorkspaceChromeBandView"/> внутри MFD.</summary>
154 public bool ShowIdeHealthStrip =>
155 MainWindowPresentationCapabilitiesProjection.ShowIdeHealthStrip(Capabilities);
156
157 /// <summary>IDE Health на странице оболочки Mfd (вместо нижней полосы) — при <c>ide_health_strip</c> и <c>ide_health_surface = dedicated_page</c> (v1 — колонка зоны Mfd).</summary>
158 public bool ShowIdeHealthMfdPage =>
159 MainWindowPresentationCapabilitiesProjection.ShowIdeHealthMfdPage(Capabilities);
160
161 /// <summary>
162 /// Полоса оповещений EICAS v1 (над полосой Workspace Health). Видно при <c>eicas_alerts_bar</c> и непустом списке (Dark Cockpit).
163 /// Отдельный контур от build/tests/debug/git (ADR 0021 §5; словарь §1.1).
164 /// </summary>
165 public bool ShowEicasAlertsBar =>
166 MainWindowPresentationCapabilitiesProjection.ShowEicasAlertsBar(Capabilities, EicasMessages.Count);
167
168 /// <summary>Область разметки над нижним доком: Workspace Health и/или полоса EICAS (<see cref="Views.WorkspaceChromeBandView"/>).</summary>
169 public bool ShowWorkspaceChromeBand =>
170 MainWindowPresentationCapabilitiesProjection.ShowWorkspaceChromeBand(
171 ShowIdeHealthStrip,
172 ShowEicasAlertsBar);
173
174 /// <summary>Зона под чатом в MFD: полоса EICAS / IDE Health и/или док (терминал, сборка, Problems, Git, инструменты).</summary>
175 public bool ShowWorkspaceBottomChrome =>
176 MainWindowPresentationCapabilitiesProjection.ShowWorkspaceBottomChrome(
177 ShowIdeHealthStrip,
178 ShowEicasAlertsBar,
179 IsMfdContourContentVisible);
180
181 /// <summary>Чат в одной строке с PFD/Forward; MFD не пересекает нижнюю строку MainGrid.</summary>
182 public int ChatPanelMainGridRowSpan => 1;
183
184 public string TelemetryButtonText =>
185 MainWindowPresentationSurfaceProjection.TelemetryButtonCaption(IsTerminalVisible);
186 public bool ShowEditorGroup2 => EditorGroupCount >= 2;
187 public bool ShowEditorGroup3 => EditorGroupCount >= 3;
188
189 /// <summary>Нижние вкладки «События / Тесты / Гипотезы / Отладка» при включённом доке.</summary>
190 public bool InstrumentationTabs =>
191 MainWindowPresentationCapabilitiesProjection.InstrumentationTabs(IsInstrumentationDockVisible, Capabilities);
192
193 /// <summary>Вкладка «Гипотезы» — семья Debug и capabilities (ADR 0003, ADR 0010).</summary>
194 public bool HypothesesTab =>
195 MainWindowPresentationCapabilitiesProjection.HypothesesTab(IsInstrumentationDockVisible, Capabilities);
196
197 /// <summary>Пункт меню для док-панели инструментирования (можно отключить и в Focus).</summary>
198 public bool ShowInstrumentationLayoutMenu => true;
199
200 public bool IsSafetyObserve =>
201 MainWindowPresentationCapabilitiesProjection.IsSafetyLevel(SafetyLevel, AgentSafetyLevel.Observe);
202 public bool IsSafetyConfirm =>
203 MainWindowPresentationCapabilitiesProjection.IsSafetyLevel(SafetyLevel, AgentSafetyLevel.Confirm);
204 public bool IsSafetyAutonomous =>
205 MainWindowPresentationCapabilitiesProjection.IsSafetyLevel(SafetyLevel, AgentSafetyLevel.Autonomous);
206
207 /// <summary>Подпись режима безопасности (как на мокапе Power).</summary>
208 public string SafetyLevelDescription =>
209 MainWindowPresentationSurfaceProjection.SafetyLevelDescription(SafetyLevel);
210
211 public double SafetyObserveOpacity =>
212 MainWindowPresentationSurfaceProjection.SafetyBadgeOpacity(IsSafetyObserve);
213 public double SafetyConfirmOpacity =>
214 MainWindowPresentationSurfaceProjection.SafetyBadgeOpacity(IsSafetyConfirm);
215 public double SafetyAutonomousOpacity =>
216 MainWindowPresentationSurfaceProjection.SafetyBadgeOpacity(IsSafetyAutonomous);
217
218 public bool HasFocusPlanItems => FocusPlanItems.Count > 0;
219
220 public bool IsRiskSummaryVisible =>
221 MainWindowPresentationSurfaceProjection.IsAgentSummaryVisibleComparedToPlaceholder(
222 RiskSummary,
223 MainWindowPresentationSurfaceProjection.DefaultRiskSummaryPlaceholder);
224
225 public bool IsResultSummaryVisible =>
226 MainWindowPresentationSurfaceProjection.IsAgentSummaryVisibleComparedToPlaceholder(
227 ResultSummary,
228 MainWindowPresentationSurfaceProjection.DefaultResultSummaryPlaceholder);
229
230 public bool IsRiskCardVisible =>
231 MainWindowPresentationCapabilitiesProjection.IsRiskCardVisible(Capabilities, IsRiskSummaryVisible);
232
233 public bool IsResultCardVisible =>
234 MainWindowPresentationCapabilitiesProjection.IsResultCardVisible(Capabilities, IsResultSummaryVisible);
235 public bool IsLocBadgeVisible => LocBadge > 0;
236
237 /// <summary>Строка бейджа LOC: число непустых строк и ось Low/Medium/High (пороги из <c>[loc_limits]</c>).</summary>
238 public string LocBadgeSummary =>
239 MainWindowPresentationCapabilitiesProjection.LocBadgeSummary(LocBadge, LocTierLabel);
240 public bool IsImpactedTestsBadgeVisible => ImpactedTestsBadge > 0;
241 public bool IsActiveTaskProgressVisible => ActiveTaskProgress > 0;
242
243 /// <summary>Строки из канала IDE Health (один снимок на <see cref="MainWindowViewModel.RebuildIdeHealth"/>, без повторного <c>Build()</c> в геттерах).</summary>
244 public string IdeHealthBuildText =>
245 IdeHealthStripPresentationProjection.SolutionBuildLineText(_lastIdeHealthInputSnapshot);
246
247 /// <summary>Короткий статус для «кольца» сборки в Power cockpit.</summary>
248 public string IdeHealthBuildCockpitShort =>
249 IdeHealthStripPresentationProjection.SolutionBuildCockpitShort(_lastIdeHealthInputSnapshot);
250
251 public string IdeHealthTestsText =>
252 IdeHealthStripPresentationProjection.SolutionTestsLineText(_lastIdeHealthInputSnapshot);
253
254 /// <summary>Компактная строка тестов для полосы Power.</summary>
255 public string IdeHealthTestsCockpitShort =>
256 IdeHealthStripPresentationProjection.SolutionTestsCockpitShort(_lastIdeHealthInputSnapshot);
257
258 /// <summary>Есть активная DAP-сессия (режим отладки, как в VS).</summary>
259 public bool HasDebugSession => _dapDebug.HasActiveSession;
260
261 /// <summary>Выполнение остановлено — доступны шаги и просмотр стека.</summary>
262 public bool IsDebugExecutionPaused =>
263 MainWindowPresentationDapProjection.IsDebugExecutionPaused(
264 _dapDebug.HasActiveSession,
265 _dapDebug.IsExecutionStopped);
266
267 /// <summary>Процесс запущен под отладчиком, выполнение идёт.</summary>
268 public bool IsDebugExecutionRunning =>
269 MainWindowPresentationDapProjection.IsDebugExecutionRunning(
270 _dapDebug.HasActiveSession,
271 _dapDebug.IsExecutionStopped);
272
273 public string IdeHealthDebugText =>
274 IdeHealthStripPresentationProjection.SolutionDebugLineText(_lastIdeHealthInputSnapshot);
275
276 /// <summary>Короткий статус отладки для Power.</summary>
277 public string IdeHealthDebugCockpitShort =>
278 IdeHealthStripPresentationProjection.SolutionDebugCockpitShort(_lastIdeHealthInputSnapshot);
279
280 public string ChatPanelToggleButtonText =>
281 MainWindowPresentationSurfaceProjection.MfdRegionToggleCaption(IsMfdRegionExpanded);
282
283 public bool IsPfdRegionCollapsed => !IsPfdRegionExpanded;
284
285 public bool IsMfdRegionCollapsed => !IsMfdRegionExpanded;
286
287 public bool IsSolutionPanelHidden => !IsPfdRegionExpanded;
288 public bool IsBuildPanelHidden => !IsBuildOutputVisible;
289 public bool IsChatPanelHidden => !IsMfdRegionExpanded;
290 public bool IsTerminalPanelHidden => !IsTerminalVisible;
291 public bool IsProblemsPanelVisible => Capabilities.ProblemsPanelVisible;
292
293 /// <summary>
294 /// Хотя бы один элемент контента вторичного контура колонки MFD (стек <c>MfdShellPageStack</c>) включён через «Вид»:
295 /// терминал, вывод сборки, Git, вкладки инструментации или страница Problems (если разрешена возможностями режима).
296 /// </summary>
297 public bool IsMfdContourContentVisible =>
298 MainWindowPresentationSurfaceProjection.IsMfdContourContentVisible(
299 IsProblemsPanelVisible,
300 IsTerminalVisible,
301 IsBuildOutputVisible,
302 InstrumentationTabs,
303 IsGitPanelVisible);
304
305 /// <summary>Совместимость: старые имена региона MFD в main grid (см. <see cref="ChatPanelColumnPixelWidth"/> и т.д.).</summary>
306 public int MfdRegionPixelWidth => ChatPanelColumnPixelWidth;
307
308 public bool IsMfdRegionVisible => IsChatPanelColumnVisible;
309
310 public string MfdRegionToggleButtonText => ChatPanelToggleButtonText;
311
312 /// <summary>Снимок для Skia mount — тот же тик, что <see cref="IdeHealthBuildCockpitShort"/>; обновляется в <see cref="MainWindowViewModel.RebuildIdeHealth"/>.</summary>
313 public IdeHealthStatusMountPayload IdeHealthMountPayload =>
314 _lastIdeHealthMountPayload ?? new IdeHealthStatusMountPayload("", "", "", SafetyLevel);
315
316 public bool IsPfdIdeHealthMountVisible =>
317 MainWindowPresentationSurfaceProjection.IsIdeHealthSkiaMountVisibleInDockedColumn(
318 UseSkiaInstrumentMount,
319 IsPfdColumnVisible);
320
321 public bool IsMfdIdeHealthMountVisible =>
322 MainWindowPresentationSurfaceProjection.IsIdeHealthSkiaMountVisibleInDockedColumn(
323 UseSkiaInstrumentMount,
324 IsMfdColumnVisible);
325
326 public bool IsMfdHostWindowIdeHealthMountVisible =>
327 MainWindowPresentationSurfaceProjection.IsIdeHealthSkiaMountVisibleForHostWindow(
328 UseSkiaInstrumentMount,
329 IsMfdHostWindowShellOpen);
330
331 public bool IsPfdHostWindowIdeHealthMountVisible =>
332 MainWindowPresentationSurfaceProjection.IsIdeHealthSkiaMountVisibleForHostWindow(
333 UseSkiaInstrumentMount,
334 IsPfdHostWindowShellOpen);
335
336 public IdeHealthStatusMountContext? PfdIdeHealthMountContext =>
337 MainWindowPresentationSurfaceProjection.ResolvePfdIdeHealthMountContext(
338 UseSkiaInstrumentMount,
339 IsPfdHostWindowShellOpen,
340 IsPfdColumnVisible,
341 _instrumentMountPolicyResolver,
342 _settings.Display,
343 MainWindowPresentationSurfaceProjection.MountPolicySurfaceId(ActiveAttentionLayoutSurface),
344 IdeHealthMountPayload);
345
346 public IdeHealthStatusMountContext? MfdIdeHealthMountContext =>
347 MainWindowPresentationSurfaceProjection.ResolveMfdIdeHealthMountContext(
348 UseSkiaInstrumentMount,
349 IsMfdHostWindowShellOpen,
350 IsMfdColumnVisible,
351 _instrumentMountPolicyResolver,
352 _settings.Display,
353 MainWindowPresentationSurfaceProjection.MountPolicySurfaceId(ActiveAttentionLayoutSurface),
354 IdeHealthMountPayload);
355}
356
View only · write via MCP/CIDE