Forge
csharp4405de34
1using CascadeIDE.Cockpit;
2using CascadeIDE.Cockpit.Cds;
3using CascadeIDE.Cockpit.Composition.HostSurface;
4using CascadeIDE.Cockpit.Composition.Shell;
5using CascadeIDE.Contracts;
6using CascadeIDE.Features.Agent.Environment;
7using CascadeIDE.Features.UiChrome;
8using CascadeIDE.Lang;
9using CascadeIDE.Models;
10
11namespace CascadeIDE.Features.Shell.Application;
12
13/// <summary>
14/// Статические проекции для вычисляемых свойств главного окна (видимость, подписи, mount-контекст без логики на VM).
15/// </summary>
16[PresentationProjection]
17public static class MainWindowPresentationSurfaceProjection
18{
19 /// <summary>Кадр хоста: intent + CDS style → shell + инструменты (ADR 0036 п.3, 0047).</summary>
20 public static MainWindowHostSurfaceFrame ComposeHostSurfaceFrame(
21 IMainWindowHostSurfaceInput host,
22 string normalizedUiMode,
23 MfdShellPage currentMfdShellPage,
24 PrimaryWorkSurfaceKind primaryWorkSurface) =>
25 MainWindowHostSurfaceProjection.ComposeFrame(
26 host,
27 ResolveExpandedMfdWidthPixels(normalizedUiMode, currentMfdShellPage, primaryWorkSurface),
28 UiWorkspaceLayoutRuntimeMetrics.MfdRegionCollapsedWidthPixels);
29
30 /// <summary>
31 /// Ширина колонки MFD: для страницы «Чат» — не уже <see cref="UiWorkspaceLayoutRuntimeMetrics.MfdRegionExpandedAgentChatWidthPixels"/> (520).
32 /// </summary>
33 public static int ResolveExpandedMfdWidthPixels(
34 string normalizedUiMode,
35 MfdShellPage currentMfdShellPage,
36 PrimaryWorkSurfaceKind primaryWorkSurface)
37 {
38 _ = primaryWorkSurface;
39 var modeDefault = UiModeCatalog.GetMfdRegionExpandedWidthPixels(normalizedUiMode);
40 if (currentMfdShellPage != MfdShellPage.Chat)
41 return modeDefault;
42
43 return Math.Max(modeDefault, UiWorkspaceLayoutRuntimeMetrics.MfdRegionExpandedAgentChatWidthPixels);
44 }
45
46 public const string DefaultRiskSummaryPlaceholder = "Риски не зафиксированы.";
47 public const string DefaultResultSummaryPlaceholder = "Результатов пока нет.";
48
49 public static string ResolveWindowTitle(string normalizedUiMode)
50 {
51 var o = UiModeCatalog.GetWindowTitleOverride(normalizedUiMode);
52 if (o is not null)
53 return o;
54 return UiModeFamilyResolver.FromNormalizedMode(normalizedUiMode) switch
55 {
56 UiModeFamily.Power => "CascadeIDE — Power Mode [Autonomous Agent Cockpit]",
57 UiModeFamily.AgentChat => "CascadeIDE — Agent Chat",
58 UiModeFamily.Debug => "CascadeIDE — Debug",
59 UiModeFamily.Editor => "CascadeIDE — Editor",
60 _ => "CascadeIDE",
61 };
62 }
63
64 public static string InstrumentMountDisplayStyle(DisplaySettings display) =>
65 string.IsNullOrWhiteSpace(display.Mount.DefaultStyle)
66 ? InstrumentMountPolicyIds.V1
67 : display.Mount.DefaultStyle.Trim();
68
69 public static string MountPolicySurfaceId(AttentionLayoutSurfaceKind surface) =>
70 surface switch
71 {
72 AttentionLayoutSurfaceKind.MainWindowDockedGrid => "main_window_docked_grid",
73 AttentionLayoutSurfaceKind.MainWindowPlusMfdHostTopLevel => "main_window_plus_mfd_host_top_level",
74 AttentionLayoutSurfaceKind.MainWindowPlusPfdHostTopLevel => "main_window_plus_pfd_host_top_level",
75 AttentionLayoutSurfaceKind.MainWindowPlusPfdMfdHostTopLevel => "main_window_plus_pfd_mfd_host_top_level",
76 _ => "main_window_docked_grid",
77 };
78
79 /// <summary>Сплиттер и колонка main grid: ширина слота &gt; 0.</summary>
80 public static bool IsMainGridSplitColumnVisible(int columnWidthPixels) => columnWidthPixels > 0;
81
82 public static bool IsIdeHealthSkiaMountVisibleInDockedColumn(bool useSkiaInstrumentMount, bool columnVisible) =>
83 useSkiaInstrumentMount && columnVisible;
84
85 public static bool IsIdeHealthSkiaMountVisibleForHostWindow(bool useSkiaInstrumentMount, bool hostShellOpen) =>
86 useSkiaInstrumentMount && hostShellOpen;
87
88 public static string ResolveInstrumentMountStyleForSlot(
89 IInstrumentMountPolicyResolver resolver,
90 DisplaySettings displaySettings,
91 AttentionLayoutSurfaceKind attentionSurface,
92 string slotId,
93 string instrumentId)
94 {
95 var surfaceId = MountPolicySurfaceId(attentionSurface);
96 return resolver.Resolve(displaySettings, surfaceId, slotId, instrumentId);
97 }
98
99 public static bool IsMfdContourContentVisible(
100 bool problemsPanelVisible,
101 bool isTerminalVisible,
102 bool isBuildOutputVisible,
103 bool instrumentationTabs,
104 bool isGitPanelVisible) =>
105 problemsPanelVisible || isTerminalVisible || isBuildOutputVisible || instrumentationTabs || isGitPanelVisible;
106
107 public static string TelemetryButtonCaption(bool terminalVisible) =>
108 terminalVisible ? "Telemetry: on" : "Show telemetry";
109
110 public static string MfdRegionToggleCaption(bool isMfdRegionExpanded) =>
111 isMfdRegionExpanded ? "◀" : "▶";
112
113 public static string SafetyLevelDescription(string safetyLevel) =>
114 safetyLevel switch
115 {
116 AgentSafetyLevel.Observe => Resources.Safety_Description_Observe,
117 AgentSafetyLevel.Confirm => Resources.Safety_Description_Confirm,
118 AgentSafetyLevel.Autonomous => Resources.Safety_Description_Autonomous,
119 _ => "",
120 };
121
122 public static double SafetyBadgeOpacity(bool isActiveLevel) => isActiveLevel ? 1 : 0.38;
123
124 /// <summary>Текст задан и отличается от плейсхолдера «нет данных».</summary>
125 public static bool IsAgentSummaryVisibleComparedToPlaceholder(string? text, string placeholder) =>
126 !string.IsNullOrWhiteSpace(text)
127 && !string.Equals(text, placeholder, StringComparison.Ordinal);
128
129 /// <remarks>Повторяет ветвление прежних геттеров <c>PfdIdeHealthMountContext</c>/<c>MfdIdeHealthMountContext</c>.</remarks>
130 public static IdeHealthStatusMountContext? ResolvePfdIdeHealthMountContext(
131 bool useSkiaInstrumentMount,
132 bool isPfdHostWindowShellOpen,
133 bool isPfdColumnVisible,
134 IInstrumentMountPolicyResolver resolver,
135 DisplaySettings displaySettings,
136 string mountPolicySurfaceIdForMainDockedGrid,
137 IdeHealthStatusMountPayload payload)
138 {
139 if (!useSkiaInstrumentMount)
140 return null;
141 if (isPfdHostWindowShellOpen)
142 return IdeHealthMountContextFactory.Create(
143 resolver,
144 displaySettings,
145 "main_window_plus_pfd_host_top_level",
146 CockpitSlotIds.Pfd,
147 payload);
148 if (isPfdColumnVisible)
149 return IdeHealthMountContextFactory.Create(
150 resolver,
151 displaySettings,
152 mountPolicySurfaceIdForMainDockedGrid,
153 CockpitSlotIds.Pfd,
154 payload);
155 return null;
156 }
157
158 public static IdeHealthStatusMountContext? ResolveMfdIdeHealthMountContext(
159 bool useSkiaInstrumentMount,
160 bool isMfdHostWindowShellOpen,
161 bool isMfdColumnVisible,
162 IInstrumentMountPolicyResolver resolver,
163 DisplaySettings displaySettings,
164 string mountPolicySurfaceIdForMainDockedGrid,
165 IdeHealthStatusMountPayload payload)
166 {
167 if (!useSkiaInstrumentMount)
168 return null;
169 if (isMfdHostWindowShellOpen)
170 return IdeHealthMountContextFactory.Create(
171 resolver,
172 displaySettings,
173 "main_window_plus_mfd_host_top_level",
174 CockpitSlotIds.Mfd,
175 payload);
176 if (isMfdColumnVisible)
177 return IdeHealthMountContextFactory.Create(
178 resolver,
179 displaySettings,
180 mountPolicySurfaceIdForMainDockedGrid,
181 CockpitSlotIds.Mfd,
182 payload);
183 return null;
184 }
185}
186
View only · write via MCP/CIDE