From e9eeea8d3d083689e8bc2801ce7bdc905d17bbb3 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Sat, 15 Dec 2018 09:44:06 -0800 Subject: [PATCH] Extract Windows only dependency from shared .netstandard project --- .../Library/Providers/LibraryConfig.cs | 3 + .../Library/Widgets/LibraryWidget.cs | 50 +-- MatterControlLib/MatterControlLib.csproj | 6 - .../Queue/OptionsMenu/PartsSheetCreator.cs | 327 ------------------ MatterControlLib/RootSystemWindow.cs | 8 +- 5 files changed, 6 insertions(+), 388 deletions(-) delete mode 100644 MatterControlLib/Queue/OptionsMenu/PartsSheetCreator.cs diff --git a/MatterControlLib/Library/Providers/LibraryConfig.cs b/MatterControlLib/Library/Providers/LibraryConfig.cs index e91795338..d37ed4f20 100644 --- a/MatterControlLib/Library/Providers/LibraryConfig.cs +++ b/MatterControlLib/Library/Providers/LibraryConfig.cs @@ -36,6 +36,7 @@ using MatterHackers.Agg.Image; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.MatterControl.CustomWidgets; +using MatterHackers.MatterControl.PrintQueue; namespace MatterHackers.MatterControl.Library { @@ -130,6 +131,8 @@ namespace MatterHackers.MatterControl.Library public LibraryCollectionContainer LibraryCollectionContainer { get; internal set; } + public List MenuExtensions { get; } = new List(); + public IContentProvider GetContentProvider(ILibraryItem item) { string contentType = (item as ILibraryAssetStream)?.ContentType ?? (item as ILibraryObject3D)?.ContentType; diff --git a/MatterControlLib/Library/Widgets/LibraryWidget.cs b/MatterControlLib/Library/Widgets/LibraryWidget.cs index f6cb3b6ea..f440a4ba7 100644 --- a/MatterControlLib/Library/Widgets/LibraryWidget.cs +++ b/MatterControlLib/Library/Widgets/LibraryWidget.cs @@ -978,58 +978,12 @@ namespace MatterHackers.MatterControl.PrintLibrary // Extension point - RegisteredLibraryActions not defined in this file/assembly can insert here via this named token menuActions.AddRange(ApplicationController.Instance.RegisteredLibraryActions("StandardLibraryOperations")); -#if !__ANDROID__ menuActions.Add(new MenuSeparator("Other")); - // PDF export is limited to Windows - if (AggContext.OperatingSystem == OSType.Windows) + foreach(var extension in ApplicationController.Instance.Library.MenuExtensions) { - menuActions.Add(new LibraryAction(ActionScope.ListItem) - { - Title = "Create Part Sheet".Localize(), - Action = (selectedLibraryItems, listView) => - { - UiThread.RunOnIdle(() => - { - var printItems = selectedLibraryItems.OfType(); - if (printItems.Any()) - { - AggContext.FileDialogs.SaveFileDialog( - new SaveFileDialogParams("Save Parts Sheet|*.pdf") - { - ActionButtonLabel = "Save Parts Sheet".Localize(), - Title = ApplicationController.Instance.ProductName + " - " + "Save".Localize() - }, - (saveParams) => - { - if (!string.IsNullOrEmpty(saveParams.FileName)) - { - var feedbackWindow = new SavePartsSheetFeedbackWindow( - printItems.Count(), - printItems.FirstOrDefault()?.Name, - theme.BackgroundColor); - - var currentPartsInQueue = new PartsSheet(printItems, saveParams.FileName); - currentPartsInQueue.UpdateRemainingItems += feedbackWindow.StartingNextPart; - currentPartsInQueue.DoneSaving += feedbackWindow.DoneSaving; - - feedbackWindow.ShowAsSystemWindow(); - - currentPartsInQueue.SaveSheets().ConfigureAwait(false); - } - }); - } - }); - }, - IsEnabled = (selectedListItems, listView) => - { - // Multiselect - disallow containers - return listView.SelectedItems.Any() - && listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink)); - } - }); + menuActions.Add(extension); } -#endif menuActions.Add(new LibraryAction(ActionScope.ListItem) { diff --git a/MatterControlLib/MatterControlLib.csproj b/MatterControlLib/MatterControlLib.csproj index 9e2cbe447..594708e68 100644 --- a/MatterControlLib/MatterControlLib.csproj +++ b/MatterControlLib/MatterControlLib.csproj @@ -93,12 +93,6 @@ - - - PdfSharp.dll - - - diff --git a/MatterControlLib/Queue/OptionsMenu/PartsSheetCreator.cs b/MatterControlLib/Queue/OptionsMenu/PartsSheetCreator.cs deleted file mode 100644 index b10053797..000000000 --- a/MatterControlLib/Queue/OptionsMenu/PartsSheetCreator.cs +++ /dev/null @@ -1,327 +0,0 @@ -/* -Copyright (c) 2017, Lars Brubaker, 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. -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using MatterHackers.Agg; -using MatterHackers.Agg.Font; -using MatterHackers.Agg.Image; -using MatterHackers.Agg.Platform; -using MatterHackers.Agg.VertexSource; -using MatterHackers.DataConverters3D; -using MatterHackers.MatterControl.DataStorage; -using MatterHackers.MatterControl.Library; -using MatterHackers.VectorMath; -using PdfSharp.Drawing; -using PdfSharp.Pdf; - -namespace MatterHackers.MatterControl -{ - public class PartsSheet - { - internal class PartImage - { - internal double xOffset = 0; - internal bool wasDrawn = false; - internal ImageBuffer image; - - public PartImage(ImageBuffer imageOfPart) - { - this.image = imageOfPart; - } - } - - private string pathAndFileToSaveTo; - - public event EventHandler DoneSaving; - - public event EventHandler UpdateRemainingItems; - - public class FileNameAndPresentationName - { - public string fileName; - public string presentationName; - - public FileNameAndPresentationName(string fileName, string presentationName) - { - this.fileName = fileName; - this.presentationName = presentationName; - } - } - - private IEnumerable itemSource; - private List partImagesToPrint = new List(); - private const double inchesPerMm = 0.0393701; - - private static bool currentlySaving = false; - - public Vector2 SheetSizeMM { get; set; } - - public Vector2 SheetSizeInches - { - get { return SheetSizeMM * inchesPerMm; } - set { SheetSizeMM = value / inchesPerMm; } - } - - public double PixelPerMM => inchesPerMm * SheetDpi; - - public BorderDouble PageMarginMM { get; } = new BorderDouble(10, 5); - - public BorderDouble PageMarginPixels => PageMarginMM * PixelPerMM; - - public double PartMarginMM { get; } = 2; - - public double PartMarginPixels => PartMarginMM * PixelPerMM; - - public double PartPaddingMM { get; } = 2; - - public double PartPaddingPixels => PartPaddingMM * PixelPerMM; - - public int SheetDpi { get; set; } - - public PartsSheet(IEnumerable itemSource, string pathAndFileToSaveTo) - { - this.pathAndFileToSaveTo = pathAndFileToSaveTo; - SheetDpi = 300; - SheetSizeInches = new Vector2(8.5, 11); - - this.itemSource = itemSource; - } - - private void OnDoneSaving() - { - DoneSaving?.Invoke(this, new StringEventArgs(Path.GetFileName("Saving to PDF"))); - } - - public async Task SaveSheets() - { - await Task.Run((Func)(async () => - { - currentlySaving = true; - // first create images for all the parts - foreach (var item in itemSource) - { - var object3D = await item.CreateContent(); - - var loadedMeshGroups = object3D.VisibleMeshes().ToList(); - if (loadedMeshGroups?.Count > 0) - { - AxisAlignedBoundingBox aabb = loadedMeshGroups[0].Mesh.GetAxisAlignedBoundingBox(loadedMeshGroups[0].WorldMatrix()); - - for (int i = 1; i < loadedMeshGroups.Count; i++) - { - aabb = AxisAlignedBoundingBox.Union(aabb, loadedMeshGroups[i].Mesh.GetAxisAlignedBoundingBox(loadedMeshGroups[i].WorldMatrix())); - } - - RectangleDouble bounds2D = new RectangleDouble(aabb.minXYZ.X, aabb.minXYZ.Y, aabb.maxXYZ.X, aabb.maxXYZ.Y); - double widthInMM = bounds2D.Width + PartMarginMM * 2; - double textSpaceMM = 5; - double heightMM = textSpaceMM + bounds2D.Height + PartMarginMM * 2; - - TypeFacePrinter typeFacePrinter = new TypeFacePrinter(item.Name, 28, Vector2.Zero, Justification.Center, Baseline.BoundsCenter); - double sizeOfNameX = typeFacePrinter.GetSize().X + PartMarginPixels * 2; - Vector2 sizeOfRender = new Vector2(widthInMM * PixelPerMM, heightMM * PixelPerMM); - - ImageBuffer imageOfPart = new ImageBuffer((int)(Math.Max(sizeOfNameX, sizeOfRender.X)), (int)(sizeOfRender.Y)); - typeFacePrinter.Origin = new Vector2(imageOfPart.Width / 2, (textSpaceMM / 2) * PixelPerMM); - - Graphics2D partGraphics2D = imageOfPart.NewGraphics2D(); - - RectangleDouble rectBounds = new RectangleDouble(0, 0, imageOfPart.Width, imageOfPart.Height); - double strokeWidth = .5 * PixelPerMM; - rectBounds.Inflate(-strokeWidth / 2); - RoundedRect rect = new RoundedRect(rectBounds, PartMarginMM * PixelPerMM); - partGraphics2D.Render(rect, Color.LightGray); - Stroke rectOutline = new Stroke(rect, strokeWidth); - partGraphics2D.Render(rectOutline, Color.DarkGray); - - foreach (var meshGroup in loadedMeshGroups) - { - PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, meshGroup.Mesh, meshGroup.WorldMatrix(), new Vector2(-bounds2D.Left + PartMarginMM, -bounds2D.Bottom + textSpaceMM + PartMarginMM), PixelPerMM, Color.Black); - } - partGraphics2D.Render(typeFacePrinter, Color.Black); - - partImagesToPrint.Add(new PartImage(imageOfPart)); - } - - UpdateRemainingItems?.Invoke(this, new StringEventArgs(item.Name)); - } - - partImagesToPrint.Sort(BiggestToLittlestImages); - - PdfDocument document = new PdfDocument(); - document.Info.Title = "MatterHackers Parts Sheet"; - document.Info.Author = "MatterHackers Inc."; - document.Info.Subject = "This is a list of the parts that are in a queue from MatterControl."; - document.Info.Keywords = "MatterControl, STL, 3D Printing"; - - int nextPartToPrintIndex = 0; - int plateNumber = 1; - bool done = false; - - while (!done && nextPartToPrintIndex < partImagesToPrint.Count) - { - PdfPage pdfPage = document.AddPage(); - CreateOnePage(plateNumber++, ref nextPartToPrintIndex, pdfPage); - } - - try - { - // save the final document - document.Save(pathAndFileToSaveTo); - - // Now try and open the document. This will launch whatever PDF viewer is on the system and ask it - // to show the file (at least on Windows). - Process.Start(pathAndFileToSaveTo); - } - catch (Exception) - { - } - - OnDoneSaving(); - currentlySaving = false; - })); - } - - private static int BiggestToLittlestImages(PartImage one, PartImage two) - { - return two.image.Height.CompareTo(one.image.Height); - } - - private void CreateOnePage(int plateNumber, ref int nextPartToPrintIndex, PdfPage pdfPage) - { - ImageBuffer plateInventoryImage = new ImageBuffer((int)(300 * 8.5), 300 * 11); - Graphics2D plateGraphics = plateInventoryImage.NewGraphics2D(); - double currentlyPrintingHeightPixels = PrintTopOfPage(plateInventoryImage, plateGraphics); - - Vector2 offset = new Vector2(PageMarginPixels.Left, currentlyPrintingHeightPixels); - double tallestHeight = 0; - List partsOnLine = new List(); - while (nextPartToPrintIndex < partImagesToPrint.Count) - { - ImageBuffer image = partImagesToPrint[nextPartToPrintIndex].image; - tallestHeight = Math.Max(tallestHeight, image.Height); - - if (partsOnLine.Count > 0 && offset.X + image.Width > plateInventoryImage.Width - PageMarginPixels.Right) - { - if (partsOnLine.Count == 1) - { - plateGraphics.Render(partsOnLine[0].image, plateInventoryImage.Width / 2 - partsOnLine[0].image.Width / 2, offset.Y - tallestHeight); - } - else - { - foreach (PartImage partToDraw in partsOnLine) - { - plateGraphics.Render(partToDraw.image, partToDraw.xOffset, offset.Y - tallestHeight); - } - } - - offset.X = PageMarginPixels.Left; - offset.Y -= (tallestHeight + PartPaddingPixels * 2); - tallestHeight = 0; - partsOnLine.Clear(); - if (offset.Y - image.Height < PageMarginPixels.Bottom) - { - break; - } - } - else - { - partImagesToPrint[nextPartToPrintIndex].xOffset = offset.X; - partsOnLine.Add(partImagesToPrint[nextPartToPrintIndex]); - //plateGraphics.Render(image, offset.x, offset.y - image.Height); - offset.X += image.Width + PartPaddingPixels * 2; - nextPartToPrintIndex++; - } - } - - // print the last line of parts - foreach (PartImage partToDraw in partsOnLine) - { - plateGraphics.Render(partToDraw.image, partToDraw.xOffset, offset.Y - tallestHeight); - } - - TypeFacePrinter printer = new TypeFacePrinter(string.Format("{0}", Path.GetFileNameWithoutExtension(pathAndFileToSaveTo)), 32, justification: Justification.Center); - printer.Origin = new Vector2(plateGraphics.DestImage.Width / 2, 110); - plateGraphics.Render(printer, Color.Black); - - printer = new TypeFacePrinter(string.Format("Page {0}", plateNumber), 28, justification: Justification.Center); - printer.Origin = new Vector2(plateGraphics.DestImage.Width / 2, 60); - plateGraphics.Render(printer, Color.Black); - - string folderToSavePrintsTo = Path.Combine(ApplicationDataStorage.Instance.ApplicationTempDataPath, "plateImages"); - string jpegFileName = Path.Combine(folderToSavePrintsTo, plateNumber.ToString() + ".jpeg"); - - Directory.CreateDirectory(folderToSavePrintsTo); - - AggContext.ImageIO.SaveImageData(jpegFileName, plateInventoryImage); - - XGraphics gfx = XGraphics.FromPdfPage(pdfPage); - XImage jpegImage = XImage.FromFile(jpegFileName); - //double width = jpegImage.PixelWidth * 72 / jpegImage.HorizontalResolution; - //double height = jpegImage.PixelHeight * 72 / jpegImage. .HorizontalResolution; - - gfx.DrawImage(jpegImage, 0, 0, pdfPage.Width, pdfPage.Height); - } - - private double PrintTopOfPage(ImageBuffer plateInventoryImage, Graphics2D plateGraphics) - { - plateGraphics.Clear(Color.White); - - double currentlyPrintingHeightPixels = plateInventoryImage.Height - PageMarginMM.Top * PixelPerMM; - - string logoPathAndFile = Path.Combine("Images", "PartSheetLogo.png"); - if (AggContext.StaticData.FileExists(logoPathAndFile)) - { - ImageBuffer logoImage = AggContext.StaticData.LoadImage(logoPathAndFile); - currentlyPrintingHeightPixels -= logoImage.Height; - plateGraphics.Render(logoImage, (plateInventoryImage.Width - logoImage.Width) / 2, currentlyPrintingHeightPixels); - } - - currentlyPrintingHeightPixels -= PartPaddingPixels; - - double underlineHeightMM = 1; - - var lineBounds = new RectangleDouble(0, 0, plateInventoryImage.Width - PageMarginPixels.Left * 2, underlineHeightMM * PixelPerMM); - lineBounds.Offset(PageMarginPixels.Left, currentlyPrintingHeightPixels - lineBounds.Height); - plateGraphics.FillRectangle(lineBounds, Color.Black); - - return currentlyPrintingHeightPixels - (lineBounds.Height + PartPaddingPixels); - } - - public static bool IsSaving() - { - return currentlySaving; - } - } -} \ No newline at end of file diff --git a/MatterControlLib/RootSystemWindow.cs b/MatterControlLib/RootSystemWindow.cs index b37b4dae2..de5f38370 100644 --- a/MatterControlLib/RootSystemWindow.cs +++ b/MatterControlLib/RootSystemWindow.cs @@ -255,13 +255,7 @@ namespace MatterHackers.MatterControl message = "Are you sure you want to abort the current print and close MatterControl?".Localize(); } } -#if !__ANDROID__ - else if (PartsSheet.IsSaving()) - { - caption = "Confirm Exit".Localize(); - message = "You are currently saving a parts sheet, are you sure you want to exit?".Localize(); - } -#endif + if (caption != null) { // Record that we are waiting for a response to the request to close