public override void OnMouseUp(MouseEventArgs mouseEvent)
        {
            if (CurrentTrackingType != TrackBallTransformType.None)
            {
                if (CurrentTrackingType == TrackBallTransformType.Rotation)
                {
                    EndRotateAroundOrigin();

                    // try and preserve some of the velocity
                    motionQueue.AddMoveToMotionQueue(mouseEvent.Position, UiThread.CurrentTimerMs);
                    if (!Keyboard.IsKeyDown(Keys.ShiftKey))
                    {
                        currentVelocityPerMs = motionQueue.GetVelocityPixelsPerMs();
                        if (currentVelocityPerMs.LengthSquared > 0)
                        {
                            Vector2 center = LocalBounds.Center;
                            StartRotateAroundOrigin(center);
                            runningInterval = UiThread.SetInterval(ApplyVelocity, 1.0 / updatesPerSecond);
                        }
                    }
                }

                CurrentTrackingType = TrackBallTransformType.None;
            }

            base.OnMouseUp(mouseEvent);
        }
        public override void PageIsBecomingActive()
        {
            bedStartingTemp = printer.Connection.ActualBedTemperature;

            runningInterval = UiThread.SetInterval(ShowTempChangeProgress, 1);

            if (bedTargetTemp > 0)
            {
                // start heating the bed and show our progress
                printer.Connection.TargetBedTemperature = bedTargetTemp;
            }

            if (hotEndTargetTemp > 0)
            {
                // start heating the hot end and show our progress
                printer.Connection.SetTargetHotendTemperature(0, hotEndTargetTemp);
            }

            NextButton.Enabled = false;

            // if we are trying to go to a temp of 0 than just move on to next window
            if (bedTargetTemp == 0 && hotEndTargetTemp == 0)
            {
                // advance to the next page
                UiThread.RunOnIdle(() => NextButton.InvokeClick());
            }

            base.PageIsBecomingActive();
        }
Пример #3
0
        public GamePlatform(int framesPerSecond, int maxUpdatesPerDraw, double width, double height)
            : base(width, height)
        {
            AnchorAll();
            showFrameRate          = true;
            secondsPerUpdate       = 1.0 / (double)framesPerSecond;
            this.maxUpdatesPerDraw = maxUpdatesPerDraw;

            AudioSystem.Startup();
            UiThread.SetInterval(OnIdle, secondsPerUpdate);
        }
Пример #4
0
        private void DirectoryContentsChanged(object sender, EventArgs e)
        {
            // Flag for reload
            isDirty = true;

            lastTimeContentsChanged = UiThread.CurrentTimerMs;

            // Only refresh content if we're the active container
            if (isActiveContainer &&
                waitingForRefresh == null)
            {
                waitingForRefresh = UiThread.SetInterval(WaitToRefresh, .5);
            }
        }
Пример #5
0
        private void ConnectToWidget(object drawingWidget, DrawEventArgs e)
        {
            GuiWidget parent = drawingWidget as GuiWidget;

            while (parent.BackgroundColor.Alpha0To255 == 0)
            {
                parent = parent.Parent;
            }
            startColor     = parent.BackgroundColor;
            timeSinceStart = Stopwatch.StartNew();
            widgetToHighlight.AfterDraw -= ConnectToWidget;
            var runningInterval = UiThread.SetInterval(ChangeBackgroundColor, animationDelay);

            parent.Closed += (s, e2) => runningInterval.Continue = false;
        }
Пример #6
0
        public FindBedHeight(ISetupWizard setupWizard,
                             string pageDescription,
                             string setZHeightCoarseInstruction1,
                             string setZHeightCoarseInstruction2,
                             double moveDistance,
                             List <PrintLevelingWizard.ProbePosition> probePositions,
                             int probePositionsBeingEditedIndex)
            : base(setupWizard, pageDescription, setZHeightCoarseInstruction1)
        {
            this.probePositions                 = probePositions;
            this.moveAmount                     = moveDistance;
            this.lastReportedPosition           = printer.Connection.LastReportedPosition;
            this.probePositionsBeingEditedIndex = probePositionsBeingEditedIndex;

            GuiWidget spacer = new GuiWidget(15, 15);

            contentRow.AddChild(spacer);

            FlowLayoutWidget zButtonsAndInfo = new FlowLayoutWidget();

            zButtonsAndInfo.HAnchor |= Agg.UI.HAnchor.Center;
            FlowLayoutWidget zButtons = CreateZButtons();

            zButtonsAndInfo.AddChild(zButtons);

            zButtonsAndInfo.AddChild(new GuiWidget(15, 10));

            // textFields
            TextWidget zPosition = new TextWidget("Z: 0.0      ", pointSize: 12, textColor: theme.TextColor)
            {
                VAnchor = VAnchor.Center,
                Margin  = new BorderDouble(10, 0),
            };

            runningInterval = UiThread.SetInterval(() =>
            {
                Vector3 destinationPosition = printer.Connection.CurrentDestination;
                zPosition.Text = "Z: {0:0.00}".FormatWith(destinationPosition.Z);
            }, .3);

            zButtonsAndInfo.AddChild(zPosition);

            contentRow.AddChild(zButtonsAndInfo);

            contentRow.AddChild(
                this.CreateTextField(setZHeightCoarseInstruction2));
        }
Пример #7
0
        public InlineEditControl(string defaultSizeString = "-0000.00", Agg.Font.Justification justification = Agg.Font.Justification.Left)
        {
            base.Visible = false;

            double pointSize = 12;

            numberDisplay = new TextWidget(defaultSizeString, 0, 0, pointSize, justification: justification)
            {
                Visible = false,
                VAnchor = VAnchor.Bottom,
                HAnchor = HAnchor.Left,
                Text    = "0",
            };
            AddChild(numberDisplay);

            numberEdit = new NumberEdit(0, 50, 50, pointSize, pixelWidth: numberDisplay.Width, allowNegatives: true, allowDecimals: true)
            {
                Visible          = false,
                VAnchor          = VAnchor.Bottom,
                HAnchor          = HAnchor.Left,
                SelectAllOnFocus = true,
            };
            numberEdit.InternalNumberEdit.TextChanged += (s, e) =>
            {
                numberDisplay.Text = GetDisplayString == null ? "None" : GetDisplayString.Invoke(Value);
                base.OnTextChanged(e);
            };
            numberEdit.InternalNumberEdit.MaxDecimalsPlaces = 2;

            numberEdit.EditComplete += (s, e) =>
            {
                EditComplete?.Invoke(this, e);
                timeSinceMouseUp.Restart();
                numberEdit.Visible    = false;
                numberDisplay.Visible = true;
            };

            AddChild(numberEdit);

            VAnchor = VAnchor.Fit;
            HAnchor = HAnchor.Fit;

            var runningInterval = UiThread.SetInterval(HideIfApplicable, .1);

            this.Closed += (s, e) => runningInterval.Continue = false;
        }
        private void LookForTempRequest(object sender, EventArgs e)
        {
            var stringEvent = e as StringEventArgs;

            if (stringEvent != null &&
                stringEvent.Data.Contains("M104"))
            {
                startingTemp = printer.Connection.GetActualHotendTemperature(0);
                RunningInterval runningInterval = null;
                runningInterval = UiThread.SetInterval(() =>
                {
                    runningInterval.Continue  = !HasBeenClosed && progressBar.RatioComplete < 1;
                    progressBar.Visible       = true;
                    double targetTemp         = printer.Connection.GetTargetHotendTemperature(0);
                    double actualTemp         = printer.Connection.GetActualHotendTemperature(0);
                    double totalDelta         = targetTemp - startingTemp;
                    double currentDelta       = actualTemp - startingTemp;
                    double ratioDone          = totalDelta != 0 ? (currentDelta / totalDelta) : 1;
                    progressBar.RatioComplete = Math.Min(Math.Max(0, ratioDone), 1);
                    progressBarText.Text      = $"Temperature: {actualTemp:0} / {targetTemp:0}";
                }, 1);
            }
        }
Пример #9
0
        public override void OnMouseUp(MouseEventArgs mouseEvent)
        {
            if (!LockTrackBall && TrackBallController.CurrentTrackingType != TrackBallTransformType.None)
            {
                if (TrackBallController.CurrentTrackingType == TrackBallTransformType.Rotation)
                {
                    // try and preserve some of the velocity
                    motionQueue.AddMoveToMotionQueue(mouseEvent.Position, UiThread.CurrentTimerMs);

                    if (!Keyboard.IsKeyDown(Keys.ShiftKey))
                    {
                        currentVelocityPerMs = motionQueue.GetVelocityPixelsPerMs();
                        if (currentVelocityPerMs.LengthSquared > 0)
                        {
                            runningInterval = UiThread.SetInterval(ApplyVelocity, 1.0 / updatesPerSecond);
                        }
                    }
                }

                TrackBallController.OnMouseUp();
            }

            base.OnMouseUp(mouseEvent);
        }
