diff --git a/ApplicationView/MainApplicationWidget.cs b/ApplicationView/MainApplicationWidget.cs index cf5d72c94..81d295096 100644 --- a/ApplicationView/MainApplicationWidget.cs +++ b/ApplicationView/MainApplicationWidget.cs @@ -434,18 +434,9 @@ namespace MatterHackers.MatterControl ApplicationClosed?.Invoke(null, null); } - static void LoadUITheme() + static void LoadOemOrDefaultTheme() { - // if the user setting has a theme color assume it is correct and use it right away - if (UserSettings.Instance != null) - { - var themeName = UserSettings.Instance.get(UserSettingsKey.ActiveThemeName); - if (!string.IsNullOrEmpty(themeName)) - { - ActiveTheme.Instance = ActiveTheme.GetThemeColors(themeName); - return; - } - } + ActiveTheme.SuspendEvents(); // if not check for the oem color and use it if set // else default to "Blue - Light" @@ -456,9 +447,10 @@ namespace MatterHackers.MatterControl } else { - UserSettings.Instance.set(UserSettingsKey.ActiveThemeName, oemColor); ActiveTheme.Instance = ActiveTheme.GetThemeColors(oemColor); } + + ActiveTheme.ResumeEvents(); } public static ApplicationController Instance @@ -471,11 +463,10 @@ namespace MatterHackers.MatterControl { globalInstance = new ApplicationController(); - // set the colors - LoadUITheme(); + // Set the default theme colors + LoadOemOrDefaultTheme(); - // We previously made a call to Reload, which fired the method twice due to it being in the static constructor. Accessing - // any property will run the static constructor and perform the Reload behavior without the overhead of duplicate calls + // Accessing any property on ProfileManager will run the static constructor and spin up the ProfileManager instance bool na = ProfileManager.Instance.IsGuestProfile; if (UserSettings.Instance.DisplayMode == ApplicationDisplayType.Touchscreen) diff --git a/DataStorage/Classic/ClassicSqlitePrinterProfiles.cs b/DataStorage/Classic/ClassicSqlitePrinterProfiles.cs index 49bc1e3d5..a59772c7b 100644 --- a/DataStorage/Classic/ClassicSqlitePrinterProfiles.cs +++ b/DataStorage/Classic/ClassicSqlitePrinterProfiles.cs @@ -108,8 +108,6 @@ namespace MatterHackers.MatterControl.DataStorage.ClassicDB ProfileManager.Instance.LastProfileID = printer.Id.ToString(); } - printerSettings.UserLayer[SettingsKey.active_theme_name] = UserSettings.Instance.get(UserSettingsKey.ActiveThemeName); - // Import macros from the database var allMacros = Datastore.Instance.dbSQLite.Query("SELECT * FROM CustomCommands WHERE PrinterId = " + printer.Id); printerSettings.Macros = allMacros.Select(macro => new GCodeMacro() diff --git a/DataStorage/Models.cs b/DataStorage/Models.cs index 554795d70..783867091 100644 --- a/DataStorage/Models.cs +++ b/DataStorage/Models.cs @@ -334,6 +334,8 @@ namespace MatterHackers.MatterControl.DataStorage public string PrintingGCodeFileName { get; set; } + public double RecoveryCount { get; set; } + public double PercentDone { get; set; } public bool PrintComplete { get; set; } diff --git a/History/PrintHistoryListItem.cs b/History/PrintHistoryListItem.cs index e4b506316..224b0043d 100644 --- a/History/PrintHistoryListItem.cs +++ b/History/PrintHistoryListItem.cs @@ -146,7 +146,19 @@ namespace MatterHackers.MatterControl.PrintHistory if (printTask.PercentDone > 0) { timeIndicator.AutoExpandBoundsToText = true; - timeIndicator.Text += " ({0:0.0}%)".FormatWith(printTask.PercentDone); + timeIndicator.Text += $" ({printTask.PercentDone:0.0}%)"; + + if(printTask.RecoveryCount > 0) + { + if (printTask.RecoveryCount == 1) + { + timeIndicator.Text += " - " + "recovered once".Localize(); + } + else + { + timeIndicator.Text += " - " + "recovered {0} times".FormatWith(printTask.RecoveryCount); + } + } } timeIndicator.Margin = new BorderDouble(right: 6); diff --git a/PrinterCommunication/PrinterConnectionAndCommunication.cs b/PrinterCommunication/PrinterConnectionAndCommunication.cs index d8184a99b..751e67d2d 100644 --- a/PrinterCommunication/PrinterConnectionAndCommunication.cs +++ b/PrinterCommunication/PrinterConnectionAndCommunication.cs @@ -265,8 +265,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication ReadLineContainsCallBacks.AddCallbackToKey("T:", ReadTemperatures); - ReadLineContainsCallBacks.AddCallbackToKey("rs ", PrinterRequestsResend); // smoothie is lower case and no : - ReadLineContainsCallBacks.AddCallbackToKey("RS:", PrinterRequestsResend); + ReadLineStartCallBacks.AddCallbackToKey("rs ", PrinterRequestsResend); // smoothie is lower case and no : + ReadLineStartCallBacks.AddCallbackToKey("RS:", PrinterRequestsResend); ReadLineContainsCallBacks.AddCallbackToKey("Resend:", PrinterRequestsResend); ReadLineContainsCallBacks.AddCallbackToKey("FIRMWARE_NAME:", PrinterStatesFirmware); @@ -1470,17 +1470,22 @@ namespace MatterHackers.MatterControl.PrinterCommunication { FoundStringEventArgs foundStringEventArgs = e as FoundStringEventArgs; - string[] splitOnColon = foundStringEventArgs.LineToCheck.Split(':'); - - if (splitOnColon.Length > 1) + if (foundStringEventArgs != null + && !string.IsNullOrEmpty(foundStringEventArgs.LineToCheck)) { - int result = 0; - if (int.TryParse(splitOnColon[1], out result)) + string line = foundStringEventArgs.LineToCheck; + // marlin and repetier send a : before the number and then and ok + if (!GCodeFile.GetFirstNumberAfter(":", line, ref currentLineIndexToSend)) { - currentLineIndexToSend = result; + // smoothie sends an N before the number and no ok + if (GCodeFile.GetFirstNumberAfter("N", line, ref currentLineIndexToSend)) + { + // clear waiting for ok because smoothie will not send it + PrintingCanContinue(null, null); + } } - if(currentLineIndexToSend >= allCheckSumLinesSent.Count) + if (currentLineIndexToSend >= allCheckSumLinesSent.Count) { SendLineToPrinterNow("M110 N1"); } @@ -2222,6 +2227,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication private void AttemptToConnect(string serialPortName, int baudRate) { + // make sure we don't have a left over print task + activePrintTask = null; + connectionFailureMessage = LocalizedString.Get("Unknown Reason"); if (PrinterIsConnected) @@ -2450,6 +2458,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication && activePrintTask != null) // We are resuming a failed print (do lots of interesting stuff). { pauseHandlingStream1 = new PauseHandlingStream(new PrintRecoveryStream(gCodeFileStream0, activePrintTask.PercentDone)); + // And increment the recovery count + activePrintTask.RecoveryCount++; + activePrintTask.Commit(); } else { diff --git a/SettingsManagement/UserSettings.cs b/SettingsManagement/UserSettings.cs index 28ec0d284..4dc3f9241 100644 --- a/SettingsManagement/UserSettings.cs +++ b/SettingsManagement/UserSettings.cs @@ -11,7 +11,6 @@ namespace MatterHackers.MatterControl public const string UpdateFeedType = nameof(UpdateFeedType); public const string ApplicationDisplayMode = nameof(ApplicationDisplayMode); public const string defaultRenderSetting = nameof(defaultRenderSetting); - public const string ActiveThemeName = nameof(ActiveThemeName); public const string ThumbnailRenderingMode = nameof(ThumbnailRenderingMode); public const string CredentialsInvalid = nameof(CredentialsInvalid); public const string CredentialsInvalidReason = nameof(CredentialsInvalidReason); diff --git a/SlicerConfiguration/Settings/ActiveSliceSettings.cs b/SlicerConfiguration/Settings/ActiveSliceSettings.cs index f8cdcd9aa..9b7ece61e 100644 --- a/SlicerConfiguration/Settings/ActiveSliceSettings.cs +++ b/SlicerConfiguration/Settings/ActiveSliceSettings.cs @@ -40,6 +40,7 @@ using MatterHackers.Agg.PlatformAbstract; using MatterHackers.SerialPortCommunication.FrostedSerial; using MatterHackers.Agg.UI; using System.Threading.Tasks; +using MatterHackers.Localizations; namespace MatterHackers.MatterControl.SlicerConfiguration { @@ -51,7 +52,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public static RootedObjectEventHandler ActiveProfileModified = new RootedObjectEventHandler(); public static RootedObjectEventHandler SettingChanged = new RootedObjectEventHandler(); - private static PrinterSettings activeInstance = null; + private static PrinterSettings activeInstance = PrinterSettings.Empty; public static PrinterSettings Instance { get @@ -60,37 +61,31 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } set { - // EmptyProfile instances may differ but IDs are always be the same. Only process if instance and IDs differ if (activeInstance != value - && activeInstance?.ID != value.ID) + && value != null) { - // If we have an active printer, run Disable otherwise skip to prevent empty ActiveSliceSettings due to null ActivePrinter - if (activeInstance != null) + // If we have an active printer, run Disable + if (activeInstance != PrinterSettings.Empty) { PrinterConnectionAndCommunication.Instance.Disable(); } activeInstance = value; - if (activeInstance != null) - { - BedSettings.SetMakeAndModel(activeInstance.GetValue(SettingsKey.make), activeInstance.GetValue(SettingsKey.model)); - } - SwitchToPrinterTheme(MatterControlApplication.IsLoading); + BedSettings.SetMakeAndModel(activeInstance.GetValue(SettingsKey.make), activeInstance.GetValue(SettingsKey.model)); + + SwitchToPrinterTheme(!MatterControlApplication.IsLoading); if (!MatterControlApplication.IsLoading) { OnActivePrinterChanged(null); - if (ActiveSliceSettings.Instance.PrinterSelected) + if (ActiveSliceSettings.Instance.PrinterSelected + && Instance.GetValue(SettingsKey.auto_connect)) { - if (Instance.GetValue(SettingsKey.auto_connect)) + UiThread.RunOnIdle(() => { - UiThread.RunOnIdle(() => - { - //PrinterConnectionAndCommunication.Instance.HaltConnectionThread(); - PrinterConnectionAndCommunication.Instance.ConnectToActivePrinter(); - }, 2); - } + PrinterConnectionAndCommunication.Instance.ConnectToActivePrinter(); + }, 2); } } } @@ -132,39 +127,28 @@ namespace MatterHackers.MatterControl.SlicerConfiguration /// public static void SwitchToPrinterTheme(bool doReloadEvent) { - if (ActiveSliceSettings.Instance != null) + if (ActiveSliceSettings.Instance.PrinterSelected) { - if (ActiveSliceSettings.Instance.PrinterSelected) + //Attempt to load userSetting theme as default + string activeThemeName = ActiveSliceSettings.Instance.GetValue(SettingsKey.active_theme_name); + if (!string.IsNullOrEmpty(activeThemeName)) { - //Attempt to load userSetting theme as default - if (ActiveSliceSettings.Instance.Contains(SettingsKey.active_theme_name)) + if (!doReloadEvent) { - string activeThemeName = ActiveSliceSettings.Instance.GetValue(SettingsKey.active_theme_name); - if (!doReloadEvent) - { - ActiveTheme.SuspendEvents(); - } - ActiveTheme.Instance = ActiveTheme.GetThemeColors(activeThemeName); - - // Save the theme so we can load it first thing on startup before a profile is loaded. - UserSettings.Instance.set(UserSettingsKey.ActiveThemeName, ActiveTheme.Instance.Name); - - ActiveTheme.ResumeEvents(); + ActiveTheme.SuspendEvents(); } + + ActiveTheme.Instance = ActiveTheme.GetThemeColors(activeThemeName); + + ActiveTheme.ResumeEvents(); } } } - static ActiveSliceSettings() - { - // Load last profile or fall back to empty - Instance = ProfileManager.Instance?.LoadWithoutRecovery(ProfileManager.Instance.LastProfileID) ?? ProfileManager.LoadEmptyProfile(); - } - internal static async Task SwitchToProfile(string printerID) { ProfileManager.Instance.LastProfileID = printerID; - Instance = (await ProfileManager.LoadProfileAsync(printerID)) ?? ProfileManager.LoadEmptyProfile(); + Instance = (await ProfileManager.LoadProfileAsync(printerID)) ?? PrinterSettings.Empty; } private static void OnActivePrinterChanged(EventArgs e) diff --git a/SlicerConfiguration/Settings/PrinterSettings.cs b/SlicerConfiguration/Settings/PrinterSettings.cs index b99fe0d60..9d72b4e4c 100644 --- a/SlicerConfiguration/Settings/PrinterSettings.cs +++ b/SlicerConfiguration/Settings/PrinterSettings.cs @@ -59,6 +59,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration private static PrinterSettingsLayer baseLayerCache; + public static PrinterSettings Empty { get; } + public int DocumentVersion { get; set; } = LatestVersion; public string ID { get; set; } @@ -75,6 +77,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public PrinterSettingsLayer StagedUserSettings { get; set; } = new PrinterSettingsLayer(); + static PrinterSettings() + { + Empty = new PrinterSettings() { ID = "EmptyProfile" }; + Empty.UserLayer[SettingsKey.printer_name] = "Printers...".Localize(); + } + public PrinterSettings() { this.Helpers = new SettingsHelpers(this); @@ -91,6 +99,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } } } + public IEnumerable ActionMacros() { foreach (var macro in Macros) @@ -357,7 +366,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { // If we still have failed to recover a profile, create an empty profile with // just enough data to delete the printer - printerSettings = ProfileManager.LoadEmptyProfile(); + printerSettings = PrinterSettings.Empty; printerSettings.ID = printerInfo.ID; printerSettings.UserLayer[SettingsKey.device_token] = printerInfo.DeviceToken; printerSettings.Helpers.SetComPort(printerInfo.ComPort); @@ -548,6 +557,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } [JsonIgnore] public SettingsHelpers Helpers { get; set; } + [JsonIgnore] public bool PrinterSelected => OemLayer?.Keys.Count > 0; @@ -978,12 +988,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { var persistenceLayer = layer ?? UserLayer; - if(settingsKey == SettingsKey.active_theme_name) - { - // also save it to the user settings so we can load it first thing on startup before a profile is loaded. - UserSettings.Instance.set(UserSettingsKey.ActiveThemeName, settingsValue); - } - // If the setting exists and is set the requested value, exit without setting or saving string existingValue; if (persistenceLayer.TryGetValue(settingsKey, out existingValue) && existingValue == settingsValue) diff --git a/SlicerConfiguration/Settings/ProfileManager.cs b/SlicerConfiguration/Settings/ProfileManager.cs index bb3f4ca63..2c08ab6c6 100644 --- a/SlicerConfiguration/Settings/ProfileManager.cs +++ b/SlicerConfiguration/Settings/ProfileManager.cs @@ -29,25 +29,54 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; +using System.Threading.Tasks; +using MatterHackers.Agg; using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.DataStorage; +using MatterHackers.MatterControl.SettingsManagement; using Newtonsoft.Json; namespace MatterHackers.MatterControl.SlicerConfiguration { - using System.Collections.ObjectModel; - using System.Threading.Tasks; - using Agg; - using DataStorage; - using Localizations; - using SettingsManagement; - public class ProfileManager { public static RootedObjectEventHandler ProfilesListChanged = new RootedObjectEventHandler(); - public static ProfileManager Instance { get; private set; } + private static ProfileManager activeInstance = null; + public static ProfileManager Instance + { + get + { + return activeInstance; + } + private set + { + activeInstance = value; + + // If the loaded slice settings do not match the last active settings for this profile, change to the last active + if (ActiveSliceSettings.Instance?.ID != activeInstance.LastProfileID) + { + // Load or download on a background thread + var lastProfile = LoadProfileAsync(activeInstance.LastProfileID).Result; + + if (MatterControlApplication.IsLoading) + { + ActiveSliceSettings.Instance = lastProfile ?? PrinterSettings.Empty; + } + else + { + UiThread.RunOnIdle(() => + { + // Assign on the UI thread + ActiveSliceSettings.Instance = lastProfile ?? PrinterSettings.Empty; + }); + } + } + } + } private static EventHandler unregisterEvents; @@ -147,32 +176,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration loadedInstance = new ProfileManager() { UserName = userName }; } - // If the loaded slice settings do not match the last active settings for this profile, change to the last active - if (ActiveSliceSettings.Instance?.ID != loadedInstance.LastProfileID) - { - // async so we can safely wait for LoadProfileAsync to complete - Task.Run(async () => - { - // Load or download on a background thread - var lastProfile = await LoadProfileAsync(Instance.LastProfileID); - - if (MatterControlApplication.IsLoading) - { - // TODO: Not true - we're on a background thread in an async lambda... what is the intent of this? - // Assign on the UI thread - ActiveSliceSettings.Instance = lastProfile ?? LoadEmptyProfile(); - } - else - { - UiThread.RunOnIdle(() => - { - // Assign on the UI thread - ActiveSliceSettings.Instance = lastProfile ?? LoadEmptyProfile(); - }); - } - }); - } - return loadedInstance; } @@ -209,14 +212,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } } - public static PrinterSettings LoadEmptyProfile() - { - var emptyProfile = new PrinterSettings() { ID = "EmptyProfile" }; - emptyProfile.UserLayer[SettingsKey.printer_name] = "Printers...".Localize(); - - return emptyProfile; - } - [JsonIgnore] public string LastProfileID { diff --git a/SlicerConfiguration/Settings/SettingsHelpers.cs b/SlicerConfiguration/Settings/SettingsHelpers.cs index 60a855fc1..b232bb4c8 100644 --- a/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -196,7 +196,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration UiThread.RunOnIdle(() => { - ActiveSliceSettings.Instance = ProfileManager.LoadEmptyProfile(); + ActiveSliceSettings.Instance = PrinterSettings.Empty; // Notify listeners of a ProfileListChange event due to this printers removal ProfileManager.ProfilesListChanged.CallEvents(this, null); diff --git a/StaticData/SliceSettings/Properties.json b/StaticData/SliceSettings/Properties.json index 06ef413cf..579727c66 100644 --- a/StaticData/SliceSettings/Properties.json +++ b/StaticData/SliceSettings/Properties.json @@ -1138,6 +1138,7 @@ "ShowIfSet": "!has_hardware_leveling", "ResetAtEndOfPrint": false, "DefaultValue": "3 Point Plane", + "ReloadUiWhenChanged": true, "RebuildGCodeOnChange": false }, { diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index 2ede804d8..109535cf4 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -5671,3 +5671,18 @@ Translated:Discard Changes English:Stay Connected Translated:Stay Connected +English:Cancel Print +Translated:Cancel Print + +English:Continue Printing +Translated:Continue Printing + +English:Recovered Once +Translated:Recovered Once + +English:Recovered once +Translated:Recovered once + +English:recovered once +Translated:recovered once + diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 3a04f46f4..17c395640 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 3a04f46f41c96a0ce5f084112d2ff0000a1d9ac3 +Subproject commit 17c395640e43ceb5a4803611a8bbfe4cacd72d84 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 9a88dacf7..f7a23ccde 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 9a88dacf7849a32b08e4be1497ac18037d151970 +Subproject commit f7a23ccde5b894dc12bd1fdba867dcb1008013f5