コード例 #1
0
        private void insertTextBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
            BackgroundWorker backgroundWorker = (BackgroundWorker)sender;

            asynchMeshGroups.Clear();
            asynchMeshGroupTransforms.Clear();
            asynchPlatingDatas.Clear();

            string          currentText  = (string)e.Argument;
            TypeFacePrinter printer      = new TypeFacePrinter(currentText, new StyledTypeFace(boldTypeFace, 12));
            Vector2         size         = printer.GetSize(currentText);
            double          centerOffset = -size.x / 2;

            double ratioPerMeshGroup = 1.0 / currentText.Length;
            double currentRatioDone  = 0;

            for (int i = 0; i < currentText.Length; i++)
            {
                int newIndex = asynchMeshGroups.Count;

                TypeFacePrinter letterPrinter = new TypeFacePrinter(currentText[i].ToString(), new StyledTypeFace(boldTypeFace, 12));
                Mesh            textMesh      = VertexSourceToMesh.Extrude(letterPrinter, 10 + (i % 2));

                if (textMesh.Faces.Count > 0)
                {
                    asynchMeshGroups.Add(new MeshGroup(textMesh));

                    PlatingMeshGroupData newMeshInfo = new PlatingMeshGroupData();

                    newMeshInfo.xSpacing = printer.GetOffsetLeftOfCharacterIndex(i).x + centerOffset;
                    asynchPlatingDatas.Add(newMeshInfo);
                    asynchMeshGroupTransforms.Add(ScaleRotateTranslate.Identity());

                    PlatingHelper.CreateITraceableForMeshGroup(asynchPlatingDatas, asynchMeshGroups, newIndex, (double progress0To1, string processingState, out bool continueProcessing) =>
                    {
                        continueProcessing = true;
                        int nextPercent    = (int)((currentRatioDone + ratioPerMeshGroup * progress0To1) * 100);
                        backgroundWorker.ReportProgress(nextPercent);
                    });

                    currentRatioDone += ratioPerMeshGroup;

                    PlatingHelper.PlaceMeshGroupOnBed(asynchMeshGroups, asynchMeshGroupTransforms, newIndex);
                }

                backgroundWorker.ReportProgress((i + 1) * 95 / currentText.Length);
            }

            SetWordSpacing(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas);
            SetWordSize(asynchMeshGroups, asynchMeshGroupTransforms);
            SetWordHeight(asynchMeshGroups, asynchMeshGroupTransforms);

            if (createUnderline.Checked)
            {
                CreateUnderline(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas);
            }

            backgroundWorker.ReportProgress(95);
        }
コード例 #2
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLock = RebuildLock();

            return(Task.Run(() =>
            {
                using (new CenterAndHeightMaintainer(this))
                {
                    bool valuesChanged = false;
                    var height = Height.ClampIfNotCalculated(this, .01, 1000000, ref valuesChanged);
                    var nameToWrite = NameToWrite.Value(this);
                    if (string.IsNullOrWhiteSpace(nameToWrite))
                    {
                        Mesh = PlatonicSolids.CreateCube(20, 10, height);
                    }
                    else
                    {
                        Mesh = null;
                        this.Children.Modify(list =>
                        {
                            list.Clear();

                            var offest = 0.0;
                            double pointsToMm = 0.352778;

                            foreach (var letter in nameToWrite.ToCharArray())
                            {
                                var style = new StyledTypeFace(ApplicationController.GetTypeFace(this.Font), PointSize.Value(this));
                                var letterPrinter = new TypeFacePrinter(letter.ToString(), style)
                                {
                                    ResolutionScale = 10
                                };
                                var scaledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));

                                list.Add(new Object3D()
                                {
                                    Mesh = VertexSourceToMesh.Extrude(scaledLetterPrinter, this.Height.Value(this)),
                                    Matrix = Matrix4X4.CreateTranslation(offest, 0, 0),
                                    Name = letter.ToString()
                                });

                                offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm;
                            }
                        });
                    }
                }

                UiThread.RunOnIdle(() =>
                {
                    rebuildLock.Dispose();
                    Invalidate(InvalidateType.DisplayValues);
                    Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                });
            }));
        }
コード例 #3
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLock = RebuildLock();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Generating Text Meshes".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                using (new CenterAndHeightMaintainer(this))
                {
                    if (string.IsNullOrWhiteSpace(NameToWrite))
                    {
                        Mesh = PlatonicSolids.CreateCube(20, 10, Height);
                    }
                    else
                    {
                        Mesh = null;
                        this.Children.Modify(list =>
                        {
                            list.Clear();

                            var offest = 0.0;
                            double pointsToMm = 0.352778;

                            foreach (var letter in this.NameToWrite.ToCharArray())
                            {
                                var letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(this.Font), this.PointSize))
                                {
                                    ResolutionScale = 10
                                };
                                var scaledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));

                                list.Add(new Object3D()
                                {
                                    Mesh = VertexSourceToMesh.Extrude(scaledLetterPrinter, this.Height),
                                    Matrix = Matrix4X4.CreateTranslation(offest, 0, 0),
                                    Name = letter.ToString()
                                });

                                offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm;
                            }
                        });
                    }
                }

                rebuildLock.Dispose();
                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                return Task.CompletedTask;
            }));
        }
