예제 #1
0
        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);
            }
        }
예제 #2
0
        private void sliceItem_Done(object sender, EventArgs e)
        {
            PrintItemWrapper sliceItem = (PrintItemWrapper)sender;

            printItemWrapper.SlicingDone -= sliceItem_Done;
            SaveGCodeToNewLocation(sliceItem.GetGCodePathAndFileName(), gcodePathAndFilenameToSave);
        }
예제 #3
0
        void partToPrint_SliceDone(object sender, EventArgs e)
        {
            PrintItemWrapper partToPrint = sender as PrintItemWrapper;

            if (partToPrint != null)
            {
                partToPrint.Done -= new EventHandler(partToPrint_SliceDone);
                string gcodePathAndFileName = partToPrint.GetGCodePathAndFileName();
                if (gcodePathAndFileName != "")
                {
                    bool originalIsGCode = Path.GetExtension(partToPrint.FileLocation).ToUpper() == ".GCODE";
                    if (File.Exists(gcodePathAndFileName) &&
                        (originalIsGCode || File.ReadAllText(gcodePathAndFileName).Contains("filament used")))
                    {
                        string gcodeFileContents = "";
                        using (FileStream fileStream = new FileStream(gcodePathAndFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            using (StreamReader gcodeStreamReader = new StreamReader(fileStream))
                            {
                                gcodeFileContents = gcodeStreamReader.ReadToEnd();
                            }
                        }

                        timeSincePrintStarted.Restart();
                        PrinterCommunication.Instance.StartPrint(gcodeFileContents);
                    }
                    else
                    {
                        PrinterCommunication.Instance.CommunicationState = PrinterCommunication.CommunicationStates.Connected;
                    }
                }
            }
        }
예제 #4
0
        void sliceItem_Done(object sender, EventArgs e)
        {
            PrintItemWrapper sliceItem = (PrintItemWrapper)sender;

            printItemWrapper.SlicingDone.UnregisterEvent(sliceItem_Done, ref unregisterEvents);
            SaveGCodeToNewLocation(sliceItem.GetGCodePathAndFileName(), gcodePathAndFilenameToSave);
        }
        void PartSlicedStartPrintingToSd(object sender, EventArgs e)
        {
            // tell the printer to start the print
            PrintItemWrapper partToPrint = sender as PrintItemWrapper;

            if (partToPrint != null)
            {
                partToPrint.SlicingDone.UnregisterEvent(PartSlicedStartPrintingToSd, ref unregisterEvents);
                string gcodePathAndFileName = partToPrint.GetGCodePathAndFileName();
                if (gcodePathAndFileName != "")
                {
                    bool originalIsGCode = Path.GetExtension(partToPrint.FileLocation).ToUpper() == ".GCODE";
                    if (File.Exists(gcodePathAndFileName) &&
                        (originalIsGCode || File.ReadAllText(gcodePathAndFileName).Contains("filament used")))
                    {
                        string gcodeFileContents = "";
                        using (FileStream fileStream = new FileStream(gcodePathAndFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            using (StreamReader gcodeStreamReader = new StreamReader(fileStream))
                            {
                                gcodeFileContents = gcodeStreamReader.ReadToEnd();
                            }
                        }

                        PrinterConnectionAndCommunication.Instance.StartPrint(gcodeFileContents);
                    }
                    else
                    {
                        PrinterConnectionAndCommunication.Instance.CommunicationState = PrinterConnectionAndCommunication.CommunicationStates.Connected;
                    }
                }
            }
        }
예제 #6
0
        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 = ActiveSliceSettings.Instance != null || partIsGCode;

            if (showExportGCodeButton)
            {
                string exportGCodeTextFull = string.Format("{0} G-Code", "Export as".Localize());
                Button exportGCode         = textImageButtonFactory.Generate(exportGCodeTextFull);
                exportGCode.Name    = "Export as GCode Button";
                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  += (object sender, EventArgs e) =>
                    {
                        UiThread.RunOnIdle(() =>
                        {
                            // Close the export window
                            Close();

                            // Open a SaveFileDialog. If Save is clicked, slice the part if needed and pass the plugin the
                            // path to the gcode file and the target save path
                            FileDialog.SaveFileDialog(
                                new SaveFileDialogParams(plugin.GetExtensionFilter())
                            {
                                Title             = "MatterControl: Export File",
                                FileName          = printItemWrapper.Name,
                                ActionButtonLabel = "Export"
                            },
                                (SaveFileDialogParams saveParam) =>
                            {
                                string extension = Path.GetExtension(saveParam.FileName);
                                if (extension == "")
                                {
                                    saveParam.FileName += plugin.GetFileExtension();
                                }

                                if (partIsGCode)
                                {
                                    plugin.Generate(printItemWrapper.FileLocation, saveParam.FileName);
                                }
                                else
                                {
                                    SlicingQueue.Instance.QueuePartForSlicing(printItemWrapper);

                                    printItemWrapper.SlicingDone += (printItem, eventArgs) =>
                                    {
                                        PrintItemWrapper sliceItem = (PrintItemWrapper)printItem;
                                        if (File.Exists(sliceItem.GetGCodePathAndFileName()))
                                        {
                                            plugin.Generate(sliceItem.GetGCodePathAndFileName(), saveParam.FileName);
                                        }
                                    };
                                }
                            });
                        });
                    };                     // End exportButton Click handler

                    middleRowContainer.AddChild(exportButton);
                }
            }

            middleRowContainer.AddChild(new VerticalSpacer());

            // If print leveling is enabled then add in a check box 'Apply Leveling During Export' and default checked.
            if (showExportGCodeButton && ActiveSliceSettings.Instance.GetValue <bool>(SettingsKey.print_leveling_enabled))
            {
                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);
        }
