Forge
csharpdeeb25a2
1using System.ComponentModel;
2using Avalonia.Threading;
3using CascadeIDE.Features.Editor.Application.Monaco;
4using CascadeIDE.Services;
5
6namespace CascadeIDE.Views;
7
8public partial class MainWindow
9{
10 private void SetupEditorAndTextMate()
11 {
12 if (DataContext is not ViewModels.MainWindowViewModel vmSetup)
13 return;
14
15 _languageService = vmSetup.CSharpLanguage;
16
17 vmSetup.SetApplyEdit((path, sl, sc, el, ec, newText) =>
18 _ = vmSetup.Documents.ApplyMcpEditToDocument(path, sl, sc, el, ec, newText));
19 vmSetup.SetRevealEditorRange((path, start, end, duration) =>
20 vmSetup.EditorNavigation.TryNavigateReveal(
21 path,
22 start,
23 end,
24 duration,
25 EditorNavigationSource.Mcp));
26 vmSetup.SetFocusEditor(() =>
27 {
28 if (DataContext is not ViewModels.MainWindowViewModel vm)
29 return;
30 EditorActiveDockResolver.TryGetDockDocumentView(vm, vm.CurrentFilePath)?.FocusMonacoEditor();
31 });
32
33 if (!_workspaceEventsAttached)
34 {
35 _workspaceEventsAttached = true;
36 vmSetup.Workspace.PropertyChanged += (_, e) =>
37 {
38 if (e.PropertyName is nameof(CascadeIDE.Features.Workspace.SolutionWorkspaceViewModel.SolutionPath))
39 _languageService?.InvalidateCache();
40 };
41 }
42 }
43
44 internal void AttachTextMateWhenEditorReady()
45 {
46 // Monaco forward host: document setup is owned by DockDocumentView.
47 }
48
49 private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
50 {
51 if (e.PropertyName is nameof(ViewModels.MainWindowViewModel.CurrentFilePath)
52 && DataContext is ViewModels.MainWindowViewModel vmPath)
53 {
54 _languageService?.InvalidateCache();
55 _ = RefreshActiveDockDebugVisualsAsync(vmPath);
56 }
57
58 if (e.PropertyName is nameof(ViewModels.MainWindowViewModel.EditorSelectionStart)
59 or nameof(ViewModels.MainWindowViewModel.EditorSelectionLength)
60 && DataContext is ViewModels.MainWindowViewModel vm
61 && vm.EditorSelectionStart is { } start
62 && vm.EditorSelectionLength is { } length)
63 {
64 ApplyEditorSelection(start, length);
65 vm.EditorSelectionStart = null;
66 vm.EditorSelectionLength = null;
67 }
68
69 if ((e.PropertyName is nameof(ViewModels.MainWindowViewModel.IsPfdRegionExpanded) or nameof(ViewModels.MainWindowViewModel.IsPfdColumnVisible))
70 && DataContext is ViewModels.MainWindowViewModel vmSol)
71 UpdateSolutionColumnWidth(vmSol.IsPfdColumnVisible);
72 if ((e.PropertyName is nameof(ViewModels.MainWindowViewModel.IsMfdRegionExpanded)
73 or nameof(ViewModels.MainWindowViewModel.UiMode)
74 or nameof(ViewModels.MainWindowViewModel.CurrentMfdShellPage)
75 or nameof(ViewModels.MainWindowViewModel.MfdRegionPixelWidth) or nameof(ViewModels.MainWindowViewModel.IsMfdRegionVisible)
76 or nameof(ViewModels.MainWindowViewModel.IsMfdColumnVisible)
77 or nameof(ViewModels.MainWindowViewModel.ChatPanelColumnPixelWidth))
78 && DataContext is ViewModels.MainWindowViewModel vmChat)
79 UpdateChatColumnWidth(vmChat);
80 if (e.PropertyName is nameof(ViewModels.MainWindowViewModel.IsCommandPaletteOpen) && DataContext is ViewModels.MainWindowViewModel vmPalette)
81 HandleCommandPaletteOpenStateChanged(vmPalette.IsCommandPaletteOpen);
82 if (e.PropertyName is nameof(ViewModels.MainWindowViewModel.SelectedOllamaModel) && DataContext is ViewModels.MainWindowViewModel vm2
83 && vm2.SelectedOllamaModel == ViewModels.MainWindowViewModel.InstallNewSentinel)
84 _ = ShowInstallModelDialogAsync(vm2);
85 if (e.PropertyName is nameof(ViewModels.MainWindowViewModel.BreakpointLinesInCurrentFile)
86 or nameof(ViewModels.MainWindowViewModel.AllBreakpointLinesInCurrentFile)
87 or nameof(ViewModels.MainWindowViewModel.CurrentFilePath)
88 or nameof(ViewModels.MainWindowViewModel.DebugCurrentLineInCurrentFile)
89 or nameof(ViewModels.MainWindowViewModel.DebugPositionFile)
90 or nameof(ViewModels.MainWindowViewModel.DebugPositionLine))
91 {
92 if (DataContext is ViewModels.MainWindowViewModel mainVm)
93 _ = RefreshActiveDockDebugVisualsAsync(mainVm);
94 }
95
96 if (e.PropertyName == nameof(ViewModels.MainWindowViewModel.MainGridColumnDefinitions) && sender is ViewModels.MainWindowViewModel gridVm)
97 ApplyMainGridColumnDefinitions(gridVm);
98 if (e.PropertyName == nameof(ViewModels.MainWindowViewModel.MainGridRowDefinitions) && sender is ViewModels.MainWindowViewModel rowVm)
99 ApplyMainGridRowDefinitions(rowVm);
100 if (IsSkiaHostRelatedProperty(e.PropertyName))
101 InvalidateSkiaHosts();
102 }
103
104 private static async Task RefreshActiveDockDebugVisualsAsync(ViewModels.MainWindowViewModel vm)
105 {
106 var dock = EditorActiveDockResolver.TryGetDockDocumentView(vm, vm.CurrentFilePath);
107 if (dock is null)
108 return;
109
110 await dock.PushMonacoDebugVisualsAsync().ConfigureAwait(true);
111
112 if (vm.DebugCurrentLineInCurrentFile is var debugLine && debugLine > 0)
113 await dock.GotoLineColumnAsync(debugLine, 1).ConfigureAwait(true);
114 }
115
116 private void OnGotoEditorLineColumn(int line1, int column1)
117 {
118 if (DataContext is not ViewModels.MainWindowViewModel vm)
119 return;
120
121 var dock = EditorActiveDockResolver.TryGetDockDocumentView(vm, vm.CurrentFilePath);
122 if (dock is null)
123 return;
124
125 _ = dock.GotoLineColumnAsync(line1, column1);
126 }
127
128 private void ApplyEditorSelection(int start, int length)
129 {
130 if (DataContext is not ViewModels.MainWindowViewModel vm)
131 return;
132
133 var dock = EditorActiveDockResolver.TryGetDockDocumentView(vm, vm.CurrentFilePath);
134 if (dock is null)
135 return;
136
137 _ = dock.SetSelectionAsync(start, length);
138 }
139
140 private void OnRefreshActiveEditorEpochDim(bool dimmed)
141 {
142 if (DataContext is not ViewModels.MainWindowViewModel vm)
143 return;
144
145 var dock = EditorActiveDockResolver.TryGetDockDocumentView(vm, vm.CurrentFilePath);
146 if (dock is null)
147 return;
148
149 _ = dock.SetEpochDimAsync(dimmed);
150 }
151
152 internal void WireAgentVerifyEpochDim(ViewModels.MainWindowViewModel vm)
153 {
154 vm.RefreshActiveEditorEpochDimRequested -= OnRefreshActiveEditorEpochDim;
155 vm.RefreshActiveEditorEpochDimRequested += OnRefreshActiveEditorEpochDim;
156 }
157
158 private const int RevealEditorRangeMaxAttempts = 10;
159
160 private void RevealEditorRangeInDock(string? filePath, int startLine, int endLine, int? durationMs = null) =>
161 RevealEditorRangeInDockWithRetry(filePath, startLine, endLine, durationMs, attempt: 0);
162
163 private void RevealEditorRangeInDockWithRetry(string? filePath, int startLine, int endLine, int? durationMs, int attempt)
164 {
165 if (DataContext is not ViewModels.MainWindowViewModel vm)
166 return;
167
168 if (EditorActiveDockResolver.TryGetDockDocumentView(vm, filePath)?.TryRevealEditorRange(startLine, endLine, durationMs) == true)
169 return;
170
171 if (attempt >= RevealEditorRangeMaxAttempts)
172 return;
173
174 Dispatcher.UIThread.Post(
175 () => RevealEditorRangeInDockWithRetry(filePath, startLine, endLine, durationMs, attempt + 1),
176 DispatcherPriority.Background);
177 }
178}
179
View only · write via MCP/CIDE