use DI in Godot Nodes
This commit is contained in:
@@ -9,10 +9,12 @@ namespace SharpIDE.Application.Features.FileWatching;
|
|||||||
|
|
||||||
public class IdeFileSavedToDiskHandler
|
public class IdeFileSavedToDiskHandler
|
||||||
{
|
{
|
||||||
|
private readonly IdeOpenTabsFileManager _openTabsFileManager;
|
||||||
public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
|
public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
|
||||||
|
|
||||||
public IdeFileSavedToDiskHandler()
|
public IdeFileSavedToDiskHandler(IdeOpenTabsFileManager openTabsFileManager)
|
||||||
{
|
{
|
||||||
|
_openTabsFileManager = openTabsFileManager;
|
||||||
GlobalEvents.Instance.IdeFileSavedToDisk.Subscribe(HandleIdeFileChanged);
|
GlobalEvents.Instance.IdeFileSavedToDisk.Subscribe(HandleIdeFileChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +42,11 @@ public class IdeFileSavedToDiskHandler
|
|||||||
private async Task HandleWorkspaceFileChanged(SharpIdeFile file)
|
private async Task HandleWorkspaceFileChanged(SharpIdeFile file)
|
||||||
{
|
{
|
||||||
// TODO: Don't reload from disk if we raised the change event ourselves (e.g. save from IDE). Cleanup this whole disaster
|
// TODO: Don't reload from disk if we raised the change event ourselves (e.g. save from IDE). Cleanup this whole disaster
|
||||||
var wasOpenAndUpdated = await IdeOpenTabsFileManager.Instance.ReloadFileFromDiskIfOpenInEditor(file);
|
var wasOpenAndUpdated = await _openTabsFileManager.ReloadFileFromDiskIfOpenInEditor(file);
|
||||||
if (file.IsRoslynWorkspaceFile)
|
if (file.IsRoslynWorkspaceFile)
|
||||||
{
|
{
|
||||||
var fileText = wasOpenAndUpdated ?
|
var fileText = wasOpenAndUpdated ?
|
||||||
await IdeOpenTabsFileManager.Instance.GetFileTextAsync(file) :
|
await _openTabsFileManager.GetFileTextAsync(file) :
|
||||||
await File.ReadAllTextAsync(file.Path);
|
await File.ReadAllTextAsync(file.Path);
|
||||||
await RoslynAnalysis.UpdateDocument(file, fileText);
|
await RoslynAnalysis.UpdateDocument(file, fileText);
|
||||||
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
|
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
|
||||||
|
|||||||
66
src/SharpIDE.Godot/DiAutoload.cs
Normal file
66
src/SharpIDE.Godot/DiAutoload.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using Godot;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using SharpIDE.Application.Features.Build;
|
||||||
|
using SharpIDE.Application.Features.FilePersistence;
|
||||||
|
using SharpIDE.Application.Features.FileWatching;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
|
|
||||||
|
namespace SharpIDE.Godot;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
|
public class InjectAttribute : Attribute;
|
||||||
|
|
||||||
|
public partial class DiAutoload : Node
|
||||||
|
{
|
||||||
|
private ServiceProvider? _serviceProvider;
|
||||||
|
|
||||||
|
public override void _EnterTree()
|
||||||
|
{
|
||||||
|
GD.Print("[Injector] _EnterTree called");
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
// Register services here
|
||||||
|
services.AddSingleton<BuildService>();
|
||||||
|
services.AddSingleton<RunService>();
|
||||||
|
services.AddSingleton<IdeFileExternalChangeHandler>();
|
||||||
|
services.AddSingleton<IdeFileSavedToDiskHandler>();
|
||||||
|
services.AddSingleton<IdeFileWatcher>();
|
||||||
|
services.AddSingleton<IdeOpenTabsFileManager>();
|
||||||
|
|
||||||
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
|
GetTree().NodeAdded += OnNodeAdded;
|
||||||
|
GD.Print("[Injector] Service provider built and NodeAdded event subscribed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNodeAdded(Node node)
|
||||||
|
{
|
||||||
|
// Inject dependencies into every new node
|
||||||
|
InjectDependencies(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InjectDependencies(object target)
|
||||||
|
{
|
||||||
|
var type = target.GetType();
|
||||||
|
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
|
foreach (var field in type.GetFields(flags))
|
||||||
|
{
|
||||||
|
if (Attribute.IsDefined(field, typeof(InjectAttribute)))
|
||||||
|
{
|
||||||
|
var service = _serviceProvider!.GetService(field.FieldType);
|
||||||
|
if (service is null)
|
||||||
|
{
|
||||||
|
GD.PrintErr($"[Injector] No service registered for {field.FieldType}");
|
||||||
|
GetTree().Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
field.SetValue(target, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/SharpIDE.Godot/DiAutoload.cs.uid
Normal file
1
src/SharpIDE.Godot/DiAutoload.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c1ong07uc2rx4
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using GDExtensionBindgen;
|
using GDExtensionBindgen;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using SharpIDE.Application.Features.Build;
|
||||||
|
|
||||||
namespace SharpIDE.Godot.Features.Build;
|
namespace SharpIDE.Godot.Features.Build;
|
||||||
|
|
||||||
@@ -8,10 +9,12 @@ public partial class BuildPanel : Control
|
|||||||
{
|
{
|
||||||
private Terminal _terminal = null!;
|
private Terminal _terminal = null!;
|
||||||
private ChannelReader<string>? _buildOutputChannelReader;
|
private ChannelReader<string>? _buildOutputChannelReader;
|
||||||
|
|
||||||
|
[Inject] private readonly BuildService _buildService = null!;
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_terminal = new Terminal(GetNode<Control>("%Terminal"));
|
_terminal = new Terminal(GetNode<Control>("%Terminal"));
|
||||||
Singletons.BuildService.BuildStarted += OnBuildStarted;
|
_buildService.BuildStarted += OnBuildStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
@@ -27,6 +30,6 @@ public partial class BuildPanel : Control
|
|||||||
private async Task OnBuildStarted()
|
private async Task OnBuildStarted()
|
||||||
{
|
{
|
||||||
await this.InvokeAsync(() => _terminal.Clear());
|
await this.InvokeAsync(() => _terminal.Clear());
|
||||||
_buildOutputChannelReader ??= Singletons.BuildService.BuildTextWriter.ConsoleChannel.Reader;
|
_buildOutputChannelReader ??= _buildService.BuildTextWriter.ConsoleChannel.Reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ using R3;
|
|||||||
using SharpIDE.Application.Features.Analysis;
|
using SharpIDE.Application.Features.Analysis;
|
||||||
using SharpIDE.Application.Features.Debugging;
|
using SharpIDE.Application.Features.Debugging;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public partial class CodeEditorPanel : MarginContainer
|
|||||||
private TabContainer _tabContainer = null!;
|
private TabContainer _tabContainer = null!;
|
||||||
private ExecutionStopInfo? _debuggerExecutionStopInfo;
|
private ExecutionStopInfo? _debuggerExecutionStopInfo;
|
||||||
|
|
||||||
|
[Inject] private readonly RunService _runService = null!;
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_tabContainer = GetNode<TabContainer>("TabContainer");
|
_tabContainer = GetNode<TabContainer>("TabContainer");
|
||||||
@@ -125,7 +127,7 @@ public partial class CodeEditorPanel : MarginContainer
|
|||||||
_debuggerExecutionStopInfo = null;
|
_debuggerExecutionStopInfo = null;
|
||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
await Singletons.RunService.SendDebuggerStepOver(threadId);
|
await _runService.SendDebuggerStepOver(threadId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,8 @@ using SharpIDE.Application;
|
|||||||
using SharpIDE.Application.Features.Analysis;
|
using SharpIDE.Application.Features.Analysis;
|
||||||
using SharpIDE.Application.Features.Debugging;
|
using SharpIDE.Application.Features.Debugging;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.FilePersistence;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
using SharpIDE.RazorAccess;
|
using SharpIDE.RazorAccess;
|
||||||
@@ -39,6 +41,10 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
private ImmutableArray<CodeAction> _currentCodeActionsInPopup = [];
|
private ImmutableArray<CodeAction> _currentCodeActionsInPopup = [];
|
||||||
private bool _fileChangingSuppressBreakpointToggleEvent;
|
private bool _fileChangingSuppressBreakpointToggleEvent;
|
||||||
|
|
||||||
|
[Inject] private readonly IdeOpenTabsFileManager _openTabsFileManager = null!;
|
||||||
|
[Inject] private readonly RunService _runService = null!;
|
||||||
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
SyntaxHighlighter = _syntaxHighlighter;
|
SyntaxHighlighter = _syntaxHighlighter;
|
||||||
@@ -112,7 +118,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
var lineInt = (int)line;
|
var lineInt = (int)line;
|
||||||
var breakpointAdded = IsLineBreakpointed(lineInt);
|
var breakpointAdded = IsLineBreakpointed(lineInt);
|
||||||
var lineForDebugger = lineInt + 1; // Godot is 0-indexed, Debugging is 1-indexed
|
var lineForDebugger = lineInt + 1; // Godot is 0-indexed, Debugging is 1-indexed
|
||||||
var breakpoints = Singletons.RunService.Breakpoints.GetOrAdd(_currentFile, []);
|
var breakpoints = _runService.Breakpoints.GetOrAdd(_currentFile, []);
|
||||||
if (breakpointAdded)
|
if (breakpointAdded)
|
||||||
{
|
{
|
||||||
breakpoints.Add(new Breakpoint { Line = lineForDebugger } );
|
breakpoints.Add(new Breakpoint { Line = lineForDebugger } );
|
||||||
@@ -265,7 +271,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
_currentFile.IsDirty.Value = true;
|
_currentFile.IsDirty.Value = true;
|
||||||
await Singletons.OpenTabsFileManager.UpdateFileTextInMemory(_currentFile, Text);
|
await _openTabsFileManager.UpdateFileTextInMemory(_currentFile, Text);
|
||||||
await _textChangedCts.CancelAsync(); // Currently the below methods throw, TODO Fix with suppress throwing, and handle
|
await _textChangedCts.CancelAsync(); // Currently the below methods throw, TODO Fix with suppress throwing, and handle
|
||||||
_textChangedCts.Dispose();
|
_textChangedCts.Dispose();
|
||||||
_textChangedCts = new CancellationTokenSource();
|
_textChangedCts = new CancellationTokenSource();
|
||||||
@@ -298,7 +304,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
// TODO: This can be more efficient - we can just update in memory and proceed with highlighting etc. Save to disk in background.
|
// TODO: This can be more efficient - we can just update in memory and proceed with highlighting etc. Save to disk in background.
|
||||||
foreach (var (affectedFile, updatedText) in affectedFiles)
|
foreach (var (affectedFile, updatedText) in affectedFiles)
|
||||||
{
|
{
|
||||||
await Singletons.OpenTabsFileManager.UpdateInMemoryIfOpenAndSaveAsync(affectedFile, updatedText);
|
await _openTabsFileManager.UpdateInMemoryIfOpenAndSaveAsync(affectedFile, updatedText);
|
||||||
affectedFile.FileContentsChangedExternally.InvokeParallelFireAndForget();
|
affectedFile.FileContentsChangedExternally.InvokeParallelFireAndForget();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -306,7 +312,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
|
|
||||||
private async Task OnFileChangedExternallyInMemory()
|
private async Task OnFileChangedExternallyInMemory()
|
||||||
{
|
{
|
||||||
var fileContents = await Singletons.OpenTabsFileManager.GetFileTextAsync(_currentFile);
|
var fileContents = await _openTabsFileManager.GetFileTextAsync(_currentFile);
|
||||||
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
||||||
var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile);
|
var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile);
|
||||||
var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile);
|
var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile);
|
||||||
@@ -341,7 +347,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
{
|
{
|
||||||
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); // get off the UI thread
|
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); // get off the UI thread
|
||||||
_currentFile = file;
|
_currentFile = file;
|
||||||
var readFileTask = Singletons.OpenTabsFileManager.GetFileTextAsync(file);
|
var readFileTask = _openTabsFileManager.GetFileTextAsync(file);
|
||||||
_currentFile.FileContentsChangedExternally.Subscribe(OnFileChangedExternallyInMemory);
|
_currentFile.FileContentsChangedExternally.Subscribe(OnFileChangedExternallyInMemory);
|
||||||
_currentFile.FileContentsChangedExternallyFromDisk.Subscribe(OnFileChangedExternallyFromDisk);
|
_currentFile.FileContentsChangedExternallyFromDisk.Subscribe(OnFileChangedExternallyFromDisk);
|
||||||
|
|
||||||
@@ -365,7 +371,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
|
|
||||||
private async Task OnFileChangedExternallyFromDisk()
|
private async Task OnFileChangedExternallyFromDisk()
|
||||||
{
|
{
|
||||||
await Singletons.OpenTabsFileManager.ReloadFileFromDisk(_currentFile);
|
await _openTabsFileManager.ReloadFileFromDisk(_currentFile);
|
||||||
await OnFileChangedExternallyInMemory();
|
await OnFileChangedExternallyInMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,14 +438,14 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
{
|
{
|
||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
await Singletons.OpenTabsFileManager.SaveAllOpenFilesAsync();
|
await _openTabsFileManager.SaveAllOpenFilesAsync();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (@event.IsActionPressed(InputStringNames.SaveFile))
|
else if (@event.IsActionPressed(InputStringNames.SaveFile))
|
||||||
{
|
{
|
||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
await Singletons.OpenTabsFileManager.SaveFileAsync(_currentFile);
|
await _openTabsFileManager.SaveFileAsync(_currentFile);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Ardalis.GuardClauses;
|
|||||||
using Godot;
|
using Godot;
|
||||||
using SharpIDE.Application.Features.Debugging;
|
using SharpIDE.Application.Features.Debugging;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
namespace SharpIDE.Godot.Features.Debug_.Tab.SubTabs;
|
namespace SharpIDE.Godot.Features.Debug_.Tab.SubTabs;
|
||||||
@@ -15,6 +16,8 @@ public partial class ThreadsVariablesSubTab : Control
|
|||||||
public SharpIdeProjectModel Project { get; set; } = null!;
|
public SharpIdeProjectModel Project { get; set; } = null!;
|
||||||
// private ThreadModel? _selectedThread = null!; // null when not at a stop point
|
// private ThreadModel? _selectedThread = null!; // null when not at a stop point
|
||||||
|
|
||||||
|
[Inject] private readonly RunService _runService = null!;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_threadsVboxContainer = GetNode<VBoxContainer>("%ThreadsPanel/VBoxContainer");
|
_threadsVboxContainer = GetNode<VBoxContainer>("%ThreadsPanel/VBoxContainer");
|
||||||
@@ -26,7 +29,7 @@ public partial class ThreadsVariablesSubTab : Control
|
|||||||
|
|
||||||
private async Task OnDebuggerExecutionStopped(ExecutionStopInfo stopInfo)
|
private async Task OnDebuggerExecutionStopped(ExecutionStopInfo stopInfo)
|
||||||
{
|
{
|
||||||
var result = await Singletons.RunService.GetInfoAtStopPoint();
|
var result = await _runService.GetInfoAtStopPoint();
|
||||||
var threadScenes = result.Threads.Select(s =>
|
var threadScenes = result.Threads.Select(s =>
|
||||||
{
|
{
|
||||||
var threadListItem = _threadListItemScene.Instantiate<Control>();
|
var threadListItem = _threadListItemScene.Instantiate<Control>();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
using SharpIDE.Godot.Features.BottomPanel;
|
using SharpIDE.Godot.Features.BottomPanel;
|
||||||
|
|
||||||
@@ -11,6 +12,8 @@ public partial class RunMenuItem : HBoxContainer
|
|||||||
private Button _runButton = null!;
|
private Button _runButton = null!;
|
||||||
private Button _debugButton = null!;
|
private Button _debugButton = null!;
|
||||||
private Button _stopButton = null!;
|
private Button _stopButton = null!;
|
||||||
|
|
||||||
|
[Inject] private readonly RunService _runService = null!;
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_label = GetNode<Label>("Label");
|
_label = GetNode<Label>("Label");
|
||||||
@@ -47,18 +50,18 @@ public partial class RunMenuItem : HBoxContainer
|
|||||||
|
|
||||||
private async void OnStopButtonPressed()
|
private async void OnStopButtonPressed()
|
||||||
{
|
{
|
||||||
await Singletons.RunService.CancelRunningProject(Project);
|
await _runService.CancelRunningProject(Project);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnRunButtonPressed()
|
private async void OnRunButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Run);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Run);
|
||||||
await Singletons.RunService.RunProject(Project).ConfigureAwait(false);
|
await _runService.RunProject(Project).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnDebugButtonPressed()
|
private async void OnDebugButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Debug);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Debug);
|
||||||
await Singletons.RunService.RunProject(Project, true).ConfigureAwait(false);
|
await _runService.RunProject(Project, true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
|
using SharpIDE.Application.Features.Analysis;
|
||||||
using SharpIDE.Application.Features.Build;
|
using SharpIDE.Application.Features.Build;
|
||||||
|
using SharpIDE.Application.Features.Evaluation;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
using SharpIDE.Godot.Features.BottomPanel;
|
using SharpIDE.Godot.Features.BottomPanel;
|
||||||
|
|
||||||
@@ -18,6 +21,9 @@ file enum ProjectContextMenuOptions
|
|||||||
public partial class SolutionExplorerPanel
|
public partial class SolutionExplorerPanel
|
||||||
{
|
{
|
||||||
private Texture2D _runIcon = ResourceLoader.Load<Texture2D>("uid://bkty6563cthj8");
|
private Texture2D _runIcon = ResourceLoader.Load<Texture2D>("uid://bkty6563cthj8");
|
||||||
|
[Inject] private readonly BuildService _buildService = null!;
|
||||||
|
[Inject] private readonly RunService _runService = null!;
|
||||||
|
|
||||||
private void OpenContextMenuProject(SharpIdeProjectModel project)
|
private void OpenContextMenuProject(SharpIdeProjectModel project)
|
||||||
{
|
{
|
||||||
var menu = new PopupMenu();
|
var menu = new PopupMenu();
|
||||||
@@ -38,7 +44,7 @@ public partial class SolutionExplorerPanel
|
|||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Run);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Run);
|
||||||
await Singletons.RunService.RunProject(project);
|
await _runService.RunProject(project);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (actionId is ProjectContextMenuOptions.Build)
|
if (actionId is ProjectContextMenuOptions.Build)
|
||||||
@@ -63,9 +69,9 @@ public partial class SolutionExplorerPanel
|
|||||||
menu.Position = new Vector2I((int)globalMousePosition.X, (int)globalMousePosition.Y);
|
menu.Position = new Vector2I((int)globalMousePosition.X, (int)globalMousePosition.Y);
|
||||||
menu.Popup();
|
menu.Popup();
|
||||||
}
|
}
|
||||||
private static async Task MsBuildProject(SharpIdeProjectModel project, BuildType buildType)
|
private async Task MsBuildProject(SharpIdeProjectModel project, BuildType buildType)
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
||||||
await Singletons.BuildService.MsBuildAsync(project.FilePath, buildType);
|
await _buildService.MsBuildAsync(project.FilePath, buildType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using Microsoft.Build.Locator;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using SharpIDE.Application.Features.Analysis;
|
using SharpIDE.Application.Features.Analysis;
|
||||||
using SharpIDE.Application.Features.Build;
|
using SharpIDE.Application.Features.Build;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
@@ -40,19 +38,22 @@ public partial class IdeRoot : Control
|
|||||||
private readonly PackedScene _runMenuItemScene = ResourceLoader.Load<PackedScene>("res://Features/Run/RunMenuItem.tscn");
|
private readonly PackedScene _runMenuItemScene = ResourceLoader.Load<PackedScene>("res://Features/Run/RunMenuItem.tscn");
|
||||||
private TaskCompletionSource _nodeReadyTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
private TaskCompletionSource _nodeReadyTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
[Inject] private readonly IdeFileSavedToDiskHandler _savedToDiskHandler = null!;
|
||||||
|
[Inject] private readonly IdeFileExternalChangeHandler _fileExternalChangeHandler = null!;
|
||||||
|
[Inject] private readonly IdeFileWatcher _fileWatcher = null!;
|
||||||
|
[Inject] private readonly BuildService _buildService = null!;
|
||||||
|
|
||||||
public override void _EnterTree()
|
public override void _EnterTree()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance = new GodotGlobalEvents();
|
GodotGlobalEvents.Instance = new GodotGlobalEvents();
|
||||||
GlobalEvents.Instance = new GlobalEvents();
|
GlobalEvents.Instance = new GlobalEvents();
|
||||||
BuildService.Instance = new BuildService(); // TODO: Sort out this mess with singletons, especially access across Application services
|
BuildService.Instance = new BuildService(); // TODO: Sort out this mess with singletons, especially access across Application services
|
||||||
IdeOpenTabsFileManager.Instance = new IdeOpenTabsFileManager();
|
IdeOpenTabsFileManager.Instance = new IdeOpenTabsFileManager();
|
||||||
Singletons.RunService = new RunService();
|
}
|
||||||
Singletons.BuildService = BuildService.Instance;
|
|
||||||
Singletons.FileWatcher?.Dispose();
|
public override void _ExitTree()
|
||||||
Singletons.FileWatcher = new IdeFileWatcher();
|
{
|
||||||
Singletons.OpenTabsFileManager = IdeOpenTabsFileManager.Instance;
|
_fileWatcher.Dispose();
|
||||||
Singletons.FileExternalChangeHandler = new IdeFileExternalChangeHandler();
|
|
||||||
Singletons.FileSavedToDiskHandler = new IdeFileSavedToDiskHandler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
@@ -94,22 +95,22 @@ public partial class IdeRoot : Control
|
|||||||
private async void OnBuildSlnButtonPressed()
|
private async void OnBuildSlnButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
||||||
await Singletons.BuildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath);
|
await _buildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath);
|
||||||
}
|
}
|
||||||
private async void OnRebuildSlnButtonPressed()
|
private async void OnRebuildSlnButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
||||||
await Singletons.BuildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Rebuild);
|
await _buildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Rebuild);
|
||||||
}
|
}
|
||||||
private async void OnCleanSlnButtonPressed()
|
private async void OnCleanSlnButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
||||||
await Singletons.BuildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Clean);
|
await _buildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Clean);
|
||||||
}
|
}
|
||||||
private async void OnRestoreSlnButtonPressed()
|
private async void OnRestoreSlnButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Build);
|
||||||
await Singletons.BuildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Restore);
|
await _buildService.MsBuildAsync(_solutionExplorerPanel.SolutionModel.FilePath, BuildType.Restore);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnSolutionExplorerPanelOnFileSelected(SharpIdeFile file, SharpIdeFileLinePosition? fileLinePosition)
|
private async Task OnSolutionExplorerPanelOnFileSelected(SharpIdeFile file, SharpIdeFileLinePosition? fileLinePosition)
|
||||||
@@ -129,11 +130,11 @@ public partial class IdeRoot : Control
|
|||||||
_bottomPanelManager.Solution = solutionModel;
|
_bottomPanelManager.Solution = solutionModel;
|
||||||
_searchWindow.Solution = solutionModel;
|
_searchWindow.Solution = solutionModel;
|
||||||
_searchAllFilesWindow.Solution = solutionModel;
|
_searchAllFilesWindow.Solution = solutionModel;
|
||||||
Singletons.FileExternalChangeHandler.SolutionModel = solutionModel;
|
_fileExternalChangeHandler.SolutionModel = solutionModel;
|
||||||
Singletons.FileSavedToDiskHandler.SolutionModel = solutionModel;
|
_savedToDiskHandler.SolutionModel = solutionModel;
|
||||||
Callable.From(_solutionExplorerPanel.RepopulateTree).CallDeferred();
|
Callable.From(_solutionExplorerPanel.RepopulateTree).CallDeferred();
|
||||||
RoslynAnalysis.StartSolutionAnalysis(solutionModel);
|
RoslynAnalysis.StartSolutionAnalysis(solutionModel);
|
||||||
Singletons.FileWatcher.StartWatching(solutionModel);
|
_fileWatcher.StartWatching(solutionModel);
|
||||||
|
|
||||||
var infraProject = solutionModel.AllProjects.SingleOrDefault(s => s.Name == "WebUi");
|
var infraProject = solutionModel.AllProjects.SingleOrDefault(s => s.Name == "WebUi");
|
||||||
var diFile = infraProject?.Folders.Single(s => s.Name == "Pages").Files.Single(s => s.Name == "TestPage.razor");
|
var diFile = infraProject?.Folders.Single(s => s.Name == "Pages").Files.Single(s => s.Name == "TestPage.razor");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Godot;
|
|||||||
using Microsoft.Build.Locator;
|
using Microsoft.Build.Locator;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.FilePersistence;
|
||||||
using SharpIDE.Godot.Features.IdeSettings;
|
using SharpIDE.Godot.Features.IdeSettings;
|
||||||
using SharpIDE.Godot.Features.SlnPicker;
|
using SharpIDE.Godot.Features.SlnPicker;
|
||||||
|
|
||||||
@@ -20,8 +21,11 @@ public partial class IdeWindow : Control
|
|||||||
private IdeRoot? _ideRoot;
|
private IdeRoot? _ideRoot;
|
||||||
private SlnPicker? _slnPicker;
|
private SlnPicker? _slnPicker;
|
||||||
|
|
||||||
|
[Inject] private readonly IdeOpenTabsFileManager _openTabsFileManager = null!;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
GD.Print("IdeWindow _Ready called");
|
||||||
ResourceLoader.LoadThreadedRequest(SlnPickerScenePath);
|
ResourceLoader.LoadThreadedRequest(SlnPickerScenePath);
|
||||||
ResourceLoader.LoadThreadedRequest(IdeRootScenePath);
|
ResourceLoader.LoadThreadedRequest(IdeRootScenePath);
|
||||||
MSBuildLocator.RegisterDefaults();
|
MSBuildLocator.RegisterDefaults();
|
||||||
@@ -45,7 +49,7 @@ public partial class IdeWindow : Control
|
|||||||
|
|
||||||
private void OnFocusExited()
|
private void OnFocusExited()
|
||||||
{
|
{
|
||||||
_ = Task.GodotRun(async () => await Singletons.OpenTabsFileManager.SaveAllOpenFilesAsync());
|
_ = Task.GodotRun(async () => await _openTabsFileManager.SaveAllOpenFilesAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PickSolution(bool fullscreen = false)
|
public void PickSolution(bool fullscreen = false)
|
||||||
|
|||||||
@@ -8,11 +8,5 @@ namespace SharpIDE.Godot;
|
|||||||
|
|
||||||
public static class Singletons
|
public static class Singletons
|
||||||
{
|
{
|
||||||
public static RunService RunService { get; set; } = null!;
|
|
||||||
public static BuildService BuildService { get; set; } = null!;
|
|
||||||
public static IdeFileWatcher FileWatcher { get; set; } = null!;
|
|
||||||
public static IdeOpenTabsFileManager OpenTabsFileManager { get; set; } = null!;
|
|
||||||
public static IdeFileExternalChangeHandler FileExternalChangeHandler { get; set; } = null!;
|
|
||||||
public static IdeFileSavedToDiskHandler FileSavedToDiskHandler { get; set; } = null!;
|
|
||||||
public static AppState AppState { get; set; } = null!;
|
public static AppState AppState { get; set; } = null!;
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ config/icon="uid://tpjfx7mo6cwj"
|
|||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
|
DiAutoload="*res://DiAutoload.cs"
|
||||||
FrameProviderDispatcher="*res://addons/R3.Godot/FrameProviderDispatcher.cs"
|
FrameProviderDispatcher="*res://addons/R3.Godot/FrameProviderDispatcher.cs"
|
||||||
ObservableTrackerRuntimeHook="*res://addons/R3.Godot/ObservableTrackerRuntimeHook.cs"
|
ObservableTrackerRuntimeHook="*res://addons/R3.Godot/ObservableTrackerRuntimeHook.cs"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user