diff --git a/MatterControl.csproj b/MatterControl.csproj index 3b9e4fd04..068c5333b 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -44,6 +44,7 @@ + diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index f63609800..4d69eecbb 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -261,6 +261,8 @@ namespace MatterHackers.MatterControl public ThemeConfig MenuTheme => AppContext.MenuTheme; + public event EventHandler ShellFileOpened; + public RunningTasksConfig Tasks { get; set; } = new RunningTasksConfig(); public IReadOnlyList ActivePrinters => _activePrinters; @@ -2497,6 +2499,11 @@ If you experience adhesion problems, please re-run leveling." }; } + public void ShellOpenFile(string file) + { + UiThread.RunOnIdle(() => this.ShellFileOpened?.Invoke(this, file)); + } + public class CloudSyncEventArgs : EventArgs { public bool IsAuthenticated { get; set; } diff --git a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs index 6f8c0d854..c3d30778e 100644 --- a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs +++ b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs @@ -29,12 +29,15 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; +using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.Library; using MatterHackers.MatterControl.PartPreviewWindow.PlusTab; using MatterHackers.MatterControl.PrintLibrary; using MatterHackers.MatterControl.SlicerConfiguration; @@ -280,6 +283,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ApplicationController.Instance.Tasks.TasksChanged += Tasks_TasksChanged; tabControl.ActiveTabChanged += TabControl_ActiveTabChanged; + ApplicationController.Instance.ShellFileOpened += this.Instance_OpenNewFile; + UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent((s, e) => { SetLinkButtonsVisibility(s, new StringEventArgs("Unknown")); @@ -288,6 +293,40 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ApplicationController.Instance.MainView = this; } + private async void Instance_OpenNewFile(object sender, string filePath) + { + + var history = ApplicationController.Instance.Library.PlatingHistory; + + var workspace = new PartWorkspace() + { + Name = Path.GetFileName(filePath), + SceneContext = new BedConfig(history) + }; + + ApplicationController.Instance.Workspaces.Add(workspace); + + var scene = new Object3D(); + scene.Children.Add( + new Object3D + { + MeshPath = filePath, + Name = Path.GetFileName(filePath) + }); + + await workspace.SceneContext.LoadContent( + new EditContext() + { + ContentStore = ApplicationController.Instance.Library.PlatingHistory, + SourceItem = new InMemoryLibraryItem(scene) + }); + + ApplicationController.Instance.Workspaces.Add(workspace); + + var newTab = CreatePartTab(workspace); + tabControl.ActiveTab = newTab; + } + private void TabControl_ActiveTabChanged(object sender, EventArgs e) { if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage) @@ -473,11 +512,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow BackgroundColor = menuTheme.BackgroundColor }; - widget.Closed += (s2, e2) => - { - themePanel.BackgroundColor = panelBackgroundColor; - }; - var section = ApplicationSettingsPage.CreateThemePanel(menuTheme); widget.AddChild(section); @@ -617,6 +651,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow UserSettings.Instance.SettingChanged -= SetLinkButtonsVisibility; ApplicationController.Instance.OpenPrintersChanged -= OpenPrinters_Changed; ApplicationController.Instance.Tasks.TasksChanged -= Tasks_TasksChanged; + ApplicationController.Instance.ShellFileOpened -= Instance_OpenNewFile; tabControl.ActiveTabChanged -= TabControl_ActiveTabChanged; unregisterEvents?.Invoke(this, null); diff --git a/Program.cs b/Program.cs index 3bf1a2fbd..1099e8727 100644 --- a/Program.cs +++ b/Program.cs @@ -30,9 +30,13 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Globalization; using System.IO; +using System.Linq; +using System.ServiceModel; +using System.ServiceModel.Description; using System.Threading; using MatterHackers.Agg.Platform; using MatterHackers.MatterControl.DataStorage; +using MatterHackers.MatterControl.PrintQueue; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.SerialPortCommunication.FrostedSerial; using Microsoft.Extensions.Configuration; @@ -41,6 +45,10 @@ namespace MatterHackers.MatterControl { class Program { + private static EventWaitHandle waitHandle; + + private static string mainServiceName = ""; + [STAThread] static void Main(string[] args) { @@ -64,6 +72,40 @@ namespace MatterHackers.MatterControl string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + //#if IS_WINDOWS + waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "MatterControl#Startup", out bool created); + + if (!created) + { + // If an instance is already running, create a service proxy and execute ShellOpenFile + var proxy = new ServiceProxy(); + + // and at least one argument is an acceptable shell file extension + var itemsToAdd = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower())); + if (itemsToAdd.Any()) + { + // notify the running instance of the event + proxy.ShellOpenFile(itemsToAdd.ToArray()); + } + + System.Threading.Thread.Sleep(1000); + + // Finally, close the process spawned by Explorer.exe + return; + } + //#endif + + var serviceHost = new ServiceHost( + typeof(LocalService), + new Uri[] { new Uri("net.pipe://localhost/") }); + + serviceHost.AddServiceEndpoint(typeof(IMainService), new NetNamedPipeBinding(), mainServiceName); + serviceHost.Open(); + + Console.Write( + "Service started: {0};", + string.Join(", ", serviceHost.Description.Endpoints.Select(s => s.ListenUri.AbsoluteUri).ToArray())); + // Load optional user configuration IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: true) @@ -97,5 +139,55 @@ namespace MatterHackers.MatterControl var systemWindow = Application.LoadRootWindow(width, height); systemWindow.ShowAsSystemWindow(); } + + private static string[] shellFileExtensions = new string[] { ".stl", ".amf" }; + + private static readonly object locker = new object(); + + public class LocalService : IMainService + { + public void ShellOpenFile(string[] files) + { + // If at least one argument is an acceptable shell file extension + var itemsToAdd = files.Where(f => File.Exists(f) + && shellFileExtensions.Contains(Path.GetExtension(f).ToLower())); + + if (itemsToAdd.Any()) + { + lock (locker) + { + // Add each file + foreach (string file in itemsToAdd) + { + ApplicationController.Instance.ShellOpenFile(file); + } + } + } + } + } + + public class ServiceProxy : ClientBase + { + public ServiceProxy() + : base( + new ServiceEndpoint( + ContractDescription.GetContract(typeof(IMainService)), + new NetNamedPipeBinding(), + new EndpointAddress($"net.pipe://localhost/{mainServiceName}"))) + { + } + + public void ShellOpenFile(string[] files) + { + Channel.ShellOpenFile(files); + } + } + } + + [ServiceContract] + public interface IMainService + { + [OperationContract] + void ShellOpenFile(string[] files); } }