Пример #10
0
        public override void OnLoad(EventArgs args)
        {
            // hook our parent so we can turn off the bed when we are done with leveling
            this.DialogWindow.Closed += WizardWindow_Closed;

            bedStartingTemp = printer.Connection.ActualBedTemperature;

            runningInterval = UiThread.SetInterval(ShowTempChangeProgress, 1);

            if (bedTargetTemp > 0)
            {
                // start heating the bed and show our progress
                printer.Connection.TargetBedTemperature = bedTargetTemp;
            }

            for (int i = 0; i < targetHotendTemps.Length; i++)
            {
                if (targetHotendTemps[i] > 0)
                {
                    // start heating the hot end and show our progress
                    printer.Connection.SetTargetHotendTemperature(i, targetHotendTemps[i]);
                }
            }

            NextButton.Enabled = false;

            // if we are trying to go to a temp of 0 than just move on to next window
            if (bedTargetTemp == 0 &&
                targetHotendTemps.All(i => i == 0))
            {
                // advance to the next page
                UiThread.RunOnIdle(() => NextButton.InvokeClick());
            }

            base.OnLoad(args);
        }
        protected override IEnumerator <WizardPage> GetPages()
        {
            var extruderCount = printer.Settings.GetValue <int>(SettingsKey.extruder_count);

            var levelingStrings = new LevelingStrings();

            var title        = "Unload Material".Localize();
            var instructions = "Please select the material you want to unload.".Localize();

            if (extruderCount > 1)
            {
                instructions = "Please select the material you want to unload from extruder {0}.".Localize().FormatWith(extruderIndex + 1);
            }

            // select the material
            yield return(new SelectMaterialPage(this, title, instructions, "Unload".Localize(), extruderIndex, false, false)
            {
                WindowTitle = Title
            });

            var theme = ApplicationController.Instance.Theme;

            // wait for extruder to heat
            {
                var targetHotendTemp = printer.Settings.Helpers.ExtruderTargetTemperature(extruderIndex);
                var temps            = new double[4];
                temps[extruderIndex] = targetHotendTemp;
                yield return(new WaitForTempPage(
                                 this,
                                 "Waiting For Printer To Heat".Localize(),
                                 (extruderCount > 1 ? "Waiting for hotend {0} to heat to ".Localize().FormatWith(extruderIndex + 1) : "Waiting for the hotend to heat to ".Localize()) + targetHotendTemp + "°C.\n"
                                 + "This will ensure that filament is able to flow through the nozzle.".Localize() + "\n"
                                 + "\n"
                                 + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n"
                                 + "Avoid contact with your skin.".Localize(),
                                 0,
                                 temps));
            }

            // show the unloading filament progress bar
            {
                int extruderPriorToUnload = printer.Connection.ActiveExtruderIndex;

                RunningInterval runningGCodeCommands  = null;
                var             unloadingFilamentPage = new WizardPage(this, "Unloading Filament".Localize(), "")
                {
                    PageLoad = (page) =>
                    {
                        page.NextButton.Enabled = false;

                        // add the progress bar
                        var holder = new FlowLayoutWidget()
                        {
                            Margin = new BorderDouble(3, 0, 0, 10),
                        };
                        var progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
                        {
                            FillColor       = theme.PrimaryAccentColor,
                            BorderColor     = theme.TextColor,
                            BackgroundColor = Color.White,
                            VAnchor         = VAnchor.Center,
                        };
                        var progressBarText = new TextWidget("", pointSize: 10, textColor: theme.TextColor)
                        {
                            AutoExpandBoundsToText = true,
                            Margin  = new BorderDouble(5, 0, 0, 0),
                            VAnchor = VAnchor.Center,
                        };
                        holder.AddChild(progressBar);
                        holder.AddChild(progressBarText);
                        page.ContentRow.AddChild(holder);

                        if (extruderCount > 1)
                        {
                            // reset the extruder that was active
                            printer.Connection.QueueLine($"T{extruderIndex}");
                        }

                        // reset the extrusion amount so this is easier to debug
                        printer.Connection.QueueLine("G92 E0");

                        // Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
                        printer.Connection.QueueLine("M302 S1");
                        // send a dwell to empty out the current move commands
                        printer.Connection.QueueLine("G4 P1");
                        // put in a second one to use as a signal for the first being processed
                        printer.Connection.QueueLine("G4 P1");
                        // start heating up the extruder
                        if (extruderIndex == 0)
                        {
                            printer.Connection.SetTargetHotendTemperature(0, printer.Settings.GetValue <double>(SettingsKey.temperature));
                        }
                        else
                        {
                            printer.Connection.SetTargetHotendTemperature(extruderIndex, printer.Settings.GetValue <double>(SettingsKey.temperature + extruderIndex.ToString()));
                        }

                        var loadingSpeedMmPerS     = printer.Settings.GetValue <double>(SettingsKey.load_filament_speed);
                        var loadLengthMm           = Math.Max(1, printer.Settings.GetValue <double>(SettingsKey.unload_filament_length));
                        var remainingLengthMm      = loadLengthMm;
                        var maxSingleExtrudeLength = 20;

                        Stopwatch runningTime   = null;
                        var       expectedTimeS = loadLengthMm / loadingSpeedMmPerS;

                        // push some out first
                        var currentE = printer.Connection.CurrentExtruderDestination;
                        printer.Connection.QueueLine("G1 E{0:0.###} F600".FormatWith(currentE + 15));

                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                if (runningTime == null)
                                {
                                    runningTime = Stopwatch.StartNew();
                                }

                                if (progressBar.RatioComplete < 1 ||
                                    remainingLengthMm >= .001)
                                {
                                    var thisExtrude = Math.Min(remainingLengthMm, maxSingleExtrudeLength);
                                    currentE        = printer.Connection.CurrentExtruderDestination;
                                    printer.Connection.QueueLine("G1 E{0:0.###} F{1}".FormatWith(currentE - thisExtrude, loadingSpeedMmPerS * 60));
                                    // make sure we wait for this command to finish so we can cancel the unload at any time without delay
                                    printer.Connection.QueueLine("G4 P1");
                                    remainingLengthMm        -= thisExtrude;
                                    var elapsedSeconds        = runningTime.Elapsed.TotalSeconds;
                                    progressBar.RatioComplete = Math.Min(1, elapsedSeconds / expectedTimeS);
                                    progressBarText.Text      = $"Unloading Filament: {Math.Max(0, expectedTimeS - elapsedSeconds):0}";
                                }
                            }

                            if (progressBar.RatioComplete == 1 &&
                                remainingLengthMm <= .001)
                            {
                                UiThread.ClearInterval(runningGCodeCommands);
                                page.NextButton.InvokeClick();
                            }
                        },
                                                                    .1);
                    },
                    PageClose = () =>
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };
                unloadingFilamentPage.Closed += (s, e) =>
                {
                    UiThread.ClearInterval(runningGCodeCommands);
                    if (extruderCount > 1)
                    {
                        // reset the extruder that was active
                        printer.Connection.QueueLine($"T{extruderPriorToUnload}");
                    }
                    printer.Connection.QueueLine("G92 E0");
                };

                yield return(unloadingFilamentPage);
            }

            // put up a success message
            yield return(new DoneUnloadingPage(this, extruderIndex));
        }