예제 #7
0
        private static void CreateSlicedPartsThread()
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            while (!haltSlicingThread)
            {
                if (listOfSlicingItems.Count > 0)
                {
                    PrintItemWrapper itemToSlice     = listOfSlicingItems[0];
                    bool             doMergeInSlicer = false;
                    string           mergeRules      = "";
                    doMergeInSlicer = ActiveSliceSettings.Instance.ActiveSliceEngineType() == SlicingEngineTypes.MatterSlice;
                    string[] stlFileLocations = GetStlFileLocations(itemToSlice.FileLocation, doMergeInSlicer, ref mergeRules);
                    string   fileToSlice      = stlFileLocations[0];
                    // check that the STL file is currently on disk
                    if (File.Exists(fileToSlice))
                    {
                        itemToSlice.CurrentlySlicing = true;

                        string currentConfigurationFileAndPath = Path.Combine(ApplicationDataStorage.Instance.GCodeOutputPath, "config_" + ActiveSliceSettings.Instance.GetLongHashCode().ToString() + ".ini");
                        ActiveSliceSettings.Instance.GenerateConfigFile(currentConfigurationFileAndPath, true);

                        string gcodePathAndFileName = itemToSlice.GetGCodePathAndFileName();
                        bool   gcodeFileIsComplete  = itemToSlice.IsGCodeFileComplete(gcodePathAndFileName);

                        if (!File.Exists(gcodePathAndFileName) || !gcodeFileIsComplete)
                        {
                            string commandArgs = "";

                            switch (ActiveSliceSettings.Instance.ActiveSliceEngineType())
                            {
                            case SlicingEngineTypes.Slic3r:
                                commandArgs = "--load \"" + currentConfigurationFileAndPath + "\" --output \"" + gcodePathAndFileName + "\" \"" + fileToSlice + "\"";
                                break;

                            case SlicingEngineTypes.CuraEngine:
                                commandArgs = "-v -o \"" + gcodePathAndFileName + "\" " + EngineMappingCura.GetCuraCommandLineSettings() + " \"" + fileToSlice + "\"";
                                break;

                            case SlicingEngineTypes.MatterSlice:
                            {
                                EngineMappingsMatterSlice.WriteMatterSliceSettingsFile(currentConfigurationFileAndPath);
                                if (mergeRules == "")
                                {
                                    commandArgs = "-v -o \"" + gcodePathAndFileName + "\" -c \"" + currentConfigurationFileAndPath + "\"";
                                }
                                else
                                {
                                    commandArgs = "-b {0} -v -o \"".FormatWith(mergeRules) + gcodePathAndFileName + "\" -c \"" + currentConfigurationFileAndPath + "\"";
                                }
                                foreach (string filename in stlFileLocations)
                                {
                                    commandArgs = commandArgs + " \"" + filename + "\"";
                                }
                            }
                            break;
                            }

#if false
                            Mesh        loadedMesh = StlProcessing.Load(fileToSlice);
                            SliceLayers layers     = new SliceLayers();
                            layers.GetPerimetersForAllLayers(loadedMesh, .2, .2);
                            layers.DumpSegmentsToGcode("test.gcode");
#endif

                            if (OsInformation.OperatingSystem == OSType.Android ||
                                ((OsInformation.OperatingSystem == OSType.Mac || runInProcess) &&
                                 ActiveSliceSettings.Instance.ActiveSliceEngineType() == SlicingEngineTypes.MatterSlice))
                            {
                                itemCurrentlySlicing = itemToSlice;
                                MatterHackers.MatterSlice.LogOutput.GetLogWrites += SendProgressToItem;
                                MatterSlice.MatterSlice.ProcessArgs(commandArgs);
                                MatterHackers.MatterSlice.LogOutput.GetLogWrites -= SendProgressToItem;
                                itemCurrentlySlicing = null;
                            }
                            else
                            {
                                slicerProcess = new Process();
                                slicerProcess.StartInfo.Arguments = commandArgs;
                                string slicerFullPath = getSlicerFullPath();

                                slicerProcess.StartInfo.CreateNoWindow         = true;
                                slicerProcess.StartInfo.WindowStyle            = ProcessWindowStyle.Hidden;
                                slicerProcess.StartInfo.RedirectStandardError  = true;
                                slicerProcess.StartInfo.RedirectStandardOutput = true;

                                slicerProcess.StartInfo.FileName        = slicerFullPath;
                                slicerProcess.StartInfo.UseShellExecute = false;

                                slicerProcess.OutputDataReceived += (sender, args) =>
                                {
                                    if (args.Data != null)
                                    {
                                        string message = args.Data;
                                        message = message.Replace("=>", "").Trim();
                                        if (message.Contains(".gcode"))
                                        {
                                            message = "Saving intermediate file";
                                        }
                                        message += "...";
                                        UiThread.RunOnIdle(() =>
                                        {
                                            itemToSlice.OnSlicingOutputMessage(new StringEventArgs(message));
                                        });
                                    }
                                };

                                slicerProcess.Start();
                                slicerProcess.BeginOutputReadLine();
                                string stdError = slicerProcess.StandardError.ReadToEnd();

                                slicerProcess.WaitForExit();
                                lock (slicerProcess)
                                {
                                    slicerProcess = null;
                                }
                            }
                        }

                        try
                        {
                            if (File.Exists(gcodePathAndFileName) &&
                                File.Exists(currentConfigurationFileAndPath))
                            {
                                // make sure we have not already written the settings onto this file
                                bool fileHaseSettings = false;
                                int  bufferSize       = 32000;
                                using (Stream fileStream = File.OpenRead(gcodePathAndFileName))
                                {
                                    byte[] buffer = new byte[bufferSize];
                                    fileStream.Seek(Math.Max(0, fileStream.Length - bufferSize), SeekOrigin.Begin);
                                    int    numBytesRead = fileStream.Read(buffer, 0, bufferSize);
                                    string fileEnd      = System.Text.Encoding.UTF8.GetString(buffer);
                                    if (fileEnd.Contains("GCode settings used"))
                                    {
                                        fileHaseSettings = true;
                                    }
                                }

                                if (!fileHaseSettings)
                                {
                                    using (StreamWriter gcodeWirter = File.AppendText(gcodePathAndFileName))
                                    {
                                        string oemName = "MatterControl";
                                        if (OemSettings.Instance.WindowTitleExtra != null && OemSettings.Instance.WindowTitleExtra.Trim().Length > 0)
                                        {
                                            oemName = oemName + " - {0}".FormatWith(OemSettings.Instance.WindowTitleExtra);
                                        }

                                        gcodeWirter.WriteLine("; {0} Version {1} Build {2} : GCode settings used".FormatWith(oemName, VersionInfo.Instance.ReleaseVersion, VersionInfo.Instance.BuildVersion));
                                        gcodeWirter.WriteLine("; Date {0} Time {1}:{2:00}".FormatWith(DateTime.Now.Date, DateTime.Now.Hour, DateTime.Now.Minute));

                                        foreach (string line in File.ReadLines(currentConfigurationFileAndPath))
                                        {
                                            gcodeWirter.WriteLine("; {0}".FormatWith(line));
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception)
                        {
                        }
                    }

                    UiThread.RunOnIdle(() =>
                    {
                        itemToSlice.CurrentlySlicing = false;
                        itemToSlice.DoneSlicing      = true;
                    });

                    lock (listOfSlicingItems)
                    {
                        listOfSlicingItems.RemoveAt(0);
                    }
                }

                Thread.Sleep(100);
            }
        }
예제 #8
0
        void CreateAndAddChildren(object state)
        {
            TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();

            textImageButtonFactory.normalTextColor   = ActiveTheme.Instance.PrimaryTextColor;
            textImageButtonFactory.hoverTextColor    = ActiveTheme.Instance.PrimaryTextColor;
            textImageButtonFactory.disabledTextColor = ActiveTheme.Instance.PrimaryTextColor;
            textImageButtonFactory.pressedTextColor  = ActiveTheme.Instance.PrimaryTextColor;

            CloseAndRemoveAllChildren();
            gcodeViewWidget = null;
            gcodeProcessingStateInfoText = null;

            FlowLayoutWidget mainContainerTopToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom);

            mainContainerTopToBottom.HAnchor = Agg.UI.HAnchor.Max_FitToChildren_ParentWidth;
            mainContainerTopToBottom.VAnchor = Agg.UI.VAnchor.Max_FitToChildren_ParentHeight;

            buttonBottomPanel                 = new FlowLayoutWidget(FlowDirection.LeftToRight);
            buttonBottomPanel.HAnchor         = HAnchor.ParentLeftRight;
            buttonBottomPanel.Padding         = new BorderDouble(3, 3);
            buttonBottomPanel.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;

            generateGCodeButton        = textImageButtonFactory.Generate(LocalizedString.Get("Generate"));
            generateGCodeButton.Click += new EventHandler(generateButton_Click);
            buttonBottomPanel.AddChild(generateGCodeButton);

            layerSelectionButtonsPanel         = new FlowLayoutWidget(FlowDirection.RightToLeft);
            layerSelectionButtonsPanel.HAnchor = HAnchor.ParentLeftRight;
            layerSelectionButtonsPanel.Padding = new BorderDouble(0);

            GuiWidget holdPanelOpen = new GuiWidget(1, generateGCodeButton.Height);

            layerSelectionButtonsPanel.AddChild(holdPanelOpen);

            if (widgetHasCloseButton)
            {
                Button closeButton = textImageButtonFactory.Generate(LocalizedString.Get("Close"));
                layerSelectionButtonsPanel.AddChild(closeButton);
                closeButton.Click += (sender, e) =>
                {
                    CloseOnIdle();
                };
            }

            FlowLayoutWidget centerPartPreviewAndControls = new FlowLayoutWidget(FlowDirection.LeftToRight);

            centerPartPreviewAndControls.AnchorAll();

            gcodeDisplayWidget = new GuiWidget(HAnchor.ParentLeftRight, Agg.UI.VAnchor.ParentBottomTop);

            SetProcessingMessage("Press 'Add' to select an item.".Localize());
            if (printItem != null)
            {
                SetProcessingMessage(LocalizedString.Get("Loading GCode..."));
                if (Path.GetExtension(printItem.FileLocation).ToUpper() == ".GCODE")
                {
                    gcodeDisplayWidget.AddChild(CreateGCodeViewWidget(printItem.FileLocation));
                }
                else
                {
                    if (File.Exists(printItem.FileLocation))
                    {
                        string gcodePathAndFileName = printItem.GetGCodePathAndFileName();
                        bool   gcodeFileIsComplete  = printItem.IsGCodeFileComplete(gcodePathAndFileName);

                        if (printItem.SlicingHadError)
                        {
                            SetProcessingMessage(slicingErrorMessage);
                        }
                        else
                        {
                            SetProcessingMessage(pressGenerateMessage);
                        }

                        if (File.Exists(gcodePathAndFileName) && gcodeFileIsComplete)
                        {
                            gcodeDisplayWidget.AddChild(CreateGCodeViewWidget(gcodePathAndFileName));
                        }

                        // we only hook these up to make sure we can regenerate the gcode when we want
                        printItem.SlicingOutputMessage.RegisterEvent(sliceItem_SlicingOutputMessage, ref unregisterEvents);
                        printItem.SlicingDone.RegisterEvent(sliceItem_Done, ref unregisterEvents);
                    }
                    else
                    {
                        SetProcessingMessage(string.Format("{0}\n'{1}'", fileNotFoundMessage, printItem.Name));
                    }
                }
            }
            else
            {
                generateGCodeButton.Visible = false;
            }

            centerPartPreviewAndControls.AddChild(gcodeDisplayWidget);

            buttonRightPanel         = CreateRightButtonPanel();
            buttonRightPanel.Visible = false;
            centerPartPreviewAndControls.AddChild(buttonRightPanel);

            // add in a spacer
            layerSelectionButtonsPanel.AddChild(new GuiWidget(HAnchor.ParentLeftRight));
            buttonBottomPanel.AddChild(layerSelectionButtonsPanel);

            mainContainerTopToBottom.AddChild(centerPartPreviewAndControls);
            mainContainerTopToBottom.AddChild(buttonBottomPanel);
            this.AddChild(mainContainerTopToBottom);

            meshViewerWidget = new MeshViewerWidget(viewerVolume, bedCenter, bedShape, "".Localize());
            meshViewerWidget.AnchorAll();
            meshViewerWidget.AllowBedRenderingWhenEmpty = true;
            gcodeDisplayWidget.AddChild(meshViewerWidget);
            meshViewerWidget.Visible = false;
            meshViewerWidget.TrackballTumbleWidget.DrawGlContent += new EventHandler(TrackballTumbleWidget_DrawGlContent);

            viewControls2D = new ViewControls2D();
            AddChild(viewControls2D);
            viewControls3D = new ViewControls3D(meshViewerWidget);
            viewControls3D.PartSelectVisible = false;
            AddChild(viewControls3D);
            viewControls3D.rotateButton.ClickButton(null);
            viewControls3D.Visible = false;

            viewControlsToggle         = new ViewControlsToggle();
            viewControlsToggle.HAnchor = Agg.UI.HAnchor.ParentRight;
            AddChild(viewControlsToggle);
            viewControlsToggle.Visible = false;

            //viewControls3D.translateButton.ClickButton(null);

            // move things into the right place and scale
            {
                Vector3 bedCenter3D = new Vector3(bedCenter, 0);
                meshViewerWidget.PrinterBed.Translate(bedCenter3D);
                meshViewerWidget.TrackballTumbleWidget.TrackBallController.Scale = .05;
                meshViewerWidget.TrackballTumbleWidget.TrackBallController.Translate(-bedCenter3D);
            }

            viewControls2D.translateButton.Click += (sender, e) =>
            {
                gcodeViewWidget.TransformState = ViewGcodeWidget.ETransformState.Move;
            };
            viewControls2D.scaleButton.Click += (sender, e) =>
            {
                gcodeViewWidget.TransformState = ViewGcodeWidget.ETransformState.Scale;
            };

            AddHandlers();
        }