コード例 #4
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLock = RebuildLock();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Mirror".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                using (new CenterAndHeightMantainer(this))
                {
                    this.Children.Modify((List <IObject3D> list) =>
                    {
                        list.Clear();

                        var offest = 0.0;
                        double pointsToMm = 0.352778;
                        foreach (var letter in NameToWrite.ToCharArray())
                        {
                            var letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(Font), PointSize))
                            {
                                ResolutionScale = 10
                            };
                            var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));
                            IObject3D letterObject = new Object3D()
                            {
                                Mesh = VertexSourceToMesh.Extrude(scalledLetterPrinter, Height)
                            };

                            letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0);
                            list.Add(letterObject);

                            offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm;
                        }
                    });
                }

                rebuildLock.Dispose();
                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                return Task.CompletedTask;
            }));
        }
コード例 #5
0
        public void Write(string lineString)
        {
            string[] splitOnNL = lineString.Split('\n');
            foreach (string line in splitOnNL)
            {
                if (line.Length > 0)
                {
                    printer.Text = line;
                    Vector2 stringSize = printer.GetSize();

                    int arrayIndex = (lineCount % TOTOL_POW2);
                    lines[arrayIndex] = line;

                    lineCount++;
                }
            }

            Invalidate();
        }
コード例 #6
0
ファイル: TextObject3D.cs プロジェクト: yg12344/MatterControl
        private void Rebuild(UndoBuffer undoBuffer)
        {
            this.DebugDepth("Rebuild");
            using (RebuildLock())
            {
                var aabb = this.GetAxisAlignedBoundingBox();

                this.Children.Modify((list) =>
                {
                    list.Clear();

                    var offest        = 0.0;
                    double pointsToMm = 0.352778;
                    foreach (var letter in NameToWrite.ToCharArray())
                    {
                        var letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(Font), PointSize))
                        {
                            ResolutionScale = 10
                        };
                        var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));
                        IObject3D letterObject   = new Object3D()
                        {
                            Mesh = VertexSourceToMesh.Extrude(scalledLetterPrinter, Height)
                        };

                        letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0);
                        list.Add(letterObject);

                        offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm;
                    }
                });


                if (aabb.ZSize > 0)
                {
                    // If the part was already created and at a height, maintain the height.
                    PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
                }
            }

            Invalidate(new InvalidateArgs(this, InvalidateType.Content));
        }
コード例 #7
0
        private void InsertTextDoWork(string currentText)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            asynchMeshGroups.Clear();
            asynchMeshGroupTransforms.Clear();
            asynchPlatingDatas.Clear();

            TypeFacePrinter brailPrinter = new TypeFacePrinter(currentText, new StyledTypeFace(brailTypeFace, 12));

            int            firstNewCharacter = 0;
            StyledTypeFace boldStyled        = new StyledTypeFace(boldTypeFace, 12);

            if (includeText.Checked)
            {
                TypeFacePrinter normalPrinter = new TypeFacePrinter(currentText, boldStyled);
                Vector2         normalSize    = normalPrinter.GetSize();
                AddCharacterMeshes(currentText, normalPrinter);

                firstNewCharacter = asynchPlatingDatas.Count;
            }

            AddCharacterMeshes(currentText, brailPrinter);
            Vector2 brailSize = brailPrinter.GetSize();

            for (int i = firstNewCharacter; i < asynchPlatingDatas.Count; i++)
            {
                asynchPlatingDatas[i].spacing = asynchPlatingDatas[i - firstNewCharacter].spacing + new Vector2(0, -boldStyled.CapHeightInPixels * 1.5);
            }

            CreateBase(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas);

            SetWordPositions(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas);
            SetWordSize(asynchMeshGroups, asynchMeshGroupTransforms);
            SetWordHeight(asynchMeshGroups, asynchMeshGroupTransforms);

            CenterTextOnScreen(asynchMeshGroups, asynchMeshGroupTransforms);

            processingProgressControl.PercentComplete = 95;
        }
