diff --git a/GodotAddinVS/Commands/CommandResetGodot.cs b/GodotAddinVS/Commands/CommandResetGodot.cs new file mode 100644 index 0000000..83c4c7c --- /dev/null +++ b/GodotAddinVS/Commands/CommandResetGodot.cs @@ -0,0 +1,101 @@ +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System; +using System.ComponentModel.Design; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Microsoft.VisualStudio.Settings; +using Microsoft.VisualStudio.Shell.Settings; +using Task = System.Threading.Tasks.Task; + +namespace GodotAddinVS.Commands { + /// + /// Command handler + /// + internal sealed class CommandResetGodot { + /// + /// Command ID. + /// + public const int CommandId = 256; + + /// + /// Command menu group (command set GUID). + /// + public static readonly Guid CommandSet = new Guid("38009f93-330e-4875-ab88-e127fd85bb88"); + + /// + /// VS Package that provides this command, not null. + /// + private readonly AsyncPackage package; + + /// + /// Initializes a new instance of the class. + /// Adds our command handlers for menu (commands must exist in the command table file) + /// + /// Owner package, not null. + /// Command service to add command to, not null. + private CommandResetGodot(AsyncPackage package, OleMenuCommandService commandService) { + this.package = package ?? throw new ArgumentNullException(nameof(package)); + commandService = commandService ?? throw new ArgumentNullException(nameof(commandService)); + + var menuCommandID = new CommandID(CommandSet, CommandId); + var menuItem = new MenuCommand(this.Execute, menuCommandID); + commandService.AddCommand(menuItem); + } + + /// + /// Gets the instance of the command. + /// + public static CommandResetGodot Instance { + get; + private set; + } + + /// + /// Gets the service provider from the owner package. + /// + private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider { + get { + return this.package; + } + } + + /// + /// Initializes the singleton instance of the command. + /// + /// Owner package, not null. + public static async Task InitializeAsync(AsyncPackage package) { + // Switch to the main thread - the call to AddCommand in CommandResetGodot's constructor requires + // the UI thread. + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); + + OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; + Instance = new CommandResetGodot(package, commandService); + } + + /// + /// This function is the callback used to execute the command when the menu item is clicked. + /// See the constructor to see how the menu item is associated with this function using + /// OleMenuCommandService service and MenuCommand class. + /// + /// Event sender. + /// Event args. + private void Execute(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var settingsManager = new ShellSettingsManager(package); + var config = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + + var ofd = new OpenFileDialog { + Filter = @"GoDot executable (.exe)|*.exe" + }; + var result = ofd.ShowDialog(null); + + if (result != DialogResult.OK) return; + config.SetString("External Tools", "GoDotExecutable", ofd.FileName); + config.SetString("External Tools", "GoDotPath", Path.GetDirectoryName(ofd.FileName)); + } + } +} diff --git a/GodotAddinVS/Commands/CommandRunGodot.cs b/GodotAddinVS/Commands/CommandRunGodot.cs new file mode 100644 index 0000000..0b32050 --- /dev/null +++ b/GodotAddinVS/Commands/CommandRunGodot.cs @@ -0,0 +1,132 @@ +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Microsoft.VisualStudio.Settings; +using Microsoft.VisualStudio.Shell.Settings; +using Task = System.Threading.Tasks.Task; + +namespace GodotAddinVS.Commands { + /// + /// Command handler + /// + internal sealed class CommandRunGodot { + /// + /// Command ID. + /// + public const int CommandId = 256; + + /// + /// Command menu group (command set GUID). + /// + public static readonly Guid CommandSet = new Guid("d71528ca-92b8-49bb-8655-8b478b495499"); + + /// + /// VS Package that provides this command, not null. + /// + private readonly AsyncPackage package; + + /// + /// Initializes a new instance of the class. + /// Adds our command handlers for menu (commands must exist in the command table file) + /// + /// Owner package, not null. + /// Command service to add command to, not null. + private CommandRunGodot(AsyncPackage package, OleMenuCommandService commandService) { + this.package = package ?? throw new ArgumentNullException(nameof(package)); + commandService = commandService ?? throw new ArgumentNullException(nameof(commandService)); + + var menuCommandId = new CommandID(CommandSet, CommandId); + var menuItem = new MenuCommand(Execute, menuCommandId); + commandService.AddCommand(menuItem); + } + + /// + /// Gets the instance of the command. + /// + public static CommandRunGodot Instance { + get; + private set; + } + + /// + /// Gets the service provider from the owner package. + /// + private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider { + get { + return this.package; + } + } + + /// + /// Initializes the singleton instance of the command. + /// + /// Owner package, not null. + public static async Task InitializeAsync(AsyncPackage package) { + // Switch to the main thread - the call to AddCommand in CommandRunGodot's constructor requires + // the UI thread. + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); + + var commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; + Instance = new CommandRunGodot(package, commandService); + } + + /// + /// This function is the callback used to execute the command when the menu item is clicked. + /// See the constructor to see how the menu item is associated with this function using + /// OleMenuCommandService service and MenuCommand class. + /// + /// Event sender. + /// Event args. + private void Execute(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + + string goDotPath; + string goDotExecutable; + + var settingsManager = new ShellSettingsManager(package); + var config = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + + if (!config.CollectionExists("External Tools")) { + config.CreateCollection("External Tools"); + } + + if (!config.PropertyExists("External Tools", "GoDotExecutable")) { + var ofd = new OpenFileDialog { + Filter = @"GoDot executable (.exe)|*.exe" + }; + var result = ofd.ShowDialog(null); + + if (result == DialogResult.OK) { + goDotExecutable = ofd.FileName; + goDotPath = Path.GetDirectoryName(goDotExecutable); + + config.SetString("External Tools", "GoDotExecutable", goDotExecutable); + config.SetString("External Tools", "GoDotPath", goDotPath); + } else return; + + } else { + goDotPath = config.GetString("External Tools", "GoDotPath"); + goDotExecutable = config.GetString("External Tools", "GoDotExecutable"); + } + + if (string.IsNullOrEmpty(goDotExecutable)) { + MessageBox.Show("GoDot", "GoDot path not set"); + return; + } + + if (!File.Exists(goDotExecutable)) { + MessageBox.Show("GoDot", @$"GoDot does not exist at {goDotExecutable}"); + return; + } + + Process.Start(goDotExecutable); + } + } +} diff --git a/GodotAddinVS/GodotAddinVS.csproj b/GodotAddinVS/GodotAddinVS.csproj index cb3223c..b61454f 100644 --- a/GodotAddinVS/GodotAddinVS.csproj +++ b/GodotAddinVS/GodotAddinVS.csproj @@ -46,6 +46,8 @@ 4 + + @@ -73,6 +75,11 @@ + + + + + @@ -109,6 +116,7 @@ GodotCompletionProviders + $(GetVsixSourceItemsDependsOn);IncludeNuGetResolvedAssets diff --git a/GodotAddinVS/GodotPackage.cs b/GodotAddinVS/GodotPackage.cs index fcb9552..975c78e 100644 --- a/GodotAddinVS/GodotPackage.cs +++ b/GodotAddinVS/GodotPackage.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -68,6 +68,10 @@ namespace GodotAddinVS // Do any initialization that requires the UI thread after switching to the UI thread. await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + // Commands + await Commands.CommandRunGodot.InitializeAsync(this); + await Commands.CommandResetGodot.InitializeAsync(this); + RegisterProjectFactory(new GodotFlavoredProjectFactory(this)); GodotSolutionEventsListener = new GodotSolutionEventsListener(this); diff --git a/GodotAddinVS/GodotPackage.vsct b/GodotAddinVS/GodotPackage.vsct index 717ae5c..2c2ba77 100644 --- a/GodotAddinVS/GodotPackage.vsct +++ b/GodotAddinVS/GodotPackage.vsct @@ -1,9 +1,10 @@ - + + + + + + + + \ No newline at end of file