private CalibrationControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.printer = printer;

            // add in the controls for configuring auto leveling
            {
                SettingsRow settingsRow;

                this.AddChild(settingsRow = new SettingsRow(
                                  "Printer Calibration".Localize(),
                                  null,
                                  theme));

                // run leveling button
                var runWizardButton = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
                {
                    VAnchor     = VAnchor.Center,
                    Margin      = theme.ButtonSpacing,
                    Name        = "Run Leveling Button",
                    ToolTipText = "Run Calibration".Localize()
                };

                runWizardButton.Click += (s, e) =>
                {
                    UiThread.RunOnIdle(() =>
                    {
                        DialogWindow.Show(new PrinterCalibrationWizard(printer, theme));
                    });
                };
                settingsRow.AddChild(runWizardButton);

                // only show the switch if leveling can be turned off (it can't if it is required).
                if (!printer.Settings.GetValue <bool>(SettingsKey.print_leveling_required_to_print))
                {
                    // put in the switch
                    printLevelingSwitch = new RoundedToggleSwitch(theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(left: 16),
                        Checked = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled)
                    };
                    printLevelingSwitch.CheckedStateChanged += (sender, e) =>
                    {
                        printer.Settings.Helpers.DoPrintLeveling(printLevelingSwitch.Checked);
                    };

                    // TODO: Why is this listener conditional? If the leveling changes somehow, shouldn't we be updated the UI to reflect that?
                    // Register listeners
                    printer.Settings.PrintLevelingEnabledChanged += Settings_PrintLevelingEnabledChanged;

                    settingsRow.AddChild(printLevelingSwitch);
                }
            }

            // Register listeners
            printer.Connection.CommunicationStateChanged += PrinterStatusChanged;

            SetVisibleControls();
        }
Example #2
0
        public NozzleOffsetCalibrationResultsPage(ISetupWizard setupWizard, PrinterConfig printer, double xOffset, double yOffset)
            : base(setupWizard)
        {
            this.WindowTitle = "Nozzle Offset Calibration Wizard".Localize();
            this.HeaderText  = "Nozzle Offset Calibration".Localize() + ":";
            this.Name        = "Nozzle Offset Calibration Wizard";

            this.CreateTextField("Congratulations, your nozzle offsets have been collected and are ready to be saved. Click next to save and finish the wizard".Localize());

            var row = new SettingsRow(
                "X Offset".Localize(),
                null,
                theme,
                AggContext.StaticData.LoadIcon("probing_32x32.png", 16, 16, theme.InvertIcons));

            contentRow.AddChild(row);

            row.AddChild(new TextWidget(xOffset.ToString("0.###") + "mm", pointSize: theme.DefaultFontSize, textColor: theme.TextColor)
            {
                VAnchor = VAnchor.Center,
                Margin  = new BorderDouble(right: 10)
            });

            row = new SettingsRow(
                "Y Offset".Localize(),
                null,
                theme,
                AggContext.StaticData.LoadIcon("probing_32x32.png", 16, 16, theme.InvertIcons));
            contentRow.AddChild(row);

            row.AddChild(new TextWidget(yOffset.ToString("0.###") + "mm", pointSize: theme.DefaultFontSize, textColor: theme.TextColor)
            {
                VAnchor = VAnchor.Center,
                Margin  = new BorderDouble(right: 10)
            });

            this.NextButton.Visible = false;

            var nextButton = theme.CreateDialogButton("Finish".Localize());

            nextButton.Name   = "FinishCalibration";
            nextButton.Click += (s, e) =>
            {
                // TODO: removed fixed index
                var hotendOffset = printer.Settings.Helpers.ExtruderOffset(1);
                hotendOffset.X += xOffset;
                hotendOffset.Y += yOffset;

                printer.Settings.Helpers.SetExtruderOffset(1, hotendOffset);

                this.DialogWindow.CloseOnIdle();
            };

            theme.ApplyPrimaryActionStyle(nextButton);

            this.AddPageAction(nextButton);
        }
        private CalibrationControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.printer = printer;

            // add in the controls for configuring auto leveling
            {
                SettingsRow calibrationRow;

                this.AddChild(calibrationRow = new SettingsRow(
                                  "Printer Calibration".Localize(),
                                  null,
                                  theme));

                var runWizardButton = new IconButton(StaticData.Instance.LoadIcon("compass.png", 16, 16, theme.InvertIcons), theme)
                {
                    VAnchor     = VAnchor.Center,
                    Margin      = theme.ButtonSpacing,
                    Name        = "Printer Calibration Button",
                    ToolTipText = "Run Calibration".Localize()
                };

                runWizardButton.Click += (s, e) =>
                {
                    UiThread.RunOnIdle(() =>
                    {
                        DialogWindow.Show(new PrinterCalibrationWizard(printer, theme));
                    });
                };
                calibrationRow.AddChild(runWizardButton);
            }

            // Register listeners
            printer.Connection.CommunicationStateChanged += PrinterStatusChanged;

            SetVisibleControls();
        }
Example #4
0
        private AdjustmentControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            double sliderWidth      = 300 * GuiWidget.DeviceScale;
            double sliderThumbWidth = 10 * GuiWidget.DeviceScale;

            this.printer = printer;

            SettingsRow settingsRow;

            {
                this.AddChild(settingsRow = new SettingsRow(
                                  "Speed Multiplier".Localize(),
                                  null,
                                  theme));

                // Remove the HorizontalSpacer
                settingsRow.Children.Last().Close();

                feedRateRatioSlider = new SolidSlider(new Vector2(), sliderThumbWidth, theme, minFeedRateRatio, maxFeedRateRatio)
                {
                    Name               = "Feed Rate Slider",
                    Margin             = new BorderDouble(5, 0),
                    Value              = FeedRateMultiplyerStream.FeedRateRatio,
                    HAnchor            = HAnchor.Stretch,
                    VAnchor            = VAnchor.Center,
                    TotalWidthInPixels = sliderWidth,
                };
                theme.ApplySliderStyle(feedRateRatioSlider);
                feedRateRatioSlider.ValueChanged += (sender, e) =>
                {
                    feedRateValue.ActuallNumberEdit.Value = Math.Round(feedRateRatioSlider.Value, 2);
                };
                feedRateRatioSlider.SliderReleased += (s, e) =>
                {
                    // Update state for runtime use
                    FeedRateMultiplyerStream.FeedRateRatio = Math.Round(feedRateRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.feedrate_ratio,
                        FeedRateMultiplyerStream.FeedRateRatio.ToString());
                };
                settingsRow.AddChild(feedRateRatioSlider);

                feedRateValue = new MHNumberEdit(Math.Round(FeedRateMultiplyerStream.FeedRateRatio, 2), theme, allowDecimals: true, minValue: minFeedRateRatio, maxValue: maxFeedRateRatio, pixelWidth: 40 * GuiWidget.DeviceScale)
                {
                    Name             = "Feed Rate NumberEdit",
                    SelectAllOnFocus = true,
                    Margin           = new BorderDouble(0, 0, 5, 0),
                    VAnchor          = VAnchor.Center | VAnchor.Fit,
                    Padding          = 0
                };
                feedRateValue.ActuallNumberEdit.EditComplete += (sender, e) =>
                {
                    feedRateRatioSlider.Value = feedRateValue.ActuallNumberEdit.Value;

                    // Update state for runtime use
                    FeedRateMultiplyerStream.FeedRateRatio = Math.Round(feedRateRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.feedrate_ratio,
                        FeedRateMultiplyerStream.FeedRateRatio.ToString());
                };
                settingsRow.AddChild(feedRateValue);
            }

            {
                this.AddChild(settingsRow = new SettingsRow(
                                  "Extrusion Multiplier".Localize(),
                                  null,
                                  theme));

                // Remove the HorizontalSpacer
                settingsRow.Children.Last().Close();

                extrusionRatioSlider = new SolidSlider(new Vector2(), sliderThumbWidth, theme, minExtrutionRatio, maxExtrusionRatio, Orientation.Horizontal)
                {
                    Name = "Extrusion Multiplier Slider",
                    TotalWidthInPixels = sliderWidth,
                    HAnchor            = HAnchor.Stretch,
                    VAnchor            = VAnchor.Center,
                    Margin             = new BorderDouble(5, 0),
                    Value = ExtrusionMultiplyerStream.ExtrusionRatio
                };
                theme.ApplySliderStyle(extrusionRatioSlider);
                extrusionRatioSlider.ValueChanged += (sender, e) =>
                {
                    extrusionValue.ActuallNumberEdit.Value = Math.Round(extrusionRatioSlider.Value, 2);
                };
                extrusionRatioSlider.SliderReleased += (s, e) =>
                {
                    // Update state for runtime use
                    ExtrusionMultiplyerStream.ExtrusionRatio = Math.Round(extrusionRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.extrusion_ratio,
                        ExtrusionMultiplyerStream.ExtrusionRatio.ToString());
                };
                settingsRow.AddChild(extrusionRatioSlider);

                extrusionValue = new MHNumberEdit(Math.Round(ExtrusionMultiplyerStream.ExtrusionRatio, 2), theme, allowDecimals: true, minValue: minExtrutionRatio, maxValue: maxExtrusionRatio, pixelWidth: 40 * GuiWidget.DeviceScale)
                {
                    Name             = "Extrusion Multiplier NumberEdit",
                    SelectAllOnFocus = true,
                    Margin           = new BorderDouble(0, 0, 5, 0),
                    VAnchor          = VAnchor.Center | VAnchor.Fit,
                    Padding          = 0
                };
                extrusionValue.ActuallNumberEdit.EditComplete += (sender, e) =>
                {
                    extrusionRatioSlider.Value = extrusionValue.ActuallNumberEdit.Value;

                    // Update state for runtime use
                    ExtrusionMultiplyerStream.ExtrusionRatio = Math.Round(extrusionRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.extrusion_ratio,
                        ExtrusionMultiplyerStream.ExtrusionRatio.ToString());
                };
                settingsRow.AddChild(extrusionValue);
            }

            // Register listeners
            printer.Settings.SettingChanged += Printer_SettingChanged;
        }