コード例 #8
0
        public Task SaveSheets()
        {
            return(ApplicationController.Instance.Tasks.Execute(
                       "Export Part Sheet".Localize(),
                       null,
                       async(reporter, cancelationToken) =>
            {
                var progressStatus = new ProgressStatus();

                var processCount = 0.0;
                currentlySaving = true;
                // first create images for all the parts
                foreach (var item in itemSource)
                {
                    progressStatus.Status = item.Name;
                    reporter.Report(progressStatus);

                    var xxx = itemSource.Count();
                    var yyy = itemSource.FirstOrDefault()?.Name;

                    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));
                    }

                    progressStatus.Progress0To1 = Math.Min(processCount / itemSource.Count, .95);
                    reporter.Report(progressStatus);
                    processCount++;
                }

                progressStatus.Status = "Saving".Localize();
                reporter.Report(progressStatus);

                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)
                {
                }

                currentlySaving = false;

                progressStatus.Progress0To1 = 1;
                reporter.Report(progressStatus);
            }));
        }
コード例 #9
0
ファイル: PartsSheet.cs プロジェクト: csselph/MatterControl
        public void SavingFunction()
        {
            currentlySaving        = true;
            countThatHaveBeenSaved = 0;
            // first create images for all the parts
            foreach (string stlFileName in stlFilesToPrint)
            {
                Mesh loadedMesh = StlProcessing.Load(stlFileName);
                if (loadedMesh != null)
                {
                    AxisAlignedBoundingBox aabb     = loadedMesh.GetAxisAlignedBoundingBox();
                    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;

                    string          partName        = System.IO.Path.GetFileName(System.IO.Path.GetFileName(stlFileName));
                    TypeFacePrinter typeFacePrinter = new TypeFacePrinter(partName, 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), 32, new BlenderBGRA());
                    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, RGBA_Bytes.LightGray);
                    Stroke rectOutline = new Stroke(rect, strokeWidth);
                    partGraphics2D.Render(rectOutline, RGBA_Bytes.DarkGray);

                    PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, loadedMesh, new Vector2(-bounds2D.Left + PartMarginMM, -bounds2D.Bottom + textSpaceMM + PartMarginMM), PixelPerMM, RGBA_Bytes.Black);
                    partGraphics2D.Render(typeFacePrinter, RGBA_Bytes.Black);

                    partImagesToPrint.Add(new PartImage(imageOfPart));
                }
                countThatHaveBeenSaved++;
                if (UpdateRemainingItems != null)
                {
                    UpdateRemainingItems(this, new StringEventArgs(Path.GetFileName(stlFileName)));
                }
            }

            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
            {
                document.Save(pathAndFileToSaveTo);
                Process.Start(pathAndFileToSaveTo);
            }
            catch {
            }

            OnDoneSaving();
            currentlySaving = false;
        }
コード例 #10
0
        public void SavingFunction()
        {
            currentlySaving        = true;
            countThatHaveBeenSaved = 0;
            // first create images for all the parts
            foreach (FileNameAndPresentationName queuePartFileName in queuPartFilesToAdd)
            {
                List <MeshGroup> loadedMeshGroups = null;
                if (File.Exists(queuePartFileName.fileName))
                {
                    loadedMeshGroups = MeshFileIo.Load(queuePartFileName.fileName);
                }

                if (loadedMeshGroups != null)
                {
                    bool firstMeshGroup         = true;
                    AxisAlignedBoundingBox aabb = null;
                    foreach (MeshGroup meshGroup in loadedMeshGroups)
                    {
                        if (firstMeshGroup)
                        {
                            aabb           = meshGroup.GetAxisAlignedBoundingBox();
                            firstMeshGroup = false;
                        }
                        else
                        {
                            aabb = AxisAlignedBoundingBox.Union(aabb, meshGroup.GetAxisAlignedBoundingBox());
                        }
                    }
                    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(queuePartFileName.presentationName, 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), 32, new BlenderBGRA());
                    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, RGBA_Bytes.LightGray);
                    Stroke rectOutline = new Stroke(rect, strokeWidth);
                    partGraphics2D.Render(rectOutline, RGBA_Bytes.DarkGray);

                    foreach (MeshGroup meshGroup in loadedMeshGroups)
                    {
                        foreach (Mesh loadedMesh in meshGroup.Meshes)
                        {
                            PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, loadedMesh, new Vector2(-bounds2D.Left + PartMarginMM, -bounds2D.Bottom + textSpaceMM + PartMarginMM), PixelPerMM, RGBA_Bytes.Black);
                        }
                    }
                    partGraphics2D.Render(typeFacePrinter, RGBA_Bytes.Black);

                    partImagesToPrint.Add(new PartImage(imageOfPart));

                    countThatHaveBeenSaved++;
                }

                if (UpdateRemainingItems != null)
                {
                    UpdateRemainingItems(this, new StringEventArgs(Path.GetFileName(queuePartFileName.presentationName)));
                }
            }

            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 lanch 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;
        }