diff --git a/ApplicationView/ApplicationController.cs b/ApplicationView/ApplicationController.cs index 593336544..f7735f3cc 100644 --- a/ApplicationView/ApplicationController.cs +++ b/ApplicationView/ApplicationController.cs @@ -266,8 +266,6 @@ namespace MatterHackers.MatterControl public ApplicationView MainView; - public event EventHandler ApplicationClosed; - private EventHandler unregisterEvents; private Dictionary> registeredLibraryActions = new Dictionary>(); @@ -504,16 +502,7 @@ namespace MatterHackers.MatterControl UiThread.RunOnIdle(ReloadAll); } }, ref unregisterEvents); - - // Remove consumed ClientToken from running list on shutdown - ApplicationClosed += (s, e) => - { - ApplicationSettings.Instance.ReleaseClientToken(); - - // Release the waiting ThumbnailGeneration task so it can shutdown gracefully - thumbGenResetEvent?.Set(); - }; - + PrinterConnection.ErrorReported.RegisterEvent((s, e) => { var foundStringEventArgs = e as FoundStringEventArgs; @@ -716,6 +705,9 @@ namespace MatterHackers.MatterControl public void OnApplicationClosed() { + // Release the waiting ThumbnailGeneration task so it can shutdown gracefully + thumbGenResetEvent?.Set(); + // Save changes before close if (this.ActivePrinter != null && this.ActivePrinter != emptyPrinter) @@ -723,7 +715,7 @@ namespace MatterHackers.MatterControl this.ActivePrinter.Bed.Save(); } - ApplicationClosed?.Invoke(null, null); + ApplicationSettings.Instance.ReleaseClientToken(); } static void LoadOemOrDefaultTheme() @@ -1113,7 +1105,7 @@ namespace MatterHackers.MatterControl private string doNotAskAgainMessage = "Don't remind me again".Localize(); - public async Task PrintPart(string partFilePath, string gcodeFilePath, string printItemName, PrinterConfig printer, View3DWidget view3DWidget, SliceProgressReporter reporter, bool overrideAllowGCode = false) + public async Task PrintPart(string partFilePath, string gcodeFilePath, string printItemName, PrinterConfig printer, SliceProgressReporter reporter, bool overrideAllowGCode = false) { // Exit if called in a non-applicable state if (this.ActivePrinter.Connection.CommunicationState != CommunicationStates.Connected @@ -1201,7 +1193,6 @@ namespace MatterHackers.MatterControl printer, partFilePath, gcodeFilePath, - view3DWidget, reporter); partToPrint_SliceDone(partFilePath, gcodeFilePath); @@ -1275,7 +1266,7 @@ namespace MatterHackers.MatterControl } } - public async Task SliceFileLoadOutput(PrinterConfig printer, string partFilePath, string gcodeFilePath, View3DWidget view3DWidget, SliceProgressReporter reporter) + public async Task SliceFileLoadOutput(PrinterConfig printer, string partFilePath, string gcodeFilePath, SliceProgressReporter reporter) { var gcodeLoadCancellationTokenSource = new CancellationTokenSource(); diff --git a/ApplicationView/PrinterModels.cs b/ApplicationView/PrinterModels.cs index fa92fdd9d..53038a1c7 100644 --- a/ApplicationView/PrinterModels.cs +++ b/ApplicationView/PrinterModels.cs @@ -50,8 +50,10 @@ namespace MatterHackers.MatterControl using MatterHackers.PolygonMesh; using MatterHackers.VectorMath; using MatterHackers.MatterControl.PartPreviewWindow; + using System.Collections.Generic; + using MatterHackers.MatterControl.PrintLibrary; - public class BedConfig + public class BedConfig { public event EventHandler ActiveLayerChanged; @@ -117,18 +119,60 @@ namespace MatterHackers.MatterControl return new FileSystemFileItem(mcxPath); } - internal void ClearPlate() + internal async Task ClearPlate() { // Clear existing this.LoadedGCode = null; this.GCodeRenderer = null; // Load - this.LoadContent(new EditContext() + await this.LoadContent(new EditContext() { ContentStore = ApplicationController.Instance.Library.PlatingHistory, SourceItem = BedConfig.NewPlatingItem() - }).ConfigureAwait(false); + }); + } + + public InsertionGroup AddToPlate(IEnumerable selectedLibraryItems) + { + InsertionGroup insertionGroup = null; + + var context = ApplicationController.Instance.DragDropData; + var scene = context.SceneContext.Scene; + scene.Children.Modify(list => + { + list.Add( + insertionGroup = new InsertionGroup( + selectedLibraryItems, + context.View3DWidget, + scene, + context.SceneContext.BedCenter, + dragOperationActive: () => false)); + }); + + return insertionGroup; + } + + public async Task StashAndPrint(IEnumerable selectedLibraryItems) + { + // Clear plate + await this.ClearPlate(); + + // Add content + var insertionGroup = this.AddToPlate(selectedLibraryItems); + await insertionGroup.LoadingItemsTask; + + // Persist changes + this.Save(); + + // Slice and print + var context = this.EditContext; + await ApplicationController.Instance.PrintPart( + context.PartFilePath, + context.GCodeFilePath, + context.SourceItem.Name, + this.Printer, + null); } internal static ILibraryItem LoadLastPlateOrNew() diff --git a/Library/Widgets/InsertionGroup.cs b/Library/Widgets/InsertionGroup.cs index e4ef76e2d..19e7a2017 100644 --- a/Library/Widgets/InsertionGroup.cs +++ b/Library/Widgets/InsertionGroup.cs @@ -49,6 +49,8 @@ namespace MatterHackers.MatterControl.PrintLibrary private InteractiveScene scene; private View3DWidget view3DWidget; + public Task LoadingItemsTask { get; } + static InsertionGroup() { // Create the placeholder mesh and position it at z0 @@ -64,7 +66,7 @@ namespace MatterHackers.MatterControl.PrintLibrary this.scene = scene; this.view3DWidget = view3DWidget; - Task.Run((Func)(async () => + this.LoadingItemsTask = Task.Run((Func)(async () => { var newItemOffset = Vector2.Zero; if (!dragOperationActive()) diff --git a/Library/Widgets/PrintLibraryWidget.cs b/Library/Widgets/PrintLibraryWidget.cs index e14a8a7b6..5bfa67180 100644 --- a/Library/Widgets/PrintLibraryWidget.cs +++ b/Library/Widgets/PrintLibraryWidget.cs @@ -365,7 +365,6 @@ namespace MatterHackers.MatterControl.PrintLibrary // TODO: Sort out the right way to have an ActivePrinter context that looks and behaves correctly var activeContext = ApplicationController.Instance.DragDropData; var printer = activeContext.Printer; - //var printerTabPage = activeContext.View3DWidget.Parents().FirstOrDefault(); switch (selectedLibraryItems.FirstOrDefault()) { @@ -384,19 +383,7 @@ namespace MatterHackers.MatterControl.PrintLibrary { UiThread.RunOnIdle(async () => { - printer.Bed.ClearPlate(); - - AddToPlate(selectedLibraryItems); - - var context = printer.Bed.EditContext; - - await ApplicationController.Instance.PrintPart( - context.PartFilePath, - context.GCodeFilePath, - context.SourceItem.Name, - printer, - activeContext.View3DWidget, - null); + await printer.Bed.StashAndPrint(selectedLibraryItems); }); } break; @@ -405,11 +392,14 @@ namespace MatterHackers.MatterControl.PrintLibrary }, IsEnabled = (selectedListItems, listView) => { + var communicationState = ApplicationController.Instance.DragDropData?.Printer?.Connection.CommunicationState; + // Singleselect - disallow containers return listView.SelectedItems.Count == 1 && selectedListItems.FirstOrDefault()?.Model is ILibraryItem firstItem && !(firstItem is ILibraryContainer) - && ApplicationController.Instance.DragDropData?.Printer?.Connection.CommunicationState == CommunicationStates.Connected; + && (communicationState == CommunicationStates.Connected + || communicationState == CommunicationStates.FinishedPrint); } }); @@ -419,7 +409,11 @@ namespace MatterHackers.MatterControl.PrintLibrary Title = "Add to Plate".Localize(), Action = (selectedLibraryItems, listView) => { - AddToPlate(selectedLibraryItems); + // TODO: Sort out the right way to have an ActivePrinter context that looks and behaves correctly + var activeContext = ApplicationController.Instance.DragDropData; + var printer = activeContext.Printer; + + printer.Bed.AddToPlate(selectedLibraryItems); }, IsEnabled = (selectedListItems, listView) => { @@ -696,22 +690,6 @@ namespace MatterHackers.MatterControl.PrintLibrary }); } - private static void AddToPlate(IEnumerable selectedLibraryItems) - { - var context = ApplicationController.Instance.DragDropData; - var scene = context.SceneContext.Scene; - scene.Children.Modify(list => - { - list.Add( - new InsertionGroup( - selectedLibraryItems, - context.View3DWidget, - scene, - context.SceneContext.BedCenter, - dragOperationActive: () => false)); - }); - } - public override void OnClosed(ClosedEventArgs e) { if (libraryView?.ActiveContainer != null) diff --git a/PartPreviewWindow/View3D/PrinterActionsBar.cs b/PartPreviewWindow/View3D/PrinterActionsBar.cs index 01cc163b3..a03d5246c 100644 --- a/PartPreviewWindow/View3D/PrinterActionsBar.cs +++ b/PartPreviewWindow/View3D/PrinterActionsBar.cs @@ -293,7 +293,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow context.GCodeFilePath, context.SourceItem.Name, printer, - printerTabPage.view3DWidget, null); }); }; @@ -314,7 +313,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow context.GCodeFilePath, context.SourceItem.Name, printer, - printerTabPage.view3DWidget, null); }); }; diff --git a/PartPreviewWindow/View3D/SlicePopupMenu.cs b/PartPreviewWindow/View3D/SlicePopupMenu.cs index 1d5a094df..1817cf950 100644 --- a/PartPreviewWindow/View3D/SlicePopupMenu.cs +++ b/PartPreviewWindow/View3D/SlicePopupMenu.cs @@ -128,7 +128,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow printer, printer.Bed.EditContext.PartFilePath, printer.Bed.EditContext.GCodeFilePath, - printerTabPage.view3DWidget, new SliceProgressReporter(this.PopupContent, printer)); } catch (Exception ex) diff --git a/PartPreviewWindow/View3D/View3DWidget.cs b/PartPreviewWindow/View3D/View3DWidget.cs index 3c2c9a9d3..f7283cdfa 100644 --- a/PartPreviewWindow/View3D/View3DWidget.cs +++ b/PartPreviewWindow/View3D/View3DWidget.cs @@ -394,7 +394,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow Title = "Clear Bed".Localize(), Action = () => { - UiThread.RunOnIdle(sceneContext.ClearPlate); + UiThread.RunOnIdle(() => + { + sceneContext.ClearPlate().ConfigureAwait(false); + }); } } }; diff --git a/PrinterEmulator/Emulator.cs b/PrinterEmulator/Emulator.cs index c56f0aa0a..b2bb77391 100644 --- a/PrinterEmulator/Emulator.cs +++ b/PrinterEmulator/Emulator.cs @@ -51,7 +51,7 @@ namespace MatterHackers.PrinterEmulator // Dictionary of command and response callback private Dictionary> responses; - private bool shutDown = false; + private bool shuttingDown = false; public Heater HeatedBed { get; } = new Heater("HeatedBed") { CurrentTemperature = 26 }; @@ -148,8 +148,7 @@ namespace MatterHackers.PrinterEmulator public void Dispose() { - ShutDown(); - + this.ShutDown(); Emulator.Instance = null; } @@ -250,9 +249,13 @@ namespace MatterHackers.PrinterEmulator public void ShutDown() { - HeatedBed.Stop(); - Hotend.Stop(); - shutDown = true; + if (!shuttingDown) + { + shuttingDown = true; + + HeatedBed.Stop(); + Hotend.Stop(); + } } public void SimulateReboot() @@ -452,6 +455,8 @@ namespace MatterHackers.PrinterEmulator // Maintain temperatures Task.Run(() => { + Thread.CurrentThread.Name = $"EmulatorHeator{identifier}"; + var random = new Random(); double requiredLoops = 0; @@ -583,7 +588,7 @@ namespace MatterHackers.PrinterEmulator public void Close() { - this.shutDown = true; + this.ShutDown(); } public void Open() @@ -599,7 +604,8 @@ namespace MatterHackers.PrinterEmulator Task.Run(() => { - while (!shutDown) + Thread.CurrentThread.Name = "EmulatorDtr"; + while (!shuttingDown) { if (this.DtrEnable != DsrState) { @@ -613,13 +619,20 @@ namespace MatterHackers.PrinterEmulator Task.Run(() => { - while (!shutDown || receiveQueue.Count > 0) + Thread.CurrentThread.Name = "EmulatorPipeline"; + + while (!shuttingDown || receiveQueue.Count > 0) { if (receiveQueue.Count == 0) { receiveResetEvent.WaitOne(); } + if (shuttingDown) + { + return; + } + if (receiveQueue.Count == 0) { Thread.Sleep(10); @@ -648,11 +661,8 @@ namespace MatterHackers.PrinterEmulator this.IsOpen = false; - this.Close(); this.Dispose(); }); - - this.IsOpen = true; } public void QueueResponse(string line) diff --git a/SettingsManagement/OemSettings.cs b/SettingsManagement/OemSettings.cs index 4d87a4169..30f1bf8cf 100644 --- a/SettingsManagement/OemSettings.cs +++ b/SettingsManagement/OemSettings.cs @@ -205,6 +205,11 @@ namespace MatterHackers.MatterControl.SettingsManagement await Task.Delay(20000); await ProfileManager.LoadOemProfileAsync(publicDevice, oem, model); + if (MatterControlApplication.Instance.ApplicationExiting) + { + return; + } + if (syncReport != null) { reportValue.Status = string.Format("Downloading public profiles for {0}...", oem); diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index f92ab5bbb..0759ce93e 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit f92ab5bbbcf8fe99440e067e52cdb289a0ff57d0 +Subproject commit 0759ce93ef5eb6ef6b728c6c4d70233fe9db4429 diff --git a/Tests/MatterControl.Tests/MatterControl/MatterControlUtilities.cs b/Tests/MatterControl.Tests/MatterControl/MatterControlUtilities.cs index d64859d98..ccdc92535 100644 --- a/Tests/MatterControl.Tests/MatterControl/MatterControlUtilities.cs +++ b/Tests/MatterControl.Tests/MatterControl/MatterControlUtilities.cs @@ -286,7 +286,7 @@ namespace MatterHackers.MatterControl.Tests.Automation // An unpredictable period of time will pass between Clicking Save, everything reloading and us returning to the caller. // Block until ReloadAll has completed then close and return to the caller, at which point hopefully everything is reloaded. - WaitForReloadAll(testRunner, () => testRunner.ClickByName("Save & Continue Button")); + testRunner.WaitForReloadAll(() => testRunner.ClickByName("Save & Continue Button")); testRunner.ClickByName("Cancel Wizard Button"); testRunner.Delay(1);