mattercontrol/CustomWidgets/ExportPrintItemWindow.cs
2015-11-13 18:06:44 -08:00

604 lines
No EOL
21 KiB
C#

using MatterHackers.Agg;
using MatterHackers.Agg.PlatformAbstract;
using MatterHackers.Agg.UI;
using MatterHackers.GCodeVisualizer;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.Queue.OptionsMenu;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.VectorMath;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace MatterHackers.MatterControl
{
public class ExportPrintItemWindow : SystemWindow
{
private CheckBox showInFolderAfterSave;
private CheckBox applyLeveling;
private PrintItemWrapper printItemWrapper;
private string gcodePathAndFilenameToSave;
private string x3gPathAndFilenameToSave;
private bool partIsGCode = false;
private string documentsPath;
public ExportPrintItemWindow(PrintItemWrapper printItemWrapper)
: base(400, 300)
{
this.printItemWrapper = printItemWrapper;
if (Path.GetExtension(printItemWrapper.FileLocation).ToUpper() == ".GCODE")
{
partIsGCode = true;
}
string McExportFileTitleBeg = LocalizedString.Get("MatterControl");
string McExportFileTitleEnd = LocalizedString.Get("Export File");
string McExportFileTitleFull = string.Format("{0}: {1}", McExportFileTitleBeg, McExportFileTitleEnd);
this.Title = McExportFileTitleFull;
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
this.Name = "Export Item Window";
CreateWindowContent();
ActivePrinterProfile.Instance.ActivePrinterChanged.RegisterEvent(ReloadAfterPrinterProfileChanged, ref unregisterEvents);
ActivePrinterProfile.Instance.DoPrintLevelingChanged.RegisterEvent(ReloadAfterPrinterProfileChanged, ref unregisterEvents);
}
private string applyLevelingDuringExportString = "Apply leveling to gcode during export".Localize();
public void CreateWindowContent()
{
this.RemoveAllChildren();
TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
FlowLayoutWidget topToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom);
topToBottom.Padding = new BorderDouble(3, 0, 3, 5);
topToBottom.AnchorAll();
// Creates Header
FlowLayoutWidget headerRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
headerRow.HAnchor = HAnchor.ParentLeftRight;
headerRow.Margin = new BorderDouble(0, 3, 0, 0);
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
//Creates Text and adds into header
{
TextWidget elementHeader = new TextWidget("File export options:".Localize(), pointSize: 14);
elementHeader.TextColor = ActiveTheme.Instance.PrimaryTextColor;
elementHeader.HAnchor = HAnchor.ParentLeftRight;
elementHeader.VAnchor = Agg.UI.VAnchor.ParentBottom;
headerRow.AddChild(elementHeader);
topToBottom.AddChild(headerRow);
}
// Creates container in the middle of window
FlowLayoutWidget middleRowContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
{
middleRowContainer.HAnchor = HAnchor.ParentLeftRight;
middleRowContainer.VAnchor = VAnchor.ParentBottomTop;
middleRowContainer.Padding = new BorderDouble(5);
middleRowContainer.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor;
}
if (!partIsGCode)
{
string exportStlText = LocalizedString.Get("Export as");
string exportStlTextFull = string.Format("{0} STL", exportStlText);
Button exportAsStlButton = textImageButtonFactory.Generate(exportStlTextFull);
exportAsStlButton.HAnchor = HAnchor.ParentLeft;
exportAsStlButton.Cursor = Cursors.Hand;
exportAsStlButton.Click += new EventHandler(exportSTL_Click);
middleRowContainer.AddChild(exportAsStlButton);
}
if (!partIsGCode)
{
string exportAmfText = LocalizedString.Get("Export as");
string exportAmfTextFull = string.Format("{0} AMF", exportAmfText);
Button exportAsAmfButton = textImageButtonFactory.Generate(exportAmfTextFull);
exportAsAmfButton.HAnchor = HAnchor.ParentLeft;
exportAsAmfButton.Cursor = Cursors.Hand;
exportAsAmfButton.Click += new EventHandler(exportAMF_Click);
middleRowContainer.AddChild(exportAsAmfButton);
}
bool showExportGCodeButton = ActivePrinterProfile.Instance.ActivePrinter != null || partIsGCode;
if (showExportGCodeButton)
{
string exportGCodeText = LocalizedString.Get("Export as");
string exportGCodeTextFull = string.Format("{0} GCode", exportGCodeText);
Button exportGCode = textImageButtonFactory.Generate(exportGCodeTextFull);
exportGCode.HAnchor = HAnchor.ParentLeft;
exportGCode.Cursor = Cursors.Hand;
exportGCode.Click += new EventHandler((object sender, EventArgs e) =>
{
UiThread.RunOnIdle(ExportGCode_Click);
});
middleRowContainer.AddChild(exportGCode);
PluginFinder<ExportGcodePlugin> exportPluginFinder = new PluginFinder<ExportGcodePlugin>();
foreach (ExportGcodePlugin plugin in exportPluginFinder.Plugins)
{
//Create export button for each Plugin found
string exportButtonText = plugin.getButtonText().Localize();
Button exportButton = textImageButtonFactory.Generate(exportButtonText);
exportButton.HAnchor = HAnchor.ParentLeft;
exportButton.Cursor = Cursors.Hand;
exportButton.Click += new EventHandler((object sender, EventArgs e) =>
{
SaveFileDialogParams saveParams = new SaveFileDialogParams(plugin.getExtensionFilter(), title: plugin.getButtonText());
saveParams.Title = "MatterControl: Export File";
saveParams.ActionButtonLabel = "Export";
FileDialog.SaveFileDialog(saveParams, delegate(SaveFileDialogParams saveParam)
{
string extension = Path.GetExtension(saveParam.FileName);
if (extension == "")
{
saveParam.FileName += plugin.getFileExtension();
}
if (partIsGCode)
{
Close();
plugin.generate(printItemWrapper.FileLocation, saveParam.FileName);
}
else
{
Close();
SlicingQueue.Instance.QueuePartForSlicing(printItemWrapper);
printItemWrapper.SlicingDone += new EventHandler((object slicingCompleteSender, EventArgs slicingEventArgs) =>
{
PrintItemWrapper sliceItem = (PrintItemWrapper)slicingCompleteSender;
if (File.Exists(sliceItem.GetGCodePathAndFileName()))
{
plugin.generate(sliceItem.GetGCodePathAndFileName(), saveParam.FileName);
}
});//End SlicingDone Event handler
}
});//End SaveFileDialog delegate
});//End Click Event handler
middleRowContainer.AddChild(exportButton);
}
//bool showExportX3GButton = ActivePrinterProfile.Instance.ActivePrinter.DriverType == "X3G";
bool showExportX3GButton = false;
if (showExportX3GButton)
{
string exportAsX3GText = "Export as X3G".Localize();
Button exportAsX3G = textImageButtonFactory.Generate(exportAsX3GText);
exportAsX3G.HAnchor = HAnchor.ParentLeft;
exportAsX3G.Cursor = Cursors.Hand;
exportAsX3G.Click += new EventHandler((object sender, EventArgs e) =>
{
UiThread.RunOnIdle(ExportX3G_Click);
});
middleRowContainer.AddChild(exportAsX3G);
}
}
middleRowContainer.AddChild(new VerticalSpacer());
// If print leveling is enabled then add in a check box 'Apply Leveling During Export' and default checked.
if (showExportGCodeButton && ActivePrinterProfile.Instance.DoPrintLeveling)
{
applyLeveling = new CheckBox(LocalizedString.Get(applyLevelingDuringExportString), ActiveTheme.Instance.PrimaryTextColor, 10);
applyLeveling.Checked = true;
applyLeveling.HAnchor = HAnchor.ParentLeft;
applyLeveling.Cursor = Cursors.Hand;
//applyLeveling.Margin = new BorderDouble(top: 10);
middleRowContainer.AddChild(applyLeveling);
}
// TODO: make this work on the mac and then delete this if
if (OsInformation.OperatingSystem == OSType.Windows
|| OsInformation.OperatingSystem == OSType.X11)
{
showInFolderAfterSave = new CheckBox(LocalizedString.Get("Show file in folder after save"), ActiveTheme.Instance.PrimaryTextColor, 10);
showInFolderAfterSave.HAnchor = HAnchor.ParentLeft;
showInFolderAfterSave.Cursor = Cursors.Hand;
//showInFolderAfterSave.Margin = new BorderDouble(top: 10);
middleRowContainer.AddChild(showInFolderAfterSave);
}
if (!showExportGCodeButton)
{
string noGCodeMessageTextBeg = LocalizedString.Get("Note");
string noGCodeMessageTextEnd = LocalizedString.Get("To enable GCode export, select a printer profile.");
string noGCodeMessageTextFull = string.Format("{0}: {1}", noGCodeMessageTextBeg, noGCodeMessageTextEnd);
TextWidget noGCodeMessage = new TextWidget(noGCodeMessageTextFull, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 10);
noGCodeMessage.HAnchor = HAnchor.ParentLeft;
middleRowContainer.AddChild(noGCodeMessage);
}
//Creates button container on the bottom of window
FlowLayoutWidget buttonRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
{
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
buttonRow.HAnchor = HAnchor.ParentLeftRight;
buttonRow.Padding = new BorderDouble(0, 3);
}
Button cancelButton = textImageButtonFactory.Generate("Cancel");
cancelButton.Name = "Export Item Window Cancel Button";
cancelButton.Cursor = Cursors.Hand;
cancelButton.Click += (sender, e) =>
{
CloseOnIdle();
};
buttonRow.AddChild(new HorizontalSpacer());
buttonRow.AddChild(cancelButton);
topToBottom.AddChild(middleRowContainer);
topToBottom.AddChild(buttonRow);
this.AddChild(topToBottom);
}
private string Get8Name(string longName)
{
longName.Replace(' ', '_');
return longName.Substring(0, Math.Min(longName.Length, 8));
}
private void ExportGCode_Click()
{
SaveFileDialogParams saveParams = new SaveFileDialogParams("Export GCode|*.gcode", title: "Export GCode");
saveParams.Title = "MatterControl: Export File";
saveParams.ActionButtonLabel = "Export";
saveParams.FileName = Path.GetFileNameWithoutExtension(printItemWrapper.Name);
Close();
FileDialog.SaveFileDialog(saveParams, onExportGcodeFileSelected);
}
private void onExportGcodeFileSelected(SaveFileDialogParams saveParams)
{
if (saveParams.FileName != null)
{
ExportGcodeCommandLineUtility(saveParams.FileName);
}
}
public void ExportGcodeCommandLineUtility(String nameOfFile)
{
try
{
if (!string.IsNullOrEmpty(nameOfFile))
{
gcodePathAndFilenameToSave = nameOfFile;
string extension = Path.GetExtension(gcodePathAndFilenameToSave);
if (extension == "")
{
File.Delete(gcodePathAndFilenameToSave);
gcodePathAndFilenameToSave += ".gcode";
}
string sourceExtension = Path.GetExtension(printItemWrapper.FileLocation).ToUpper();
if (MeshFileIo.ValidFileExtensions().Contains(sourceExtension))
{
SlicingQueue.Instance.QueuePartForSlicing(printItemWrapper);
printItemWrapper.SlicingDone += sliceItem_Done;
}
else if (partIsGCode)
{
SaveGCodeToNewLocation(printItemWrapper.FileLocation, gcodePathAndFilenameToSave);
}
}
}
catch
{
}
}
private void ExportX3G_Click()
{
SaveFileDialogParams saveParams = new SaveFileDialogParams("Export X3G|*.x3g", title: "Export X3G");
saveParams.Title = "MatterControl: Export File";
saveParams.ActionButtonLabel = "Export";
FileDialog.SaveFileDialog(saveParams, onExportX3gFileSelected);
}
private void onExportX3gFileSelected(SaveFileDialogParams saveParams)
{
if (saveParams.FileName != null)
{
x3gPathAndFilenameToSave = saveParams.FileName;
string extension = Path.GetExtension(x3gPathAndFilenameToSave);
if (extension == "")
{
File.Delete(gcodePathAndFilenameToSave);
x3gPathAndFilenameToSave += ".x3g";
}
string saveExtension = Path.GetExtension(printItemWrapper.FileLocation).ToUpper();
if (MeshFileIo.ValidFileExtensions().Contains(saveExtension))
{
Close();
SlicingQueue.Instance.QueuePartForSlicing(printItemWrapper);
printItemWrapper.SlicingDone += x3gItemSlice_Complete;
}
else if (partIsGCode)
{
Close();
generateX3GfromGcode(printItemWrapper.FileLocation, x3gPathAndFilenameToSave);
}
}
}
private void SaveGCodeToNewLocation(string source, string dest)
{
try
{
if (ActivePrinterProfile.Instance.DoPrintLeveling)
{
GCodeFileLoaded unleveledGCode = new GCodeFileLoaded(source);
if (applyLeveling.Checked)
{
PrintLevelingData levelingData = PrintLevelingData.GetForPrinter(ActivePrinterProfile.Instance.ActivePrinter);
if (levelingData != null)
{
for (int lineIndex = 0; lineIndex < unleveledGCode.LineCount; lineIndex++)
{
PrinterMachineInstruction instruction = unleveledGCode.Instruction(lineIndex);
Vector3 currentDestination = instruction.Position;
List<string> linesToWrite = null;
switch (levelingData.CurrentPrinterLevelingSystem)
{
case PrintLevelingData.LevelingSystem.Probe2Points:
instruction.Line = LevelWizard2Point.ApplyLeveling(instruction.Line, currentDestination, instruction.movementType);
linesToWrite = LevelWizard2Point.ProcessCommand(instruction.Line);
break;
case PrintLevelingData.LevelingSystem.Probe3Points:
instruction.Line = LevelWizard3Point.ApplyLeveling(instruction.Line, currentDestination, instruction.movementType);
linesToWrite = LevelWizard3Point.ProcessCommand(instruction.Line);
break;
case PrintLevelingData.LevelingSystem.Probe7PointRadial:
instruction.Line = LevelWizard7PointRadial.ApplyLeveling(instruction.Line, currentDestination, instruction.movementType);
linesToWrite = LevelWizard7PointRadial.ProcessCommand(instruction.Line);
break;
case PrintLevelingData.LevelingSystem.Probe13PointRadial:
instruction.Line = LevelWizard13PointRadial.ApplyLeveling(instruction.Line, currentDestination, instruction.movementType);
linesToWrite = LevelWizard13PointRadial.ProcessCommand(instruction.Line);
break;
default:
throw new NotImplementedException();
}
instruction.Line = linesToWrite[0];
linesToWrite.RemoveAt(0);
// now insert any new lines
foreach (string line in linesToWrite)
{
PrinterMachineInstruction newInstruction = new PrinterMachineInstruction(line);
unleveledGCode.Insert(++lineIndex, newInstruction);
}
}
}
}
unleveledGCode.Save(dest);
}
else
{
File.Copy(source, dest, true);
}
ShowFileIfRequested(dest);
}
catch
{
}
}
private void ShowFileIfRequested(string filename)
{
if (OsInformation.OperatingSystem == OSType.Windows)
{
if (showInFolderAfterSave.Checked)
{
#if IS_WINDOWS_FORMS
WindowsFormsAbstract.ShowFileInFolder(filename);
#endif
}
}
}
public override void OnClosed(EventArgs e)
{
printItemWrapper.SlicingDone -= sliceItem_Done;
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
private event EventHandler unregisterEvents;
private void ReloadAfterPrinterProfileChanged(object sender, EventArgs e)
{
CreateWindowContent();
}
private void exportAMF_Click(object sender, EventArgs mouseEvent)
{
UiThread.RunOnIdle(() =>
{
SaveFileDialogParams saveParams = new SaveFileDialogParams("Save as AMF|*.amf", initialDirectory: documentsPath);
saveParams.Title = "MatterControl: Export File";
saveParams.ActionButtonLabel = "Export";
saveParams.FileName = printItemWrapper.Name;
Close();
FileDialog.SaveFileDialog(saveParams, onExportAmfFileSelected);
});
}
private async void onExportAmfFileSelected(SaveFileDialogParams saveParams)
{
await Task.Run(() => SaveAmf(saveParams));
}
private void SaveAmf(SaveFileDialogParams saveParams)
{
try
{
if (saveParams.FileName != null)
{
string filePathToSave = saveParams.FileName;
if (filePathToSave != null && filePathToSave != "")
{
string extension = Path.GetExtension(filePathToSave);
if (extension == "")
{
File.Delete(filePathToSave);
filePathToSave += ".amf";
}
if (Path.GetExtension(printItemWrapper.FileLocation).ToUpper() == Path.GetExtension(filePathToSave).ToUpper())
{
File.Copy(printItemWrapper.FileLocation, filePathToSave, true);
}
else
{
List<MeshGroup> meshGroups = MeshFileIo.Load(printItemWrapper.FileLocation);
MeshFileIo.Save(meshGroups, filePathToSave);
}
ShowFileIfRequested(filePathToSave);
}
}
}
catch
{
}
}
private void exportSTL_Click(object sender, EventArgs mouseEvent)
{
UiThread.RunOnIdle(() =>
{
SaveFileDialogParams saveParams = new SaveFileDialogParams("Save as STL|*.stl");
saveParams.Title = "MatterControl: Export File";
saveParams.ActionButtonLabel = "Export";
saveParams.FileName = printItemWrapper.Name;
Close();
FileDialog.SaveFileDialog(saveParams, onExportStlFileSelected);
});
}
private async void onExportStlFileSelected(SaveFileDialogParams saveParams)
{
await Task.Run(() => SaveStl(saveParams));
}
private void SaveStl(SaveFileDialogParams saveParams)
{
try
{
if (saveParams.FileName != null)
{
string filePathToSave = saveParams.FileName;
if (filePathToSave != null && filePathToSave != "")
{
string extension = Path.GetExtension(filePathToSave);
if (extension == "")
{
File.Delete(filePathToSave);
filePathToSave += ".stl";
}
if (Path.GetExtension(printItemWrapper.FileLocation).ToUpper() == Path.GetExtension(filePathToSave).ToUpper())
{
File.Copy(printItemWrapper.FileLocation, filePathToSave, true);
}
else
{
List<MeshGroup> meshGroups = MeshFileIo.Load(printItemWrapper.FileLocation);
MeshFileIo.Save(meshGroups, filePathToSave);
}
ShowFileIfRequested(filePathToSave);
}
}
}
catch
{
}
}
private void sliceItem_Done(object sender, EventArgs e)
{
PrintItemWrapper sliceItem = (PrintItemWrapper)sender;
printItemWrapper.SlicingDone -= sliceItem_Done;
SaveGCodeToNewLocation(sliceItem.GetGCodePathAndFileName(), gcodePathAndFilenameToSave);
}
private void x3gItemSlice_Complete(object sender, EventArgs e)
{
PrintItemWrapper sliceItem = (PrintItemWrapper)sender;
printItemWrapper.SlicingDone -= x3gItemSlice_Complete;
if (File.Exists(sliceItem.GetGCodePathAndFileName()))
{
generateX3GfromGcode(sliceItem.GetGCodePathAndFileName(), x3gPathAndFilenameToSave);
}
}
private string getGpxExectutablePath()
{
switch (OsInformation.OperatingSystem)
{
case OSType.Windows:
string gpxRelativePath = Path.Combine("..", "gpx.exe");
if (!File.Exists(gpxRelativePath))
{
gpxRelativePath = Path.Combine(".", "gpx.exe");
}
return Path.GetFullPath(gpxRelativePath);
case OSType.Mac:
return Path.Combine(ApplicationDataStorage.Instance.ApplicationPath, "gpx");
case OSType.X11:
return Path.GetFullPath(Path.Combine(".", "gpx.exe"));
default:
throw new NotImplementedException();
}
}
private void generateX3GfromGcode(string gcodeInputPath, string x3gOutputPath, string machineType = "r2")
{
string gpxExecutablePath = getGpxExectutablePath();
string gpxArgs = string.Format("-p -m {2} \"{0}\" \"{1}\" ", gcodeInputPath, x3gOutputPath, machineType);
ProcessStartInfo exportX3GProcess = new ProcessStartInfo(gpxExecutablePath);
exportX3GProcess.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
exportX3GProcess.Arguments = gpxArgs;
Process.Start(exportX3GProcess);
ShowFileIfRequested(x3gOutputPath);
}
}
}