Example #5
0
        private CalibrationControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.printer = printer;

            // add in the controls for configuring auto leveling
            {
                SettingsRow settingsRow;

                this.AddChild(settingsRow = new SettingsRow(
                                  "Print Leveling Plane".Localize(),
                                  null,
                                  theme,
                                  AggContext.StaticData.LoadIcon("leveling_32x32.png", 16, 16, theme.InvertIcons)));

                // run leveling button
                var runWizardButton = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
                {
                    VAnchor = VAnchor.Center,
                    Margin  = theme.ButtonSpacing,

                    ToolTipText = "Print Leveling Wizard - Can be re-calculated anytime there seems to be a problem with initial layer consistency".Localize()
                };
                runWizardButton.Click += (s, e) =>
                {
                    UiThread.RunOnIdle(() =>
                    {
                        LevelingWizard.ShowPrintLevelWizard(printer, theme);
                    });
                };
                settingsRow.AddChild(runWizardButton);

                // only show the switch if leveling can be turned off (it can't if it is required).
                if (!printer.Settings.GetValue <bool>(SettingsKey.print_leveling_required_to_print))
                {
                    // put in the switch
                    var printLevelingSwitch = new RoundedToggleSwitch(theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(left: 16),
                        Checked = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled)
                    };
                    printLevelingSwitch.CheckedStateChanged += (sender, e) =>
                    {
                        printer.Settings.Helpers.DoPrintLeveling(printLevelingSwitch.Checked);
                    };

                    printer.Settings.PrintLevelingEnabledChanged.RegisterEvent((sender, e) =>
                    {
                        printLevelingSwitch.Checked = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled);
                    }, ref unregisterEvents);

                    settingsRow.AddChild(printLevelingSwitch);
                }

                // add in the controls for configuring probe offset
                if (printer.Settings.GetValue <bool>(SettingsKey.has_z_probe) &&
                    printer.Settings.GetValue <bool>(SettingsKey.use_z_probe))
                {
                    this.AddChild(settingsRow = new SettingsRow(
                                      "Print Leveling Probe".Localize(),
                                      null,
                                      theme,
                                      AggContext.StaticData.LoadIcon("probing_32x32.png", 16, 16, theme.InvertIcons)));

                    var runCalibrateProbeButton = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
                    {
                        VAnchor     = VAnchor.Center,
                        Margin      = theme.ButtonSpacing,
                        ToolTipText = "Probe Calibration Wizard - needed for initial setup - normally should remain calibrated unless there are changes to hardware.".Localize()
                    };
                    runCalibrateProbeButton.Click += (s, e) =>
                    {
                        UiThread.RunOnIdle(() =>
                        {
                            LevelingWizard.ShowProbeCalibrationWizard(printer, theme);
                        });
                    };

                    settingsRow.BorderColor = Color.Transparent;
                    settingsRow.AddChild(runCalibrateProbeButton);
                }
            }

            printer.Connection.CommunicationStateChanged.RegisterEvent(PrinterStatusChanged, ref unregisterEvents);
            printer.Connection.EnableChanged.RegisterEvent(PrinterStatusChanged, ref unregisterEvents);

            SetVisibleControls();
        }
        public ValidationErrorsPanel(IEnumerable <ValidationError> errors, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor         = HAnchor.Absolute;
            this.VAnchor         = VAnchor.Fit | VAnchor;
            this.BackgroundColor = theme.ResolveColor(theme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30));

            var errorImage   = StaticData.Instance.LoadIcon("SettingsGroupError_16x.png", 16, 16).SetToColor(theme.TextColor);
            var warningImage = StaticData.Instance.LoadIcon("SettingsGroupWarning_16x.png", 16, 16).SetToColor(theme.TextColor);
            var infoImage    = StaticData.Instance.LoadIcon("StatusInfoTip_16x.png", 16, 16);

            foreach (var validationError in errors.OrderByDescending(e => e.ErrorLevel))
            {
                if (validationError.ErrorLevel == ValidationErrorLevel.Warning &&
                    UserSettings.Instance.get($"Ignore_{validationError.ID}") == "true")
                {
                    continue;
                }

                string errorText, errorDetails;

                if (validationError is SettingsValidationError settingsValidationError)
                {
                    errorText = string.Format(
                        "{0} {1}",
                        settingsValidationError.PresentationName,
                        validationError.ErrorLevel == ValidationErrorLevel.Error ? "Error".Localize() : "Warning".Localize());

                    errorDetails = validationError.Error + "\n\n" + settingsValidationError.Location;
                }
                else
                {
                    errorText    = validationError.Error;
                    errorDetails = validationError.Details ?? "";
                }

                var row = new SettingsRow(errorText, errorDetails, theme, validationError.ErrorLevel == ValidationErrorLevel.Error ? errorImage : warningImage, fullRowSelect: true)
                {
                    ArrowDirection = ArrowDirection.Left,
                    Name           = validationError.ID + " Row"
                };

                if (validationError.FixAction is NamedAction action)
                {
                    // Show fix button
                    var button = new LinkLabel(action.Title, theme, pointSize: theme.FontSize10)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(right: 8),
                        Enabled = action.IsEnabled == null || action.IsEnabled(),
                        Name    = validationError.ID + " Button"
                    };

                    if (!string.IsNullOrEmpty(action.ID))
                    {
                        button.Name = action.ID;
                    }

                    button.Click += (s, e) =>
                    {
                        // Invoke FixAction
                        action.Action.Invoke();
                        this.ClosePopup();
                    };

                    row.AddChild(button);

                    row.ActionWidget  = button;
                    row.FullRowSelect = true;
                }
                else
                {
                    // Show info indicator hinting that hover will reveal additional details
                    row.AddChild(new IconButton(infoImage, theme)
                    {
                        Selectable = false
                    });
                }

                if (validationError.ErrorLevel == ValidationErrorLevel.Warning)
                {
                    var dismissButton = theme.CreateSmallResetButton();
                    dismissButton.HAnchor     = HAnchor.Absolute;
                    dismissButton.Margin      = new BorderDouble(right: theme.ButtonHeight / 2 - dismissButton.Width / 2);
                    dismissButton.Name        = "Dismiss " + validationError.ID;
                    dismissButton.ToolTipText = "Dismiss".Localize();
                    dismissButton.Click      += (sender, e) =>
                    {
                        UserSettings.Instance.set($"Ignore_{validationError.ID}", "true");
                        this.ClosePopup();
                    };

                    row.AddChild(dismissButton);

                    // Enable selection without regard to FullRowSelect
                    dismissButton.Selectable = true;
                }

                this.AddChild(row);
            }
        }
Example #7
0
        public RenderOptionsButton(ThemeConfig theme, InteractionLayer interactionLayer)
            : base(theme)
        {
            this.HAnchor = HAnchor.Fit;
            this.VAnchor = VAnchor.Fit;

            this.AddChild(new IconButton(AggContext.StaticData.LoadIcon("web.png", theme.InvertIcons), theme)
            {
                Selectable = false
            });

            this.PopupContent = () =>
            {
                var menuTheme = AppContext.MenuTheme;

                var subPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
                {
                    Padding         = theme.DefaultContainerPadding,
                    BackgroundColor = menuTheme.BackgroundColor,
                    HAnchor         = HAnchor.Absolute,
                    VAnchor         = VAnchor.Fit
                };

                subPanel.BoundsChanged += (s, e) =>
                {
                    Console.WriteLine();
                };

                foreach (var drawable in ApplicationController.Instance.DragDropData.View3DWidget.InteractionLayer.Drawables)
                {
                    var row = new SettingsRow(drawable.Title, drawable.Description, theme);
                    subPanel.AddChild(row);

                    var toggleSwitch = new RoundedToggleSwitch(theme)
                    {
                        Checked = drawable.Enabled
                    };
                    toggleSwitch.CheckedStateChanged += (s, e) =>
                    {
                        drawable.Enabled = toggleSwitch.Checked;
                    };
                    row.AddChild(toggleSwitch);
                }

                foreach (var drawable in ApplicationController.Instance.DragDropData.View3DWidget.InteractionLayer.ItemDrawables)
                {
                    var row = new SettingsRow(drawable.Title, drawable.Description, theme);
                    subPanel.AddChild(row);

                    var toggleSwitch = new RoundedToggleSwitch(theme)
                    {
                        Checked = drawable.Enabled
                    };
                    toggleSwitch.CheckedStateChanged += (s, e) =>
                    {
                        drawable.Enabled = toggleSwitch.Checked;
                    };
                    row.AddChild(toggleSwitch);
                }

                subPanel.Width = 400;

                return(subPanel);
            };
        }
        public ValidationErrorsPanel(IEnumerable <ValidationError> errors, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor         = HAnchor.Absolute;
            this.VAnchor         = VAnchor.Fit | VAnchor;
            this.BackgroundColor = theme.ResolveColor(theme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30));

            var errorImage   = AggContext.StaticData.LoadIcon("SettingsGroupError_16x.png", 16, 16, theme.InvertIcons);
            var warningImage = AggContext.StaticData.LoadIcon("SettingsGroupWarning_16x.png", 16, 16, theme.InvertIcons);
            var infoImage    = AggContext.StaticData.LoadIcon("StatusInfoTip_16x.png", 16, 16);
            var fixIcon      = AggContext.StaticData.LoadIcon("noun_1306.png", 16, 16, theme.InvertIcons);

            foreach (var validationError in errors.OrderByDescending(e => e.ErrorLevel))
            {
                if (validationError.ErrorLevel == ValidationErrorLevel.Warning &&
                    UserSettings.Instance.get($"Ignore_{validationError.ID}") == "true")
                {
                    continue;
                }

                string errorText, errorDetails;

                var settingsValidationError = validationError as SettingsValidationError;
                if (settingsValidationError != null)
                {
                    errorText = string.Format(
                        "{0} {1}",
                        settingsValidationError.PresentationName,
                        validationError.ErrorLevel == ValidationErrorLevel.Error ? "Error".Localize() : "Warning".Localize());

                    errorDetails = validationError.Error;
                }
                else
                {
                    errorText    = validationError.Error;
                    errorDetails = validationError.Details ?? "";
                }

                var row = new SettingsRow(errorText, errorDetails, theme, validationError.ErrorLevel == ValidationErrorLevel.Error ? errorImage : warningImage)
                {
                    ArrowDirection = ArrowDirection.Left
                };

                if (validationError.FixAction is NamedAction action)
                {
                    // Show fix button
                    var button = new LinkLabel(action.Title, theme, pointSize: theme.FontSize10)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(right: 8),
                        Enabled = action.IsEnabled == null || action.IsEnabled()
                    };

                    if (!string.IsNullOrEmpty(action.ID))
                    {
                        button.Name = action.ID;
                    }

                    button.Click += (s, e) =>
                    {
                        // Invoke FixAction
                        action.Action.Invoke();

                        // Close popup on FixAction button click
                        if (this.Parents <PopupWidget>().FirstOrDefault() is PopupWidget popupWidget)
                        {
                            UiThread.RunOnIdle(popupWidget.CloseMenu);
                        }
                    };

                    row.AddChild(button);
                }
                else
                {
                    // Show info indicator hinting that hover will reveal additional details
                    var button = new IconButton(infoImage, theme)
                    {
                        Selectable = false
                    };
                    row.AddChild(button);
                }

                if (validationError.ErrorLevel == ValidationErrorLevel.Warning)
                {
                    var dismissButton = theme.CreateSmallResetButton();
                    dismissButton.HAnchor     = HAnchor.Absolute;
                    dismissButton.Margin      = new BorderDouble(right: theme.ButtonHeight / 2 - dismissButton.Width / 2);
                    dismissButton.Name        = "Dismiss " + validationError.ID;
                    dismissButton.ToolTipText = "Dismiss".Localize();
                    dismissButton.Click      += (sender, e) =>
                    {
                        UserSettings.Instance.set($"Ignore_{validationError.ID}", "true");
                    };

                    row.AddChild(dismissButton);
                }

                this.AddChild(row);
            }
        }
