diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index 30f10fc82..535607a16 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -2254,7 +2254,12 @@ namespace MatterHackers.MatterControl var errors = SettingsValidation.SettingsValid(printer); if(errors.Count > 0) { - StyledMessageBox.ShowMessageBox(String.Join("\n__________________\n\n", errors.ToArray()), "Slice Error".Localize()); + // Project to newline separated Error/Details string + var formattedErrors = errors.Select(err => $"{err.Error}\n\n{err.Details}").ToArray(); + + StyledMessageBox.ShowMessageBox( + string.Join("\n__________________\n\n", formattedErrors), + "Export Error".Localize()); } else // there are no erros continue printing { diff --git a/MatterControlLib/ApplicationView/SettingsValidation.cs b/MatterControlLib/ApplicationView/SettingsValidation.cs index 7d99fb2a7..5ca69e718 100644 --- a/MatterControlLib/ApplicationView/SettingsValidation.cs +++ b/MatterControlLib/ApplicationView/SettingsValidation.cs @@ -37,11 +37,11 @@ namespace MatterHackers.MatterControl { public static class SettingsValidation { - public static List SettingsValid(PrinterConfig printer) + public static List SettingsValid(PrinterConfig printer) { var settings = printer.Settings; - var errors = new List(); + var errors = new List(); try { @@ -49,34 +49,46 @@ namespace MatterHackers.MatterControl { if (settings.GetValue(SettingsKey.layer_height) > settings.GetValue(SettingsKey.nozzle_diameter)) { - var error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( - GetSettingsName(SettingsKey.layer_height), GetSettingsName(SettingsKey.nozzle_diameter)); var details = "{0} = {1}\n{2} = {3}".FormatWith(GetSettingsName(SettingsKey.layer_height), settings.GetValue(SettingsKey.layer_height), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue(SettingsKey.nozzle_diameter)); - var location = GetSettingsLocation(SettingsKey.layer_height); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( + GetSettingsName(SettingsKey.layer_height), GetSettingsName(SettingsKey.nozzle_diameter)), + Details = $"{details}\n\n{GetSettingsLocation(SettingsKey.layer_height)}" + }); } else if (settings.GetValue(SettingsKey.layer_height) <= 0) { - var error = "{0} must be greater than 0.".Localize().FormatWith( - GetSettingsName(SettingsKey.layer_height)); - var location = GetSettingsLocation(SettingsKey.layer_height); - errors.Add($"{error}\n\n{location}"); + errors.Add( + new ValidationError() + { + Error = "{0} must be greater than 0.".Localize().FormatWith(GetSettingsName(SettingsKey.layer_height)), + Details = GetSettingsLocation(SettingsKey.layer_height) + }); } else if (settings.GetValue(SettingsKey.first_layer_height) > settings.GetValue(SettingsKey.nozzle_diameter)) { - var error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( - GetSettingsName(SettingsKey.layer_height), - GetSettingsName(SettingsKey.nozzle_diameter)); var details = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.first_layer_height), settings.GetValue(SettingsKey.first_layer_height), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue(SettingsKey.nozzle_diameter)); + var location = GetSettingsLocation(SettingsKey.first_layer_height); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( + GetSettingsName(SettingsKey.layer_height), + GetSettingsName(SettingsKey.nozzle_diameter)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } } @@ -87,20 +99,30 @@ namespace MatterHackers.MatterControl { foreach (string startGCodeLine in startGCode) { + var location = GetSettingsLocation(SettingsKey.start_gcode); + if (startGCodeLine.StartsWith("G29")) { - var location = GetSettingsLocation(SettingsKey.start_gcode); - var error = "Start G-Code cannot contain G29 if Print Recovery is enabled.".Localize(); var details = "Your Start G-Code should not contain a G29 if you are planning on using Print Recovery. Change your start G-Code or turn off Print Recovery.".Localize(); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "Start G-Code cannot contain G29 if Print Recovery is enabled.".Localize(), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (startGCodeLine.StartsWith("G30")) { - var location = GetSettingsLocation(SettingsKey.start_gcode); - var error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(); var details = "Your Start G-Code should not contain a G30 if you are planning on using Print Recovery. Change your start G-Code or turn off Print Recovery.".Localize(); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } } } @@ -113,17 +135,27 @@ namespace MatterHackers.MatterControl if (startGCodeLine.StartsWith("G29")) { var location = GetSettingsLocation(SettingsKey.start_gcode); - var error = "Start G-Code cannot contain G29 if Print Leveling is enabled.".Localize(); var details = "Your Start G-Code should not contain a G29 if you are planning on using print leveling. Change your start G-Code or turn off print leveling.".Localize(); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "Start G-Code cannot contain G29 if Print Leveling is enabled.".Localize(), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (startGCodeLine.StartsWith("G30")) { var location = GetSettingsLocation(SettingsKey.start_gcode); - var error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(); var details = "Your Start G-Code should not contain a G30 if you are planning on using print leveling. Change your start G-Code or turn off print leveling.".Localize(); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } } } @@ -135,89 +167,133 @@ namespace MatterHackers.MatterControl location += "\n" + "Controls".Localize(); location += "\n • " + "Movement".Localize(); location += "\n • " + "Z Offset".Localize(); - var error = "Z Offset is too large.".Localize(); + var details = "The Z Offset for your printer, sometimes called Baby Stepping, is greater than 2mm and invalid. Clear the value and re-level the bed.".Localize(); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "Z Offset is too large.".Localize(), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.first_layer_extrusion_width) > settings.GetValue(SettingsKey.nozzle_diameter) * 4) { - var error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( - GetSettingsName(SettingsKey.first_layer_extrusion_width), - GetSettingsName(SettingsKey.nozzle_diameter)); var details = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width), settings.GetValue(SettingsKey.first_layer_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue(SettingsKey.nozzle_diameter)); + string location = GetSettingsLocation(SettingsKey.first_layer_extrusion_width); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( + GetSettingsName(SettingsKey.first_layer_extrusion_width), + GetSettingsName(SettingsKey.nozzle_diameter)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.first_layer_extrusion_width) <= 0) { - var error = "{0} must be greater than 0.".Localize().FormatWith( - GetSettingsName(SettingsKey.first_layer_extrusion_width)); var details = "{0} = {1}".FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width), settings.GetValue(SettingsKey.first_layer_extrusion_width)); string location = GetSettingsLocation(SettingsKey.first_layer_extrusion_width); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be greater than 0.".Localize().FormatWith( + GetSettingsName(SettingsKey.first_layer_extrusion_width)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.external_perimeter_extrusion_width) > settings.GetValue(SettingsKey.nozzle_diameter) * 4) { - var error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( - GetSettingsName(SettingsKey.external_perimeter_extrusion_width), - GetSettingsName(SettingsKey.nozzle_diameter)); var details = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width), settings.GetValue(SettingsKey.external_perimeter_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue(SettingsKey.nozzle_diameter)); string location = GetSettingsLocation(SettingsKey.external_perimeter_extrusion_width); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( + GetSettingsName(SettingsKey.external_perimeter_extrusion_width), + GetSettingsName(SettingsKey.nozzle_diameter)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.external_perimeter_extrusion_width) <= 0) { - var error = "{0} must be greater than 0.".Localize().FormatWith( - GetSettingsName(SettingsKey.external_perimeter_extrusion_width)); var details = "{0} = {1}".FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width), settings.GetValue(SettingsKey.external_perimeter_extrusion_width)); var location = GetSettingsLocation(SettingsKey.external_perimeter_extrusion_width); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "{0} must be greater than 0.".Localize().FormatWith( + GetSettingsName(SettingsKey.external_perimeter_extrusion_width)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.min_fan_speed) > 100) { - var error = "The {0} can only go as high as 100%.".Localize().FormatWith( - GetSettingsName(SettingsKey.min_fan_speed)); var details = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue(SettingsKey.min_fan_speed)); + var location = GetSettingsLocation(SettingsKey.min_fan_speed); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "The {0} can only go as high as 100%.".Localize().FormatWith( + GetSettingsName(SettingsKey.min_fan_speed)), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.max_fan_speed) > 100) { - var error = "The {0} can only go as high as 100%.".Localize().FormatWith( - GetSettingsName(SettingsKey.max_fan_speed)); var details = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue(SettingsKey.max_fan_speed)); var location = GetSettingsLocation(SettingsKey.max_fan_speed); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "The {0} can only go as high as 100%.".Localize().FormatWith( + GetSettingsName(SettingsKey.max_fan_speed)), + Details = "{0}\n\n{1".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.extruder_count) < 1) { - var error = "The {0} must be at least 1.".Localize().FormatWith( - GetSettingsName(SettingsKey.extruder_count)); var details = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue(SettingsKey.extruder_count)); + var location = GetSettingsLocation(SettingsKey.extruder_count); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "The {0} must be at least 1.".Localize().FormatWith( + GetSettingsName(SettingsKey.extruder_count)), + Details= "{0}\n\n{1}".FormatWith(details, location) + }); } if (settings.GetValue(SettingsKey.fill_density) < 0 || settings.GetValue(SettingsKey.fill_density) > 1) @@ -227,7 +303,14 @@ namespace MatterHackers.MatterControl var details = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue(SettingsKey.fill_density)); var location = GetSettingsLocation(SettingsKey.filament_density); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + + errors.Add( + new ValidationError() + { + Error = error, + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } // marlin firmware can only take a max of 128 bytes in a single instrection, make sure no lines are longer than that @@ -256,8 +339,12 @@ namespace MatterHackers.MatterControl } catch (Exception e) { - errors.Add(e.Message); - errors.Add(e.StackTrace.Replace("\r", "")); + errors.Add( + new ValidationError() + { + Error = "Unexpected error validating settings".Localize(), + Details = e.Message + }); } return errors; @@ -291,7 +378,7 @@ namespace MatterHackers.MatterControl return settingData.PresentationName.Localize(); } - private static bool ValidateGCodeLinesShortEnough(string gCodeSetting, PrinterConfig printer, List errors) + private static bool ValidateGCodeLinesShortEnough(string gCodeSetting, PrinterConfig printer, List errors) { string[] gCodeString = printer.Settings.GetValue(SettingsKey.start_gcode).Replace("\\n", "\n").Split('\n'); @@ -307,10 +394,15 @@ namespace MatterHackers.MatterControl { var location = GetSettingsLocation(gCodeSetting); - var error = "All G-Code lines mush be shorter than 100 characters (excluding comments).".Localize().FormatWith(data.PresentationName); var details = "Found a line that is {0} characters long.\n{1}...".Localize().FormatWith(length, trimedLine.Substring(0, 20)); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + errors.Add( + new ValidationError() + { + Error = "All G-Code lines mush be shorter than 100 characters (excluding comments).".Localize().FormatWith(data.PresentationName), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } + return false; } } @@ -318,7 +410,7 @@ namespace MatterHackers.MatterControl return true; } - private static void ValidateGoodSpeedSettingGreaterThan0(string speedSetting, PrinterConfig printer, List errors) + private static void ValidateGoodSpeedSettingGreaterThan0(string speedSetting, PrinterConfig printer, List errors) { var actualSpeedValueString = printer.Settings.GetValue(speedSetting); var speedValueString = actualSpeedValueString; @@ -326,9 +418,10 @@ namespace MatterHackers.MatterControl { speedValueString = speedValueString.Substring(0, speedValueString.Length - 1); } + bool valueWasNumber = true; - double speedToCheck; - if (!double.TryParse(speedValueString, out speedToCheck)) + + if (!double.TryParse(speedValueString, out double speedToCheck)) { valueWasNumber = false; } @@ -342,9 +435,14 @@ namespace MatterHackers.MatterControl { var location = GetSettingsLocation(speedSetting); - var error = "The {0} must be greater than 0.".Localize().FormatWith(data.PresentationName); var details = "It is currently set to {0}.".Localize().FormatWith(actualSpeedValueString); - errors.Add("{0}\n\n{1}\n\n{2}".FormatWith(error, details, location)); + + errors.Add( + new ValidationError() + { + Error = "The {0} must be greater than 0.".Localize().FormatWith(data.PresentationName), + Details = "{0}\n\n{1}".FormatWith(details, location) + }); } } } diff --git a/MatterControlLib/ApplicationView/ValidationError.cs b/MatterControlLib/ApplicationView/ValidationError.cs new file mode 100644 index 000000000..4f61da6b6 --- /dev/null +++ b/MatterControlLib/ApplicationView/ValidationError.cs @@ -0,0 +1,42 @@ +/* +Copyright (c) 2019, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +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. +*/ + +namespace MatterHackers.MatterControl +{ + public class ValidationError + { + public string Error { get; set; } + + public string Details { get; set; } + + public string Source { get; set; } + + public string SourceName { get; set; } + } +} \ No newline at end of file diff --git a/MatterControlLib/CustomWidgets/ExportPrintItemPage.cs b/MatterControlLib/CustomWidgets/ExportPrintItemPage.cs index 653e1b256..286a068a5 100644 --- a/MatterControlLib/CustomWidgets/ExportPrintItemPage.cs +++ b/MatterControlLib/CustomWidgets/ExportPrintItemPage.cs @@ -226,7 +226,7 @@ namespace MatterHackers.MatterControl savePath += targetExtension; } - List exportErrors = null; + List exportErrors = null; if (activePlugin != null) { @@ -245,7 +245,12 @@ namespace MatterHackers.MatterControl { UiThread.RunOnIdle(() => { - StyledMessageBox.ShowMessageBox(String.Join("\n__________________\n\n", exportErrors.ToArray()), "Export Error".Localize()); + // Project to newline separated Error/Details string + var formattedErrors = exportErrors.Select(err => $"{err.Error}\n\n{err.Details}").ToArray(); + + StyledMessageBox.ShowMessageBox( + string.Join("\n__________________\n\n", formattedErrors), + "Export Error".Localize()); }); } }); diff --git a/MatterControlLib/Library/Export/FolderExport.cs b/MatterControlLib/Library/Export/FolderExport.cs index 4f5d1b133..9ca2fc8e6 100644 --- a/MatterControlLib/Library/Export/FolderExport.cs +++ b/MatterControlLib/Library/Export/FolderExport.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.Library.Export public bool ExportPossible(ILibraryAsset libraryItem) => true; - public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) + public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) { var streamItems = libraryItems.OfType(); if (streamItems.Any()) @@ -92,7 +92,13 @@ namespace MatterHackers.MatterControl.Library.Export return null; } - return new List() { "No items to Export".Localize() }; + return new List() + { + new ValidationError() + { + Error = "No items to Export".Localize() + } + }; } } } diff --git a/MatterControlLib/Library/Export/GCodeExport.cs b/MatterControlLib/Library/Export/GCodeExport.cs index 2897ab95f..a62fce913 100644 --- a/MatterControlLib/Library/Export/GCodeExport.cs +++ b/MatterControlLib/Library/Export/GCodeExport.cs @@ -136,7 +136,7 @@ namespace MatterHackers.MatterControl.Library.Export return container; } - public virtual async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) + public virtual async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) { var firstItem = libraryItems.OfType().FirstOrDefault(); if (firstItem != null) @@ -264,7 +264,14 @@ namespace MatterHackers.MatterControl.Library.Export } } - return new List() { "Item cannot be exported".Localize() + " " + firstItem != null ? firstItem.ToString() : "" }; + return new List + { + new ValidationError() + { + Error = "Item cannot be exported".Localize(), + Details = firstItem?.ToString() ?? "" + } + }; } public bool ApplyLeveling { get; set; } = true; diff --git a/MatterControlLib/Library/Export/IExportPlugin.cs b/MatterControlLib/Library/Export/IExportPlugin.cs index f299cf216..ba9a066d2 100644 --- a/MatterControlLib/Library/Export/IExportPlugin.cs +++ b/MatterControlLib/Library/Export/IExportPlugin.cs @@ -46,7 +46,7 @@ namespace MatterHackers.MatterControl void Initialize(PrinterConfig printer); - Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken); + Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken); bool Enabled { get; } string DisabledReason { get; } diff --git a/MatterControlLib/Library/Export/StlExport.cs b/MatterControlLib/Library/Export/StlExport.cs index 389583566..2ce888d7c 100644 --- a/MatterControlLib/Library/Export/StlExport.cs +++ b/MatterControlLib/Library/Export/StlExport.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.Library.Export public bool ExportPossible(ILibraryAsset libraryItem) => true; - public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) + public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) { var firstItem = libraryItems.OfType().FirstOrDefault(); if (firstItem is ILibraryAsset libraryItem) @@ -72,7 +72,14 @@ namespace MatterHackers.MatterControl.Library.Export } } - return new List() { "Item cannot be exported as STL".Localize() + " " + firstItem != null ? firstItem.ToString() : "" }; + return new List() + { + new ValidationError() + { + Error = "Item cannot be exported as STL".Localize(), + Details = firstItem?.ToString() ?? "" + } + }; } } } diff --git a/MatterControlLib/Library/Export/ZipExport.cs b/MatterControlLib/Library/Export/ZipExport.cs index aa9b3be8d..ff2d04d6e 100644 --- a/MatterControlLib/Library/Export/ZipExport.cs +++ b/MatterControlLib/Library/Export/ZipExport.cs @@ -62,7 +62,7 @@ namespace MatterHackers.MatterControl.Library.Export public bool ExportPossible(ILibraryAsset libraryItem) => true; - public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) + public async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) { var streamItems = libraryItems.OfType(); if (streamItems.Any()) @@ -101,7 +101,13 @@ namespace MatterHackers.MatterControl.Library.Export return null; } - return new List() { "No Items to Export".Localize() }; + return new List() + { + new ValidationError() + { + Error = "No Items to Export".Localize() + } + }; } } } diff --git a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs index 231f4f7fc..86fe552da 100644 --- a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs +++ b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs @@ -547,10 +547,16 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if(errors.Count > 0) { doSlicing = false; - StyledMessageBox.ShowMessageBox(String.Join("\n__________________\n\n", errors.ToArray()), "Slicing Error".Localize()); + + // Project to newline separated Error/Details string + var formattedErrors = errors.Select(err => $"{err.Error}\n\n{err.Details}").ToArray(); + + StyledMessageBox.ShowMessageBox( + string.Join("\n__________________\n\n", formattedErrors), + "Slicing Error".Localize()); } } - + if(doSlicing) { activelySlicing = true; diff --git a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/SliceButton.cs b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/SliceButton.cs index a61e640e0..2e750833b 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/SliceButton.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/SliceButton.cs @@ -32,6 +32,7 @@ using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.PrinterCommunication; using System; +using System.Linq; using System.Threading.Tasks; namespace MatterHackers.MatterControl.PartPreviewWindow @@ -105,7 +106,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (errors.Count > 0) { doSlicing = false; - StyledMessageBox.ShowMessageBox(String.Join("\n__________________\n\n", errors.ToArray()), "Slicing Error".Localize()); + + // Project to newline separated Error/Details string + var formattedErrors = errors.Select(err => $"{err.Error}\n\n{err.Details}").ToArray(); + + StyledMessageBox.ShowMessageBox( + string.Join("\n__________________\n\n", formattedErrors), + "Slicing Error".Localize()); } } diff --git a/MatterControlLib/PrinterCommunication/Drivers/X3G/X3GExport.cs b/MatterControlLib/PrinterCommunication/Drivers/X3G/X3GExport.cs index cf5c46dd2..4072099a4 100644 --- a/MatterControlLib/PrinterCommunication/Drivers/X3G/X3GExport.cs +++ b/MatterControlLib/PrinterCommunication/Drivers/X3G/X3GExport.cs @@ -77,7 +77,7 @@ namespace MatterHackers.MatterControl.Plugins.X3GDriver public override bool ExportPossible(ILibraryAsset libraryItem) => true; - public override async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) + public override async Task> Generate(IEnumerable libraryItems, string outputPath, IProgress progress, CancellationToken cancellationToken) { string gcodePath = Path.ChangeExtension(outputPath, "_gcode");