Forge
csharpdeeb25a2
1using System.ComponentModel;
2using Avalonia;
3using Avalonia.Controls;
4using Avalonia.Input;
5using Avalonia.Interactivity;
6using CascadeIDE.Cockpit.Surface;
7
8namespace CascadeIDE.Views;
9
10public partial class MainWindow : PointerTrackingWindow
11{
12 private Services.CSharpLanguageService? _languageService;
13 private MarkdownPreviewWindow? _previewWindow;
14 private ViewModels.MarkdownPreviewWindowViewModel? _previewVm;
15 private ViewModels.MainWindowViewModel? _boundMainVm;
16 private PropertyChangedEventHandler? _navigationMapHandler;
17 private bool _workspaceEventsAttached;
18 private static readonly object HighlightLogLock = new();
19
20 public MainWindow()
21 {
22 InitializeComponent();
23 Closing += OnMainWindowClosing;
24 // Глобальные хоткеи: tunnel + KeyGestureChordMatching + KeyBindings (см. MainWindowHotkeyService).
25 AddHandler(InputElement.KeyDownEvent, OnDebugShortcutKeyDown, RoutingStrategies.Tunnel, handledEventsToo: true);
26 DataContextChanged += OnDataContextChanged;
27 Loaded += OnMainWindowLoaded;
28 Activated += OnMainWindowFocusChanged;
29 Deactivated += OnMainWindowFocusChanged;
30 // Хосты PFD/MFD/PM: после первого показа главного окна — иначе Show(child, owner) падает, пока owner ещё не visible (headless/тесты).
31 Opened += OnMainWindowOpenedPresentationHosts;
32 }
33
34 private void OnMainWindowFocusChanged(object? sender, EventArgs e)
35 {
36 if (DataContext is not ViewModels.MainWindowViewModel vm)
37 return;
38
39 vm.NotifyCideWindowFocusChanged(IsActive);
40 }
41
42 private void OnMainWindowOpenedPresentationHosts(object? sender, EventArgs e)
43 {
44 Opened -= OnMainWindowOpenedPresentationHosts;
45 TryOpenPfdHostWindowOnStartup();
46 TryOpenMfdHostWindowOnStartup();
47 TryOpenPmSplitHostWindowOnStartup();
48 }
49
50 private void OnMainWindowClosing(object? sender, WindowClosingEventArgs e)
51 {
52 if (DataContext is ViewModels.MainWindowViewModel vm)
53 {
54 vm.ShutdownEditorStabilizedInput();
55 vm.ReleaseWorkspaceHealthChannel();
56 }
57 }
58
59 private void OnMainWindowLoaded(object? sender, RoutedEventArgs e)
60 {
61 if (DataContext is ViewModels.MainWindowViewModel vm)
62 {
63 _boundMainVm = vm;
64 if (vm.PresentationRequestsMainWindowMaximized)
65 WindowState = WindowState.Maximized;
66 }
67
68 TryApplyHotkeys();
69
70 if (DataContext is ViewModels.MainWindowViewModel loadedVm)
71 {
72 _ = loadedVm.FlushPendingMagicLinksAsync();
73 _ = loadedVm.TryCompletePresentationTierFirstRunAsync(this);
74 }
75 }
76
77 private void TryApplyHotkeys()
78 {
79 if (DataContext is ViewModels.MainWindowViewModel vm)
80 Features.Shell.Application.MainWindowViewServices.ApplyHotkeys(this, vm);
81 }
82
83 private void OnDataContextChanged(object? sender, EventArgs e)
84 {
85 if (DataContext is ViewModels.MainWindowViewModel vm)
86 {
87 if (_boundMainVm is not null)
88 _boundMainVm.GotoActiveEditorLineColumnRequested -= OnGotoEditorLineColumn;
89 _boundMainVm = vm;
90 vm.GotoActiveEditorLineColumnRequested += OnGotoEditorLineColumn;
91 WireAgentVerifyEpochDim(vm);
92
93 vm.LoadSendMessageKeyFromStorage();
94 vm.LoadComposerNewLineKeyFromStorage();
95 vm.PropertyChanged += OnViewModelPropertyChanged;
96 _navigationMapHandler ??= OnNavigationMapPropertyChanged;
97 vm.NavigationMap.PropertyChanged += _navigationMapHandler;
98 vm.RequestOpenSolution = () => _ = ShowOpenSolutionDialogAsync();
99 vm.RequestCreateNewSolution = () => _ = ShowCreateNewSolutionDialogAsync();
100 vm.RequestOpenFolder = () => _ = ShowOpenFolderDialogAsync();
101 vm.RequestOpenFile = () => _ = ShowOpenFileDialogAsync();
102 vm.RequestClose = Close;
103 vm.RequestShowAbout = ShowAbout;
104 vm.RequestOpenSettings = ShowSettingsWindow;
105 vm.RequestToggleMfdHostWindow = ToggleMfdHostWindow;
106 vm.RequestTogglePfdHostWindow = TogglePfdHostWindow;
107 vm.RequestTogglePmSplitHostWindow = TogglePmSplitHostWindow;
108 vm.RequestOpenThemeFile = ShowOpenThemeFileDialogAsync;
109 vm.RequestShowMarkdownPreviewWindow = ShowMarkdownPreviewWindow;
110 vm.RequestShowMarkdownPreviewForEditor = ShowMarkdownPreviewForEditor;
111 vm.RequestConfirmation = ShowConfirmationDialogAsync;
112 vm.RequestPickDebugTarget = ShowPickDebugTargetAsync;
113 vm.RequestAttachProcessId = ShowAttachProcessIdAsync;
114 vm.RequestShowInfoAsync = ShowInfoDialogAsync;
115 vm.RequestPickFeatureDocAsync = (title, docs) => FeatureDocsPickDialog.ShowAsync(this, title, docs);
116 vm.RequestSaveMarkdownFile = ShowSaveExpandedMarkdownDialogAsync;
117 vm.CaptureWindowForMcpAsync = (ws, rel, scope) => CaptureWindowForMcpCoreAsync(ws, rel, scope);
118 vm.GetUiLayoutProvider = () => UiLayoutSnapshot.BuildJsonAllWindows(this);
119 vm.GetColorsUnderCursorProvider = () => Features.Shell.Application.MainWindowViewServices.GetColorsUnderCursorJson(this);
120 vm.GetControlAppearanceProvider = name =>
121 Features.Shell.Application.MainWindowViewServices.GetControlAppearanceJson(this, name ?? "");
122 vm.SetControlLayoutProvider = (name, json) =>
123 Features.Shell.Application.MainWindowViewServices.ApplyControlLayout(this, name, json);
124 vm.AddControlProvider = (parentName, controlType, content, controlName) => Services.UiControlAdd.AddControl(this, parentName, controlType, content, controlName);
125 vm.SetControlTextProvider = (name, text) =>
126 {
127 var result = Services.UiControlSetText.SetText(this, name, text);
128 if (name is "ChatInputBox" or "IntercomSkiaSurface")
129 vm.ChatPanel.ChatInput = text ?? "";
130 return result;
131 };
132 vm.ClickControlProvider = (name) => Services.UiControlClick.Click(this, this, name);
133 vm.SendKeysProvider = (name, keys) => Services.UiControlSendKeys.SendKeys(this, this, name, keys);
134 vm.SetFocusProvider = (name) => Services.UiControlSetFocus.SetFocus(this, this, name);
135 vm.HighlightControlProvider = ShowHighlightForControl;
136 vm.SetPanelSizeProvider = (panel, width, height) => Services.UiPanelResize.Resize(this, panel, width, height);
137 UpdateChatColumnWidth(vm);
138 UpdateSolutionColumnWidth(vm.IsPfdColumnVisible);
139 SetupEditorAndTextMate();
140 TryApplyHotkeys();
141 ApplyMainGridColumnDefinitions(vm);
142 AttachSkiaHostRenderers();
143 InvalidateSkiaHosts();
144 }
145 else
146 {
147 if (_boundMainVm is not null)
148 {
149 _boundMainVm.GotoActiveEditorLineColumnRequested -= OnGotoEditorLineColumn;
150 _boundMainVm.PropertyChanged -= OnViewModelPropertyChanged;
151 if (_navigationMapHandler is not null)
152 _boundMainVm.NavigationMap.PropertyChanged -= _navigationMapHandler;
153 _boundMainVm.CaptureWindowForMcpAsync = null;
154 _boundMainVm = null;
155 }
156
157 ClosePfdHostWindowIfOpen();
158 CloseMfdHostWindowIfOpen();
159 ClosePmSplitHostWindowIfOpen();
160 }
161 }
162
163 private void OnNavigationMapPropertyChanged(object? sender, PropertyChangedEventArgs e)
164 {
165 if (IsSkiaHostRelatedProperty(e.PropertyName))
166 InvalidateSkiaHosts();
167 }
168}
169
View only · write via MCP/CIDE