Example #9
0
        private FanControls(PrinterConnection printerConnection, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor = HAnchor.Stretch;
            this.HAnchor = HAnchor.Stretch;


            //Matt's test editing to add a on/off toggle switch
            bool fanActive = printerConnection.FanSpeed0To255 != 0;

            Stopwatch timeSinceLastManualSend = new Stopwatch();

            var settingsRow = new SettingsRow(
                "Part Cooling Fan".Localize(),
                null,
                theme,
                fullRowSelect: true);

            this.AddChild(settingsRow);

            var container = new FlowLayoutWidget();

            settingsRow.AddChild(container);
            settingsRow.BorderColor = Color.Transparent;

            fanSpeedDisplay = new EditableNumberDisplay(0, "100")
            {
                DisplayFormat = "{0:0}",
                Value         = printerConnection.FanSpeed0To255 * 100 / 255
            };
            fanSpeedDisplay.ValueChanged += (sender, e) =>
            {
                // limit the rate we can send this message to 2 per second so we don't get in a crazy toggle state.
                if (!timeSinceLastManualSend.IsRunning ||
                    timeSinceLastManualSend.ElapsedMilliseconds > 500)
                {
                    timeSinceLastManualSend.Restart();
                    printerConnection.FanSpeed0To255 = (int)(fanSpeedDisplay.Value * 255 / 100 + .5);
                }
            };
            container.AddChild(fanSpeedDisplay);

            container.Selectable = true;

            // put in %
            container.AddChild(new TextWidget("%", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
            {
                VAnchor = VAnchor.Center
            });

            var toggleSwitch = new RoundedToggleSwitch(theme)
            {
                Margin  = new BorderDouble(5, 0),
                VAnchor = VAnchor.Center
            };

            toggleSwitch.CheckedStateChanged += (s, e) =>
            {
                if (!timeSinceLastManualSend.IsRunning ||
                    timeSinceLastManualSend.ElapsedMilliseconds > 500)
                {
                    timeSinceLastManualSend.Restart();
                    if (toggleSwitch.Checked)
                    {
                        printerConnection.FanSpeed0To255 = 255;
                    }
                    else
                    {
                        printerConnection.FanSpeed0To255 = 0;
                    }
                }
            };
            container.AddChild(toggleSwitch);
            settingsRow.ActionWidget = toggleSwitch;

            // CreateFanControls
            printerConnection.FanSpeedSet.RegisterEvent((s, e) =>
            {
                if ((int)printerConnection.FanSpeed0To255 > 0)
                {
                    toggleSwitch.Checked = true;
                }
                else
                {
                    toggleSwitch.Checked = false;
                }

                fanSpeedDisplay.Value = printerConnection.FanSpeed0To255 * 100 / 255;
            }
                                                        , ref unregisterEvents);
        }
Example #10
0
        private CalibrationControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.printer = printer;

            // add in the controls for configuring auto leveling
            {
                SettingsRow settingsRow;

                this.AddChild(settingsRow = new SettingsRow(
                                  "Bed Leveling".Localize(),
                                  null,
                                  theme,
                                  AggContext.StaticData.LoadIcon("leveling_32x32.png", 16, 16, theme.InvertIcons)));

                // run leveling button
                var runWizardButton = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
                {
                    VAnchor = VAnchor.Center,
                    Margin  = theme.ButtonSpacing,
                    Name    = "Run Leveling Button",

                    ToolTipText = "Run Calibration".Localize()
                };
                runWizardButton.Click += (s, e) =>
                {
                    UiThread.RunOnIdle(() =>
                    {
                        LevelingWizard.ShowPrintLevelWizard(printer, theme);
                    });
                };
                settingsRow.AddChild(runWizardButton);

                // only show the switch if leveling can be turned off (it can't if it is required).
                if (!printer.Settings.GetValue <bool>(SettingsKey.print_leveling_required_to_print))
                {
                    // put in the switch
                    var printLevelingSwitch = new RoundedToggleSwitch(theme)
                    {
                        VAnchor = VAnchor.Center,
                        Margin  = new BorderDouble(left: 16),
                        Checked = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled)
                    };
                    printLevelingSwitch.CheckedStateChanged += (sender, e) =>
                    {
                        printer.Settings.Helpers.DoPrintLeveling(printLevelingSwitch.Checked);
                    };

                    void Settings_PrintLevelingEnabledChanged(object sender, EventArgs e)
                    {
                        printLevelingSwitch.Checked = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled);
                    }

                    printer.Settings.PrintLevelingEnabledChanged += Settings_PrintLevelingEnabledChanged;
                    this.Closed += (s, e) =>
                    {
                        printer.Settings.PrintLevelingEnabledChanged -= Settings_PrintLevelingEnabledChanged;
                    };

                    settingsRow.AddChild(printLevelingSwitch);
                }

                // add in the controls for configuring probe offset
                if (printer.Settings.GetValue <bool>(SettingsKey.has_z_probe) &&
                    printer.Settings.GetValue <bool>(SettingsKey.use_z_probe))
                {
                    this.AddChild(settingsRow = new SettingsRow(
                                      "Calibrate Probe Offset".Localize(),
                                      null,
                                      theme,
                                      AggContext.StaticData.LoadIcon("probing_32x32.png", 16, 16, theme.InvertIcons)));

                    var runCalibrateProbeButton = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
                    {
                        VAnchor     = VAnchor.Center,
                        Margin      = theme.ButtonSpacing,
                        ToolTipText = "Run Calibration".Localize()
                    };
                    runCalibrateProbeButton.Click += (s, e) =>
                    {
                        UiThread.RunOnIdle(() =>
                        {
                            LevelingWizard.ShowProbeCalibrationWizard(printer, theme);
                        });
                    };

                    settingsRow.BorderColor = Color.Transparent;
                    settingsRow.AddChild(runCalibrateProbeButton);
                }
            }

            printer.Connection.CommunicationStateChanged.RegisterEvent(PrinterStatusChanged, ref unregisterEvents);
            printer.Connection.EnableChanged.RegisterEvent(PrinterStatusChanged, ref unregisterEvents);

            SetVisibleControls();
        }
        private TemperatureControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor = HAnchor.Stretch;
            this.HAnchor = HAnchor.Stretch;
            this.printer = printer;

            int hotendCount = printer.Settings.Helpers.HotendCount();

            // add in the hotend controls
            for (int extruderIndex = 0; extruderIndex < hotendCount; extruderIndex++)
            {
                var settingsRow = new SettingsRow(
                    hotendCount == 1 ? "Hotend".Localize() : "Hotend {0}".Localize().FormatWith(extruderIndex + 1),
                    null,
                    theme);

                settingsRow.AddChild(new TemperatureWidgetHotend(printer, extruderIndex, theme, hotendCount));

                this.AddChild(settingsRow);
            }

            if (printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed))
            {
                var settingsRow = new SettingsRow(
                    "Bed".Localize(),
                    null,
                    theme);

                settingsRow.AddChild(new TemperatureWidgetBed(printer, theme));

                this.AddChild(settingsRow);
            }

            // add in the all heaters section
            var heatersRow = new SettingsRow(
                "All Heaters".Localize(),
                null,
                theme);

            this.AddChild(heatersRow);
            var container = new FlowLayoutWidget();

            heatersRow.AddChild(container);

            preHeatButton = new TextButton("Preheat".Localize(), theme)
            {
                BackgroundColor = theme.MinimalShade,
                Margin          = new BorderDouble(right: 10)
            };
            container.AddChild(preHeatButton);
            preHeatButton.Click += (s, e) =>
            {
                // turn on the bed
                printer.Connection.TargetBedTemperature = printer.Settings.GetValue <double>(SettingsKey.bed_temperature);
                for (int extruderIndex = 0; extruderIndex < hotendCount; extruderIndex++)
                {
                    printer.Connection.SetTargetHotendTemperature(extruderIndex, printer.Settings.Helpers.ExtruderTargetTemperature(extruderIndex));
                }

                printer.Connection.TurnOffBedAndExtruders(TurnOff.AfterDelay);
            };

            offButton = new TextButton("Off".Localize(), theme)
            {
                BackgroundColor = theme.MinimalShade,
            };
            container.AddChild(offButton);
            offButton.Click += (s, e) =>
            {
                printer.Connection.TurnOffBedAndExtruders(TurnOff.Now);
            };

            if (printer.Settings.GetValue <bool>(SettingsKey.has_fan_per_extruder))
            {
                for (int i = 0; i < printer.Settings.GetValue <int>(SettingsKey.extruder_count); i++)
                {
                    this.AddChild(new FanControlsRow(i, $"Part Cooling Fan {i}".Localize(), printer, theme));
                }
            }
            else             // just add one
            {
                this.AddChild(new FanControlsRow(0, "Part Cooling Fan".Localize(), printer, theme));
            }

            // Register listeners
            printer.Connection.CommunicationStateChanged += Printer_StatusChanged;
            SetVisibleControls();
        }
		private static GuiWidget CreateSettingInfoUIControls(SliceSettingData settingData, List<PrinterSettingsLayer> layerCascade, PrinterSettingsLayer persistenceLayer,
			NamedSettingsLayers viewFilter,
			int extruderIndex, out bool addControl, ref int tabIndexForItem)
		{
			addControl = true;
			GuiWidget container = new GuiWidget();

			string sliceSettingValue = GetActiveValue(settingData.SlicerConfigName, layerCascade);

			GuiWidget nameArea = new GuiWidget(HAnchor.ParentLeftRight, VAnchor.FitToChildren | VAnchor.ParentCenter);
			var dataArea = new FlowLayoutWidget();
			GuiWidget unitsArea = new GuiWidget(HAnchor.AbsolutePosition, VAnchor.FitToChildren | VAnchor.ParentCenter)
			{
				Width = settingData.ShowAsOverride ? 50 * GuiWidget.DeviceScale : 5,
			};
			GuiWidget restoreArea = new GuiWidget(HAnchor.AbsolutePosition, VAnchor.FitToChildren | VAnchor.ParentCenter)
			{
				Width = settingData.ShowAsOverride ? 30 * GuiWidget.DeviceScale : 0,
			};

			var settingsRow = new SettingsRow(layerCascade)
			{
				SettingsKey = settingData.SlicerConfigName,
				SettingsValue = sliceSettingValue,
			};
			settingsRow.AddChild(nameArea);
			settingsRow.AddChild(dataArea);
			settingsRow.AddChild(unitsArea);
			settingsRow.AddChild(restoreArea);
			settingsRow.Name = settingData.SlicerConfigName + " Edit Field";

			if (!PrinterSettings.KnownSettings.Contains(settingData.SlicerConfigName))
			{
				// the setting we think we are adding is not in the known settings it may have been deprecated
				TextWidget settingName = new TextWidget(String.Format("Setting '{0}' not found in known settings", settingData.SlicerConfigName));
				settingName.TextColor = ActiveTheme.Instance.PrimaryTextColor;
				//settingName.MinimumSize = new Vector2(minSettingNameWidth, settingName.MinimumSize.y);
				nameArea.AddChild(settingName);
				nameArea.BackgroundColor = RGBA_Bytes.Red;
			}
			else
			{
				int intEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
				int doubleEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
				int vectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
				int multiLineEditHeight = (int)(120 * GuiWidget.DeviceScale + .5);

				if (settingData.DataEditType != SliceSettingData.DataEditTypes.MULTI_LINE_TEXT)
				{
					var nameHolder = new GuiWidget(HAnchor.ParentLeftRight, VAnchor.FitToChildren | VAnchor.ParentCenter)
					{
						Padding = new BorderDouble(0, 0, 5, 0),
						HAnchor = HAnchor.ParentLeftRight,
					};

					nameHolder.AddChild(new WrappedTextWidget(settingData.PresentationName.Localize(), pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor));

					nameArea.AddChild(nameHolder);
				}

				switch (settingData.DataEditType)
				{
					case SliceSettingData.DataEditTypes.INT:
						{
							FlowLayoutWidget content = new FlowLayoutWidget();
							int currentValue;
							int.TryParse(sliceSettingValue, out currentValue);

							var intEditWidget = new MHNumberEdit(currentValue, pixelWidth: intEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true,
								Name = settingData.PresentationName + " Edit",
							};
							intEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							content.AddChild(intEditWidget);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								dataArea.AddChild(CreateQuickMenu(settingData, persistenceLayer, content, intEditWidget.ActuallNumberEdit.InternalTextEditWidget, layerCascade));
							}
							else
							{
								dataArea.AddChild(content);
							}

							settingsRow.ValueChanged = (text) =>
							{
								intEditWidget.Text = text;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.DOUBLE:
						{
							double currentValue;
							double.TryParse(sliceSettingValue, out currentValue);

							var doubleEditWidget = new MHNumberEdit(currentValue, allowNegatives: true, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(doubleEditWidget);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2 = 0;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.POSITIVE_DOUBLE:
						{
							const string multiValuesAreDiffernt = "-";
							FlowLayoutWidget content = new FlowLayoutWidget();

							var doubleEditWidget = new MHNumberEdit(0, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								Name = settingData.PresentationName + " Textbox",
								SelectAllOnFocus = true
							};

							double currentValue;
							bool ChangesMultipleOtherSettings = settingData.SetSettingsOnChange.Count > 0;
							if (ChangesMultipleOtherSettings)
							{
								bool allTheSame = true;
								string setting = GetActiveValue(settingData.SetSettingsOnChange[0], layerCascade);
								for (int i = 1; i < settingData.SetSettingsOnChange.Count; i++)
								{
									string nextSetting = GetActiveValue(settingData.SetSettingsOnChange[i], layerCascade);
									if (setting != nextSetting)
									{
										allTheSame = false;
										break;
									}
								}

								if (allTheSame && setting.EndsWith("mm"))
								{
									double.TryParse(setting.Substring(0, setting.Length - 2), out currentValue);
									doubleEditWidget.ActuallNumberEdit.Value = currentValue;
								}
								else
								{
									doubleEditWidget.ActuallNumberEdit.InternalNumberEdit.Text = multiValuesAreDiffernt;
								}
							}
							else // just set the setting normally
							{
								double.TryParse(sliceSettingValue, out currentValue);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue;
							}
							doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget.MarkAsStartingState();
							
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								NumberEdit numberEdit = (NumberEdit)sender;
								// If this setting sets other settings, then do that.
								if (ChangesMultipleOtherSettings
									&& numberEdit.Text != multiValuesAreDiffernt)
								{
									foreach (string setting in settingData.SetSettingsOnChange)
									{
										ActiveSliceSettings.Instance.SetValue(setting, numberEdit.Value.ToString() + "mm", persistenceLayer);
									}
								}

								// also always save to the local setting
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, numberEdit.Value.ToString(), persistenceLayer);
								settingsRow.UpdateStyle();
								OnSettingsChanged(settingData);
							};
							content.AddChild(doubleEditWidget);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								dataArea.AddChild(CreateQuickMenu(settingData, persistenceLayer, content, doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget, layerCascade));
							}
							else
							{
								dataArea.AddChild(content);
							}

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2 = 0;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.OFFSET:
						{
							double currentValue;
							double.TryParse(sliceSettingValue, out currentValue);
							var doubleEditWidget = new MHNumberEdit(currentValue, allowDecimals: true, allowNegatives: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true

							};
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString(), persistenceLayer);
								settingsRow.UpdateStyle();
								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(doubleEditWidget);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.DOUBLE_OR_PERCENT:
						{
							FlowLayoutWidget content = new FlowLayoutWidget();

							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								var textEditWidget = (TextEditWidget)sender;
								string text = textEditWidget.Text.Trim();

								bool isPercent = text.Contains("%");
								if (isPercent)
								{
									text = text.Substring(0, text.IndexOf("%"));
								}
								double result;
								double.TryParse(text, out result);
								text = result.ToString();
								if (isPercent)
								{
									text += "%";
								}
								textEditWidget.Text = text;
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
							{
								// select everything up to the % (if present)
								InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
								int percentIndex = textEditWidget.Text.IndexOf("%");
								if (percentIndex != -1)
								{
									textEditWidget.SetSelection(0, percentIndex - 1);
								}
							};

							content.AddChild(stringEdit);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								dataArea.AddChild(CreateQuickMenu(settingData, persistenceLayer, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget, layerCascade));
							}
							else
							{
								dataArea.AddChild(content);
							}

							settingsRow.ValueChanged = (text) =>
							{
								stringEdit.Text = text;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.INT_OR_MM:
						{
							FlowLayoutWidget content = new FlowLayoutWidget();

							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};

							string startingText = stringEdit.Text;
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								TextEditWidget textEditWidget = (TextEditWidget)sender;
								// only validate when we lose focus
								if (!textEditWidget.ContainsFocus)
								{
									string text = textEditWidget.Text;
									text = text.Trim();
									bool isMm = text.Contains("mm");
									if (isMm)
									{
										text = text.Substring(0, text.IndexOf("mm"));
									}
									double result;
									double.TryParse(text, out result);
									text = result.ToString();
									if (isMm)
									{
										text += "mm";
									}
									else
									{
										result = (int)result;
										text = result.ToString();
									}
									textEditWidget.Text = text;
									startingText = stringEdit.Text;
								}
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, textEditWidget.Text, persistenceLayer);
								settingsRow.UpdateStyle();
								OnSettingsChanged(settingData);

								// make sure we are still looking for the final validation before saving.
								if (textEditWidget.ContainsFocus)
								{
									UiThread.RunOnIdle(() =>
									{
										string currentText = textEditWidget.Text;
										int cursorIndex = textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore;
										textEditWidget.Text = startingText;
										textEditWidget.InternalTextEditWidget.MarkAsStartingState();
										textEditWidget.Text = currentText;
										textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore = cursorIndex;
									});
								}
							};

							stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
							{
								// select everything up to the mm (if present)
								InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
								int mMIndex = textEditWidget.Text.IndexOf("mm");
								if (mMIndex != -1)
								{
									textEditWidget.SetSelection(0, mMIndex - 1);
								}
							};

							content.AddChild(stringEdit);
							unitsArea.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								dataArea.AddChild(CreateQuickMenu(settingData, persistenceLayer, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget, layerCascade));
							}
							else
							{
								dataArea.AddChild(content);
							}

							settingsRow.ValueChanged = (text) =>
							{
								stringEdit.Text = text;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.CHECK_BOX:
						{
							var checkBoxWidget = new CheckBox("")
							{
								Name = settingData.PresentationName + " Checkbox",
								ToolTipText = settingData.HelpText,
								VAnchor = Agg.UI.VAnchor.ParentBottom,
								TextColor = ActiveTheme.Instance.PrimaryTextColor,
								Checked = sliceSettingValue == "1"
							};
							checkBoxWidget.Click += (sender, e) =>
							{
								bool isChecked = ((CheckBox)sender).Checked;
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							dataArea.AddChild(checkBoxWidget);

							settingsRow.ValueChanged = (text) =>
							{
								checkBoxWidget.Checked = text == "1";
							};
						}
						break;

					case SliceSettingData.DataEditTypes.STRING:
						{
							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: settingData.ShowAsOverride ? 120 : 200, tabIndex: tabIndexForItem++)
							{
								Name = settingData.PresentationName + " Edit",
							};
							stringEdit.ToolTipText = settingData.HelpText;
							
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text, persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							dataArea.AddChild(stringEdit);

							settingsRow.ValueChanged = (text) =>
							{
								stringEdit.Text = text;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.MULTI_LINE_TEXT:
						{
							string convertedNewLines = sliceSettingValue.Replace("\\n", "\n");
							var stringEdit = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndexForItem++, typeFace: ApplicationController.MonoSpacedTypeFace)
							{
								HAnchor = HAnchor.ParentLeftRight,
							};

							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"), persistenceLayer);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							nameArea.HAnchor = HAnchor.AbsolutePosition;
							nameArea.Width = 0;
							dataArea.AddChild(stringEdit);
							dataArea.HAnchor = HAnchor.ParentLeftRight;

							settingsRow.ValueChanged = (text) =>
							{
								stringEdit.Text = text.Replace("\\n", "\n");
							};
						}
						break;

					case SliceSettingData.DataEditTypes.COM_PORT:
						{
#if __ANDROID__
							addControl = false;
#endif
							// The COM_PORT control is unique in its approach to the SlicerConfigName. It uses "com_port" settings name to
							// bind to a context that will place it in the SliceSetting view but it binds its values to a machine
							// specific dictionary key that is not exposed in the UI. At runtime we lookup and store to '<machinename>_com_port'
							// ensuring that a single printer can be shared across different devices and we'll select the correct com port in each case
							var selectableOptions = new DropDownList("None", maxHeight: 200)
							{
								ToolTipText = settingData.HelpText,
								Margin = new BorderDouble(),
								Name = "Com Port Dropdown"
							};

							selectableOptions.Click += (s, e) =>
							{
								AddComMenuItems(settingData, persistenceLayer, settingsRow, selectableOptions);
							};

							AddComMenuItems(settingData, persistenceLayer, settingsRow, selectableOptions);

							dataArea.AddChild(selectableOptions);

							settingsRow.ValueChanged = (text) =>
							{
								// Lookup the machine specific comport value rather than the passed in text value
								selectableOptions.SelectedLabel = ActiveSliceSettings.Instance.Helpers.ComPort();
							};
						}
						break;

					case SliceSettingData.DataEditTypes.LIST:
						{
							var selectableOptions = new DropDownList("None", maxHeight: 200)
							{
								ToolTipText = settingData.HelpText,
								Margin = new BorderDouble()
							};

							foreach (string listItem in settingData.ExtraSettings.Split(','))
							{
								MenuItem newItem = selectableOptions.AddItem(listItem);
								if (newItem.Text == sliceSettingValue)
								{
									selectableOptions.SelectedLabel = sliceSettingValue;
								}

								newItem.Selected += (sender, e) =>
								{
									MenuItem menuItem = ((MenuItem)sender);
									ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, menuItem.Text, persistenceLayer);

									settingsRow.UpdateStyle();

									OnSettingsChanged(settingData);
								};
							}

							dataArea.AddChild(selectableOptions);

							settingsRow.ValueChanged = (text) =>
							{
								selectableOptions.SelectedLabel = text;
							};
						}
						break;

					case SliceSettingData.DataEditTypes.HARDWARE_PRESENT:
						{
							var checkBoxWidget = new CheckBox("")
							{
								Name = settingData.PresentationName + " Checkbox",
								ToolTipText = settingData.HelpText,
								VAnchor = Agg.UI.VAnchor.ParentBottom,
								TextColor = ActiveTheme.Instance.PrimaryTextColor,
								Checked = sliceSettingValue == "1"
							};

							checkBoxWidget.Click += (sender, e) =>
							{
								bool isChecked = ((CheckBox)sender).Checked;
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0", persistenceLayer);

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							dataArea.AddChild(checkBoxWidget);

							settingsRow.ValueChanged = (text) =>
							{
								checkBoxWidget.Checked = text == "1";
							};
						}
						break;

					case SliceSettingData.DataEditTypes.VECTOR2:
						{
							string[] xyValueStrings = sliceSettingValue.Split(',');
							if (xyValueStrings.Length != 2)
							{
								xyValueStrings = new string[] { "0", "0" };
							}

							double currentXValue;
							double.TryParse(xyValueStrings[0], out currentXValue);

							var xEditWidget = new MHNumberEdit(currentXValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};

							double currentYValue;
							double.TryParse(xyValueStrings[1], out currentYValue);

							var yEditWidget = new MHNumberEdit(currentYValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true,
								Margin = new BorderDouble(20, 0, 0, 0),
							};

							xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer);

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(xEditWidget);
							dataArea.AddChild(new TextWidget("X", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
							{
								VAnchor = VAnchor.ParentCenter,
								Margin = new BorderDouble(5, 0),
							});

							yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								ActiveSliceSettings.Instance.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer);

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(yEditWidget);
							var yLabel = new GuiWidget(HAnchor.ParentLeftRight, VAnchor.FitToChildren | VAnchor.ParentCenter)
							{
								Padding = new BorderDouble(5, 0),
								HAnchor = HAnchor.ParentLeftRight,
							};
							yLabel.AddChild(new WrappedTextWidget("Y", pointSize: 9, textColor: ActiveTheme.Instance.PrimaryTextColor));
							unitsArea.AddChild(yLabel);

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2;
								string[] xyValueStrings2 = text.Split(',');
								if (xyValueStrings2.Length != 2)
								{
									xyValueStrings2 = new string[] { "0", "0" };
								}

								double.TryParse(xyValueStrings2[0], out currentValue2);
								xEditWidget.ActuallNumberEdit.Value = currentValue2;

								double.TryParse(xyValueStrings2[1], out currentValue2);
								yEditWidget.ActuallNumberEdit.Value = currentValue2;
							};

						}
						break;

					case SliceSettingData.DataEditTypes.OFFSET2:
						{
							Vector2 offset = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(extruderIndex);

							var xEditWidget = new MHNumberEdit(offset.x, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true,
							};

							var yEditWidget = new MHNumberEdit(offset.y, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true,
								Margin = new BorderDouble(20, 0, 0, 0),
							};

							xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								int extruderIndexLocal = extruderIndex;
								SaveCommaSeparatedIndexSetting(extruderIndexLocal, layerCascade, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer);

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(xEditWidget);
							dataArea.AddChild(new TextWidget("X", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
							{
								VAnchor = VAnchor.ParentCenter,
								Margin = new BorderDouble(5, 0),
							});

							yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								int extruderIndexLocal = extruderIndex;
								SaveCommaSeparatedIndexSetting(extruderIndexLocal, layerCascade, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString(), persistenceLayer);

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							dataArea.AddChild(yEditWidget);
							var yLabel = new GuiWidget(HAnchor.ParentLeftRight, VAnchor.FitToChildren | VAnchor.ParentCenter)
							{
								Padding = new BorderDouble(5, 0),
								HAnchor = HAnchor.ParentLeftRight,
							};
							yLabel.AddChild(new WrappedTextWidget("Y", pointSize: 9, textColor: ActiveTheme.Instance.PrimaryTextColor));
							unitsArea.AddChild(yLabel);

							settingsRow.ValueChanged = (text) =>
							{
								Vector2 offset2 = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(extruderIndex);
								xEditWidget.ActuallNumberEdit.Value = offset2.x;
								yEditWidget.ActuallNumberEdit.Value = offset2.y;
							};
						}
						break;

					default:
						var missingSetting = new TextWidget(String.Format("Missing the setting for '{0}'.", settingData.DataEditType.ToString()))
						{
							TextColor = ActiveTheme.Instance.PrimaryTextColor,
							BackgroundColor = RGBA_Bytes.Red
						};
						dataArea.AddChild(missingSetting);
						break;
				}
			}

			container.HAnchor = HAnchor.ParentLeftRight;
			container.VAnchor = VAnchor.FitToChildren;

			Button restoreButton = null;
			if (settingData.ShowAsOverride)
			{
				restoreButton = new Button(new ButtonViewStates(new ImageWidget(restoreNormal), new ImageWidget(restoreHover), new ImageWidget(restorePressed), new ImageWidget(restoreNormal)))
				{
					Name = "Restore " + settingData.SlicerConfigName,
					VAnchor = VAnchor.ParentCenter,
					Margin = new BorderDouble(0, 0, 5, 0),
					ToolTipText = "Restore Default".Localize()
				};

				restoreButton.Click += (sender, e) =>
				{
					// Revert the user override 
					if (persistenceLayer == null)
					{
						ActiveSliceSettings.Instance.ClearValue(settingData.SlicerConfigName);
					}
					else
					{
						ActiveSliceSettings.Instance.ClearValue(settingData.SlicerConfigName, persistenceLayer);
					}

					settingsRow.RefreshValue(layerCascade);
					OnSettingsChanged(settingData);
				};

				restoreArea.AddChild(restoreButton);
			}

			container.AddChild(settingsRow);

			// Define the UpdateStyle implementation
			settingsRow.UpdateStyle = () =>
			{
				if (persistenceLayer.ContainsKey(settingData.SlicerConfigName))
				{
					switch (viewFilter)
					{
						case NamedSettingsLayers.All:
							if (settingData.ShowAsOverride)
							{
								settingsRow.BackgroundColor = userSettingBackgroundColor;
							}
							break;
						case NamedSettingsLayers.Material:
							settingsRow.BackgroundColor = materialSettingBackgroundColor;
							break;
						case NamedSettingsLayers.Quality:
							settingsRow.BackgroundColor = qualitySettingBackgroundColor;
							break;
					}

					if(restoreButton != null) restoreButton.Visible = true;
				}
				else if (layerCascade == null)
				{
					if (ActiveSliceSettings.Instance.SettingExistsInLayer(settingData.SlicerConfigName, NamedSettingsLayers.Material))
					{
						settingsRow.BackgroundColor = materialSettingBackgroundColor;
					}
					else if (ActiveSliceSettings.Instance.SettingExistsInLayer(settingData.SlicerConfigName, NamedSettingsLayers.Quality))
					{
						settingsRow.BackgroundColor = qualitySettingBackgroundColor;
					}
					else
					{
						settingsRow.BackgroundColor = RGBA_Bytes.Transparent;
					}

					if (restoreButton != null) restoreButton.Visible = false;
				}
				else
				{
					if (restoreButton != null) restoreButton.Visible = false;
					settingsRow.BackgroundColor = RGBA_Bytes.Transparent;
				}
			};

			// Invoke the UpdateStyle implementation
			settingsRow.UpdateStyle();

			return container;
		}
        private AdjustmentControls(PrinterConfig printer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            double sliderWidth      = 300 * GuiWidget.DeviceScale;
            double sliderThumbWidth = 10 * GuiWidget.DeviceScale;

            Color sliderTrackColor = theme.Colors.IsDarkTheme ? new Color(theme.Shade, 65) : theme.SlightShade;

            SettingsRow settingsRow;

            {
                this.AddChild(settingsRow = new SettingsRow(
                                  "Speed Multiplier".Localize(),
                                  null,
                                  theme));

                // Remove the HorizontalSpacer
                settingsRow.Children.Last().Close();

                feedRateRatioSlider = new SolidSlider(new Vector2(), sliderThumbWidth, minFeedRateRatio, maxFeedRateRatio)
                {
                    Name               = "Feed Rate Slider",
                    Margin             = new BorderDouble(5, 0),
                    Value              = FeedRateMultiplyerStream.FeedRateRatio,
                    HAnchor            = HAnchor.Stretch,
                    VAnchor            = VAnchor.Center,
                    TotalWidthInPixels = sliderWidth,
                };
                feedRateRatioSlider.View.TrackColor  = sliderTrackColor;
                feedRateRatioSlider.View.TrackRadius = 4;
                feedRateRatioSlider.ValueChanged    += (sender, e) =>
                {
                    feedRateValue.ActuallNumberEdit.Value = Math.Round(feedRateRatioSlider.Value, 2);
                };
                feedRateRatioSlider.SliderReleased += (s, e) =>
                {
                    // Update state for runtime use
                    FeedRateMultiplyerStream.FeedRateRatio = Math.Round(feedRateRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.feedrate_ratio,
                        FeedRateMultiplyerStream.FeedRateRatio.ToString());
                };
                settingsRow.AddChild(feedRateRatioSlider);

                feedRateValue = new MHNumberEdit(Math.Round(FeedRateMultiplyerStream.FeedRateRatio, 2), allowDecimals: true, minValue: minFeedRateRatio, maxValue: maxFeedRateRatio, pixelWidth: 40 * GuiWidget.DeviceScale)
                {
                    Name             = "Feed Rate NumberEdit",
                    SelectAllOnFocus = true,
                    Margin           = new BorderDouble(0, 0, 5, 0),
                    VAnchor          = VAnchor.Center | VAnchor.Fit,
                    Padding          = 0
                };
                feedRateValue.ActuallNumberEdit.EditComplete += (sender, e) =>
                {
                    feedRateRatioSlider.Value = feedRateValue.ActuallNumberEdit.Value;

                    // Update state for runtime use
                    FeedRateMultiplyerStream.FeedRateRatio = Math.Round(feedRateRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.feedrate_ratio,
                        FeedRateMultiplyerStream.FeedRateRatio.ToString());
                };
                settingsRow.AddChild(feedRateValue);
            }

            {
                this.AddChild(settingsRow = new SettingsRow(
                                  "Extrusion Multiplier".Localize(),
                                  null,
                                  theme));

                // Remove the HorizontalSpacer
                settingsRow.Children.Last().Close();

                extrusionRatioSlider = new SolidSlider(new Vector2(), sliderThumbWidth, minExtrutionRatio, maxExtrusionRatio, Orientation.Horizontal)
                {
                    Name = "Extrusion Multiplier Slider",
                    TotalWidthInPixels = sliderWidth,
                    HAnchor            = HAnchor.Stretch,
                    VAnchor            = VAnchor.Center,
                    Margin             = new BorderDouble(5, 0),
                    Value = ExtrusionMultiplyerStream.ExtrusionRatio
                };
                extrusionRatioSlider.View.TrackColor  = sliderTrackColor;
                extrusionRatioSlider.View.TrackRadius = 4;
                extrusionRatioSlider.ValueChanged    += (sender, e) =>
                {
                    extrusionValue.ActuallNumberEdit.Value = Math.Round(extrusionRatioSlider.Value, 2);
                };
                extrusionRatioSlider.SliderReleased += (s, e) =>
                {
                    // Update state for runtime use
                    ExtrusionMultiplyerStream.ExtrusionRatio = Math.Round(extrusionRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.extrusion_ratio,
                        ExtrusionMultiplyerStream.ExtrusionRatio.ToString());
                };
                settingsRow.AddChild(extrusionRatioSlider);

                extrusionValue = new MHNumberEdit(Math.Round(ExtrusionMultiplyerStream.ExtrusionRatio, 2), allowDecimals: true, minValue: minExtrutionRatio, maxValue: maxExtrusionRatio, pixelWidth: 40 * GuiWidget.DeviceScale)
                {
                    Name             = "Extrusion Multiplier NumberEdit",
                    SelectAllOnFocus = true,
                    Margin           = new BorderDouble(0, 0, 5, 0),
                    VAnchor          = VAnchor.Center | VAnchor.Fit,
                    Padding          = 0
                };
                extrusionValue.ActuallNumberEdit.EditComplete += (sender, e) =>
                {
                    extrusionRatioSlider.Value = extrusionValue.ActuallNumberEdit.Value;

                    // Update state for runtime use
                    ExtrusionMultiplyerStream.ExtrusionRatio = Math.Round(extrusionRatioSlider.Value, 2);

                    // Persist data for future use
                    printer.Settings.SetValue(
                        SettingsKey.extrusion_ratio,
                        ExtrusionMultiplyerStream.ExtrusionRatio.ToString());
                };
                settingsRow.AddChild(extrusionValue);
            }

            ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
            {
                var eventArgs = e as StringEventArgs;
                if (eventArgs?.Data == SettingsKey.extrusion_ratio)
                {
                    double extrusionRatio                  = printer.Settings.GetValue <double>(SettingsKey.extrusion_ratio);
                    extrusionRatioSlider.Value             = extrusionRatio;
                    extrusionValue.ActuallNumberEdit.Value = Math.Round(extrusionRatio, 2);
                }
                else if (eventArgs?.Data == SettingsKey.feedrate_ratio)
                {
                    double feedrateRatio                  = printer.Settings.GetValue <double>(SettingsKey.feedrate_ratio);
                    feedRateRatioSlider.Value             = feedrateRatio;
                    feedRateValue.ActuallNumberEdit.Value = Math.Round(feedrateRatio, 2);
                }
            }, ref unregisterEvents);
        }
