diff --git a/ApplicationView/MainApplicationWidget.cs b/ApplicationView/MainApplicationWidget.cs index 9990b328a..9bd6ba146 100644 --- a/ApplicationView/MainApplicationWidget.cs +++ b/ApplicationView/MainApplicationWidget.cs @@ -48,6 +48,7 @@ using System.Threading.Tasks; namespace MatterHackers.MatterControl { + using Agg.Font; using OemProfileDictionary = Dictionary>; public abstract class ApplicationView : GuiWidget @@ -218,6 +219,22 @@ namespace MatterHackers.MatterControl } } + private static TypeFace monoSpacedTypeFace = null; + public static TypeFace MonoSpacedTypeFace + { + get + { + if (monoSpacedTypeFace == null) + { + monoSpacedTypeFace = TypeFace.LoadFrom(StaticData.Instance.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg"))); + } + + return monoSpacedTypeFace; + } + + private set { } + } + /// /// Requests fresh content from online services, falling back to cached content if offline /// @@ -472,24 +489,26 @@ namespace MatterHackers.MatterControl if (!System.IO.File.Exists(@"/storage/sdcard0/Download/LaunchTestPrint.stl")) { bool showAuthWindow = WizardWindow.ShouldShowAuthPanel?.Invoke() ?? false; - if (showAuthWindow) - { - //Launch window to prompt user to log in - UiThread.RunOnIdle(() => WizardWindow.ShowPrinterSetup()); - } - else - { - //If user in logged in sync before checking to prompt to create printer - ApplicationController.SyncPrinterProfiles().ContinueWith((task) => - { - ApplicationController.Instance.ReloadAdvancedControlsPanel(); - if (!ProfileManager.Instance.ActiveProfiles.Any()) - { - // Start the setup wizard if no profiles exist - UiThread.RunOnIdle(() => WizardWindow.ShowPrinterSetup()); - } - }); - } + if (showAuthWindow) + { + //Launch window to prompt user to log in + UiThread.RunOnIdle(() => WizardWindow.ShowPrinterSetup()); + } + else + { + //If user in logged in sync before checking to prompt to create printer + if (ApplicationController.SyncPrinterProfiles == null) + { + RunSetupIfRequired(); + } + else + { + ApplicationController.SyncPrinterProfiles.Invoke().ContinueWith((task) => + { + RunSetupIfRequired(); + }); + } + } if (OsInformation.OperatingSystem != OSType.Windows) { @@ -515,7 +534,18 @@ namespace MatterHackers.MatterControl }, 2); } } - private EventHandler unregisterEvent; + + private static void RunSetupIfRequired() + { + ApplicationController.Instance.ReloadAdvancedControlsPanel(); + if (!ProfileManager.Instance.ActiveProfiles.Any()) + { + // Start the setup wizard if no profiles exist + UiThread.RunOnIdle(() => WizardWindow.ShowPrinterSetup()); + } + } + + private EventHandler unregisterEvent; public void StartPrintingTest() { QueueData.Instance.RemoveAll(); diff --git a/ApplicationView/MenuRow/MenuOptionFile.cs b/ApplicationView/MenuRow/MenuOptionFile.cs index 5898137c3..c922e87fb 100644 --- a/ApplicationView/MenuRow/MenuOptionFile.cs +++ b/ApplicationView/MenuRow/MenuOptionFile.cs @@ -65,7 +65,10 @@ namespace MatterHackers.MatterControl private void ImportSettingsFile(string settingsFilePath) { - ProfileManager.ImportFromExisting(settingsFilePath); + if(!ProfileManager.ImportFromExisting(settingsFilePath)) + { + StyledMessageBox.ShowMessageBox(null, "Oops! Settings file '{0}' did not contain any settings we could import.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize()); + } } private void importFile_Click() diff --git a/BrailleBuilder/View3DBrailleBuilder.cs b/BrailleBuilder/View3DBrailleBuilder.cs index 371c6f90c..54953f4f3 100644 --- a/BrailleBuilder/View3DBrailleBuilder.cs +++ b/BrailleBuilder/View3DBrailleBuilder.cs @@ -127,18 +127,17 @@ namespace MatterHackers.MatterControl.Plugins.BrailleBuilder internal struct MeshSelectInfo { - internal bool downOnPart; - internal PlaneShape hitPlane; internal Vector3 planeDownHitPos; internal Vector3 lastMoveDelta; } private TypeFace brailTypeFace; - private TypeFace boldTypeFace; + private TypeFace monoSpacedTypeFace; public View3DBrailleBuilder(Vector3 viewerVolume, Vector2 bedCenter, BedShape bedShape) { - boldTypeFace = TypeFace.LoadFrom(StaticData.Instance.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg"))); + monoSpacedTypeFace = ApplicationController.MonoSpacedTypeFace; + brailTypeFace = TypeFace.LoadFrom(StaticData.Instance.ReadAllText(Path.Combine("Fonts", "Braille.svg"))); MeshGroupExtraData = new List(); @@ -374,7 +373,7 @@ namespace MatterHackers.MatterControl.Plugins.BrailleBuilder TypeFacePrinter brailPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(brailTypeFace, 12)); int firstNewCharacter = 0; - StyledTypeFace boldStyled = new StyledTypeFace(boldTypeFace, 12); + StyledTypeFace boldStyled = new StyledTypeFace(monoSpacedTypeFace, 12); if (includeText.Checked) { diff --git a/ControlElements/MHTextEditWidget.cs b/ControlElements/MHTextEditWidget.cs index 8ad73aed4..5940d93bf 100644 --- a/ControlElements/MHTextEditWidget.cs +++ b/ControlElements/MHTextEditWidget.cs @@ -1,4 +1,5 @@ using MatterHackers.Agg; +using MatterHackers.Agg.Font; using MatterHackers.Agg.UI; using MatterHackers.VectorMath; using System; @@ -16,10 +17,10 @@ namespace MatterHackers.MatterControl get { return actuallTextEditWidget; } } - public MHTextEditWidget(string text = "", double x = 0, double y = 0, double pointSize = 12, double pixelWidth = 0, double pixelHeight = 0, bool multiLine = false, int tabIndex = 0, string messageWhenEmptyAndNotSelected = "") + public MHTextEditWidget(string text = "", double x = 0, double y = 0, double pointSize = 12, double pixelWidth = 0, double pixelHeight = 0, bool multiLine = false, int tabIndex = 0, string messageWhenEmptyAndNotSelected = "", TypeFace typeFace = null) { Padding = new BorderDouble(3); - actuallTextEditWidget = new TextEditWidget(text, x, y, pointSize, pixelWidth, pixelHeight, multiLine, tabIndex: tabIndex); + actuallTextEditWidget = new TextEditWidget(text, x, y, pointSize, pixelWidth, pixelHeight, multiLine, tabIndex: tabIndex, typeFace: typeFace); actuallTextEditWidget.HAnchor = Agg.UI.HAnchor.ParentLeftRight; actuallTextEditWidget.MinimumSize = new Vector2(Math.Max(actuallTextEditWidget.MinimumSize.x, pixelWidth), Math.Max(actuallTextEditWidget.MinimumSize.y, pixelHeight)); actuallTextEditWidget.VAnchor = Agg.UI.VAnchor.ParentBottom; diff --git a/PrinterCommunication/PrinterConnectionAndCommunication.cs b/PrinterCommunication/PrinterConnectionAndCommunication.cs index c08421ccd..1cac99f52 100644 --- a/PrinterCommunication/PrinterConnectionAndCommunication.cs +++ b/PrinterCommunication/PrinterConnectionAndCommunication.cs @@ -2467,7 +2467,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication loadedGCode = GCodeFile.Load(gcodeFilename); gCodeFileStream0 = new GCodeFileStream(loadedGCode); - if(activePrintTask != null) // We are resuming a failed print (do lots of interesting stuff). + if(ActiveSliceSettings.Instance.GetValue(SettingsKey.resume_is_enabled) + && activePrintTask != null) // We are resuming a failed print (do lots of interesting stuff). { pauseHandlingStream1 = new PauseHandlingStream(new ResumePrintingStream(gCodeFileStream0, activePrintTask.PercentDone)); } diff --git a/PrinterControls/TerminalWindow/TerminalWidget.cs b/PrinterControls/TerminalWindow/TerminalWidget.cs index 9bce5fdf0..1e5540dcc 100644 --- a/PrinterControls/TerminalWindow/TerminalWidget.cs +++ b/PrinterControls/TerminalWindow/TerminalWidget.cs @@ -29,6 +29,8 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg; using MatterHackers.Agg.UI; +using MatterHackers.Agg.Font; +using MatterHackers.Agg.PlatformAbstract; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.PrinterCommunication; @@ -138,7 +140,7 @@ namespace MatterHackers.MatterControl manualEntryLayout.BackgroundColor = this.backgroundColor; manualEntryLayout.HAnchor = HAnchor.ParentLeftRight; { - manualCommandTextEdit = new MHTextEditWidget(""); + manualCommandTextEdit = new MHTextEditWidget("", typeFace: ApplicationController.MonoSpacedTypeFace); //manualCommandTextEdit.BackgroundColor = RGBA_Bytes.White; manualCommandTextEdit.Margin = new BorderDouble(right: 3); manualCommandTextEdit.HAnchor = HAnchor.ParentLeftRight; @@ -304,4 +306,4 @@ namespace MatterHackers.MatterControl manualCommandTextEdit.Text = ""; } } -} \ No newline at end of file +} diff --git a/PrinterControls/TerminalWindow/TextScrollWidget.cs b/PrinterControls/TerminalWindow/TextScrollWidget.cs index 6c877fe2c..c75255c39 100644 --- a/PrinterControls/TerminalWindow/TextScrollWidget.cs +++ b/PrinterControls/TerminalWindow/TextScrollWidget.cs @@ -91,8 +91,7 @@ namespace MatterHackers.MatterControl public TextScrollWidget(List sourceLines) { - string pathToFont = StaticData.Instance.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg")); - printer = new TypeFacePrinter("", new StyledTypeFace(TypeFace.LoadFrom(pathToFont), 12)); + printer = new TypeFacePrinter("", new StyledTypeFace(ApplicationController.MonoSpacedTypeFace, 12)); printer.DrawFromHintedCache = true; this.allSourceLines = sourceLines; this.visibleLines = sourceLines; diff --git a/SetupWizard/ImportSettingsPage.cs b/SetupWizard/ImportSettingsPage.cs index 016383ad3..7bacd4a63 100644 --- a/SetupWizard/ImportSettingsPage.cs +++ b/SetupWizard/ImportSettingsPage.cs @@ -62,6 +62,7 @@ namespace MatterHackers.MatterControl this.destinationLayer = destinationLayer; this.sectionName = sectionName; + // TODO: Need to handle load failures for import attempts settingsToImport = PrinterSettings.LoadFile(settingsFilePath); this.headerLabel.Text = "Select What to Import".Localize(); @@ -197,7 +198,7 @@ namespace MatterHackers.MatterControl HashSet skipKeys = new HashSet { - "layer_name", + SettingsKey.layer_name, "layer_id", }; @@ -225,9 +226,9 @@ namespace MatterHackers.MatterControl } } - if (!isMergeIntoUserLayer && material.ContainsKey("layer_name")) + if (!isMergeIntoUserLayer && material.ContainsKey(SettingsKey.layer_name)) { - destinationLayer["layer_name"] = material["layer_name"]; + destinationLayer[SettingsKey.layer_name] = material[SettingsKey.layer_name]; } } else if (selectedQuality > -1) @@ -242,9 +243,9 @@ namespace MatterHackers.MatterControl } } - if (!isMergeIntoUserLayer && quality.ContainsKey("layer_name")) + if (!isMergeIntoUserLayer && quality.ContainsKey(SettingsKey.layer_name)) { - destinationLayer["layer_name"] = quality["layer_name"]; + destinationLayer[SettingsKey.layer_name] = quality[SettingsKey.layer_name]; } } else @@ -268,7 +269,7 @@ namespace MatterHackers.MatterControl string successMessage = importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath)); if (!isMergeIntoUserLayer) { - string sourceName = isMergeIntoUserLayer ? Path.GetFileNameWithoutExtension(settingsFilePath) : destinationLayer["layer_name"]; + string sourceName = isMergeIntoUserLayer ? Path.GetFileNameWithoutExtension(settingsFilePath) : destinationLayer[SettingsKey.layer_name]; successMessage = ImportSettingsPage.importSettingSuccessMessage.FormatWith(sourceName, sectionName); } @@ -431,11 +432,18 @@ namespace MatterHackers.MatterControl { if(newPrinterButton.Checked) { - ProfileManager.ImportFromExisting(settingsFilePath); - WizardWindow.ChangeToPage(new ImportSucceeded(importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath))) + if(ProfileManager.ImportFromExisting(settingsFilePath)) { - WizardWindow = this.WizardWindow, - }); + WizardWindow.ChangeToPage(new ImportSucceeded(importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath))) + { + WizardWindow = this.WizardWindow, + }); + } + else + { + displayFailedToImportMessage(settingsFilePath); + } + } else if(mergeButton.Checked) { @@ -464,7 +472,7 @@ namespace MatterHackers.MatterControl { case ProfileManager.ProfileExtension: newLayer = new PrinterSettingsLayer(); - newLayer["layer_name"] = Path.GetFileNameWithoutExtension(settingsFilePath); + newLayer[SettingsKey.layer_name] = Path.GetFileNameWithoutExtension(settingsFilePath); if (newQualityPresetButton.Checked) { @@ -485,10 +493,8 @@ namespace MatterHackers.MatterControl case ".slice": // legacy presets file extension case ".ini": var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath); - string layerHeight; - bool isSlic3r = importType == ".slice" || settingsToImport.TryGetValue(SettingsKey.layer_height, out layerHeight); - if (isSlic3r) + bool containsValidSetting = false; { newLayer = new PrinterSettingsLayer(); newLayer.Name = Path.GetFileNameWithoutExtension(settingsFilePath); @@ -502,37 +508,44 @@ namespace MatterHackers.MatterControl foreach (var item in settingsToImport) { - string currentValue = ActiveSliceSettings.Instance.GetValue(item.Key, baseAndOEMCascade).Trim(); - // Compare the value to import to the layer cascade value and only set if different - if (currentValue != item.Value) + if(ActiveSliceSettings.Instance.Contains(item.Key)) { - newLayer[item.Key] = item.Value; + containsValidSetting = true; + string currentValue = ActiveSliceSettings.Instance.GetValue(item.Key, baseAndOEMCascade).Trim(); + // Compare the value to import to the layer cascade value and only set if different + if (currentValue != item.Value) + { + newLayer[item.Key] = item.Value; + } } + } - if (newMaterialPresetButton.Checked) + if(containsValidSetting) { - ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer); + if (newMaterialPresetButton.Checked) + { + ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer); + } + else + { + ActiveSliceSettings.Instance.QualityLayers.Add(newLayer); + } + + ActiveSliceSettings.Instance.Save(); + + WizardWindow.ChangeToPage(new ImportSucceeded(importSettingSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath), sectionName)) + { + WizardWindow = this.WizardWindow, + }); } else { - ActiveSliceSettings.Instance.QualityLayers.Add(newLayer); + displayFailedToImportMessage(settingsFilePath); } - ActiveSliceSettings.Instance.Save(); + } - WizardWindow.ChangeToPage(new ImportSucceeded(importSettingSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath), sectionName)) - { - WizardWindow = this.WizardWindow, - }); - } - else - { - // looks like a cura file -#if DEBUG - throw new NotImplementedException("need to import from 'cure.ini' files"); -#endif - } break; default: @@ -558,34 +571,38 @@ namespace MatterHackers.MatterControl case ".slice": // old presets format case ".ini": - var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath); - string layerHeight; - - bool isSlic3r = settingsToImport.TryGetValue(SettingsKey.layer_height, out layerHeight); - //if (isSlic3r) + // create a scope for variables { + var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath); + + bool containsValidSetting = false; var activeSettings = ActiveSliceSettings.Instance; foreach (var item in settingsToImport) { - // Compare the value to import to the layer cascade value and only set if different - string currentValue = activeSettings.GetValue(item.Key, null).Trim(); - if (currentValue != item.Value) + if (activeSettings.Contains(item.Key)) { - activeSettings.UserLayer[item.Key] = item.Value; + containsValidSetting = true; + string currentValue = activeSettings.GetValue(item.Key).Trim(); + // Compare the value to import to the layer cascade value and only set if different + if (currentValue != item.Value) + { + activeSettings.UserLayer[item.Key] = item.Value; + } } } + if (containsValidSetting) + { + activeSettings.Save(); - activeSettings.Save(); - - UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel); + UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel); + } + else + { + displayFailedToImportMessage(settingsFilePath); + } + WizardWindow.Close(); } - //else - { - // looks like a cura file - //throw new NotImplementedException("need to import from 'cure.ini' files"); - } - WizardWindow.Close(); break; default: @@ -598,5 +615,10 @@ namespace MatterHackers.MatterControl } Invalidate(); } + + private void displayFailedToImportMessage(string settingsFilePath) + { + StyledMessageBox.ShowMessageBox(null, "Oops! Settings file '{0}' did not contain any settings we could import.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize()); + } } } diff --git a/SetupWizard/LicenseAgreementPage.cs b/SetupWizard/LicenseAgreementPage.cs index 53057661d..86393971e 100644 --- a/SetupWizard/LicenseAgreementPage.cs +++ b/SetupWizard/LicenseAgreementPage.cs @@ -48,29 +48,14 @@ public class LicenseAgreementPage : WizardPage scrollable.ScrollArea.HAnchor = HAnchor.ParentLeftRight; contentRow.AddChild(scrollable); - var textBox = new WrappedTextWidget("Loading End User License Agreement...", textColor: ActiveTheme.Instance.PrimaryTextColor, doubleBufferText: false); + var textBox = new WrappedTextWidget(eulaText, textColor: ActiveTheme.Instance.PrimaryTextColor, doubleBufferText: false) + { + DrawFromHintedCache = true, + Name = "LicenseAgreementPage", + }; scrollable.ScrollArea.Margin = new BorderDouble(0, 0, 15, 0); scrollable.AddChild(textBox); - // wrap the text on a thread and show it when it is ready - { - UiThread.RunOnIdle(async () => - { - WrappedTextWidget eulaTextBox = textBox; - await Task.Run(() => - { - eulaTextBox = new WrappedTextWidget(eulaText, textColor: ActiveTheme.Instance.PrimaryTextColor, doubleBufferText: false) - { - DrawFromHintedCache = true, - Name = "LicenseAgreementPage", - }; - }); - - scrollable.ScrollArea.RemoveChild(textBox); - scrollable.AddChild(eulaTextBox); - }); - } - var acceptButton = textImageButtonFactory.Generate("Accept".Localize()); acceptButton.Click += (s, e) => { diff --git a/SlicerConfiguration/Settings/ActiveSliceSettings.cs b/SlicerConfiguration/Settings/ActiveSliceSettings.cs index 9c907604e..de3551194 100644 --- a/SlicerConfiguration/Settings/ActiveSliceSettings.cs +++ b/SlicerConfiguration/Settings/ActiveSliceSettings.cs @@ -78,16 +78,14 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { OnActivePrinterChanged(null); - string[] comportNames = FrostedSerialPort.GetPortNames(); - if (ActiveSliceSettings.Instance.PrinterSelected) { if (Instance.GetValue(SettingsKey.auto_connect)) { UiThread.RunOnIdle(() => { - //PrinterConnectionAndCommunication.Instance.HaltConnectionThread(); - PrinterConnectionAndCommunication.Instance.ConnectToActivePrinter(); + //PrinterConnectionAndCommunication.Instance.HaltConnectionThread(); + PrinterConnectionAndCommunication.Instance.ConnectToActivePrinter(); }, 2); } } @@ -100,10 +98,10 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { bool themeChanged = activeInstance.GetValue(SettingsKey.active_theme_index) != updatedProfile.GetValue(SettingsKey.active_theme_index); - SliceSettingsWidget.SettingChanged.CallEvents(null, new StringEventArgs(SettingsKey.printer_name)); - activeInstance = updatedProfile; + SliceSettingsWidget.SettingChanged.CallEvents(null, new StringEventArgs(SettingsKey.printer_name)); + if (themeChanged) { UiThread.RunOnIdle(() => SwitchToPrinterTheme(true)); @@ -143,34 +141,14 @@ namespace MatterHackers.MatterControl.SlicerConfiguration static ActiveSliceSettings() { - // Load Startup Profile - var startupProfile = ProfileManager.Instance.LoadLastProfile(); - if (startupProfile != null) - { - Instance = startupProfile; - } - - if (Instance == null) - { - // Load an empty profile with just the MatterHackers base settings from config.json - Instance = ProfileManager.LoadEmptyProfile(); - } + // Load last profile or fall back to empty + Instance = ProfileManager.Instance.LoadLastProfileWithoutRecovery() ?? ProfileManager.LoadEmptyProfile(); } internal static async Task SwitchToProfile(string printerID) { - var profile = ProfileManager.LoadProfile(printerID); - ProfileManager.Instance.SetLastProfile(printerID); - - if (profile == null) - { - var printerInfo = ProfileManager.Instance[printerID]; - - profile = await ApplicationController.GetPrinterProfileAsync(printerInfo, null); - } - - Instance = profile ?? ProfileManager.LoadEmptyProfile(); + Instance = (await ProfileManager.LoadProfileAsync(printerID)) ?? ProfileManager.LoadEmptyProfile(); } private static void OnActivePrinterChanged(EventArgs e) diff --git a/SlicerConfiguration/Settings/PrinterSettings.cs b/SlicerConfiguration/Settings/PrinterSettings.cs index aef26ffb0..eb953a6af 100644 --- a/SlicerConfiguration/Settings/PrinterSettings.cs +++ b/SlicerConfiguration/Settings/PrinterSettings.cs @@ -216,126 +216,146 @@ namespace MatterHackers.MatterControl.SlicerConfiguration /// User settings overrides /// public PrinterSettingsLayer UserLayer { get; } = new PrinterSettingsLayer(); - // - public static PrinterSettings LoadFile(string printerProfilePath) + + public static PrinterSettings LoadFile(string printerProfilePath, bool performMigrations = false) { - JObject jObject = null; - try + if (performMigrations) { - jObject = JObject.Parse(File.ReadAllText(printerProfilePath)); - } - catch - { - string profileKey = Path.GetFileNameWithoutExtension(printerProfilePath); - var profile = ProfileManager.Instance[profileKey]; + JObject jObject = null; - if (MatterControlApplication.IsLoading) + try { - UiThread.RunOnIdle(() => - { - bool userIsLoggedIn = !ShouldShowAuthPanel?.Invoke() ?? false; - if (userIsLoggedIn && profile != null) - { - if (profile != null) - { - RevertToMostRecentProfile(profile).ContinueWith((t) => WarnAboutRevert(profile)); - } - else - { - RevertToOemProfile(printerProfilePath); - WarnAboutRevert(profile); - } - } - }, 4); - - return ProfileManager.LoadEmptyProfile(); + jObject = JObject.Parse(File.ReadAllText(printerProfilePath)); } - else + catch { - bool userIsLoggedIn = !ShouldShowAuthPanel?.Invoke() ?? false; - if (userIsLoggedIn && profile != null) - { - RevertToMostRecentProfile(profile).ContinueWith((t) => WarnAboutRevert(profile)); - return ProfileManager.LoadEmptyProfile(); - } - else - { - WarnAboutRevert(profile); - return RevertToOemProfile(printerProfilePath); - } + return null; + } + + int documentVersion = jObject?.GetValue("DocumentVersion")?.Value() ?? PrinterSettings.LatestVersion; + if (documentVersion < PrinterSettings.LatestVersion) + { + printerProfilePath = ProfileMigrations.MigrateDocument(printerProfilePath, documentVersion); } } - int documentVersion = jObject?.GetValue("DocumentVersion")?.Value() ?? PrinterSettings.LatestVersion; - if (documentVersion < PrinterSettings.LatestVersion) - { - printerProfilePath = ProfileMigrations.MigrateDocument(printerProfilePath, documentVersion); - } - - // Reload the document with the new schema try { return JsonConvert.DeserializeObject(File.ReadAllText(printerProfilePath)); } catch { - return RevertToOemProfile(printerProfilePath); + return null; } } - static bool warningOpen = false; + public async static Task RecoverProfile(PrinterInfo printerInfo) + { + bool userIsLoggedIn = !ShouldShowAuthPanel?.Invoke() ?? false; + if (userIsLoggedIn && printerInfo != null) + { + // Attempt to load from MCWS history + var printerSettings = await GetFirstValidHistoryItem(printerInfo); + if (printerSettings == null) + { + // Fall back to OemProfile defaults if load from history fails + printerSettings = RestoreFromOemProfile(printerInfo); + } + + if (printerSettings == null) + { + // 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.ID = printerInfo.ID; + printerSettings.UserLayer[SettingsKey.device_token] = printerInfo.DeviceToken; + printerSettings.Helpers.SetComPort(printerInfo.ComPort); + printerSettings.SetValue(SettingsKey.printer_name, printerInfo.Name); + + // Add any setting value to the OemLayer to pass the .PrinterSelected property + printerSettings.OemLayer = new PrinterSettingsLayer(); + printerSettings.OemLayer.Add("empty", "setting"); + printerSettings.Save(); + } + + if (printerSettings != null) + { + // Persist any profile recovered above as the current + printerSettings.Save(); + + // Update active instance without calling ReloadAll + ActiveSliceSettings.RefreshActiveInstance(printerSettings); + + WarnAboutRevert(printerInfo); + } + + return printerSettings; + } + + return null; + } + + private static bool warningWindowOpen = false; + public static void WarnAboutRevert(PrinterInfo profile) { - if (!warningOpen) + if (!warningWindowOpen) { - warningOpen = true; + warningWindowOpen = true; UiThread.RunOnIdle(() => { StyledMessageBox.ShowMessageBox((clicedOk) => { - warningOpen = false; + warningWindowOpen = false; }, String.Format("The profile you are attempting to load has been corrupted. We loaded your last usable {0} {1} profile from your recent profile history instead.".Localize(), profile.Make, profile.Model), "Recovered printer profile".Localize(), messageType: StyledMessageBox.MessageType.OK); }); } } - public static PrinterSettings RevertToOemProfile(string printerProfilePath) + public static PrinterSettings RestoreFromOemProfile(PrinterInfo profile) { - string profileKey = Path.GetFileNameWithoutExtension(printerProfilePath); - var profile = ProfileManager.Instance[profileKey]; - - string publicProfileDeviceToken = OemSettings.Instance.OemProfiles[profile.Make][profile.Model]; - string publicProfileToLoad = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles") + "\\" + publicProfileDeviceToken + ProfileManager.ProfileExtension; + PrinterSettings oemProfile = null; - var oemProfile = JsonConvert.DeserializeObject(File.ReadAllText(publicProfileToLoad)); - oemProfile.ID = profile.ID; - oemProfile.SetValue(SettingsKey.printer_name, profile.Name); - oemProfile.DocumentVersion = PrinterSettings.LatestVersion; + try + { + string publicProfileDeviceToken = OemSettings.Instance.OemProfiles[profile.Make][profile.Model]; + string publicProfileToLoad = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles", publicProfileDeviceToken + ProfileManager.ProfileExtension); - oemProfile.Helpers.SetComPort(profile.ComPort); - oemProfile.Save(); + oemProfile = JsonConvert.DeserializeObject(File.ReadAllText(publicProfileToLoad)); + oemProfile.ID = profile.ID; + oemProfile.SetValue(SettingsKey.printer_name, profile.Name); + oemProfile.DocumentVersion = PrinterSettings.LatestVersion; + + oemProfile.Helpers.SetComPort(profile.ComPort); + oemProfile.Save(); + } + catch { } return oemProfile; } - private static async Task RevertToMostRecentProfile(PrinterInfo profile) + private static async Task GetFirstValidHistoryItem(PrinterInfo printerInfo) { - var recentProfileHistoryItems = await ApplicationController.GetProfileHistory(profile.DeviceToken); + var recentProfileHistoryItems = await ApplicationController.GetProfileHistory(printerInfo.DeviceToken); if (recentProfileHistoryItems != null) { - string profileToken = recentProfileHistoryItems.OrderByDescending(kvp => kvp.Key).FirstOrDefault().Value; - - // Download the specified json profile and persist and activate if successful - var printerProfile = await ApplicationController.GetPrinterProfileAsync(profile, profileToken); - if (printerProfile != null) + // Iterate history, skipping the first item, limiting to the next five, attempt to load and return the first success + foreach (var keyValue in recentProfileHistoryItems.OrderByDescending(kvp => kvp.Key).Skip(1).Take(5)) { - // Persist downloaded profile - printerProfile.Save(); - - // Update active instance without calling ReloadAll - ActiveSliceSettings.RefreshActiveInstance(printerProfile); - } + // Attempt to download and parse each profile, returning if successful + try + { + var printerSettings = await ApplicationController.GetPrinterProfileAsync(printerInfo, keyValue.Value); + if (printerSettings != null) + { + return printerSettings; + } + } + catch { } + }; } + + return null; } /// @@ -371,6 +391,22 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return ""; } + public bool Contains(string sliceSetting, IEnumerable layerCascade = null) + { + if (layerCascade == null) + { + layerCascade = defaultLayerCascade; + } + foreach (PrinterSettingsLayer layer in layerCascade) + { + if (layer.ContainsKey(sliceSetting)) + { + return true; + } + } + return false; + } + [JsonIgnore] public PrinterSettingsLayer BaseLayer { diff --git a/SlicerConfiguration/Settings/PrinterSettingsLayer.cs b/SlicerConfiguration/Settings/PrinterSettingsLayer.cs index 049a7e396..5eda94dfe 100644 --- a/SlicerConfiguration/Settings/PrinterSettingsLayer.cs +++ b/SlicerConfiguration/Settings/PrinterSettingsLayer.cs @@ -73,11 +73,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { get { - return ValueOrDefault("layer_name"); + return ValueOrDefault(SettingsKey.layer_name); } set { - this["layer_name"] = value; + this[SettingsKey.layer_name] = value; } } diff --git a/SlicerConfiguration/Settings/ProfileManager.cs b/SlicerConfiguration/Settings/ProfileManager.cs index ab706050f..5496b34a5 100644 --- a/SlicerConfiguration/Settings/ProfileManager.cs +++ b/SlicerConfiguration/Settings/ProfileManager.cs @@ -121,9 +121,20 @@ namespace MatterHackers.MatterControl.SlicerConfiguration Instance = new ProfileManager(); } - // Load the last selected printer profile or an empty profile - ActiveSliceSettings.Instance = Instance.LoadLastProfile() ?? LoadEmptyProfile(); + if (!MatterControlApplication.IsLoading && ActiveSliceSettings.Instance.ID != Instance.LastProfileID) + { + Task.Run(async () => + { + // Load or download on a background thread + var lastProfile = await LoadProfileAsync(Instance.LastProfileID); + UiThread.RunOnIdle(() => + { + // Assign on the UI thread + ActiveSliceSettings.Instance = lastProfile ?? LoadEmptyProfile(); + }); + }); + } // In either case, wire up the CollectionChanged event Instance.Profiles.CollectionChanged += Profiles_CollectionChanged; @@ -196,25 +207,22 @@ namespace MatterHackers.MatterControl.SlicerConfiguration get { string activeUserName = UserSettings.Instance.get("ActiveUserName"); - string settingsKey = $"ActiveProfileID-{activeUserName}"; - - return UserSettings.Instance.get(settingsKey); + return UserSettings.Instance.get($"ActiveProfileID-{activeUserName}"); } } public bool PrintersImported { get; set; } = false; - public PrinterSettings LoadLastProfile() + public PrinterSettings LoadLastProfileWithoutRecovery() { - return LoadProfile(this.LastProfileID); + return LoadWithoutRecovery(this.LastProfileID); } public void SetLastProfile(string printerID) { string activeUserName = UserSettings.Instance.get("ActiveUserName"); - string settingsKey = $"ActiveProfileID-{activeUserName}"; - UserSettings.Instance.set(settingsKey, printerID); + UserSettings.Instance.set($"ActiveProfileID-{activeUserName}", printerID); } public string ProfilePath(PrinterInfo printer) @@ -227,46 +235,71 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return Path.Combine(ProfileManager.ProfilesPath, printerID + ProfileExtension); } + public static PrinterSettings LoadWithoutRecovery(string profileID) + { + string profilePath = Path.Combine(ProfilesPath, profileID + ProfileManager.ProfileExtension); + if (File.Exists(profilePath)) + { + try + { + return PrinterSettings.LoadFile(profilePath); + } + catch + { + return null; + } + } + + return null; + } + /// - /// Loads the specified PrinterProfile + /// Loads the specified PrinterProfile, performing recovery options if required /// /// The profile ID to load /// Return the in memory instance if already loaded. Alternatively, reload from disk /// - public static PrinterSettings LoadProfile(string profileID, bool useActiveInstance = true) + public static async Task LoadProfileAsync(string profileID, bool useActiveInstance = true) { - // Only load profiles by ID that are defined in the profiles document - if (ProfileManager.Instance[profileID] == null) - { - return null; - } - if (useActiveInstance && ActiveSliceSettings.Instance?.ID == profileID) { return ActiveSliceSettings.Instance; } - string profilePath = Path.Combine(ProfilesPath, profileID + ProfileManager.ProfileExtension); - return File.Exists(profilePath) ? LoadProfileFromDisk(profilePath) : null; + // Only load profiles by ID that are defined in the profiles document + var printerInfo = ProfileManager.Instance[profileID]; + if (printerInfo == null) + { + return null; + } + + // Attempt to load from disk, pull from the web or fall back using recovery logic + PrinterSettings printerSettings = LoadWithoutRecovery(profileID); + if (printerSettings != null) + { + return printerSettings; + } + else if (ApplicationController.GetPrinterProfileAsync != null) + { + // Attempt to load from MCWS if missing on disk + printerSettings = await ApplicationController.GetPrinterProfileAsync(printerInfo, null); + if (printerSettings != null) + { + // If successful, persist downloaded profile and return + printerSettings.Save(); + return printerSettings; + } + } + + // Otherwise attempt to recover to a working profile + return await PrinterSettings.RecoverProfile(printerInfo); } - internal static PrinterSettings LoadProfileFromDisk(string profilePath) - { - if (File.Exists(profilePath)) - { - return PrinterSettings.LoadFile(profilePath); - } - else - { - return LoadEmptyProfile(); - } - } - - internal static void ImportFromExisting(string settingsFilePath) + internal static bool ImportFromExisting(string settingsFilePath) { if (string.IsNullOrEmpty(settingsFilePath) || !File.Exists(settingsFilePath)) { - return; + return false; } var printerInfo = new PrinterInfo @@ -274,12 +307,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration Name = Path.GetFileNameWithoutExtension(settingsFilePath), ID = Guid.NewGuid().ToString() }; - + bool importSuccessful = false; string importType = Path.GetExtension(settingsFilePath).ToLower(); switch (importType) { case ProfileManager.ProfileExtension: - var profile = ProfileManager.LoadProfileFromDisk(settingsFilePath); + var profile = PrinterSettings.LoadFile(settingsFilePath); profile.ID = printerInfo.ID; profile.ClearValue(SettingsKey.device_token); printerInfo.DeviceToken = ""; @@ -290,28 +323,51 @@ namespace MatterHackers.MatterControl.SlicerConfiguration Instance.Profiles.Add(printerInfo); profile.Save(); + importSuccessful = true; break; case ".ini": - var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath); - - var layeredProfile = new PrinterSettings() + //Scope variables { - ID = printerInfo.ID, - OemLayer = settingsToImport - }; + var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath); + var layeredProfile = new PrinterSettings() + { + ID = printerInfo.ID, + }; - // TODO: Resolve name conflicts - layeredProfile.UserLayer[SettingsKey.printer_name.ToString()] = printerInfo.Name; + bool containsValidSetting = false; + var activeSettings = layeredProfile; - layeredProfile.ClearValue(SettingsKey.device_token); - printerInfo.DeviceToken = ""; - Instance.Profiles.Add(printerInfo); + foreach (var item in settingsToImport) + { + if (activeSettings.Contains(item.Key)) + { + containsValidSetting = true; + string currentValue = activeSettings.GetValue(item.Key).Trim(); + // Compare the value to import to the layer cascade value and only set if different + if (currentValue != item.Value) + { + activeSettings.OemLayer[item.Key] = item.Value; + } + } + } + if(containsValidSetting) + { + // TODO: Resolve name conflicts + layeredProfile.UserLayer[SettingsKey.printer_name] = printerInfo.Name; - layeredProfile.Save(); + layeredProfile.ClearValue(SettingsKey.device_token); + printerInfo.DeviceToken = ""; + Instance.Profiles.Add(printerInfo); + layeredProfile.Save(); + importSuccessful = true; + } + + } break; } + return importSuccessful; } internal static async void AcquireNewProfile(string make, string model, string printerName) diff --git a/SlicerConfiguration/Settings/ProfileMigrations.cs b/SlicerConfiguration/Settings/ProfileMigrations.cs index 0881c4695..bb67b0c23 100644 --- a/SlicerConfiguration/Settings/ProfileMigrations.cs +++ b/SlicerConfiguration/Settings/ProfileMigrations.cs @@ -215,7 +215,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration break; case "MatterControl.LayerName": - layer.Add("layer_name", item.Value); + layer.Add(SettingsKey.layer_name, item.Value); break; case "MatterControl.LayerID": diff --git a/SlicerConfiguration/Settings/SettingsHelpers.cs b/SlicerConfiguration/Settings/SettingsHelpers.cs index ced8becbd..ad7cfac1b 100644 --- a/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -59,6 +59,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string device_token = nameof(device_token); public const string device_type = nameof(device_type); public const string extruder_count = nameof(extruder_count); + public const string resume_is_enabled = nameof(resume_is_enabled); public const string extruders_share_temperature = nameof(extruders_share_temperature); public const string filament_cost = nameof(filament_cost); public const string filament_density = nameof(filament_density); @@ -69,6 +70,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string has_fan = nameof(has_fan); public const string has_hardware_leveling = nameof(has_hardware_leveling); public const string has_heated_bed = nameof(has_heated_bed); + public const string bed_remove_part_temperature = nameof(bed_remove_part_temperature); public const string has_power_control = nameof(has_power_control); public const string has_sd_card_reader = nameof(has_sd_card_reader); public const string layer_height = nameof(layer_height); @@ -89,6 +91,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string spiral_vase = nameof(spiral_vase); public const string start_gcode = nameof(start_gcode); public const string oem_profile_token = nameof(oem_profile_token); + public const string layer_name = nameof(layer_name); }; public class SettingsHelpers @@ -441,23 +444,23 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public bool MarkedForDelete { get; set; } = false; public string SHA1 { get; set; } - public void ChangeID(string newID) + public void ChangeID(string deviceToken) { if (ActiveSliceSettings.Instance.ID == this.ID) { - ActiveSliceSettings.Instance.ID = newID; + ActiveSliceSettings.Instance.ID = deviceToken; } string existingProfile = ProfilePath; if (File.Exists(existingProfile)) { - this.ID = newID; + this.ID = deviceToken; File.Move(existingProfile, ProfilePath); } - var profile = ProfileManager.LoadProfile(newID); - profile.ID = newID; - profile.SetValue(SettingsKey.device_token, newID); + var profile = PrinterSettings.LoadFile(ProfilePath); + profile.ID = deviceToken; + profile.SetValue(SettingsKey.device_token, deviceToken); ProfileManager.Instance.Save(); } diff --git a/SlicerConfiguration/SettingsControlSelectors.cs b/SlicerConfiguration/SettingsControlSelectors.cs index 392ed0fc6..1bf1fdef1 100644 --- a/SlicerConfiguration/SettingsControlSelectors.cs +++ b/SlicerConfiguration/SettingsControlSelectors.cs @@ -49,13 +49,23 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { private Button editButton; private NamedSettingsLayers layerType; - private DropDownList dropDownList; + GuiWidget pullDownContainer; private int extruderIndex; //For multiple materials public PresetSelectorWidget(string label, RGBA_Bytes accentColor, NamedSettingsLayers layerType, int extruderIndex) : base(FlowDirection.TopToBottom) { + SliceSettingsWidget.SettingChanged.RegisterEvent((s, e) => + { + StringEventArgs stringEvent = e as StringEventArgs; + if (stringEvent != null + && stringEvent.Data == SettingsKey.layer_name) + { + RebuildDropDownList(); + } + }, ref unregisterEvents); + this.extruderIndex = extruderIndex; this.layerType = layerType; @@ -77,14 +87,16 @@ namespace MatterHackers.MatterControl.SlicerConfiguration }; this.AddChild(labelText); - this.AddChild(GetPulldownContainer()); + pullDownContainer = new GuiWidget(HAnchor.ParentLeftRight, VAnchor.FitToChildren); + pullDownContainer.AddChild(GetPulldownContainer()); + this.AddChild(pullDownContainer); this.AddChild(new VerticalSpacer()); this.AddChild(accentBar); } - public virtual FlowLayoutWidget GetPulldownContainer() + public FlowLayoutWidget GetPulldownContainer() { - dropDownList = CreateDropdown(); + var dropDownList = CreateDropdown(); FlowLayoutWidget container = new FlowLayoutWidget(); container.HAnchor = HAnchor.ParentLeftRight; @@ -199,18 +211,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration private void RebuildDropDownList() { - // TODO: Consider adding a .Replace(existingWidget, newWidget) to GuiWidget - // Replace existing list with updated list - var parent = this.dropDownList.Parent; - - if (parent != null) - { - parent.RemoveChild(this.dropDownList); - this.dropDownList.Close(); - - this.dropDownList = CreateDropdown(); - parent.AddChild(this.dropDownList); - } + pullDownContainer.CloseAllChildren(); + pullDownContainer.AddChild(GetPulldownContainer()); } private void MenuItem_Selected(object sender, EventArgs e) @@ -320,6 +322,17 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return dropDownList; } + private event EventHandler unregisterEvents; + + public override void OnClosed(EventArgs e) + { + if (unregisterEvents != null) + { + unregisterEvents(this, null); + } + base.OnClosed(e); + } + private void SettingsLayers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { RebuildDropDownList(); diff --git a/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs b/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs index 6c5dbe689..5caa7996e 100644 --- a/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs +++ b/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs @@ -136,10 +136,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration presetNameInput.ActualTextEditWidget.EditComplete += (s, e) => { - if (!this.Focused && this.Text != initialPresetName) - { - presetsContext.PersistenceLayer.Name = presetNameInput.Text; - } + ActiveSliceSettings.Instance.SetValue(SettingsKey.layer_name, presetNameInput.Text, presetsContext.PersistenceLayer); + SliceSettingsWidget.SettingChanged.CallEvents(null, new StringEventArgs(SettingsKey.layer_name)); }; topRow.AddChild(presetNameInput); @@ -197,7 +195,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration UiThread.RunOnIdle(() => { string sanitizedName = numberMatch.Replace(presetNameInput.Text, "").Trim(); - string newProfileName = GetNonCollidingName(sanitizedName, presetsContext.PresetLayers.Select(preset => preset.ValueOrDefault("layer_name"))); + string newProfileName = GetNonCollidingName(sanitizedName, presetsContext.PresetLayers.Select(preset => preset.ValueOrDefault(SettingsKey.layer_name))); var clonedLayer = presetsContext.PersistenceLayer.Clone(); clonedLayer.Name = newProfileName; @@ -226,16 +224,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration Button closeButton = buttonFactory.Generate("Close".Localize()); closeButton.Click += (sender, e) => { - UiThread.RunOnIdle(() => - { - if (initialPresetName != presetsContext.PersistenceLayer.Name) - { - // TODO: If we get to the point where we refresh rather than reload, we need - // to rebuild the target droplist to display the new name - ApplicationController.Instance.ReloadAdvancedControlsPanel(); - } - this.Close(); - }); + this.CloseOnIdle(); }; container.AddChild(duplicateButton); diff --git a/SlicerConfiguration/SliceSettingsWidget.cs b/SlicerConfiguration/SliceSettingsWidget.cs index 1013464e8..e6443ce17 100644 --- a/SlicerConfiguration/SliceSettingsWidget.cs +++ b/SlicerConfiguration/SliceSettingsWidget.cs @@ -26,7 +26,9 @@ The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ + using MatterHackers.Agg; +using MatterHackers.Agg.Font; using MatterHackers.Agg.Image; using MatterHackers.Agg.PlatformAbstract; using MatterHackers.Agg.UI; @@ -37,6 +39,7 @@ using MatterHackers.SerialPortCommunication.FrostedSerial; using MatterHackers.VectorMath; using System; using System.Collections.Generic; +using System.IO; using System.Linq; namespace MatterHackers.MatterControl.SlicerConfiguration @@ -473,26 +476,39 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return leftSideGroupTabs; } - private bool CheckIfShouldBeShown(SliceSettingData settingData) + public static bool ParseShowString(string unsplitSettings, PrinterSettings printerSettings, List layerCascade) { - bool settingShouldBeShown = true; - if (settingData.ShowIfSet != null - && settingData.ShowIfSet != "") + if (!string.IsNullOrEmpty(unsplitSettings)) { - string showValue = "0"; - string checkName = settingData.ShowIfSet; - if (checkName.StartsWith("!")) + string[] splitSettings = unsplitSettings.Split('&'); + + foreach (var inLookupSettings in splitSettings) { - showValue = "1"; - checkName = checkName.Substring(1); - } - string sliceSettingValue = GetActiveValue(checkName, layerCascade); - if (sliceSettingValue == showValue) - { - settingShouldBeShown = false; + var lookupSettings = inLookupSettings; + if (!string.IsNullOrEmpty(lookupSettings)) + { + string showValue = "0"; + if (lookupSettings.StartsWith("!")) + { + showValue = "1"; + lookupSettings = lookupSettings.Substring(1); + } + + string sliceSettingValue = printerSettings.GetValue(lookupSettings, layerCascade); + if (sliceSettingValue == showValue) + { + return false; + } + } } } + return true; + } + + private bool CheckIfShouldBeShown(SliceSettingData settingData) + { + bool settingShouldBeShown = ParseShowString(settingData.ShowIfSet, ActiveSliceSettings.Instance, layerCascade); if (viewFilter == NamedSettingsLayers.Material || viewFilter == NamedSettingsLayers.Quality) { if (!settingData.ShowAsOverride) @@ -837,7 +853,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration }; intEditWidget.ActuallNumberEdit.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -874,7 +890,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration }; doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -945,12 +961,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { foreach (string setting in settingData.SetSettingsOnChange) { - SaveSetting(setting, numberEdit.Value.ToString() + "mm", persistenceLayer); + ActiveSliceSettings.Instance.SetValue(setting, numberEdit.Value.ToString() + "mm", persistenceLayer); } } // also always save to the local setting - SaveSetting(settingData.SlicerConfigName, numberEdit.Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, numberEdit.Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); }; @@ -987,7 +1003,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration }; doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); }; @@ -1030,7 +1046,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration text += "%"; } textEditWidget.Text = text; - SaveSetting(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -1105,7 +1121,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration textEditWidget.Text = text; startingText = stringEdit.Text; } - SaveSetting(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -1167,7 +1183,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration checkBoxWidget.Click += (sender, e) => { bool isChecked = ((CheckBox)sender).Checked; - SaveSetting(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -1192,7 +1208,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration stringEdit.ActualTextEditWidget.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, ((TextEditWidget)sender).Text, persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text, persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -1210,14 +1226,14 @@ namespace MatterHackers.MatterControl.SlicerConfiguration case SliceSettingData.DataEditTypes.MULTI_LINE_TEXT: { string convertedNewLines = sliceSettingValue.Replace("\\n", "\n"); - var stringEdit = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndexForItem++) + var stringEdit = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndexForItem++, typeFace: ApplicationController.MonoSpacedTypeFace) { HAnchor = HAnchor.ParentLeftRight, }; - + stringEdit.ActualTextEditWidget.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"), persistenceLayer); settingsRow.UpdateStyle(); OnSettingsChanged(settingData); @@ -1286,7 +1302,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration newItem.Selected += (sender, e) => { MenuItem menuItem = ((MenuItem)sender); - SaveSetting(settingData.SlicerConfigName, menuItem.Text, persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, menuItem.Text, persistenceLayer); settingsRow.UpdateStyle(); @@ -1317,7 +1333,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration checkBoxWidget.CheckedStateChanged += (sender, e) => { bool isChecked = ((CheckBox)sender).Checked; - SaveSetting(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer); settingsRow.UpdateStyle(); @@ -1362,7 +1378,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); @@ -1377,7 +1393,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer); settingsRow.UpdateStyle(); @@ -1654,7 +1670,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration newItem.Selected += (sender, e) => { - SaveSetting(settingData.SlicerConfigName, valueLocal, persistenceLayer); + ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, valueLocal, persistenceLayer); OnSettingsChanged(settingData); internalTextWidget.Text = valueLocal; internalTextWidget.OnEditComplete(null); @@ -1726,24 +1742,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } string newValue = string.Join(",", settings); - SaveSetting(slicerConfigName, newValue, persistenceLayer); - } - - protected void ReloadOptions(object sender, EventArgs e) - { - ApplicationController.Instance.ReloadAdvancedControlsPanel(); - } - - private static void SaveSetting(string name, string value, PrinterSettingsLayer persistenceLayer) - { - if (persistenceLayer == null) - { - ActiveSliceSettings.Instance.SetValue(name, value); - } - else - { - ActiveSliceSettings.Instance.SetValue(name, value, persistenceLayer); - } + ActiveSliceSettings.Instance.SetValue(slicerConfigName, newValue, persistenceLayer); } public override void OnDraw(Graphics2D graphics2D) @@ -1780,4 +1779,4 @@ namespace MatterHackers.MatterControl.SlicerConfiguration topToBottomItemList.AddChild(itemHolder, indexInChildrenList); } } -} \ No newline at end of file +} diff --git a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs index 8535618a2..259243450 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs @@ -65,6 +65,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration "print_leveling_required_to_print", "print_leveling_solution", "resume_first_layer_speed", + "resume_is_enabled", "resume_position_before_z_home", "resume_gcode", "temperature", @@ -72,7 +73,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration "z_homes_to_max", // TODO: merge the items below into the list above after some validation - setting that weren't previously mapped to Cura but probably should be. - "bed_remove_part_temperature", + SettingsKey.bed_remove_part_temperature, "extruder_wipe_temperature", "heat_extruder_before_homing", "include_firmware_updater", diff --git a/SlicerConfiguration/SlicerMapping/MappingClasses.cs b/SlicerConfiguration/SlicerMapping/MappingClasses.cs index 03166dbf1..6352db497 100644 --- a/SlicerConfiguration/SlicerMapping/MappingClasses.cs +++ b/SlicerConfiguration/SlicerMapping/MappingClasses.cs @@ -42,7 +42,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration new AsPercentOfReferenceOrDirect("first_layer_speed", "first_layer_speed", "infill_speed", 60), new AsPercentOfReferenceOrDirect("external_perimeter_speed","external_perimeter_speed", "perimeter_speed", 60), new AsPercentOfReferenceOrDirect("raft_print_speed", "raft_print_speed", "infill_speed", 60), - new MappedSetting("bed_remove_part_temperature","bed_remove_part_temperature"), + new MappedSetting(SettingsKey.bed_remove_part_temperature,SettingsKey.bed_remove_part_temperature), new MappedSetting("bridge_fan_speed","bridge_fan_speed"), new MappedSetting("bridge_speed","bridge_speed"), new MappedSetting("extruder_wipe_temperature","extruder_wipe_temperature"), diff --git a/StaticData/SliceSettings/Layouts.txt b/StaticData/SliceSettings/Layouts.txt index 96adefa4f..2e90660fb 100644 --- a/StaticData/SliceSettings/Layouts.txt +++ b/StaticData/SliceSettings/Layouts.txt @@ -321,9 +321,9 @@ Advanced manual_probe_paper_width Options Resume Failed Print - Speed + Resume Settings + resume_is_enabled resume_first_layer_speed - Homing resume_position_before_z_home Custom G-Code Start G-Code diff --git a/StaticData/SliceSettings/Properties.json b/StaticData/SliceSettings/Properties.json index 3514bc726..3190f0e7c 100644 --- a/StaticData/SliceSettings/Properties.json +++ b/StaticData/SliceSettings/Properties.json @@ -719,6 +719,20 @@ "DefaultValue": "10", "RebuildGCodeOnChange": false }, + { + "QuickMenuSettings": [ ], + "SetSettingsOnChange": [ ], + "SlicerConfigName": "resume_is_enabled", + "PresentationName": "Enable Resuming", + "HelpText": "When this is checked MatterControl will attempt to resume a print in the event of a failure, such as lost connection or lost power.", + "DataEditType": "CHECK_BOX", + "ExtraSettings": "", + "ShowAsOverride": false, + "ShowIfSet": "!has_hardware_leveling", + "ResetAtEndOfPrint": false, + "DefaultValue": "0", + "RebuildGCodeOnChange": false + }, { "QuickMenuSettings": [ ], "SetSettingsOnChange": [ ], @@ -731,6 +745,7 @@ "ShowIfSet": "!has_hardware_leveling", "ResetAtEndOfPrint": false, "DefaultValue": "0", + "ReloadUiWhenChanged": true, "RebuildGCodeOnChange": false }, { @@ -742,7 +757,7 @@ "DataEditType": "VECTOR2", "ExtraSettings": "mm", "ShowAsOverride": true, - "ShowIfSet": "!has_hardware_leveling", + "ShowIfSet": "!has_hardware_leveling&!z_homes_to_max", "ResetAtEndOfPrint": false, "DefaultValue": "0,0", "RebuildGCodeOnChange": false diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index 484c45c86..ff2739112 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -5311,3 +5311,12 @@ Translated:There is a required update available. English:Import Printer Translated:Import Printer +English:Resume Settings +Translated:Resume Settings + +English:Enable Resuming +Translated:Enable Resuming + +English:When this is checked MatterControl will attempt to resume a print in the event of a failure, such as lost connection or lost power. +Translated:When this is checked MatterControl will attempt to resume a print in the event of a failure, such as lost connection or lost power. + diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 0b4f2cd53..e76e827b9 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 0b4f2cd533b66b436fda27cb64b96588d17dd3e2 +Subproject commit e76e827b9724ee4363d1b74e53ddfa61a342bb6d diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 10849d735..7d6caf59e 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 10849d735d861506c3189f8c1f2ed58bc8e02936 +Subproject commit 7d6caf59efc2af50971616c26db7348aa1153f5b diff --git a/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs b/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs index 9dbbaec66..d0406167c 100644 --- a/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs @@ -189,9 +189,9 @@ namespace MatterControl.Tests.MatterControl { ValidateOnAllPrinters((printer, settings) => { - if (settings.OemLayer.ContainsKey("layer_name")) + if (settings.OemLayer.ContainsKey(SettingsKey.layer_name)) { - if (settings.OemLayer["layer_name"].ToUpper() == "ABS") + if (settings.OemLayer[SettingsKey.layer_name].ToUpper() == "ABS") { double absDensity = settings.GetValue(SettingsKey.filament_density); if (absDensity != 1.04) @@ -199,7 +199,7 @@ namespace MatterControl.Tests.MatterControl Assert.Fail("[filament_density] value should be set to ABS 1.04: " + printer.RelativeFilePath); } } - else if (settings.OemLayer["layer_name"].ToUpper() == "PLA") + else if (settings.OemLayer[SettingsKey.layer_name].ToUpper() == "PLA") { double absDensity = settings.GetValue(SettingsKey.filament_density); if (absDensity != 1.24) diff --git a/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs b/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs index 6d54c2efd..827ea3adc 100644 --- a/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs @@ -15,6 +15,67 @@ namespace MatterControl.Tests.MatterControl [TestFixture, Category("ConfigIni")] public class SettingsParseTests { + [Test] + public void CheckIfShouldBeShownParseTests() + { + + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "0" }; + var profile = GettProfile(settings); + Assert.IsFalse(SliceSettingsWidget.ParseShowString("has_heated_bed", profile, null)); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed", profile, null)); + } + + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "1" }; + var profile = GettProfile(settings); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed", profile, null)); + Assert.IsFalse(SliceSettingsWidget.ParseShowString("!has_heated_bed", profile, null)); + } + + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "0" }; + var profile = GettProfile(settings); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null)); + } + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "1" }; + var profile = GettProfile(settings); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null)); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null)); + } + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "0" }; + var profile = GettProfile(settings); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null)); + } + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1" }; + var profile = GettProfile(settings); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null)); + } + + { + string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1", SettingsKey.has_fan, "1" }; + var profile = GettProfile(settings); + Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect&has_fan", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect&!has_fan", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect&has_fan", profile, null)); + Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect&has_fan", profile, null)); + } + } + [Test] public void SupportInterfaceMaterialAssignedToExtruderOne() {