Пример #12
0
        private IEnumerator <WizardPage> GetPages()
        {
            var extruderCount = printer.Settings.GetValue <int>(SettingsKey.extruder_count);

            var levelingStrings = new LevelingStrings();

            var instructions = "Please select the material you want to load.".Localize();

            if (extruderCount > 1)
            {
                instructions = "Please select the material you want to load into extruder {0}.".Localize().FormatWith(extruderIndex + 1);
            }

            // select the material
            yield return(new SelectMaterialPage(this, "Load Material".Localize(), instructions, "Select".Localize(), extruderIndex, true, showAlreadyLoadedButton)
            {
                WindowTitle = WindowTitle
            });

            var theme = ApplicationController.Instance.Theme;

            // show the trim filament message
            {
                var trimFilamentPage = new WizardPage(this, "Trim Filament".Localize(), "")
                {
                    PageLoad = (page) =>
                    {
                        // start heating up the extruder
                        printer.Connection.SetTargetHotendTemperature(extruderIndex, printer.Settings.GetValue <double>(SettingsKey.temperature));

                        var markdownText   = printer.Settings.GetValue(SettingsKey.trim_filament_markdown);
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        page.ContentRow.AddChild(markdownWidget);
                    }
                };
                yield return(trimFilamentPage);
            }

            if (extruderCount > 1)
            {
                // reset the extruder that was active
                printer.Connection.QueueLine($"T{extruderIndex}");
            }

            // reset the extrusion amount so this is easier to debug
            printer.Connection.QueueLine("G92 E0");

            // show the insert filament page
            {
                RunningInterval runningGCodeCommands = null;
                var             insertFilamentPage   = new WizardPage(this, "Insert Filament".Localize(), "")
                {
                    PageLoad = (page) =>
                    {
                        var markdownText = printer.Settings.GetValue(SettingsKey.insert_filament_markdown2);
                        if (extruderIndex == 1)
                        {
                            markdownText = printer.Settings.GetValue(SettingsKey.insert_filament_1_markdown);
                        }
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        page.ContentRow.AddChild(markdownWidget);

                        // turn off the fan
                        printer.Connection.FanSpeed0To255 = 0;
                        // Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
                        printer.Connection.QueueLine("M302 S1");

                        int maxSecondsToStartLoading = 300;
                        var runningTime = Stopwatch.StartNew();
                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                printer.Connection.MoveRelative(PrinterCommunication.PrinterConnection.Axis.E, 1, 80);
                                // send a dwell to empty out the current move commands
                                printer.Connection.QueueLine("G4 P1");

                                if (runningTime.ElapsedMilliseconds > maxSecondsToStartLoading * 1000)
                                {
                                    UiThread.ClearInterval(runningGCodeCommands);
                                }
                            }
                        },
                                                                    .1);
                    },
                    PageClose = () =>
                    {
                        if (runningGCodeCommands != null)
                        {
                            UiThread.ClearInterval(runningGCodeCommands);
                        }
                    }
                };
                insertFilamentPage.Closed += (s, e) =>
                {
                    if (runningGCodeCommands != null)
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };

                yield return(insertFilamentPage);
            }

            // show the loading filament progress bar
            {
                RunningInterval runningGCodeCommands = null;
                var             loadingFilamentPage  = new WizardPage(this, "Loading Filament".Localize(), "")
                {
                    PageLoad = (page) =>
                    {
                        page.NextButton.Enabled = false;

                        // add the progress bar
                        var holder = new FlowLayoutWidget()
                        {
                            Margin = new BorderDouble(3, 0, 0, 10),
                        };
                        var progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
                        {
                            FillColor       = theme.PrimaryAccentColor,
                            BorderColor     = theme.TextColor,
                            BackgroundColor = Color.White,
                            VAnchor         = VAnchor.Center,
                        };
                        var progressBarText = new TextWidget("", pointSize: 10, textColor: theme.TextColor)
                        {
                            AutoExpandBoundsToText = true,
                            Margin  = new BorderDouble(5, 0, 0, 0),
                            VAnchor = VAnchor.Center,
                        };
                        holder.AddChild(progressBar);
                        holder.AddChild(progressBarText);
                        page.ContentRow.AddChild(holder);

                        // Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
                        printer.Connection.QueueLine("M302 S1");
                        // send a dwell to empty out the current move commands
                        printer.Connection.QueueLine("G4 P1");
                        // put in a second one to use as a signal for the first being processed
                        printer.Connection.QueueLine("G4 P1");
                        // start heating up the extruder
                        printer.Connection.SetTargetHotendTemperature(extruderIndex, printer.Settings.GetValue <double>(SettingsKey.temperature));

                        var loadingSpeedMmPerS     = printer.Settings.GetValue <double>(SettingsKey.load_filament_speed);
                        var loadLengthMm           = Math.Max(1, printer.Settings.GetValue <double>(SettingsKey.load_filament_length));
                        var remainingLengthMm      = loadLengthMm;
                        var maxSingleExtrudeLength = 20;

                        Stopwatch runningTime   = null;
                        var       expectedTimeS = loadLengthMm / loadingSpeedMmPerS;

                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                if (runningTime == null)
                                {
                                    runningTime = Stopwatch.StartNew();
                                }

                                if (progressBar.RatioComplete < 1 ||
                                    remainingLengthMm >= .001)
                                {
                                    var thisExtrude = Math.Min(remainingLengthMm, maxSingleExtrudeLength);
                                    var currentE    = printer.Connection.CurrentExtruderDestination;
                                    printer.Connection.QueueLine("G1 E{0:0.###} F{1}".FormatWith(currentE + thisExtrude, loadingSpeedMmPerS * 60));
                                    // make sure we wait for this command to finish so we can cancel the unload at any time without delay
                                    printer.Connection.QueueLine("G4 P1");
                                    remainingLengthMm        -= thisExtrude;
                                    var elapsedSeconds        = runningTime.Elapsed.TotalSeconds;
                                    progressBar.RatioComplete = Math.Min(1, elapsedSeconds / expectedTimeS);
                                    progressBarText.Text      = $"Loading Filament: {Math.Max(0, expectedTimeS - elapsedSeconds):0}";
                                }
                            }

                            if (progressBar.RatioComplete == 1 &&
                                remainingLengthMm <= .001)
                            {
                                UiThread.ClearInterval(runningGCodeCommands);
                                page.NextButton.InvokeClick();
                            }
                        },
                                                                    .1);
                    },
                    PageClose = () =>
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };
                loadingFilamentPage.Closed += (s, e) =>
                {
                    UiThread.ClearInterval(runningGCodeCommands);
                };

                yield return(loadingFilamentPage);
            }

            // wait for extruder to heat
            {
                var targetHotendTemp = printer.Settings.Helpers.ExtruderTargetTemperature(extruderIndex);
                var temps            = new double[4];
                temps[extruderIndex] = targetHotendTemp;
                yield return(new WaitForTempPage(
                                 this,
                                 "Waiting For Printer To Heat".Localize(),
                                 "Waiting for the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n"
                                 + "This will ensure that filament is able to flow through the nozzle.".Localize() + "\n"
                                 + "\n"
                                 + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n"
                                 + "Avoid contact with your skin.".Localize(),
                                 0,
                                 temps));
            }

            // extrude slowly so that we can prime the extruder
            {
                RunningInterval runningGCodeCommands = null;
                var             runningCleanPage     = new WizardPage(this, "Wait For Running Clean".Localize(), "")
                {
                    PageLoad = (page) =>
                    {
                        var markdownText = printer.Settings.GetValue(SettingsKey.running_clean_markdown2);
                        if (extruderIndex == 1)
                        {
                            markdownText = printer.Settings.GetValue(SettingsKey.running_clean_1_markdown);
                        }
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        page.ContentRow.AddChild(markdownWidget);

                        var runningTime = Stopwatch.StartNew();
                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                printer.Connection.MoveRelative(PrinterCommunication.PrinterConnection.Axis.E, 2, 140);
                                // make sure we wait for this command to finish so we can cancel the unload at any time without delay
                                printer.Connection.QueueLine("G4 P1");
                                int secondsToRun = 90;
                                if (runningTime.ElapsedMilliseconds > secondsToRun * 1000)
                                {
                                    UiThread.ClearInterval(runningGCodeCommands);
                                }
                            }
                        },
                                                                    .1);
                    },
                    PageClose = () =>
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };
                runningCleanPage.Closed += (s, e) =>
                {
                    switch (extruderIndex)
                    {
                    case 0:
                        printer.Settings.SetValue(SettingsKey.filament_has_been_loaded, "1");
                        break;

                    case 1:
                        printer.Settings.SetValue(SettingsKey.filament_1_has_been_loaded, "1");
                        break;
                    }
                    printer.Settings.SetValue(SettingsKey.filament_has_been_loaded, "1");
                };

                yield return(runningCleanPage);
            }

            // put up a success message
            yield return(new DoneLoadingPage(this, extruderIndex));
        }
        public RunningMacroPage(PrinterConfig printer, MacroCommandData macroData, ThemeConfig theme)
            : base("Cancel")
        {
            this.printer     = printer;
            this.WindowTitle = "Running Macro".Localize();
            this.HeaderText  = macroData.title;

            if (macroData.showMaterialSelector)
            {
                contentRow.AddChild(new PresetSelectorWidget(printer, "Material".Localize(), Color.Transparent, NamedSettingsLayers.Material, theme)
                {
                    BackgroundColor = Color.Transparent,
                    Margin          = new BorderDouble(0, 0, 0, 15)
                });
            }

            printer.Connection.LineSent.RegisterEvent(LookForTempRequest, ref unregisterEvents);

            if (macroData.waitOk | macroData.expireTime > 0)
            {
                var okButton = theme.CreateDialogButton("Continue".Localize());
                okButton.Click += (s, e) =>
                {
                    printer.Connection.MacroContinue();
                };

                this.AddPageAction(okButton);
            }

            if (macroData.image != null)
            {
                var imageWidget = new ImageWidget(macroData.image)
                {
                    HAnchor = HAnchor.Center,
                    Margin  = new BorderDouble(5, 15),
                };

                contentRow.AddChild(imageWidget);
            }

            var holder = new FlowLayoutWidget();

            progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
            {
                FillColor       = ActiveTheme.Instance.PrimaryAccentColor,
                BorderColor     = ActiveTheme.Instance.PrimaryTextColor,
                BackgroundColor = Color.White,
                Margin          = new BorderDouble(3, 0, 0, 10),
            };
            progressBarText = new TextWidget("", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
            {
                AutoExpandBoundsToText = true,
                Margin = new BorderDouble(5, 0, 0, 0),
            };
            holder.AddChild(progressBar);
            holder.AddChild(progressBarText);
            contentRow.AddChild(holder);
            progressBar.Visible = false;

            if (macroData.countDown > 0)
            {
                timeToWaitMs    = (long)(macroData.countDown * 1000);
                startTimeMs     = UiThread.CurrentTimerMs;
                runningInterval = UiThread.SetInterval(CountDownTime, .2);
            }
        }
Пример #14
0
        private GuiWidget GetPopupContent(ThemeConfig theme)
        {
            var widget = new IgnoredPopupWidget()
            {
                Width           = 300,
                HAnchor         = HAnchor.Absolute,
                VAnchor         = VAnchor.Fit,
                BackgroundColor = theme.Colors.PrimaryBackgroundColor,
                Padding         = new BorderDouble(12, 0)
            };

            var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit | VAnchor.Top,
            };

            widget.AddChild(container);

            GuiWidget hotendRow;

            container.AddChild(hotendRow = new SettingsItem(
                                   "Heated Bed".Localize(),
                                   theme,
                                   new SettingsItem.ToggleSwitchConfig()
            {
                Checked      = false,
                ToggleAction = (itemChecked) =>
                {
                    var goalTemp = itemChecked ? printer.Settings.GetValue <double>(SettingsKey.bed_temperature) : 0;

                    if (itemChecked)
                    {
                        SetTargetTemperature(goalTemp);
                    }
                    else
                    {
                        SetTargetTemperature(0);
                    }
                }
            },
                                   enforceGutter: false));

            var toggleWidget = hotendRow.Children.Where(o => o is ICheckbox).FirstOrDefault();

            toggleWidget.Name = "Toggle Heater";

            heatToggle = toggleWidget as ICheckbox;

            int tabIndex        = 0;
            var settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All);

            var settingsData   = SettingsOrganizer.Instance.GetSettingsData(SettingsKey.bed_temperature);
            var temperatureRow = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, theme, ref tabIndex);

            SliceSettingsRow.AddBordersToEditFields(temperatureRow);
            container.AddChild(temperatureRow);

            alwaysEnabled.Add(hotendRow);

            // add in the temp graph
            var graph = new DataViewGraph()
            {
                DynamiclyScaleRange = false,
                MinValue            = 0,
                ShowGoal            = true,
                GoalColor           = ActiveTheme.Instance.PrimaryAccentColor,
                GoalValue           = printer.Settings.GetValue <double>(SettingsKey.bed_temperature),
                MaxValue            = 150,   // could come from some profile value in the future
                Width  = widget.Width - 20,
                Height = 35,                 // this works better if it is a common multiple of the Width
                Margin = new BorderDouble(0, 5, 0, 0),
            };

            var runningInterval = UiThread.SetInterval(() =>
            {
                graph.AddData(this.ActualTemperature);
            }, 1);

            this.Closed += (s, e) => runningInterval.Continue = false;

            var valueField  = temperatureRow.Descendants <MHNumberEdit>().FirstOrDefault();
            var settingsRow = temperatureRow.DescendantsAndSelf <SliceSettingsRow>().FirstOrDefault();

            ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
            {
                if (e is StringEventArgs stringEvent)
                {
                    var temp         = printer.Settings.GetValue <double>(SettingsKey.bed_temperature);
                    valueField.Value = temp;
                    graph.GoalValue  = temp;
                    settingsRow.UpdateStyle();
                    if (stringEvent.Data == SettingsKey.bed_temperature &&
                        heatToggle.Checked)
                    {
                        SetTargetTemperature(temp);
                    }
                }
                ;
            }, ref unregisterEvents);

            container.AddChild(graph);

            return(widget);
        }
Пример #15
0
        private GuiWidget GetPopupContent(ThemeConfig menuTheme)
        {
            var widget = new IgnoredPopupWidget()
            {
                Width           = 300,
                HAnchor         = HAnchor.Absolute,
                VAnchor         = VAnchor.Fit,
                Padding         = new BorderDouble(12, 0),
                BackgroundColor = menuTheme.BackgroundColor
            };

            var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit | VAnchor.Top,
            };

            widget.AddChild(container);

            GuiWidget hotendRow;

            container.AddChild(hotendRow = new SettingsItem(
                                   "Heated Bed".Localize(),
                                   menuTheme,
                                   new SettingsItem.ToggleSwitchConfig()
            {
                Checked      = false,
                ToggleAction = (itemChecked) =>
                {
                    var goalTemp = itemChecked ? printer.Settings.GetValue <double>(SettingsKey.bed_temperature) : 0;

                    if (itemChecked)
                    {
                        SetTargetTemperature(goalTemp);
                    }
                    else
                    {
                        SetTargetTemperature(0);
                    }
                }
            },
                                   enforceGutter: false));

            var toggleWidget = hotendRow.Children.Where(o => o is ICheckbox).FirstOrDefault();

            toggleWidget.Name = "Toggle Heater";

            heatToggle = toggleWidget as ICheckbox;

            int tabIndex        = 0;
            var settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All);

            var settingsData   = PrinterSettings.SettingsData[SettingsKey.bed_temperature];
            var temperatureRow = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, menuTheme, ref tabIndex, allUiFields);

            container.AddChild(temperatureRow);

            // Add the temperature row to the always enabled list ensuring the field can be set when disconnected
            alwaysEnabled.Add(temperatureRow);

            // add in the temp graph
            var graph = new DataViewGraph()
            {
                DynamicallyScaleRange = false,
                MinValue  = 0,
                ShowGoal  = true,
                GoalColor = menuTheme.PrimaryAccentColor,
                GoalValue = printer.Settings.GetValue <double>(SettingsKey.bed_temperature),
                MaxValue  = 150,             // could come from some profile value in the future
                Width     = widget.Width - 20,
                Height    = 35,              // this works better if it is a common multiple of the Width
                Margin    = new BorderDouble(0, 5, 0, 0),
            };

            runningInterval = UiThread.SetInterval(() =>
            {
                graph.AddData(this.ActualTemperature);
            }, 1);

            var settingsRow = temperatureRow.DescendantsAndSelf <SliceSettingsRow>().FirstOrDefault();

            void Printer_SettingChanged(object s, StringEventArgs stringEvent)
            {
                if (stringEvent != null)
                {
                    string settingsKey = stringEvent.Data;
                    if (this.allUiFields.TryGetValue(settingsKey, out UIField uifield))
                    {
                        string currentValue = settingsContext.GetValue(settingsKey);
                        if (uifield.Value != currentValue)
                        {
                            uifield.SetValue(
                                currentValue,
                                userInitiated: false);
                        }
                    }

                    if (stringEvent.Data == SettingsKey.bed_temperature)
                    {
                        var temp = printer.Settings.GetValue <double>(SettingsKey.bed_temperature);
                        graph.GoalValue = temp;

                        // TODO: Why is this only when enabled? How does it get set to
                        if (heatToggle.Checked)
                        {
                            // TODO: Why is a UI widget who is listening to model events driving this behavior? What when it's not loaded?
                            SetTargetTemperature(temp);
                        }

                        settingsRow.UpdateStyle();
                    }
                }
            }

            printer.Settings.SettingChanged += Printer_SettingChanged;
            printer.Disposed += (s, e) => printer.Settings.SettingChanged -= Printer_SettingChanged;

            container.AddChild(graph);

            return(widget);
        }
Пример #16
0
        public RunningTaskRow(string title, RunningTaskDetails taskDetails, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.taskDetails = taskDetails;
            this.theme       = theme;

            this.MinimumSize = new Vector2(100 * GuiWidget.DeviceScale, 20 * GuiWidget.DeviceScale);

            var detailsPanel = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
            };

            var rowContainer = new GuiWidget()
            {
                VAnchor = VAnchor.Fit,
                HAnchor = HAnchor.Stretch,
            };

            this.AddChild(rowContainer);

            var topRow = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Padding = 0,
            };

            rowContainer.AddChild(topRow);

            progressBar = new ProgressBar()
            {
                HAnchor     = HAnchor.Stretch,
                Height      = 2 * GuiWidget.DeviceScale,
                VAnchor     = VAnchor.Absolute | VAnchor.Bottom,
                FillColor   = theme.PrimaryAccentColor,
                BorderColor = Color.Transparent,
                Margin      = new BorderDouble(32, 7, theme.ButtonHeight * 2 + 14, 0),
                Visible     = !taskDetails.IsExpanded
            };
            rowContainer.AddChild(progressBar);

            expandButton = new ExpandCheckboxButton(!string.IsNullOrWhiteSpace(title) ? title : taskDetails.Title, theme, 10)
            {
                VAnchor         = VAnchor.Center | VAnchor.Fit,
                HAnchor         = HAnchor.Stretch,
                Checked         = false,
                Padding         = 0,
                AlwaysShowArrow = true
            };
            expandButton.CheckedStateChanged += (s, e) =>
            {
                taskDetails.IsExpanded = expandButton.Checked;
                SetExpansionMode(theme, detailsPanel, expandButton.Checked);
            };
            topRow.AddChild(expandButton);

            GuiWidget resumeButton = null;

            GuiWidget pauseButton = CreateIconOrTextButton("fa-pause_12.png",
                                                           taskDetails.Options?.PauseText,
                                                           taskDetails.Options?.PauseAction,
                                                           taskDetails.Options?.PauseToolTip ?? "Pause".Localize(),
                                                           "",
                                                           theme,
                                                           0);

            if (taskDetails.Options?.IsPaused != null)
            {
                RunningInterval runningInterval = null;
                runningInterval = UiThread.SetInterval(() =>
                {
                    if (taskDetails.Options.IsPaused())
                    {
                        pauseButton.Visible  = false;
                        resumeButton.Visible = true;
                    }
                    else
                    {
                        pauseButton.Visible  = true;
                        resumeButton.Visible = false;
                    }
                    if (this.HasBeenClosed)
                    {
                        UiThread.ClearInterval(runningInterval);
                    }
                }, .2);
            }
            pauseButton.Click += (s, e) =>
            {
                taskDetails.Options?.PauseAction();
                pauseButton.Visible  = false;
                resumeButton.Visible = true;
            };
            topRow.AddChild(pauseButton);


            resumeButton = CreateIconOrTextButton("fa-play_12.png",
                                                  taskDetails.Options?.ResumeText,
                                                  taskDetails.Options?.ResumeAction,
                                                  taskDetails.Options?.ResumeToolTip ?? "Resume".Localize(),
                                                  "Resume Task Button",
                                                  theme,
                                                  0);
            // start with it hidden
            resumeButton.Visible = false;

            resumeButton.Click += (s, e) =>
            {
                taskDetails.Options?.ResumeAction();
                pauseButton.Visible  = true;
                resumeButton.Visible = false;
            };
            topRow.AddChild(resumeButton);

            var stopButton = CreateIconOrTextButton("fa-stop_12.png",
                                                    taskDetails.Options?.StopText,
                                                    taskDetails.Options?.StopAction,
                                                    taskDetails.Options?.StopToolTip ?? "Cancel".Localize(),
                                                    "Stop Task Button",
                                                    theme,
                                                    5);

            stopButton.Enabled = true;

            stopButton.Click += (s, e) =>
            {
                var stopAction = taskDetails.Options?.StopAction;
                if (stopAction == null)
                {
                    taskDetails.CancelTask();
                }
                else
                {
                    stopAction.Invoke(() =>
                    {
                        stopButton.Enabled = true;
                    });
                }

                stopButton.Enabled = false;
            };
            topRow.AddChild(stopButton);

            this.AddChild(detailsPanel);

            // Add rich progress controls
            if (taskDetails.Options?.RichProgressWidget?.Invoke() is GuiWidget guiWidget)
            {
                detailsPanel.AddChild(guiWidget);
            }
            else
            {
                expandButton.Expandable = false;
            }

            if (taskDetails.Options?.ReadOnlyReporting == true)
            {
                stopButton.Visible   = false;
                pauseButton.Visible  = false;
                resumeButton.Visible = false;

                // Ensure the top row is as big as it would be with buttons
                topRow.MinimumSize = new Vector2(0, resumeButton.Height);
            }

            SetExpansionMode(theme, detailsPanel, taskDetails.IsExpanded);

            taskDetails.ProgressChanged += TaskDetails_ProgressChanged;
        }
Пример #17
0
        public static GuiWidget PrintProgressWidget(PrinterConfig printer, ThemeConfig theme)
        {
            var bodyRow = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Top | VAnchor.Fit,
                // BackgroundColor = new Color(theme.Colors.PrimaryBackgroundColor, 128),
                MinimumSize = new Vector2(275, 140),
            };

            // Progress section
            var expandingContainer = new HorizontalSpacer()
            {
                VAnchor = VAnchor.Fit | VAnchor.Center
            };

            bodyRow.AddChild(expandingContainer);

            var topToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                VAnchor = VAnchor.Center | VAnchor.Fit,
                HAnchor = HAnchor.Stretch,
            };

            expandingContainer.AddChild(topToBottom);

            var progressRow = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };

            topToBottom.AddChild(progressRow);

            var progressDial = new ProgressDial(theme)
            {
                HAnchor = HAnchor.Center,
                VAnchor = VAnchor.Center,
                Height  = 200 * DeviceScale,
                Width   = 200 * DeviceScale,
                Name    = "Print Progress Dial"
            };

            progressRow.AddChild(progressDial);

            // create a set of controls to do baby stepping on the first layer
            var babySteppingControls = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Right,
                VAnchor = VAnchor.Center | VAnchor.Fit,
            };

            babySteppingControls.Width = 80 * GuiWidget.DeviceScale;

            progressRow.AddChild(babySteppingControls);

            // add in the move up button
            var babyStepAmount = .02;
            var upButton       = babySteppingControls.AddChild(new IconButton(StaticData.Instance.LoadIcon("Up Arrow.png", 32, 32).SetToColor(theme.TextColor), theme)
            {
                HAnchor          = HAnchor.Center,
                VAnchor          = VAnchor.Absolute,
                Margin           = 0,
                BackgroundRadius = theme.ButtonRadius,
                ToolTipText      = "Raise extruder".Localize() + "\n\n*" + "First layer only".Localize() + "*",
            });

            upButton.Click += (s, e) =>
            {
                printer.Settings.ForTools <double>(SettingsKey.baby_step_z_offset, (key, value, i) =>
                {
                    if (printer.Connection.ActiveExtruderIndex == i)
                    {
                        var currentZ = value + babyStepAmount;
                        printer.Settings.SetValue(key, currentZ.ToString("0.##"));
                    }
                });
            };

            // add in the current position display
            var zTuning = babySteppingControls.AddChild(new ZTuningWidget(printer, theme, false)
            {
                HAnchor = HAnchor.Center | HAnchor.Fit,
                VAnchor = VAnchor.Fit,
                Margin  = new BorderDouble(0, 3, 0, 0),
                Padding = 0,
            });

            babySteppingControls.AddChild(new TextWidget("Z Offset".Localize(), pointSize: 8)
            {
                TextColor = theme.TextColor,
                Margin    = new BorderDouble(0, 0, 0, 3),
                AutoExpandBoundsToText = true,
                HAnchor = HAnchor.Center,
            });

            // add in the move down button
            var downButton = babySteppingControls.AddChild(new IconButton(StaticData.Instance.LoadIcon("Down Arrow.png", 32, 32).SetToColor(theme.TextColor), theme)
            {
                HAnchor          = HAnchor.Center,
                VAnchor          = VAnchor.Absolute,
                Margin           = 0,
                BackgroundRadius = new RadiusCorners(theme.ButtonRadius, theme.ButtonRadius, 0, 0),
                ToolTipText      = "Lower extruder".Localize() + "\n\n*" + "First layer only".Localize() + "*",
            });

            downButton.Click += (s, e) =>
            {
                printer.Settings.ForTools <double>(SettingsKey.baby_step_z_offset, (key, value, i) =>
                {
                    if (printer.Connection.ActiveExtruderIndex == i)
                    {
                        var currentZ = value - babyStepAmount;
                        printer.Settings.SetValue(key, currentZ.ToString("0.##"));
                    }
                });
            };

            // build the bottom row to hold re-slice
            var bottomRow = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };

            topToBottom.AddChild(bottomRow);

            var resliceMessageRow = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Visible = false
            };

            topToBottom.AddChild(resliceMessageRow);

            var timeContainer = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Center | HAnchor.Fit,
                Margin  = 3
            };

            bottomRow.AddChild(timeContainer);

            // we can only reslice on 64 bit, because in 64 bit we always have the gcode loaded
            if (IntPtr.Size == 8 || ApplicationController.Instance.Allow32BitReSlice)
            {
                var resliceButton = new TextButton("Re-Slice", theme)
                {
                    VAnchor     = VAnchor.Center,
                    HAnchor     = HAnchor.Right,
                    Margin      = new BorderDouble(0, 0, 7, 0),
                    Name        = "Re-Slice Button",
                    ToolTipText = "Apply changes to this print".Localize() + "\n\n*" + "Plating and settings changes can be applied".Localize() + "*"
                };
                theme.MakeRoundedButton(resliceButton);
                bool activelySlicing = false;
                resliceButton.Click += (s, e) =>
                {
                    resliceButton.Enabled = false;
                    UiThread.RunOnIdle(async() =>
                    {
                        bool doSlicing = !activelySlicing && printer.Bed.EditContext.SourceItem != null;
                        if (doSlicing)
                        {
                            var errors = printer.ValidateSettings();
                            if (errors.Any(err => err.ErrorLevel == ValidationErrorLevel.Error))
                            {
                                doSlicing = false;
                                ApplicationController.Instance.ShowValidationErrors("Slicing Error".Localize(), errors);
                            }
                        }

                        if (doSlicing)
                        {
                            activelySlicing = true;
                            if (bottomRow.Name == null)
                            {
                                bottomRow.Name = await printer.Bed.EditContext.GCodeFilePath(printer);
                            }

                            await ApplicationController.Instance.Tasks.Execute("Saving".Localize(), printer, printer.Bed.SaveChanges);

                            // start up a new slice on a background thread
                            await ApplicationController.Instance.SliceItemLoadOutput(
                                printer,
                                printer.Bed.Scene,
                                await printer.Bed.EditContext.GCodeFilePath(printer));

                            // Switch to the 3D layer view if on Model view
                            if (printer.ViewState.ViewMode == PartViewMode.Model)
                            {
                                printer.ViewState.ViewMode = PartViewMode.Layers3D;
                            }

                            resliceMessageRow.Visible = true;
                            resliceMessageRow.VAnchor = VAnchor.Absolute;
                            resliceMessageRow.VAnchor = VAnchor.Fit;
                        }
                        else
                        {
                            resliceButton.Enabled = true;
                        }
                    });
                };
                bottomRow.AddChild(resliceButton);

                // setup the message row
                {
                    // when it is done queue it to the change to gcode stream
                    var switchMessage = "Switch to new G-Code?\n\nBefore you switch, check that you are seeing the changes you expect.".Localize();
                    resliceMessageRow.AddChild(new WrappedTextWidget(switchMessage, theme.DefaultFontSize, textColor: theme.TextColor)
                    {
                        Margin = new BorderDouble(7, 3)
                    });

                    var switchButtonRow = new FlowLayoutWidget(FlowDirection.RightToLeft)
                    {
                        HAnchor = HAnchor.Stretch
                    };

                    resliceMessageRow.AddChild(switchButtonRow);

                    var switchButton = new TextButton("Switch", theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(5),
                        Name    = "Switch Button"
                    };
                    theme.MakeRoundedButton(switchButton);

                    switchButtonRow.AddChild(switchButton);
                    switchButton.Click += async(s, e) =>
                    {
                        if (printer.Connection != null &&
                            (printer.Connection.Printing || printer.Connection.Paused))
                        {
                            printer.Connection.SwitchToGCode(await printer.Bed.EditContext.GCodeFilePath(printer));
                            bottomRow.Name = await printer.Bed.EditContext.GCodeFilePath(printer);
                        }

                        activelySlicing           = false;
                        resliceButton.Enabled     = true;
                        resliceMessageRow.Visible = false;
                    };

                    var cancelButton = new TextButton("Cancel", theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(0, 5),
                        Name    = "Cancel Re-Slice Button"
                    };
                    theme.MakeRoundedButton(cancelButton);

                    switchButtonRow.AddChild(cancelButton);
                    cancelButton.Click += async(s, e) =>
                    {
                        await ApplicationController.Instance.SliceItemLoadOutput(
                            printer,
                            printer.Bed.Scene,
                            bottomRow.Name);

                        activelySlicing           = false;
                        resliceButton.Enabled     = true;
                        resliceMessageRow.Visible = false;
                    };
                }
            }

            timeContainer.AddChild(new ImageWidget(StaticData.Instance.LoadIcon("fa-clock_24.png", 24, 24).SetToColor(theme.TextColor))
            {
                VAnchor = VAnchor.Center
            });

            var timeStack = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                Margin  = new BorderDouble(10, 0, 0, 0),
                Padding = new BorderDouble(5, 0, 0, 0),
                VAnchor = VAnchor.Center | VAnchor.Fit
            };

            timeContainer.AddChild(timeStack);

            var timePrinted = new TextWidget("", pointSize: 16, textColor: theme.TextColor)
            {
                AutoExpandBoundsToText = true,
                HAnchor = HAnchor.Center,
            };

            timeStack.AddChild(timePrinted);

            var timeToEnd = new TextWidget("", pointSize: 9, textColor: theme.TextColor)
            {
                AutoExpandBoundsToText = true,
                HAnchor = HAnchor.Center,
            };

            timeStack.AddChild(timeToEnd);

            var runningInterval = UiThread.SetInterval(() =>
            {
                int totalSecondsPrinted = printer.Connection.SecondsPrinted;

                int hoursPrinted   = totalSecondsPrinted / (60 * 60);
                int minutesPrinted = totalSecondsPrinted / 60 - hoursPrinted * 60;
                var secondsPrinted = totalSecondsPrinted % 60;

                // TODO: Consider if the consistency of a common time format would look and feel better than changing formats based on elapsed duration
                timePrinted.Text = GetFormatedTime(hoursPrinted, minutesPrinted, secondsPrinted);

                int totalSecondsToEnd = printer.Connection.SecondsToEnd;

                int hoursToEnd   = totalSecondsToEnd / (60 * 60);
                int minutesToEnd = totalSecondsToEnd / 60 - hoursToEnd * 60;
                var secondsToEnd = totalSecondsToEnd % 60;

                timeToEnd.Text = GetFormatedTime(hoursToEnd, minutesToEnd, secondsToEnd);

                progressDial.LayerIndex = printer.Connection.CurrentlyPrintingLayer;
                if (progressDial.LayerIndex > 0)
                {
                    babySteppingControls.Visible = false;
                }

                progressDial.LayerCompletedRatio = printer.Connection.RatioIntoCurrentLayerSeconds;
                progressDial.CompletedRatio      = printer.Connection.PercentComplete / 100;

                switch (printer.Connection.CommunicationState)
                {
                case CommunicationStates.PreparingToPrint:
                case CommunicationStates.Printing:
                case CommunicationStates.Paused:
                    bodyRow.Visible = true;
                    break;

                default:
                    bodyRow.Visible = false;
                    break;
                }
            }, 1);

            bodyRow.Closed += (s, e) => UiThread.ClearInterval(runningInterval);

            bodyRow.Visible = false;

            return(bodyRow);
        }
Пример #18
0
        protected override IEnumerator <PrinterSetupWizardPage> GetWizardSteps()
        {
            var levelingStrings = new LevelingStrings(printer.Settings);

            var title        = "Select Material".Localize();
            var instructions = "Please select the material you will be printing with.".Localize();

            if (onlyLoad)
            {
                title        = "Load Material".Localize();
                instructions = "Please select the material you want to load.".Localize();
            }

            // select the material
            yield return(new SelectMaterialPage(this, title, instructions, onlyLoad ? "Load".Localize() : "Select".Localize(), onlyLoad));

            var theme = ApplicationController.Instance.Theme;

            // show the trim filament message
            {
                PrinterSetupWizardPage trimFilamentPage = null;
                trimFilamentPage = new PrinterSetupWizardPage(
                    this,
                    "Trim Filament".Localize(),
                    "")
                {
                    BecomingActive = () =>
                    {
                        // start heating up the extruder
                        printer.Connection.SetTargetHotendTemperature(0, printer.Settings.GetValue <double>(SettingsKey.temperature));

                        var markdownText   = printer.Settings.GetValue(SettingsKey.trim_filament_markdown);
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        trimFilamentPage.ContentRow.AddChild(markdownWidget);
                    }
                };
                yield return(trimFilamentPage);
            }

            // show the insert filament page
            {
                RunningInterval        runningGCodeCommands = null;
                PrinterSetupWizardPage insertFilamentPage   = null;
                insertFilamentPage = new PrinterSetupWizardPage(
                    this,
                    "Insert Filament".Localize(),
                    "")
                {
                    BecomingActive = () =>
                    {
                        var markdownText   = printer.Settings.GetValue(SettingsKey.insert_filament_markdown2);
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        insertFilamentPage.ContentRow.AddChild(markdownWidget);

                        // turn off the fan
                        printer.Connection.FanSpeed0To255 = 0;
                        // Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
                        printer.Connection.QueueLine("M302 S1");

                        var runningTime = Stopwatch.StartNew();
                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                printer.Connection.MoveRelative(PrinterCommunication.PrinterConnection.Axis.E, .2, 80);
                                int secondsToRun = 300;
                                if (runningTime.ElapsedMilliseconds > secondsToRun * 1000)
                                {
                                    UiThread.ClearInterval(runningGCodeCommands);
                                }
                            }
                        },
                                                                    .1);
                    },
                    BecomingInactive = () =>
                    {
                        if (runningGCodeCommands != null)
                        {
                            UiThread.ClearInterval(runningGCodeCommands);
                        }
                    }
                };
                insertFilamentPage.Closed += (s, e) =>
                {
                    if (runningGCodeCommands != null)
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };

                yield return(insertFilamentPage);
            }

            // show the loading filament progress bar
            {
                RunningInterval        runningGCodeCommands = null;
                PrinterSetupWizardPage loadingFilamentPage  = null;
                loadingFilamentPage = new PrinterSetupWizardPage(
                    this,
                    "Loading Filament".Localize(),
                    "")
                {
                    BecomingActive = () =>
                    {
                        loadingFilamentPage.NextButton.Enabled = false;

                        // add the progress bar
                        var holder = new FlowLayoutWidget()
                        {
                            Margin = new BorderDouble(3, 0, 0, 10),
                        };
                        var progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
                        {
                            FillColor       = theme.PrimaryAccentColor,
                            BorderColor     = theme.TextColor,
                            BackgroundColor = Color.White,
                            VAnchor         = VAnchor.Center,
                        };
                        var progressBarText = new TextWidget("", pointSize: 10, textColor: theme.TextColor)
                        {
                            AutoExpandBoundsToText = true,
                            Margin  = new BorderDouble(5, 0, 0, 0),
                            VAnchor = VAnchor.Center,
                        };
                        holder.AddChild(progressBar);
                        holder.AddChild(progressBarText);
                        loadingFilamentPage.ContentRow.AddChild(holder);

                        // Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
                        printer.Connection.QueueLine("M302 S1");
                        // send a dwel to empty out the current move commands
                        printer.Connection.QueueLine("G4 P1");
                        // put in a second one to use as a signal for the first being processed
                        printer.Connection.QueueLine("G4 P1");
                        // start heating up the extruder
                        printer.Connection.SetTargetHotendTemperature(0, printer.Settings.GetValue <double>(SettingsKey.temperature));

                        var loadingSpeedMmPerS     = printer.Settings.GetValue <double>(SettingsKey.load_filament_speed);
                        var loadLengthMm           = Math.Max(1, printer.Settings.GetValue <double>(SettingsKey.load_filament_length));
                        var remainingLengthMm      = loadLengthMm;
                        var maxSingleExtrudeLength = 20;

                        Stopwatch runningTime   = null;
                        var       expectedTimeS = loadLengthMm / loadingSpeedMmPerS;

                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                if (runningTime == null)
                                {
                                    runningTime = Stopwatch.StartNew();
                                }

                                if (progressBar.RatioComplete < 1)
                                {
                                    var thisExtrude = Math.Min(remainingLengthMm, maxSingleExtrudeLength);
                                    var currentE    = printer.Connection.CurrentExtruderDestination;
                                    printer.Connection.QueueLine("G1 E{0:0.###} F{1}".FormatWith(currentE + thisExtrude, loadingSpeedMmPerS * 60));
                                    remainingLengthMm        -= thisExtrude;
                                    var elapsedSeconds        = runningTime.Elapsed.TotalSeconds;
                                    progressBar.RatioComplete = Math.Min(1, elapsedSeconds / expectedTimeS);
                                    progressBarText.Text      = $"Loading Filament: {Math.Max(0, expectedTimeS - elapsedSeconds):0}";
                                }
                            }

                            if (progressBar.RatioComplete == 1 &&
                                remainingLengthMm <= .001)
                            {
                                UiThread.ClearInterval(runningGCodeCommands);
                                loadingFilamentPage.NextButton.InvokeClick();
                            }
                        },
                                                                    .1);
                    },
                    BecomingInactive = () =>
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };
                loadingFilamentPage.Closed += (s, e) =>
                {
                    UiThread.ClearInterval(runningGCodeCommands);
                };

                yield return(loadingFilamentPage);
            }

            // wait for extruder to heat
            {
                double targetHotendTemp = printer.Settings.Helpers.ExtruderTemperature(0);
                yield return(new WaitForTempPage(
                                 this,
                                 "Waiting For Printer To Heat".Localize(),
                                 "Waiting for the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n"
                                 + "This will ensure that filament is able to flow through the nozzle.".Localize() + "\n"
                                 + "\n"
                                 + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n"
                                 + "Avoid contact with your skin.".Localize(),
                                 0,
                                 targetHotendTemp));
            }

            // extrude slowly so that we can prime the extruder
            {
                RunningInterval        runningGCodeCommands = null;
                PrinterSetupWizardPage runningCleanPage     = null;
                runningCleanPage = new PrinterSetupWizardPage(
                    this,
                    "Wait For Running Clean".Localize(),
                    "")
                {
                    BecomingActive = () =>
                    {
                        var markdownText   = printer.Settings.GetValue(SettingsKey.running_clean_markdown2);
                        var markdownWidget = new MarkdownWidget(theme);
                        markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
                        runningCleanPage.ContentRow.AddChild(markdownWidget);

                        var runningTime = Stopwatch.StartNew();
                        runningGCodeCommands = UiThread.SetInterval(() =>
                        {
                            if (printer.Connection.NumQueuedCommands == 0)
                            {
                                printer.Connection.MoveRelative(PrinterCommunication.PrinterConnection.Axis.E, .35, 140);
                                int secondsToRun = 90;
                                if (runningTime.ElapsedMilliseconds > secondsToRun * 1000)
                                {
                                    UiThread.ClearInterval(runningGCodeCommands);
                                }
                            }
                        },
                                                                    .1);
                    },
                    BecomingInactive = () =>
                    {
                        UiThread.ClearInterval(runningGCodeCommands);
                    }
                };
                runningCleanPage.Closed += (s, e) =>
                {
                    UiThread.ClearInterval(runningGCodeCommands);
                    printer.Settings.SetValue(SettingsKey.filament_has_been_loaded, "1");
                };

                yield return(runningCleanPage);
            }

            // put up a success message
            PrinterSetupWizardPage finalPage = null;

            finalPage = new PrinterSetupWizardPage(this, "Success".Localize(), "Success!\n\nYour filament should now be loaded".Localize())
            {
                BecomingActive = () =>
                {
                    finalPage.ShowWizardFinished();
                }
            };

            yield return(finalPage);
        }
Пример #19
0
        public static GuiWidget PrintProgressWidget(PrinterConfig printer, ThemeConfig theme)
        {
            var bodyRow = new GuiWidget()
            {
                HAnchor = HAnchor.Fit | HAnchor.Center,
                VAnchor = VAnchor.Top | VAnchor.Fit,
                //BackgroundColor = new Color(theme.Colors.PrimaryBackgroundColor, 128),
                MinimumSize = new Vector2(275, 140),
                Selectable  = false
            };

            // Progress section
            var expandingContainer = new HorizontalSpacer()
            {
                VAnchor = VAnchor.Fit | VAnchor.Center
            };

            bodyRow.AddChild(expandingContainer);

            var progressContainer = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                Margin  = new BorderDouble(50, 0),
                VAnchor = VAnchor.Center | VAnchor.Fit,
                HAnchor = HAnchor.Center | HAnchor.Fit,
            };

            expandingContainer.AddChild(progressContainer);

            var progressDial = new ProgressDial()
            {
                HAnchor = HAnchor.Center,
                Height  = 200 * DeviceScale,
                Width   = 200 * DeviceScale
            };

            progressContainer.AddChild(progressDial);

            var timeContainer = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Center | HAnchor.Fit,
                Margin  = 3
            };

            progressContainer.AddChild(timeContainer);

            timeContainer.AddChild(new ImageWidget(AggContext.StaticData.LoadIcon("fa-clock_24.png", theme.InvertIcons))
            {
                VAnchor = VAnchor.Center
            });

            var timeWidget = new TextWidget("", pointSize: 22, textColor: theme.Colors.PrimaryTextColor)
            {
                AutoExpandBoundsToText = true,
                Margin  = new BorderDouble(10, 0, 0, 0),
                VAnchor = VAnchor.Center,
            };

            timeContainer.AddChild(timeWidget);

            var runningInterval = UiThread.SetInterval(
                () =>
            {
                int secondsPrinted = printer.Connection.SecondsPrinted;
                int hoursPrinted   = (int)(secondsPrinted / (60 * 60));
                int minutesPrinted = (secondsPrinted / 60 - hoursPrinted * 60);

                secondsPrinted = secondsPrinted % 60;

                // TODO: Consider if the consistency of a common time format would look and feel better than changing formats based on elapsed duration
                timeWidget.Text = (hoursPrinted <= 0) ? $"{minutesPrinted}:{secondsPrinted:00}" : $"{hoursPrinted}:{minutesPrinted:00}:{secondsPrinted:00}";

                progressDial.LayerIndex          = printer.Connection.CurrentlyPrintingLayer;
                progressDial.LayerCompletedRatio = printer.Connection.RatioIntoCurrentLayer;
                progressDial.CompletedRatio      = printer.Connection.PercentComplete / 100;

                switch (printer.Connection.CommunicationState)
                {
                case CommunicationStates.PreparingToPrint:
                case CommunicationStates.Printing:
                case CommunicationStates.Paused:
                    bodyRow.Visible = true;
                    break;

                default:
                    bodyRow.Visible = false;
                    break;
                }
            }, 1);

            bodyRow.Closed += (s, e) => runningInterval.Continue = false;

            bodyRow.Visible = false;

            return(bodyRow);
        }
Пример #20
0
        public RunningTaskRow(string title, RunningTaskDetails taskDetails, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.taskDetails = taskDetails;
            this.theme       = theme;

            this.MinimumSize = new Vector2(100, 20);

            var detailsPanel = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
            };

            var rowContainer = new GuiWidget()
            {
                VAnchor = VAnchor.Fit,
                HAnchor = HAnchor.Stretch,
            };

            this.AddChild(rowContainer);

            var topRow = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Padding = 0,
            };

            rowContainer.AddChild(topRow);

            progressBar = new ProgressBar()
            {
                HAnchor         = HAnchor.Stretch,
                Height          = 2,
                VAnchor         = VAnchor.Absolute | VAnchor.Bottom,
                FillColor       = ActiveTheme.Instance.PrimaryAccentColor,
                BorderColor     = Color.Transparent,
                BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor,
                Margin          = new BorderDouble(32, 7, theme.ButtonHeight * 2 + 14, 0),
            };
            rowContainer.AddChild(progressBar);

            expandButton = new ExpandCheckboxButton(!string.IsNullOrWhiteSpace(title) ? title : taskDetails.Title, theme, 10)
            {
                VAnchor = VAnchor.Center | VAnchor.Fit,
                HAnchor = HAnchor.Stretch,
                Checked = false,
                Padding = 0
            };
            expandButton.CheckedStateChanged += (s, e) =>
            {
                taskDetails.IsExpanded = expandButton.Checked;
                SetExpansionMode(theme, detailsPanel, expandButton.Checked);
            };
            topRow.AddChild(expandButton);

            IconButton resumeButton = null;

            var pauseButton = new IconButton(AggContext.StaticData.LoadIcon("fa-pause_12.png", theme.InvertIcons), theme)
            {
                Margin      = theme.ButtonSpacing,
                Enabled     = taskDetails.Options?.PauseAction != null,
                ToolTipText = taskDetails.Options?.PauseToolTip ?? "Pause".Localize()
            };

            if (taskDetails.Options?.IsPaused != null)
            {
                RunningInterval runningInterval = null;
                runningInterval = UiThread.SetInterval(() =>
                {
                    if (taskDetails.Options.IsPaused())
                    {
                        pauseButton.Visible  = false;
                        resumeButton.Visible = true;
                    }
                    else
                    {
                        pauseButton.Visible  = true;
                        resumeButton.Visible = false;
                    }
                    if (this.HasBeenClosed)
                    {
                        runningInterval.Continue = false;
                    }
                }, .2);
            }
            pauseButton.Click += (s, e) =>
            {
                taskDetails.Options?.PauseAction();
                pauseButton.Visible  = false;
                resumeButton.Visible = true;
            };
            topRow.AddChild(pauseButton);

            resumeButton = new IconButton(AggContext.StaticData.LoadIcon("fa-play_12.png", theme.InvertIcons), theme)
            {
                Visible     = false,
                Margin      = theme.ButtonSpacing,
                ToolTipText = taskDetails.Options?.ResumeToolTip ?? "Resume".Localize(),
                Name        = "Resume Task Button"
            };
            resumeButton.Click += (s, e) =>
            {
                taskDetails.Options?.ResumeAction();
                pauseButton.Visible  = true;
                resumeButton.Visible = false;
            };
            topRow.AddChild(resumeButton);

            var stopButton = new IconButton(AggContext.StaticData.LoadIcon("fa-stop_12.png", theme.InvertIcons), theme)
            {
                Margin      = theme.ButtonSpacing,
                Name        = "Stop Task Button",
                ToolTipText = taskDetails.Options?.StopToolTip ?? "Cancel".Localize()
            };

            stopButton.Click += (s, e) =>
            {
                var stopAction = taskDetails.Options?.StopAction;
                if (stopAction == null)
                {
                    taskDetails.CancelTask();
                }
                else
                {
                    stopAction.Invoke();
                }
            };
            topRow.AddChild(stopButton);

            this.AddChild(detailsPanel);

            // Add rich progress controls
            if (taskDetails.Options?.RichProgressWidget?.Invoke() is GuiWidget guiWidget)
            {
                detailsPanel.AddChild(guiWidget);
            }

            if (taskDetails.Options?.ReadOnlyReporting == true)
            {
                stopButton.Visible   = false;
                pauseButton.Visible  = false;
                resumeButton.Visible = false;

                // Ensure the top row is as big as it would be with buttons
                topRow.MinimumSize = new Vector2(0, resumeButton.Height);
            }

            SetExpansionMode(theme, detailsPanel, taskDetails.IsExpanded);

            taskDetails.ProgressChanged += TaskDetails_ProgressChanged;
        }
Пример #21
0
        public PartPreviewContent(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.AnchorAll();

            var extensionArea = new LeftClipFlowLayoutWidget()
            {
                BackgroundColor = theme.TabBarBackground,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(left: 8)
            };

            tabControl = new ChromeTabs(extensionArea, theme)
            {
                VAnchor         = VAnchor.Stretch,
                HAnchor         = HAnchor.Stretch,
                BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor,
                BorderColor     = theme.MinimalShade,
                Border          = new BorderDouble(left: 1),
                NewTabPage      = () =>
                {
                    return(new StartTabPage(this, theme));
                }
            };
            tabControl.ActiveTabChanged += (s, e) =>
            {
                if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage)
                {
                    var dragDropData = ApplicationController.Instance.DragDropData;

                    // Set reference on tab change
                    dragDropData.View3DWidget = tabPage.view3DWidget;
                    dragDropData.SceneContext = tabPage.sceneContext;
                }
            };

            // Force the ActionArea to be as high as ButtonHeight
            tabControl.TabBar.ActionArea.MinimumSize = new Vector2(0, theme.ButtonHeight);
            tabControl.TabBar.BackgroundColor        = theme.TabBarBackground;
            tabControl.TabBar.BorderColor            = theme.ActiveTabColor;

            // Force common padding into top region
            tabControl.TabBar.Padding = theme.TabbarPadding.Clone(top: theme.TabbarPadding.Top * 2, bottom: 0);

            // add in a what's new button
            var seeWhatsNewButton = new LinkLabel("What's New...".Localize(), theme)
            {
                Name        = "What's New Link",
                ToolTipText = "See what's new in this version of MatterControl".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0),
                TextColor   = theme.Colors.PrimaryTextColor
            };

            seeWhatsNewButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UserSettings.Instance.set(UserSettingsKey.LastReadWhatsNew, JsonConvert.SerializeObject(DateTime.Now));
                DialogWindow.Show(new HelpPage("What's New"));
            });

            tabControl.TabBar.ActionArea.AddChild(seeWhatsNewButton);

            // add in the update available button
            var updateAvailableButton = new LinkLabel("Update Available".Localize(), theme)
            {
                Visible = false,
            };

            // make the function inline so we don't have to create members for the buttons
            EventHandler SetLinkButtonsVisibility = (s, e) =>
            {
                if (UserSettings.Instance.HasLookedAtWhatsNew())
                {
                    // hide it
                    seeWhatsNewButton.Visible = false;
                }

                if (UpdateControlData.Instance.UpdateStatus == UpdateControlData.UpdateStatusStates.UpdateAvailable)
                {
                    updateAvailableButton.Visible = true;
                    // if we are going to show the update link hide the whats new link no matter what
                    seeWhatsNewButton.Visible = false;
                }
                else
                {
                    updateAvailableButton.Visible = false;
                }
            };

            UserSettings.Instance.Changed += SetLinkButtonsVisibility;
            Closed += (s, e) => UserSettings.Instance.Changed -= SetLinkButtonsVisibility;

            RunningInterval showUpdateInterval = null;

            updateAvailableButton.VisibleChanged += (s, e) =>
            {
                if (!updateAvailableButton.Visible)
                {
                    if (showUpdateInterval != null)
                    {
                        showUpdateInterval.Continue = false;
                        showUpdateInterval          = null;
                    }
                    return;
                }

                showUpdateInterval = UiThread.SetInterval(() =>
                {
                    double displayTime  = 1;
                    double pulseTime    = 1;
                    double totalSeconds = 0;
                    var textWidgets     = updateAvailableButton.Descendants <TextWidget>().Where((w) => w.Visible == true).ToArray();
                    Color startColor    = theme.Colors.PrimaryTextColor;
                    // Show a highlight on the button as the user did not click it
                    Animation flashBackground = null;
                    flashBackground           = new Animation()
                    {
                        DrawTarget      = updateAvailableButton,
                        FramesPerSecond = 10,
                        Update          = (s1, updateEvent) =>
                        {
                            totalSeconds += updateEvent.SecondsPassed;
                            if (totalSeconds < displayTime)
                            {
                                double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                                var color    = new Color(startColor, (int)((1 - blend) * 255));
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = color;
                                }
                            }
                            else
                            {
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = startColor;
                                }
                                flashBackground.Stop();
                            }
                        }
                    };
                    flashBackground.Start();
                }, 120);
            };

            updateAvailableButton.Name = "Update Available Link";
            SetLinkButtonsVisibility(this, null);
            updateAvailableButton.ToolTipText = "There is a new update available for download".Localize();
            updateAvailableButton.VAnchor     = VAnchor.Center;
            updateAvailableButton.Margin      = new BorderDouble(10, 0);
            updateAvailableButton.Click      += (s, e) => UiThread.RunOnIdle(() =>
            {
                UiThread.RunOnIdle(() =>
                {
                    UpdateControlData.Instance.CheckForUpdate();
                    DialogWindow.Show <CheckForUpdatesPage>();
                });
            });

            tabControl.TabBar.ActionArea.AddChild(updateAvailableButton);

            UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent(SetLinkButtonsVisibility, ref unregisterEvents);

            this.AddChild(tabControl);

            ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
            {
                if (e is StringEventArgs stringEvent &&
                    stringEvent.Data == SettingsKey.printer_name &&
                    printerTab != null)
                {
                    printerTab.Text = ActiveSliceSettings.Instance.GetValue(SettingsKey.printer_name);
                }
            }, ref unregisterEvents);

            ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
            {
                var activePrinter = ApplicationController.Instance.ActivePrinter;

                // If ActivePrinter has been nulled and a printer tab is open, close it
                var tab1 = tabControl.AllTabs.Skip(1).FirstOrDefault();
                if ((activePrinter == null || !activePrinter.Settings.PrinterSelected) &&
                    tab1?.TabContent is PrinterTabPage)
                {
                    tabControl.RemoveTab(tab1);
                }
                else
                {
                    this.CreatePrinterTab(activePrinter, theme);
                }
            }, ref unregisterEvents);

            ApplicationController.Instance.NotifyPrintersTabRightElement(extensionArea);

            // Show fixed start page
            tabControl.AddTab(
                new ChromeTab("Start".Localize(), tabControl, tabControl.NewTabPage(), theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Start Tab",
                Padding     = new BorderDouble(15, 0)
            });

            // Add a tab for the current printer
            if (ActiveSliceSettings.Instance.PrinterSelected)
            {
                this.CreatePrinterTab(ApplicationController.Instance.ActivePrinter, theme);
            }

            // Restore active tabs
            foreach (var bed in ApplicationController.Instance.Workspaces)
            {
                this.CreatePartTab("New Part", bed, theme);
            }
        }
Пример #22
0
        public static GuiWidget PrintProgressWidget(PrinterConfig printer, ThemeConfig theme)
        {
            var bodyRow = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Top | VAnchor.Fit,
                //BackgroundColor = new Color(theme.Colors.PrimaryBackgroundColor, 128),
                MinimumSize = new Vector2(275, 140),
            };

            // Progress section
            var expandingContainer = new HorizontalSpacer()
            {
                VAnchor = VAnchor.Fit | VAnchor.Center
            };

            bodyRow.AddChild(expandingContainer);

            var progressContainer = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                VAnchor = VAnchor.Center | VAnchor.Fit,
                HAnchor = HAnchor.Stretch,
            };

            expandingContainer.AddChild(progressContainer);

            var progressDial = new ProgressDial(theme)
            {
                HAnchor = HAnchor.Center,
                Height  = 200 * DeviceScale,
                Width   = 200 * DeviceScale
            };

            progressContainer.AddChild(progressDial);

            var bottomRow = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };

            progressContainer.AddChild(bottomRow);

            var resliceMessageRow = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                Visible = false
            };

            progressContainer.AddChild(resliceMessageRow);

            var timeContainer = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Center | HAnchor.Fit,
                Margin  = 3
            };

            bottomRow.AddChild(timeContainer);

            // we can only reslice on 64 bit, because in 64 bit we always have the gcode loaded
            if (IntPtr.Size == 8)
            {
                var resliceButton = new TextButton("Re-Slice", theme)
                {
                    HAnchor = HAnchor.Right,
                    VAnchor = VAnchor.Center,
                    Margin  = new BorderDouble(0, 0, 7, 0),
                    Name    = "Re-Slice Button"
                };
                bool activelySlicing = false;
                resliceButton.Click += (s, e) =>
                {
                    resliceButton.Enabled = false;
                    UiThread.RunOnIdle(async() =>
                    {
                        bool doSlicing = !activelySlicing && printer.Bed.EditContext.SourceItem != null;
                        if (doSlicing)
                        {
                            var errors = printer.ValidateSettings();
                            if (errors.Any(err => err.ErrorLevel == ValidationErrorLevel.Error))
                            {
                                doSlicing = false;
                                ApplicationController.Instance.ShowValidationErrors("Slicing Error".Localize(), errors);
                            }
                        }

                        if (doSlicing)
                        {
                            activelySlicing = true;
                            if (bottomRow.Name == null)
                            {
                                bottomRow.Name = printer.Bed.EditContext.GCodeFilePath(printer);
                            }

                            await ApplicationController.Instance.Tasks.Execute("Saving".Localize(), printer, printer.Bed.SaveChanges);

                            // start up a new slice on a background thread
                            await ApplicationController.Instance.SliceItemLoadOutput(
                                printer,
                                printer.Bed.Scene,
                                printer.Bed.EditContext.GCodeFilePath(printer));

                            // Switch to the 3D layer view if on Model view
                            if (printer.ViewState.ViewMode == PartViewMode.Model)
                            {
                                printer.ViewState.ViewMode = PartViewMode.Layers3D;
                            }

                            resliceMessageRow.Visible = true;
                            resliceMessageRow.VAnchor = VAnchor.Absolute;
                            resliceMessageRow.VAnchor = VAnchor.Fit;
                        }
                        else
                        {
                            resliceButton.Enabled = true;
                        }
                    });
                };
                bottomRow.AddChild(resliceButton);

                // setup the message row
                {
                    // when it is done queue it to the change to gcode stream
                    var switchMessage = "Switch to new G-Code?\n\nBefore you switch, check that your are seeing the changes you expect.".Localize();
                    resliceMessageRow.AddChild(new WrappedTextWidget(switchMessage, theme.DefaultFontSize, textColor: theme.TextColor)
                    {
                        Margin = new BorderDouble(7, 3)
                    });

                    var switchButtonRow = new FlowLayoutWidget(FlowDirection.RightToLeft)
                    {
                        HAnchor = HAnchor.Stretch
                    };

                    resliceMessageRow.AddChild(switchButtonRow);

                    var switchButton = new TextButton("Switch", theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(5),
                        Name    = "Switch Button"
                    };
                    switchButtonRow.AddChild(switchButton);
                    switchButton.Click += (s, e) =>
                    {
                        if (printer.Connection != null &&
                            (printer.Connection.Printing || printer.Connection.Paused))
                        {
                            printer.Connection.SwitchToGCode(printer.Bed.EditContext.GCodeFilePath(printer));
                            bottomRow.Name = printer.Bed.EditContext.GCodeFilePath(printer);
                        }

                        activelySlicing           = false;
                        resliceButton.Enabled     = true;
                        resliceMessageRow.Visible = false;
                    };

                    var cancelButton = new TextButton("Cancel", theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(5),
                        Name    = "Cancel Re-Slice Button"
                    };
                    switchButtonRow.AddChild(cancelButton);
                    cancelButton.Click += async(s, e) =>
                    {
                        await ApplicationController.Instance.SliceItemLoadOutput(
                            printer,
                            printer.Bed.Scene,
                            bottomRow.Name);

                        activelySlicing           = false;
                        resliceButton.Enabled     = true;
                        resliceMessageRow.Visible = false;
                    };
                }
            }

            timeContainer.AddChild(new ImageWidget(AggContext.StaticData.LoadIcon("fa-clock_24.png", theme.InvertIcons))
            {
                VAnchor = VAnchor.Center
            });

            var timeWidget = new TextWidget("", pointSize: 22, textColor: theme.TextColor)
            {
                AutoExpandBoundsToText = true,
                Margin  = new BorderDouble(10, 0, 0, 0),
                VAnchor = VAnchor.Center,
            };

            timeContainer.AddChild(timeWidget);

            var runningInterval = UiThread.SetInterval(
                () =>
            {
                int secondsPrinted = printer.Connection.SecondsPrinted;
                int hoursPrinted   = (int)(secondsPrinted / (60 * 60));
                int minutesPrinted = (secondsPrinted / 60 - hoursPrinted * 60);

                secondsPrinted = secondsPrinted % 60;

                // TODO: Consider if the consistency of a common time format would look and feel better than changing formats based on elapsed duration
                timeWidget.Text = (hoursPrinted <= 0) ? $"{minutesPrinted}:{secondsPrinted:00}" : $"{hoursPrinted}:{minutesPrinted:00}:{secondsPrinted:00}";

                progressDial.LayerIndex          = printer.Connection.CurrentlyPrintingLayer;
                progressDial.LayerCompletedRatio = printer.Connection.RatioIntoCurrentLayer;
                progressDial.CompletedRatio      = printer.Connection.PercentComplete / 100;

                switch (printer.Connection.CommunicationState)
                {
                case CommunicationStates.PreparingToPrint:
                case CommunicationStates.Printing:
                case CommunicationStates.Paused:
                    bodyRow.Visible = true;
                    break;

                default:
                    bodyRow.Visible = false;
                    break;
                }
            }, 1);

            bodyRow.Closed += (s, e) => UiThread.ClearInterval(runningInterval);

            bodyRow.Visible = false;

            return(bodyRow);
        }
Пример #23
0
        public MainViewWidget(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.AnchorAll();
            this.theme           = theme;
            this.Name            = "PartPreviewContent";
            this.BackgroundColor = theme.BackgroundColor;

            // Push TouchScreenMode into GuiWidget
            GuiWidget.TouchScreenMode = UserSettings.Instance.IsTouchScreen;

            var extensionArea = new LeftClipFlowLayoutWidget()
            {
                BackgroundColor = theme.TabBarBackground,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(left: 8)
            };

            tabControl = new ChromeTabs(extensionArea, theme)
            {
                VAnchor         = VAnchor.Stretch,
                HAnchor         = HAnchor.Stretch,
                BackgroundColor = theme.BackgroundColor,
                BorderColor     = theme.MinimalShade,
                Border          = new BorderDouble(left: 1),
            };

            tabControl.PlusClicked += (s, e) =>
            {
                UiThread.RunOnIdle(() =>
                {
                    this.CreatePartTab().ConfigureAwait(false);
                });
            };

            tabControl.ActiveTabChanged += (s, e) =>
            {
                if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage)
                {
                    var dragDropData = ApplicationController.Instance.DragDropData;

                    // Set reference on tab change
                    dragDropData.View3DWidget = tabPage.view3DWidget;
                    dragDropData.SceneContext = tabPage.sceneContext;

                    ApplicationController.Instance.PrinterTabSelected = true;
                }
                else
                {
                    ApplicationController.Instance.PrinterTabSelected = false;
                }

                ApplicationController.Instance.MainTabKey = tabControl.SelectedTabKey;
            };

            // Force the ActionArea to be as high as ButtonHeight
            tabControl.TabBar.ActionArea.MinimumSize = new Vector2(0, theme.ButtonHeight);
            tabControl.TabBar.BackgroundColor        = theme.TabBarBackground;
            tabControl.TabBar.BorderColor            = theme.BackgroundColor;

            // Force common padding into top region
            tabControl.TabBar.Padding = theme.TabbarPadding.Clone(top: theme.TabbarPadding.Top * 2, bottom: 0);

            // add in a what's new button
            seeWhatsNewButton = new LinkLabel("What's New...".Localize(), theme)
            {
                Name        = "What's New Link",
                ToolTipText = "See what's new in this version of MatterControl".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0),
                TextColor   = theme.TextColor
            };
            seeWhatsNewButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UserSettings.Instance.set(UserSettingsKey.LastReadWhatsNew, JsonConvert.SerializeObject(DateTime.Now));
                DialogWindow.Show(new HelpPage("What's New"));
            });

            tabControl.TabBar.ActionArea.AddChild(seeWhatsNewButton);

            // add in the update available button
            updateAvailableButton = new LinkLabel("Update Available".Localize(), theme)
            {
                Visible     = false,
                Name        = "Update Available Link",
                ToolTipText = "There is a new update available for download".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0)
            };

            // Register listeners
            UserSettings.Instance.SettingChanged += SetLinkButtonsVisibility;

            RunningInterval showUpdateInterval = null;

            updateAvailableButton.VisibleChanged += (s, e) =>
            {
                if (!updateAvailableButton.Visible)
                {
                    if (showUpdateInterval != null)
                    {
                        UiThread.ClearInterval(showUpdateInterval);
                        showUpdateInterval = null;
                    }
                    return;
                }

                showUpdateInterval = UiThread.SetInterval(() =>
                {
                    double displayTime  = 1;
                    double pulseTime    = 1;
                    double totalSeconds = 0;
                    var textWidgets     = updateAvailableButton.Descendants <TextWidget>().Where((w) => w.Visible == true).ToArray();
                    Color startColor    = theme.TextColor;
                    // Show a highlight on the button as the user did not click it
                    Animation flashBackground = null;
                    flashBackground           = new Animation()
                    {
                        DrawTarget      = updateAvailableButton,
                        FramesPerSecond = 10,
                        Update          = (s1, updateEvent) =>
                        {
                            totalSeconds += updateEvent.SecondsPassed;
                            if (totalSeconds < displayTime)
                            {
                                double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                                var color    = new Color(startColor, (int)((1 - blend) * 255));
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = color;
                                }
                            }
                            else
                            {
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = startColor;
                                }
                                flashBackground.Stop();
                            }
                        }
                    };
                    flashBackground.Start();
                }, 120);
            };

            SetLinkButtonsVisibility(this, null);
            updateAvailableButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UpdateControlData.Instance.CheckForUpdate();
                DialogWindow.Show <CheckForUpdatesPage>();
            });

            tabControl.TabBar.ActionArea.AddChild(updateAvailableButton);

            this.AddChild(tabControl);

            ApplicationController.Instance.NotifyPrintersTabRightElement(extensionArea);

            // Store tab
            tabControl.AddTab(
                new ChromeTab("Store", "Store".Localize(), tabControl, new StoreTabPage(theme), theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Store Tab",
                Padding     = new BorderDouble(15, 0),
            });

            // Library tab
            var libraryWidget = new LibraryWidget(this, theme)
            {
                BackgroundColor = theme.BackgroundColor
            };

            tabControl.AddTab(
                new ChromeTab("Library", "Library".Localize(), tabControl, libraryWidget, theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Library Tab",
                Padding     = new BorderDouble(15, 0),
            });

            // Hardware tab
            tabControl.AddTab(
                new ChromeTab(
                    "Hardware",
                    "Hardware".Localize(),
                    tabControl,
                    new HardwareTabPage(theme)
            {
                BackgroundColor = theme.BackgroundColor
            },
                    theme,
                    hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Hardware Tab",
                Padding     = new BorderDouble(15, 0),
            });

            if (ApplicationController.Instance.Workspaces.Count == 0)
            {
                this.CreatePartTab().ConfigureAwait(false);
            }

            string tabKey = ApplicationController.Instance.MainTabKey;

            if (string.IsNullOrEmpty(tabKey))
            {
                tabKey = "Hardware";
            }

            // HACK: Restore to the first printer tab if PrinterTabSelected and tabKey not found. This allows sign in/out to remain on the printer tab across different users
            if (!tabControl.AllTabs.Any(t => t.Key == tabKey) &&
                ApplicationController.Instance.PrinterTabSelected)
            {
                var key = tabControl.AllTabs.Where(t => t.TabContent is PrinterTabPage).FirstOrDefault()?.Key;
                if (key != null)
                {
                    tabKey = key;
                }
            }

            var brandMenu = new BrandMenuButton(theme)
            {
                HAnchor         = HAnchor.Fit,
                VAnchor         = VAnchor.Fit,
                BackgroundColor = theme.TabBarBackground,
                Padding         = theme.TabbarPadding.Clone(right: theme.DefaultContainerPadding)
            };

            tabControl.TabBar.ActionArea.AddChild(brandMenu, 0);

            // Restore active tabs
            foreach (var workspace in ApplicationController.Instance.Workspaces)
            {
                this.CreatePartTab(workspace);
            }

            tabControl.SelectedTabKey = tabKey;

            statusBar = new Toolbar(theme)
            {
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Absolute,
                Padding         = 1,
                Height          = 22,
                BackgroundColor = theme.BackgroundColor,
                Border          = new BorderDouble(top: 1),
                BorderColor     = theme.BorderColor20,
            };
            this.AddChild(statusBar);

            statusBar.ActionArea.VAnchor = VAnchor.Stretch;

            tasksContainer = new FlowLayoutWidget(FlowDirection.LeftToRight)
            {
                HAnchor         = HAnchor.Fit,
                VAnchor         = VAnchor.Stretch,
                BackgroundColor = theme.MinimalShade,
                Name            = "runningTasksPanel"
            };
            statusBar.AddChild(tasksContainer);

            var tasks = ApplicationController.Instance.Tasks;

            tasks.TasksChanged += (s, e) =>
            {
                RenderRunningTasks(theme, tasks);
            };

            stretchStatusPanel = new GuiWidget()
            {
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(right: 3),
                Margin          = new BorderDouble(right: 2, top: 1, bottom: 1),
                Border          = new BorderDouble(1),
                BackgroundColor = theme.MinimalShade.WithAlpha(10),
                BorderColor     = theme.SlightShade,
                Width           = 200
            };
            statusBar.AddChild(stretchStatusPanel);

            var panelBackgroundColor = theme.MinimalShade.WithAlpha(10);

            statusBar.AddChild(
                this.CreateThemeStatusPanel(theme, panelBackgroundColor));

            statusBar.AddChild(
                this.CreateNetworkStatusPanel(theme));

            this.RenderRunningTasks(theme, tasks);

            // Register listeners
            PrinterSettings.AnyPrinterSettingChanged           += Printer_SettingChanged;
            ApplicationController.Instance.OpenPrintersChanged += OpenPrinters_Changed;

            UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent((s, e) =>
            {
                SetLinkButtonsVisibility(s, new StringEventArgs("Unknown"));
            }, ref unregisterEvents);

            ApplicationController.Instance.MainView = this;
        }
Пример #24
0
        public InlineEditControl(string defaultSizeString = "-0000.00")
        {
            theme        = AppContext.Theme;
            base.Visible = false;

            double pointSize = 10;

            this.Padding = new BorderDouble(3);

            numberDisplay = new TextWidget(defaultSizeString, 0, 0, pointSize, justification: Agg.Font.Justification.Center, textColor: theme.TextColor)
            {
                Visible = false,
                VAnchor = VAnchor.Bottom,
                HAnchor = HAnchor.Left,
                Text    = "0",
                AutoExpandBoundsToText = true,
            };

            this.BeforeDraw += (s, e) =>
            {
                if (s is GuiWidget widget)
                {
                    var test = true;
                    if (test)
                    {
                        // return;
                    }

                    var bounds = widget.LocalBounds;
                    e.Graphics2D.Render(new RoundedRect(bounds, 3 * GuiWidget.DeviceScale), theme.BackgroundColor.WithAlpha(200));
                }
            };

            AddChild(numberDisplay);

            numberEdit = new MHNumberEdit(0, theme, pixelWidth: numberDisplay.Width, allowNegatives: true, allowDecimals: true)
            {
                Visible          = false,
                VAnchor          = VAnchor.Bottom,
                HAnchor          = HAnchor.Left,
                SelectAllOnFocus = true,
            };
            numberEdit.ActuallNumberEdit.InternalNumberEdit.TextChanged += (s, e) =>
            {
                numberDisplay.Text = GetDisplayString == null ? "None" : GetDisplayString.Invoke(Value);
                this.OnTextChanged(e);
            };
            numberEdit.ActuallNumberEdit.InternalNumberEdit.MaxDecimalsPlaces = 2;

            numberEdit.ActuallNumberEdit.EditComplete += (s, e) =>
            {
                EditComplete?.Invoke(this, e);
                timeSinceMouseUp.Restart();
                numberEdit.Visible    = false;
                numberDisplay.Visible = true;
            };

            AddChild(numberEdit);

            VAnchor = VAnchor.Fit;
            HAnchor = HAnchor.Fit;

            runningInterval = UiThread.SetInterval(HideIfApplicable, .1);
        }