Example #14
0
        public ValidationErrorsPanel(IEnumerable <ValidationError> errors, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor         = HAnchor.Absolute;
            this.VAnchor         = VAnchor.Fit | VAnchor;
            this.BackgroundColor = theme.ResolveColor(theme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30));

            var errorImage   = AggContext.StaticData.LoadIcon("SettingsGroupError_16x.png", 16, 16, theme.InvertIcons);
            var warningImage = AggContext.StaticData.LoadIcon("SettingsGroupWarning_16x.png", 16, 16, theme.InvertIcons);
            var infoImage    = AggContext.StaticData.LoadIcon("StatusInfoTip_16x.png", 16, 16);
            var fixIcon      = AggContext.StaticData.LoadIcon("noun_1306.png", 16, 16, theme.InvertIcons);

            foreach (var validationError in errors.OrderByDescending(e => e.ErrorLevel))
            {
                string errorText, errorDetails;

                var settingsValidationError = validationError as SettingsValidationError;
                if (settingsValidationError != null)
                {
                    errorText = string.Format(
                        "{0} {1}",
                        settingsValidationError.PresentationName,
                        validationError.ErrorLevel == ValidationErrorLevel.Error ? "Error".Localize() : "Warning".Localize());

                    errorDetails = validationError.Error;
                }
                else
                {
                    errorText    = validationError.Error;
                    errorDetails = validationError.Details ?? "";
                }

                var row = new SettingsRow(errorText, errorDetails, theme, validationError.ErrorLevel == ValidationErrorLevel.Error ? errorImage : warningImage)
                {
                    ArrowDirection = ArrowDirection.Left
                };

                if (validationError.FixAction is NamedAction action)
                {
                    // Show fix button
                    var button = new IconButton(fixIcon, theme)
                    {
                        ToolTipText = action.Title
                    };

                    if (!string.IsNullOrEmpty(action.ID))
                    {
                        button.Name = action.ID;
                    }

                    button.Click += (s, e) =>
                    {
                        action.Action.Invoke();
                    };

                    row.AddChild(button);
                }
                else
                {
                    // Show info indicator hinting that hover will reveal additional details
                    var button = new IconButton(infoImage, theme)
                    {
                        Selectable = false
                    };
                    row.AddChild(button);
                }

                this.AddChild(row);
            }
        }
		private GuiWidget CreateSettingInfoUIControls(OrganizerSettingsData settingData, double minSettingNameWidth, int extruderIndex)
		{
			GuiWidget container = new GuiWidget();
			this.HAnchor = HAnchor.ParentLeftRight;

			string sliceSettingValue = ActiveSliceSettings.Instance.GetActiveValue(settingData.SlicerConfigName);

			var settingsRow = new SettingsRow()
			{
				SettingsKey = settingData.SlicerConfigName,
				SettingsValue = sliceSettingValue
			};

			if (!ActiveSliceSettings.Instance.InBaseConfig(settingData.SlicerConfigName))
			{
				// the setting we think we are adding is not in the config.ini it may have been deprecated
				TextWidget settingName = new TextWidget(String.Format("Setting '{0}' not found in config.ini", settingData.SlicerConfigName));
				settingName.TextColor = ActiveTheme.Instance.PrimaryTextColor;
				settingName.MinimumSize = new Vector2(minSettingNameWidth, settingName.MinimumSize.y);
				settingsRow.AddChild(settingName);
				settingsRow.BackgroundColor = RGBA_Bytes.Red;
			}
			else
			{
				int intEditWidth = (int)(60 * TextWidget.GlobalPointSizeScaleRatio + .5);
				int doubleEditWidth = (int)(60 * TextWidget.GlobalPointSizeScaleRatio + .5);
				if (settingData.QuickMenuSettings.Count > 0)
				{
					doubleEditWidth = (int)(35 * TextWidget.GlobalPointSizeScaleRatio + .5);
				}
				int vectorXYEditWidth = (int)(60 * TextWidget.GlobalPointSizeScaleRatio + .5);
				int multiLineEditHeight = (int)(60 * TextWidget.GlobalPointSizeScaleRatio + .5);


				if (settingData.DataEditType != OrganizerSettingsData.DataEditTypes.MULTI_LINE_TEXT)
				{
					var nameHolder = new GuiWidget(HAnchor.AbsolutePosition, VAnchor.FitToChildren | VAnchor.ParentCenter)
					{
						Width = minSettingNameWidth,
						Padding = new BorderDouble(0, 0, 5, 0),
					};

					nameHolder.AddChild(new WrappedTextWidget(
						settingData.PresentationName.Localize(), 
						minSettingNameWidth, 
						pointSize: 10, 
						textColor: ActiveTheme.Instance.PrimaryTextColor));

					settingsRow.AddChild(nameHolder);
				}

				switch (settingData.DataEditType)
				{
					case OrganizerSettingsData.DataEditTypes.INT:
						{
							int currentValue;
							int.TryParse(sliceSettingValue, out currentValue);

							var intEditWidget = new MHNumberEdit(currentValue, pixelWidth: intEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};
							intEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							settingsRow.AddChild(intEditWidget);
							settingsRow.AddChild(GetExtraSettingsWidget(settingData));

							settingsRow.ValueChanged = (text) => intEditWidget.Text = text;
						}
						break;

					case OrganizerSettingsData.DataEditTypes.DOUBLE:
						{
							double currentValue;
							double.TryParse(sliceSettingValue, out currentValue);

							var doubleEditWidget = new MHNumberEdit(currentValue, allowNegatives: true, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(doubleEditWidget);
							settingsRow.AddChild(GetExtraSettingsWidget(settingData));

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2 = 0;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case OrganizerSettingsData.DataEditTypes.POSITIVE_DOUBLE:
						{
							const string multiValuesAreDiffernt = "-";
							FlowLayoutWidget content = new FlowLayoutWidget();

							var doubleEditWidget = new MHNumberEdit(0, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								Name = settingData.PresentationName + " Textbox",
								SelectAllOnFocus = true
							};

							double currentValue;
							bool ChangesMultipleOtherSettings = settingData.SetSettingsOnChange.Count > 0;
							if (ChangesMultipleOtherSettings)
							{
								bool allTheSame = true;
								string setting = ActiveSliceSettings.Instance.GetActiveValue(settingData.SetSettingsOnChange[0]);
								for (int i = 1; i < settingData.SetSettingsOnChange.Count; i++)
								{
									string nextSetting = ActiveSliceSettings.Instance.GetActiveValue(settingData.SetSettingsOnChange[i]);
									if (setting != nextSetting)
									{
										allTheSame = false;
										break;
									}
								}

								if (allTheSame && setting.EndsWith("mm"))
								{
									double.TryParse(setting.Substring(0, setting.Length - 2), out currentValue);
									doubleEditWidget.ActuallNumberEdit.Value = currentValue;
								}
								else
								{
									doubleEditWidget.ActuallNumberEdit.InternalNumberEdit.Text = multiValuesAreDiffernt;
								}
							}
							else // just set the setting normally
							{
								double.TryParse(sliceSettingValue, out currentValue);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue;
							}
							doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget.MarkAsStartingState();
							
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								NumberEdit numberEdit = (NumberEdit)sender;
								// If this setting sets other settings, then do that.
								if (ChangesMultipleOtherSettings
									&& numberEdit.Text != multiValuesAreDiffernt)
								{
									foreach (string setting in settingData.SetSettingsOnChange)
									{
										SaveSetting(setting, numberEdit.Value.ToString() + "mm");
									}
								}

								// also always save to the local setting
								SaveSetting(settingData.SlicerConfigName, numberEdit.Value.ToString());
								settingsRow.UpdateStyle();
								OnSettingsChanged(settingData);
							};
							content.AddChild(doubleEditWidget);
							content.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								settingsRow.AddChild(CreateQuickMenu(settingData, content, doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget));
							}
							else
							{
								settingsRow.AddChild(content);
							}

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2 = 0;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case OrganizerSettingsData.DataEditTypes.OFFSET:
						{
							double currentValue;
							double.TryParse(sliceSettingValue, out currentValue);
							var doubleEditWidget = new MHNumberEdit(currentValue, allowDecimals: true, allowNegatives: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true

							};
							doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
								settingsRow.UpdateStyle();
								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(doubleEditWidget);
							settingsRow.AddChild(GetExtraSettingsWidget(settingData));

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2;
								double.TryParse(text, out currentValue2);
								doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
							};
						}
						break;

					case OrganizerSettingsData.DataEditTypes.DOUBLE_OR_PERCENT:
						{
							FlowLayoutWidget content = new FlowLayoutWidget();

							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								var textEditWidget = (TextEditWidget)sender;
								string text = textEditWidget.Text.Trim();

								bool isPercent = text.Contains("%");
								if (isPercent)
								{
									text = text.Substring(0, text.IndexOf("%"));
								}
								double result;
								double.TryParse(text, out result);
								text = result.ToString();
								if (isPercent)
								{
									text += "%";
								}
								textEditWidget.Text = text;
								SaveSetting(settingData.SlicerConfigName, textEditWidget.Text);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
							{
								// select everything up to the % (if present)
								InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
								int percentIndex = textEditWidget.Text.IndexOf("%");
								if (percentIndex != -1)
								{
									textEditWidget.SetSelection(0, percentIndex - 1);
								}
							};

							content.AddChild(stringEdit);
							content.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								settingsRow.AddChild(CreateQuickMenu(settingData, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget));
							}
							else
							{
								settingsRow.AddChild(content);
							}

							settingsRow.ValueChanged = (text) => stringEdit.Text = text;
						}
						break;

					case OrganizerSettingsData.DataEditTypes.INT_OR_MM:
						{
							FlowLayoutWidget content = new FlowLayoutWidget();

							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};

							string startingText = stringEdit.Text;
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								TextEditWidget textEditWidget = (TextEditWidget)sender;
								// only validate when we lose focus
								if (!textEditWidget.ContainsFocus)
								{
									string text = textEditWidget.Text;
									text = text.Trim();
									bool isMm = text.Contains("mm");
									if (isMm)
									{
										text = text.Substring(0, text.IndexOf("mm"));
									}
									double result;
									double.TryParse(text, out result);
									text = result.ToString();
									if (isMm)
									{
										text += "mm";
									}
									else
									{
										result = (int)result;
										text = result.ToString();
									}
									textEditWidget.Text = text;
									startingText = stringEdit.Text;
								}
								SaveSetting(settingData.SlicerConfigName, textEditWidget.Text);

								OnSettingsChanged(settingData);

								// make sure we are still looking for the final validation before saving.
								if (textEditWidget.ContainsFocus)
								{
									UiThread.RunOnIdle(() =>
									{
										string currentText = textEditWidget.Text;
										int cursorIndex = textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore;
										textEditWidget.Text = startingText;
										textEditWidget.InternalTextEditWidget.MarkAsStartingState();
										textEditWidget.Text = currentText;
										textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore = cursorIndex;
									});
								}
							};

							stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
							{
								// select everything up to the mm (if present)
								InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
								int mMIndex = textEditWidget.Text.IndexOf("mm");
								if (mMIndex != -1)
								{
									textEditWidget.SetSelection(0, mMIndex - 1);
								}
							};

							content.AddChild(stringEdit);
							content.AddChild(GetExtraSettingsWidget(settingData));

							if (settingData.QuickMenuSettings.Count > 0)
							{
								settingsRow.AddChild(CreateQuickMenu(settingData, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget));
							}
							else
							{
								settingsRow.AddChild(content);
							}

							settingsRow.ValueChanged = (text) => stringEdit.Text = text;
						}
						break;

					case OrganizerSettingsData.DataEditTypes.CHECK_BOX:
						{
							var checkBoxWidget = new CheckBox("")
							{
								Name = settingData.PresentationName + " Checkbox",
								ToolTipText = settingData.HelpText,
								VAnchor = Agg.UI.VAnchor.ParentBottom,
								TextColor = ActiveTheme.Instance.PrimaryTextColor,
								Checked = sliceSettingValue == "1"
							};
							checkBoxWidget.CheckedStateChanged += (sender, e) =>
							{
								bool isChecked = ((CheckBox)sender).Checked;
								SaveSetting(settingData.SlicerConfigName, isChecked ? "1" : "0");
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							settingsRow.AddChild(checkBoxWidget);

							settingsRow.ValueChanged = (text) => checkBoxWidget.Checked = text == "1";
						}
						break;

					case OrganizerSettingsData.DataEditTypes.STRING:
						{
							var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: 120, tabIndex: tabIndexForItem++);
							stringEdit.ToolTipText = settingData.HelpText;
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, ((TextEditWidget)sender).Text);
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							settingsRow.AddChild(stringEdit);

							settingsRow.ValueChanged = (text) => stringEdit.Text = text;
						}
						break;

					case OrganizerSettingsData.DataEditTypes.MULTI_LINE_TEXT:
						{
							string convertedNewLines = sliceSettingValue.Replace("\\n", "\n");
							var stringEdit = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndexForItem++);
							
							stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"));
								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							settingsRow.AddChild(stringEdit);

							settingsRow.ValueChanged = (text) => stringEdit.Text = text.Replace("\\n", "\n");
						}
						break;

					case OrganizerSettingsData.DataEditTypes.LIST:
						{
							var selectableOptions = new StyledDropDownList("None", maxHeight: 200)
							{
								ToolTipText = settingData.HelpText,
								Margin = new BorderDouble()
							};

							foreach (string listItem in settingData.ExtraSettings.Split(','))
							{
								MenuItem newItem = selectableOptions.AddItem(listItem);
								if (newItem.Text == sliceSettingValue)
								{
									selectableOptions.SelectedLabel = sliceSettingValue;
								}

								newItem.Selected += (sender, e) =>
								{
									MenuItem menuItem = ((MenuItem)sender);
									SaveSetting(settingData.SlicerConfigName, menuItem.Text);

									settingsRow.UpdateStyle();

									OnSettingsChanged(settingData);
								};
							}

							settingsRow.AddChild(selectableOptions);

							settingsRow.ValueChanged = (text) => selectableOptions.SelectedLabel = text;
						}
						break;

					case OrganizerSettingsData.DataEditTypes.HARDWARE_PRESENT:
						{
							var checkBoxWidget = new CheckBox("")
							{
								Name = settingData.PresentationName + " Checkbox",
								ToolTipText = settingData.HelpText,
								VAnchor = Agg.UI.VAnchor.ParentBottom,
								TextColor = ActiveTheme.Instance.PrimaryTextColor,
								Checked = sliceSettingValue == "1"
							};

							checkBoxWidget.CheckedStateChanged += (sender, e) =>
							{
								bool isChecked = ((CheckBox)sender).Checked;
								SaveSetting(settingData.SlicerConfigName, isChecked ? "1" : "0");

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};

							settingsRow.AddChild(checkBoxWidget);

							settingsRow.ValueChanged = (text) => checkBoxWidget.Checked = text == "1";
						}
						break;

					case OrganizerSettingsData.DataEditTypes.VECTOR2:
						{
							string[] xyValueStrings = sliceSettingValue.Split(',');
							if (xyValueStrings.Length != 2)
							{
								xyValueStrings = new string[] { "0", "0" };
							}

							double currentXValue;
							double.TryParse(xyValueStrings[0], out currentXValue);

							var xEditWidget = new MHNumberEdit(currentXValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								Margin = new BorderDouble(0, 0, 30 * TextWidget.GlobalPointSizeScaleRatio, 0),
								SelectAllOnFocus = true
							};

							double currentYValue;
							double.TryParse(xyValueStrings[1], out currentYValue);

							var yEditWidget = new MHNumberEdit(currentYValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};

							xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(xEditWidget);

							yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								SaveSetting(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(yEditWidget);

							settingsRow.ValueChanged = (text) =>
							{
								double currentValue2;
								string[] xyValueStrings2 = text.Split(',');
								if (xyValueStrings2.Length != 2)
								{
									xyValueStrings2 = new string[] { "0", "0" };
								}

								double.TryParse(xyValueStrings2[0], out currentValue2);
								xEditWidget.ActuallNumberEdit.Value = currentValue2;

								double.TryParse(xyValueStrings2[1], out currentValue2);
								yEditWidget.ActuallNumberEdit.Value = currentValue2;
							};

						}
						break;

					case OrganizerSettingsData.DataEditTypes.OFFSET2:
						{
							Vector2 offset = ActiveSliceSettings.Instance.GetOffset(extruderIndex);

							var xEditWidget = new MHNumberEdit(offset.x, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true,
								Margin = new BorderDouble(0, 0, 30 * TextWidget.GlobalPointSizeScaleRatio, 0)
							};

							var yEditWidget = new MHNumberEdit(offset.y, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
							{
								ToolTipText = settingData.HelpText,
								SelectAllOnFocus = true
							};

							xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								int extruderIndexLocal = extruderIndex;
								SaveCommaSeparatedIndexSetting(extruderIndexLocal, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(xEditWidget);


							yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
							{
								int extruderIndexLocal = extruderIndex;
								SaveCommaSeparatedIndexSetting(extruderIndexLocal, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());

								settingsRow.UpdateStyle();

								OnSettingsChanged(settingData);
							};
							settingsRow.AddChild(yEditWidget);

							settingsRow.ValueChanged = (text) =>
							{
								Vector2 offset2 = ActiveSliceSettings.Instance.GetOffset(extruderIndex);
								xEditWidget.ActuallNumberEdit.Value = offset2.x;
								yEditWidget.ActuallNumberEdit.Value = offset2.y;
							};

						}
						break;

					default:
						var missingSetting = new TextWidget(String.Format("Missing the setting for '{0}'.", settingData.DataEditType.ToString()))
						{
							TextColor = ActiveTheme.Instance.PrimaryTextColor,
							BackgroundColor = RGBA_Bytes.Red
						};
						settingsRow.AddChild(missingSetting);
						break;
				}
			}

			container.HAnchor = HAnchor.ParentLeftRight;
			container.VAnchor = VAnchor.FitToChildren;

			var restoreButton = new Button(new ButtonViewStates(new ImageWidget(restoreNormal), new ImageWidget(restoreHover), new ImageWidget(restorePressed), new ImageWidget(restoreNormal)))
			{
				Name = "Restore " + settingData.SlicerConfigName,
				VAnchor = VAnchor.ParentCenter,
				Margin = new BorderDouble(0, 0, 5, 0),
				ToolTipText = "Restore Default".Localize()
			};

			restoreButton.Click += (sender, e) =>
			{
				// Revert the user override 
				if (persistenceLayer == null)
				{
					ActiveSliceSettings.Instance.ClearValue(settingData.SlicerConfigName);
				}
				else
				{
					ActiveSliceSettings.Instance.ClearValue(settingData.SlicerConfigName, persistenceLayer);
				}

				settingsRow.RefreshValue();
			};

			settingsRow.AddChild(new GuiWidget(HAnchor.ParentLeftRight));
			settingsRow.AddChild(restoreButton);

			container.AddChild(settingsRow);

			// Define the UpdateStyle implementation
			settingsRow.UpdateStyle = () =>
			{
				if (persistenceLayer.ContainsKey(settingData.SlicerConfigName))
				{
					switch (this.viewFilter)
					{
						case NamedSettingsLayers.All:
							settingsRow.BackgroundColor = userSettingBackgroundColor;
							break;
						case NamedSettingsLayers.Material:
							settingsRow.BackgroundColor = materialSettingBackgroundColor;
							break;
						case NamedSettingsLayers.Quality:
							settingsRow.BackgroundColor = qualitySettingBackgroundColor;
							break;
					}

					restoreButton.Visible = true;
				}
				else if (layerFilters == null)
				{
					if (ActiveSliceSettings.Instance.SettingExistsInLayer(settingData.SlicerConfigName, NamedSettingsLayers.Material))
					{
						settingsRow.BackgroundColor = materialSettingBackgroundColor;
					}
					else if (ActiveSliceSettings.Instance.SettingExistsInLayer(settingData.SlicerConfigName, NamedSettingsLayers.Quality))
					{
						settingsRow.BackgroundColor = qualitySettingBackgroundColor;
					}
					else
					{
						settingsRow.BackgroundColor = RGBA_Bytes.Transparent;
					}

					restoreButton.Visible = false;
				}
				else
				{
					restoreButton.Visible = false;
					settingsRow.BackgroundColor = RGBA_Bytes.Transparent;
				}
			};

			// Invoke the UpdateStyle implementation
			settingsRow.UpdateStyle();

			return container;
		}