diff --git a/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs b/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs index 3305459..f6132e9 100644 --- a/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs +++ b/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs @@ -183,7 +183,7 @@ public class DebuggingService } } } - catch (Exception ex) + catch (Exception) { throw; } diff --git a/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs b/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs index 20270a0..06e17cd 100644 --- a/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs +++ b/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs @@ -124,6 +124,6 @@ public partial class ProblemsPanel : Control var file = projectModel.Files .Concat(projectModel.Folders.SelectMany(f => f.GetAllFiles())) .Single(s => s.Path == diagnostic.Location.SourceTree?.GetMappedLineSpan(diagnostic.Location.SourceSpan).Path); - GodotGlobalEvents.InvokeFileSelected(file); + GodotGlobalEvents.InvokeFileExternallySelected(file); } } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs index 7e4ca55..d15ed57 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs @@ -24,6 +24,7 @@ public partial class SolutionExplorerPanel : MarginContainer { _tree = GetNode("Tree"); _tree.ItemMouseSelected += TreeOnItemMouseSelected; + GodotGlobalEvents.FileExternallySelected += OnFileExternallySelected; } private void TreeOnItemMouseSelected(Vector2 mousePosition, long mouseButtonIndex) @@ -36,6 +37,40 @@ public partial class SolutionExplorerPanel : MarginContainer Guard.Against.Null(sharpIdeFile, nameof(sharpIdeFile)); GodotGlobalEvents.InvokeFileSelected(sharpIdeFile); } + + private async Task OnFileExternallySelected(SharpIdeFile file) + { + GodotGlobalEvents.InvokeFileSelected(file); + var item = FindItemRecursive(_tree.GetRoot(), file); + if (item is not null) + { + await this.InvokeAsync(() => + { + item.UncollapseTree(); + _tree.SetSelected(item, 0); + _tree.ScrollToItem(item, true); + }); + } + } + + private static TreeItem? FindItemRecursive(TreeItem item, SharpIdeFile file) + { + var metadata = item.GetMetadata(0); + if (metadata.As()?.File == file) + return item; + + var child = item.GetFirstChild(); + while (child != null) + { + var result = FindItemRecursive(child, file); + if (result != null) + return result; + + child = child.GetNext(); + } + + return null; + } public void RepopulateTree() { diff --git a/src/SharpIDE.Godot/GodotGlobalEvents.cs b/src/SharpIDE.Godot/GodotGlobalEvents.cs index fbdabc4..c6ee5cd 100644 --- a/src/SharpIDE.Godot/GodotGlobalEvents.cs +++ b/src/SharpIDE.Godot/GodotGlobalEvents.cs @@ -16,6 +16,10 @@ public static class GodotGlobalEvents public static event Func FileSelected = _ => Task.CompletedTask; public static void InvokeFileSelected(SharpIdeFile file) => FileSelected.InvokeParallelFireAndForget(file); + public static event Func FileExternallySelected = _ => Task.CompletedTask; + public static void InvokeFileExternallySelected(SharpIdeFile file) => FileExternallySelected.InvokeParallelFireAndForget(file); + public static async Task InvokeFileExternallySelectedAndWait(SharpIdeFile file) => await FileExternallySelected.InvokeParallelAsync(file); + } public enum BottomPanelType diff --git a/src/SharpIDE.Godot/IdeRoot.cs b/src/SharpIDE.Godot/IdeRoot.cs index 344d64c..977c1e9 100644 --- a/src/SharpIDE.Godot/IdeRoot.cs +++ b/src/SharpIDE.Godot/IdeRoot.cs @@ -41,11 +41,11 @@ public partial class IdeRoot : Control _runMenuButton.Pressed += OnRunMenuButtonPressed; GodotGlobalEvents.FileSelected += OnSolutionExplorerPanelOnFileSelected; - _fileDialog.FileSelected += OnFileSelected; + _fileDialog.FileSelected += OnSlnFileSelected; _openSlnButton.Pressed += () => _fileDialog.Visible = true; _buildSlnButton.Pressed += OnBuildSlnButtonPressed; GodotGlobalEvents.BottomPanelVisibilityChangeRequested += async show => await this.InvokeAsync(() => _invertedVSplitContainer.InvertedSetCollapsed(!show)); - OnFileSelected(@"C:\Users\Matthew\Documents\Git\BlazorCodeBreaker\BlazorCodeBreaker.slnx"); + OnSlnFileSelected(@"C:\Users\Matthew\Documents\Git\BlazorCodeBreaker\BlazorCodeBreaker.slnx"); } private void OnRunMenuButtonPressed() @@ -67,7 +67,7 @@ public partial class IdeRoot : Control await _sharpIdeCodeEdit.SetSharpIdeFile(file); } - private void OnFileSelected(string path) + private void OnSlnFileSelected(string path) { _ = Task.GodotRun(async () => { @@ -94,9 +94,9 @@ public partial class IdeRoot : Control _runMenuButton.Disabled = false; }); - var infraProject = solutionModel.AllProjects.Single(s => s.Name == "Infrastructure"); - var diFile = infraProject.Files.Single(s => s.Name == "DependencyInjection.cs"); - await this.InvokeDeferredAsync(async () => await _sharpIdeCodeEdit.SetSharpIdeFile(diFile)); + var infraProject = solutionModel.AllProjects.Single(s => s.Name == "WebUi"); + var diFile = infraProject.Folders.Single(s => s.Name == "Pages").Files.Single(s => s.Name == "TestPage.razor"); + await this.InvokeDeferredAsync(() => GodotGlobalEvents.InvokeFileExternallySelected(diFile)); //var runnableProject = solutionModel.AllProjects.First(s => s.IsRunnable); //await this.InvokeAsync(() => _runPanel.NewRunStarted(runnableProject)); diff --git a/src/SharpIDE.Godot/SharpIdeCodeEdit.cs b/src/SharpIDE.Godot/SharpIdeCodeEdit.cs index 844c279..c44078f 100644 --- a/src/SharpIDE.Godot/SharpIdeCodeEdit.cs +++ b/src/SharpIDE.Godot/SharpIdeCodeEdit.cs @@ -57,7 +57,7 @@ public partial class SharpIdeCodeEdit : CodeEdit if (executionStopInfo.FilePath != _currentFile.Path) { var file = Solution.AllFiles.Single(s => s.Path == executionStopInfo.FilePath); - await this.InvokeAsync(async () => await SetSharpIdeFile(file)); + await GodotGlobalEvents.InvokeFileExternallySelectedAndWait(file); } var lineInt = executionStopInfo.Line - 1; // Debugging is 1-indexed, Godot is 0-indexed Guard.Against.Negative(lineInt, nameof(lineInt)); @@ -165,11 +165,15 @@ public partial class SharpIdeCodeEdit : CodeEdit // TODO: Ensure not running on UI thread public async Task SetSharpIdeFile(SharpIdeFile file) { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); // get off the UI thread _currentFile = file; var fileContents = await File.ReadAllTextAsync(_currentFile.Path); - _fileChangingSuppressBreakpointToggleEvent = true; - SetText(fileContents); - _fileChangingSuppressBreakpointToggleEvent = false; + await this.InvokeAsync(() => + { + _fileChangingSuppressBreakpointToggleEvent = true; + SetText(fileContents); + _fileChangingSuppressBreakpointToggleEvent = false; + }); var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile); var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile); var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile);