Beispiel #1
0
        public ProbePositionsWidget(PrinterConfig printer, List <Vector2> probePoints, List <ProbePosition> probePositions, ThemeConfig theme)
        {
            this.probePoints    = probePoints;
            this.probePositions = probePositions;
            this.printer        = printer;
            this.VAnchor        = VAnchor.Absolute;
            this.theme          = theme;

            extraLightColor     = theme.BackgroundColor.Blend(theme.TextColor, 0.1);
            lightColor          = theme.BackgroundColor.Blend(theme.TextColor, 0.2);
            opaqueMinimumAccent = theme.ResolveColor(theme.BackgroundColor, theme.AccentMimimalOverlay);
            opaqueAccent        = theme.ResolveColor(theme.BackgroundColor, theme.AccentMimimalOverlay.WithAlpha(140));

            bedBounds   = printer.Bed.Bounds;
            circularBed = printer.Settings.GetValue <BedShape>(SettingsKey.bed_shape) == BedShape.Circular;
        }
        public ThemeColorPanel(ThemeConfig theme, AccentColorsWidget colorSelector)
            : base(FlowDirection.TopToBottom)
        {
            this.colorSelector = colorSelector;
            this.theme         = theme;

            string currentProviderName = UserSettings.Instance.get(UserSettingsKey.ThemeName) ?? "";

            if (AppContext.ThemeProviders.TryGetValue(currentProviderName, out IColorTheme currentProvider))
            {
                _themeProvider = currentProvider;
            }
            else
            {
                _themeProvider = AppContext.ThemeProviders.Values.First();
            }

            accentPanelColor = theme.ResolveColor(theme.SectionBackgroundColor, theme.SlightShade);

            this.SelectionColor = theme.MinimalShade;

            this.AddChild(previewButtonPanel = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit,
                //BackgroundColor = activeTheme.MinimalShade
            });

            this.CreateThemeModeButtons();
        }
Beispiel #3
0
        public FloorDrawable(InteractionLayer.EditorType editorType, ISceneContext sceneContext, Color buildVolumeColor, ThemeConfig theme)
        {
            this.buildVolumeColor = buildVolumeColor;
            this.sceneContext     = sceneContext;
            this.editorType       = editorType;
            this.theme            = theme;

            bedColor      = theme.ResolveColor(Color.White, theme.BackgroundColor.WithAlpha(111));
            underBedColor = new Color(bedColor, bedColor.alpha / 4);

            gridColors = new GridColors()
            {
                Gray  = theme.ResolveColor(theme.BackgroundColor, theme.GetBorderColor((theme.IsDarkTheme ? 35 : 55))),
                Red   = theme.ResolveColor(theme.BackgroundColor, new Color(Color.Red, (theme.IsDarkTheme ? 105 : 170))),
                Green = theme.ResolveColor(theme.BackgroundColor, new Color(Color.Green, (theme.IsDarkTheme ? 105 : 170))),
                Blue  = theme.ResolveColor(theme.BackgroundColor, new Color(Color.Blue, 195))
            };
        }
Beispiel #4
0
        public MeshViewerWidget(BedConfig sceneContext, InteractionLayer interactionLayer, ThemeConfig theme, EditorType editorType = EditorType.Part)
        {
            this.EditorMode       = editorType;
            this.scene            = sceneContext.Scene;
            this.sceneContext     = sceneContext;
            this.interactionLayer = interactionLayer;
            this.World            = interactionLayer.World;
            this.theme            = theme;

            gridColors = new GridColors()
            {
                Gray  = theme.ResolveColor(theme.ActiveTabColor, theme.GetBorderColor((theme.IsDarkTheme ? 35 : 55))),
                Red   = theme.ResolveColor(theme.ActiveTabColor, new Color(Color.Red, (theme.IsDarkTheme ? 105 : 170))),
                Green = theme.ResolveColor(theme.ActiveTabColor, new Color(Color.Green, (theme.IsDarkTheme ? 105 : 170))),
                Blue  = theme.ResolveColor(theme.ActiveTabColor, new Color(Color.Blue, 195))
            };

            gCodeMeshColor = new Color(theme.Colors.PrimaryAccentColor, 35);

            scene.SelectionChanged += (sender, e) =>
            {
                Invalidate();
                lastSelectionChangedMs = UiThread.CurrentTimerMs;
            };

            BuildVolumeColor = new ColorF(.2, .8, .3, .2).ToColor();

            this.interactionLayer.DrawGlTransparentContent += Draw_GlTransparentContent;

            if (ViewOnlyTexture == null)
            {
                UiThread.RunOnIdle(() =>
                {
                    ViewOnlyTexture = new ImageBuffer(32, 32, 32);
                    var graphics2D  = ViewOnlyTexture.NewGraphics2D();
                    graphics2D.Clear(Color.White);
                    graphics2D.FillRectangle(0, 0, ViewOnlyTexture.Width / 2, ViewOnlyTexture.Height, Color.LightGray);
                    // request the texture so we can set it to repeat
                    var plugin = ImageGlPlugin.GetImageGlPlugin(ViewOnlyTexture, true, true, false);
                });
            }
        }
Beispiel #5
0
        public ProbePositionsWidget(PrinterConfig printer, List <Vector2> probePoints, ThemeConfig theme)
        {
            this.probePoints     = probePoints;
            this.printer         = printer;
            this.VAnchor         = VAnchor.Absolute;
            this.theme           = theme;
            this.BackgroundColor = theme.BedBackgroundColor;

            opaqueMinimumAccent = theme.ResolveColor(theme.BackgroundColor, theme.AccentMimimalOverlay);
            opaqueAccent        = theme.ResolveColor(theme.BackgroundColor, theme.AccentMimimalOverlay.WithAlpha(140));

            circleText = theme.TextColor;
            lightText  = circleText.WithAlpha(100);

            bedTextColor         = theme.PrinterBedTextColor;
            bedCircleColor       = theme.ResolveColor(theme.BedColor, bedTextColor.WithAlpha(50));
            simpleBedCircleColor = theme.ResolveColor(theme.BedColor, bedTextColor.WithAlpha(180));

            bedBounds   = printer.Settings.BedBounds;
            circularBed = printer.Settings.GetValue <BedShape>(SettingsKey.bed_shape) == BedShape.Circular;
        }
Beispiel #6
0
        public ValueTag(string title, string value, BorderDouble padding, int notchSize, int p2, ThemeConfig theme, bool autoBorderColor = true)
            : base(ArrowDirection.Right, padding, notchSize, p2, autoBorderColor)
        {
            this.HAnchor       = HAnchor.Fit;
            this.VAnchor       = VAnchor.Fit;
            this.FlowDirection = FlowDirection.LeftToRight;
            this.TagColor      = theme.ResolveColor(AppContext.Theme.BackgroundColor, theme.AccentMimimalOverlay.WithAlpha(50));

            this.AddChild(
                new TextWidget(title, pointSize: theme.DefaultFontSize - 1, textColor: theme.TextColor)
            {
                Margin = new BorderDouble(right: 12)
            });

            this.AddChild(
                new TextWidget(value, pointSize: theme.DefaultFontSize - 1, textColor: theme.TextColor)
            {
                Margin = new BorderDouble(left: 5)
            });
        }
        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);
            }
        }
        public TourPopover(ProductTour productTour, ThemeConfig theme, RectangleDouble targetBounds)
            : base(ArrowDirection.Left, 0, 7, 0)
        {
            this.HAnchor = HAnchor.Fit;
            this.VAnchor = VAnchor.Fit;
            this.theme   = theme;

            var targetWidget = productTour.ActiveItem.Widget;

            var column = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Fit,
                VAnchor = VAnchor.Fit
            };

            this.AddChild(column);

            var row = new GuiWidget()
            {
                Margin  = new BorderDouble(5),
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Fit
            };

            column.AddChild(row);

            var title = new TextWidget(productTour.ActiveItem.Title, pointSize: theme.DefaultFontSize, textColor: theme.PrimaryAccentColor)
            {
                HAnchor = HAnchor.Left,
                Margin  = new BorderDouble(top: 4, left: 4),
                VAnchor = VAnchor.Center,
            };

            row.AddChild(title);

            var closeButton = theme.CreateSmallResetButton();

            closeButton.HAnchor = HAnchor.Right;
            closeButton.VAnchor = VAnchor.Top;
            closeButton.Margin  = 0;
            closeButton.Click  += (s, e) =>
            {
                this.Parent.CloseOnIdle();
            };

            row.AddChild(closeButton);

            var body = this.CreateBodyWidgets(productTour);

            body.Padding = new BorderDouble(theme.DefaultContainerPadding).Clone(top: 0);
            column.AddChild(body);

            var totalWidth  = this.Width + this.DeviceMarginAndBorder.Width;
            var totalHeight = this.Height + this.DeviceMarginAndBorder.Height;

            var totalBounds = new RectangleDouble(0, 0, totalWidth, totalHeight);

            var targetCenterX = targetWidget.Width / 2;
            var targetCenterY = targetWidget.Height / 2;

            if (targetBounds.Right >= totalBounds.Width)
            {
                if (targetBounds.Bottom < totalBounds.Height / 2)
                {
                    if (targetBounds.Bottom - totalBounds.Height < 0)
                    {
                        // Down arrow
                        this.ArrowDirection = ArrowDirection.Down;

                        // Arrow centered on target in x, to the right
                        totalBounds      = this.GetTotalBounds();
                        this.ArrowOffset = (int)(totalBounds.Right - targetCenterX);

                        // Popover positioned above target, aligned right
                        this.Position = new Vector2(
                            this.LeftForAlignTargetRight(targetBounds.Right, totalBounds),
                            targetBounds.Top + 1);
                    }
                    else
                    {
                        // Right arrow
                        this.ArrowDirection = ArrowDirection.Right;

                        //  Arrow centered on target in y, to the top
                        totalBounds      = this.GetTotalBounds();
                        this.ArrowOffset = (int)(totalBounds.Height - targetCenterY);

                        // Popover positioned left of target, aligned top
                        this.Position = new Vector2(
                            this.LeftForAlignTargetRight(targetBounds.Right, totalBounds),
                            targetBounds.Top - totalBounds.Height);
                    }
                }
                else
                {
                    // Up arrow
                    this.ArrowDirection = ArrowDirection.Up;

                    // Arrow centered on target in x, to the right
                    totalBounds      = this.GetTotalBounds();
                    this.ArrowOffset = (int)(totalBounds.Right - targetCenterX);

                    // Popover positioned below target, aligned right
                    this.Position = new Vector2(
                        this.LeftForAlignTargetRight(targetBounds.Right, totalBounds),
                        targetBounds.Bottom - totalBounds.Height - 1);
                }
            }
            else
            {
                if (targetBounds.Bottom < totalBounds.Height)
                {
                    // Left arrow
                    this.ArrowDirection = ArrowDirection.Left;

                    // Arrow centered on target in y (or top - 20 if target larger than content)
                    totalBounds = this.GetTotalBounds();
                    if (targetWidget.Height > totalBounds.Height)
                    {
                        this.ArrowOffset = 20;
                    }
                    else
                    {
                        this.ArrowOffset = (int)targetCenterY;
                    }

                    // Popover positioned right of target, aligned top
                    this.Position = new Vector2(
                        targetBounds.Right + 1,
                        targetBounds.Top - totalBounds.Height);
                }
                else
                {
                    this.ArrowDirection = ArrowDirection.Up;

                    // Arrow centered on target in x, to the left
                    totalBounds      = this.GetTotalBounds();
                    this.ArrowOffset = (int)targetCenterX;

                    // Popover positioned below target, aligned left
                    this.Position = new Vector2(
                        targetBounds.Left,
                        targetBounds.Bottom - totalBounds.Height - 1);
                }
            }

            this.TagColor = theme.ResolveColor(theme.BackgroundColor, theme.AccentMimimalOverlay.WithAlpha(50));

            this.RebuildShape();
        }
Beispiel #9
0
        public PrinterTabPage(PartWorkspace workspace, ThemeConfig theme, string tabTitle)
            : base(workspace, theme, tabTitle)
        {
            gcodeOptions = sceneContext.RendererOptions;

            view3DWidget.InteractionLayer.EditorMode = InteractionLayer.EditorType.Printer;

            viewControls3D.TransformStateChanged += (s, e) =>
            {
                switch (e.TransformMode)
                {
                case ViewControls3DButtons.Translate:
                    if (gcode2DWidget != null)
                    {
                        gcode2DWidget.TransformState = GCode2DWidget.ETransformState.Move;
                    }
                    break;

                case ViewControls3DButtons.Scale:
                    if (gcode2DWidget != null)
                    {
                        gcode2DWidget.TransformState = GCode2DWidget.ETransformState.Scale;
                    }
                    break;
                }
            };

            viewControls3D.ResetView += (sender, e) =>
            {
                if (gcode2DWidget?.Visible == true)
                {
                    gcode2DWidget.CenterPartInView();
                }
            };

            var opaqueTrackColor = theme.ResolveColor(theme.BedBackgroundColor, theme.SlightShade);

            LayerScrollbar = new SliceLayerSelector(printer, theme)
            {
                VAnchor = VAnchor.Stretch,
                HAnchor = HAnchor.Right | HAnchor.Fit,
                Margin  = new BorderDouble(0, 4, 4, 4),
                Maximum = sceneContext.LoadedGCode?.LayerCount ?? 1
            };
            LayerScrollbar.SolidSlider.View.TrackColor = opaqueTrackColor;
            view3DWidget.InteractionLayer.AddChild(LayerScrollbar);

            layerRenderRatioSlider                    = new DoubleSolidSlider(new Vector2(), SliceLayerSelector.SliderWidth, theme);
            layerRenderRatioSlider.FirstValue         = 0;
            layerRenderRatioSlider.FirstValueChanged += (s, e) =>
            {
                sceneContext.RenderInfo.FeatureToStartOnRatio0To1 = layerRenderRatioSlider.FirstValue;
                sceneContext.RenderInfo.FeatureToEndOnRatio0To1   = layerRenderRatioSlider.SecondValue;

                this.Invalidate();
            };
            layerRenderRatioSlider.SecondValue         = 1;
            layerRenderRatioSlider.SecondValueChanged += (s, e) =>
            {
                if (printer?.Bed?.RenderInfo != null)
                {
                    sceneContext.RenderInfo.FeatureToStartOnRatio0To1 = layerRenderRatioSlider.FirstValue;
                    sceneContext.RenderInfo.FeatureToEndOnRatio0To1   = layerRenderRatioSlider.SecondValue;
                }

                this.Invalidate();
            };
            view3DWidget.InteractionLayer.AddChild(layerRenderRatioSlider);
            theme.ApplySliderStyle(layerRenderRatioSlider);

            layerRenderRatioSlider.View.TrackColor = opaqueTrackColor;

            AddSettingsTabBar(leftToRight, view3DWidget);

            view3DWidget.InteractionLayer.BoundsChanged += (s, e) =>
            {
                SetSliderSizes();
            };

            printerActionsBar = new PrinterActionsBar(printer, this, theme);
            theme.ApplyBottomBorder(printerActionsBar);
            printerActionsBar.modelViewButton.Enabled = sceneContext.EditableScene;

            // Must come after we have an instance of View3DWidget an its undo buffer
            topToBottom.AddChild(printerActionsBar, 0);

            var trackball = view3DWidget.InteractionLayer.Children <TrackballTumbleWidget>().FirstOrDefault();

            tumbleCubeControl = view3DWidget.InteractionLayer.Children <TumbleCubeControl>().FirstOrDefault();

            var position = view3DWidget.InteractionLayer.Children.IndexOf(trackball);

            gcodePanel = new GCodePanel(this, printer, sceneContext, theme)
            {
                Name            = "GCode3DWidget",
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Stretch,
                BackgroundColor = theme.InteractionLayerOverlayColor,
            };

            var modelViewSidePanel = view3DWidget.Descendants <VerticalResizeContainer>().FirstOrDefault();

            gcodeContainer = new VerticalResizeContainer(theme, GrabBarSide.Left)
            {
                Width            = printer?.ViewState.SelectedObjectPanelWidth ?? 200,
                VAnchor          = VAnchor.Stretch,
                HAnchor          = HAnchor.Absolute,
                SplitterBarColor = theme.SplitterBackground,
                SplitterWidth    = theme.SplitterWidth,
                Visible          = false,
            };

            gcodeContainer.AddChild(gcodePanel);
            gcodeContainer.Resized += (s, e) =>
            {
                if (printer != null)
                {
                    printer.ViewState.SelectedObjectPanelWidth = gcodeContainer.Width;
                }
            };

            modelViewSidePanel.BoundsChanged += (s, e) =>
            {
                gcodeContainer.Width = modelViewSidePanel.Width;
            };

            gcodeContainer.BoundsChanged += (s, e) =>
            {
                modelViewSidePanel.Width = gcodeContainer.Width;
            };

            var splitContainer = view3DWidget.FindDescendant("SplitContainer");

            splitContainer.AddChild(gcodeContainer);

            view3DContainer.AddChild(new RunningTasksWidget(theme, printer)
            {
                MinimumSize = new Vector2(100, 0),
                Margin      = new BorderDouble(top: printerActionsBar.Height + 1, left: favoritesBar.LocalBounds.Width + favoritesBar.DeviceMarginAndBorder.Width + 1),
                VAnchor     = VAnchor.Top | VAnchor.Fit,
                HAnchor     = HAnchor.Left | HAnchor.Fit,
            });

            // Create and append new widget
            gcode2DWidget = new GCode2DWidget(printer, theme)
            {
                Visible = (printer.ViewState.ViewMode == PartViewMode.Layers2D)
            };
            view3DWidget.InteractionLayer.AddChild(gcode2DWidget, position + 1);

            SetSliderSizes();

            this.SetViewMode(printer.ViewState.ViewMode);

            this.LayerScrollbar.Margin = LayerScrollbar.Margin.Clone(top: tumbleCubeControl.Height + tumbleCubeControl.Margin.Height + 4);

            // On load, switch to gcode view if previously editing gcode file. Listeners would normally do this but workspace loads before this UI widget
            if (this?.printerActionsBar?.modelViewButton is GuiWidget button)
            {
                button.Enabled = sceneContext.EditableScene;

                if (sceneContext.ContentType == "gcode" &&
                    this?.printerActionsBar?.layers3DButton is GuiWidget gcodeButton)
                {
                    gcodeButton.InvokeClick();
                }
            }

            // Register listeners
            printer.ViewState.VisibilityChanged += ProcessOptionalTabs;
            printer.ViewState.ViewModeChanged   += ViewState_ViewModeChanged;

            printer.Bed.RendererOptions.PropertyChanged += RendererOptions_PropertyChanged;

            // register for communication messages
            printer.Connection.CommunicationStateChanged += Connection_CommunicationStateChanged;
            printer.Connection.PauseOnLayer   += Connection_PauseOnLayer;
            printer.Connection.FilamentRunout += Connection_FilamentRunout;

            ApplicationController.Instance.ApplicationError += ApplicationController_ApplicationError;
            ApplicationController.Instance.ApplicationEvent += ApplicationController_ApplicationEvent;

            sceneContext.LoadedGCodeChanged += BedPlate_LoadedGCodeChanged;
        }
Beispiel #10
0
        public PrintPopupMenu(PrinterConfig printer, ThemeConfig theme)
            : base(theme)
        {
            this.printer         = printer;
            this.DrawArrow       = true;
            this.BackgroundColor = theme.ToolbarButtonBackground;
            this.HoverColor      = theme.ToolbarButtonHover;
            this.MouseDownColor  = theme.ToolbarButtonDown;
            this.Name            = "PrintPopupMenu";
            this.HAnchor         = HAnchor.Fit;
            this.VAnchor         = VAnchor.Fit;

            settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All);

            this.PopupHAnchor   = HAnchor.Fit;
            this.PopupVAnchor   = VAnchor.Fit;
            this.MakeScrollable = false;

            this.DynamicPopupContent = () =>
            {
                var menuTheme = ApplicationController.Instance.MenuTheme;

                int tabIndex = 0;

                allUiFields.Clear();

                var printPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
                {
                    Padding         = theme.DefaultContainerPadding,
                    BackgroundColor = menuTheme.BackgroundColor
                };

                printPanel.AddChild(new TextWidget("Options".Localize(), textColor: menuTheme.TextColor, pointSize: theme.DefaultFontSize)
                {
                    HAnchor = HAnchor.Left
                });

                var optionsPanel = new IgnoredFlowLayout()
                {
                    Name        = "PrintPopupMenu Panel",
                    HAnchor     = HAnchor.Fit | HAnchor.Left,
                    VAnchor     = VAnchor.Fit,
                    Padding     = 5,
                    MinimumSize = new Vector2(400, 65),
                };
                printPanel.AddChild(optionsPanel);

                foreach (var key in new[] { SettingsKey.layer_height, SettingsKey.fill_density, SettingsKey.create_raft })
                {
                    var settingsData = PrinterSettings.SettingsData[key];
                    var row          = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, menuTheme, ref tabIndex, allUiFields);

                    if (row is SliceSettingsRow settingsRow)
                    {
                        settingsRow.ArrowDirection = ArrowDirection.Left;
                    }

                    optionsPanel.AddChild(row);
                }

                var subPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
                {
                    Margin = new BorderDouble(2, 0)
                };

                bool anySettingOverridden = false;
                anySettingOverridden |= printer.Settings.GetValue <bool>(SettingsKey.spiral_vase);
                anySettingOverridden |= !string.IsNullOrWhiteSpace(printer.Settings.GetValue(SettingsKey.layer_to_pause));

                var sectionWidget = new SectionWidget("Advanced".Localize(), subPanel, menuTheme, expanded: anySettingOverridden)
                {
                    Name    = "Advanced Section",
                    HAnchor = HAnchor.Stretch,
                    VAnchor = VAnchor.Fit,
                    Margin  = 0
                };
                printPanel.AddChild(sectionWidget);

                foreach (var key in new[] { SettingsKey.spiral_vase, SettingsKey.layer_to_pause })
                {
                    var advancedRow = SliceSettingsTabView.CreateItemRow(
                        PrinterSettings.SettingsData[key],
                        settingsContext,
                        printer,
                        menuTheme,
                        ref tabIndex,
                        allUiFields);

                    if (advancedRow is SliceSettingsRow settingsRow)
                    {
                        settingsRow.ArrowDirection = ArrowDirection.Left;
                    }

                    subPanel.AddChild(advancedRow);
                }

                menuTheme.ApplyBoxStyle(sectionWidget);

                sectionWidget.Margin = new BorderDouble(0, 10);
                sectionWidget.ContentPanel.Children <SettingsRow>().First().Border = new BorderDouble(0, 1);
                sectionWidget.ContentPanel.Children <SettingsRow>().Last().Border  = 0;

                var printerReadyToTakeCommands = printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.FinishedPrint ||
                                                 printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.Connected;

                // add the start print button
                var setupRow = new FlowLayoutWidget()
                {
                    HAnchor = HAnchor.Stretch
                };

                // Perform validation before popup
                var errors = printer.Validate();

                // Enable print option when no validation Errors exists
                var printEnabled = !errors.Any(err => err.ErrorLevel == ValidationErrorLevel.Error);

                var startPrintButton = new TextButton("Start Print".Localize(), menuTheme)
                {
                    Name    = "Start Print Button",
                    Enabled = printEnabled
                };

                startPrintButton.Click += (s, e) =>
                {
                    // Exit if the bed is not GCode and the bed has no printable items
                    if (!printer.Bed.EditContext.IsGGCodeSource &&
                        !printer.PrintableItems(printer.Bed.Scene).Any())
                    {
                        return;
                    }

                    UiThread.RunOnIdle(async() =>
                    {
                        // Save any pending changes before starting print operation
                        await ApplicationController.Instance.Tasks.Execute("Saving Changes".Localize(), printer, printer.Bed.SaveChanges);

                        await ApplicationController.Instance.PrintPart(
                            printer.Bed.EditContext,
                            printer,
                            null,
                            CancellationToken.None);
                    });

                    this.CloseMenu();
                };

                var hasErrors   = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Error);
                var hasWarnings = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Warning &&
                                             UserSettings.Instance.get($"Ignore_{e.ID}") != "true");

                var hasErrorsOrWarnings = hasErrors || hasWarnings;
                if (hasErrorsOrWarnings)
                {
                    string label = hasErrors ? "Action Required".Localize() : "Action Recommended".Localize();

                    setupRow.AddChild(new TextWidget(label, textColor: hasErrors ? Color.Red : theme.PrimaryAccentColor, pointSize: theme.DefaultFontSize)
                    {
                        VAnchor = VAnchor.Bottom,
                        AutoExpandBoundsToText = true,
                    });
                }

                setupRow.AddChild(new HorizontalSpacer());

                // Export button {{
                bool isSailfish       = printer.Settings.GetValue <bool>("enable_sailfish_communication");
                var  exportPlugins    = PluginFinder.CreateInstancesOf <IExportPlugin>();
                var  targetPluginType = isSailfish ? typeof(X3GExport) : typeof(GCodeExport);

                // Find the first export plugin with the target type
                if (exportPlugins.FirstOrDefault(p => p.GetType() == targetPluginType) is IExportPlugin exportPlugin)
                {
                    string exportType = isSailfish ? "Export X3G".Localize() : "Export G-Code".Localize();

                    exportPlugin.Initialize(printer);

                    var exportGCodeButton = menuTheme.CreateDialogButton("Export".Localize());
                    exportGCodeButton.Name        = "Export Gcode Button";
                    exportGCodeButton.Enabled     = exportPlugin.Enabled;
                    exportGCodeButton.ToolTipText = exportPlugin.Enabled ? exportType : exportPlugin.DisabledReason;

                    exportGCodeButton.Click += (s, e) =>
                    {
                        ExportPrintItemPage.DoExport(
                            new[] { new InMemoryLibraryItem(printer.Bed.Scene) },
                            printer,
                            exportPlugin);
                    };

                    setupRow.AddChild(exportGCodeButton);
                }

                // Export button }}

                setupRow.AddChild(startPrintButton);

                printPanel.AddChild(setupRow);

                if (printEnabled)
                {
                    theme.ApplyPrimaryActionStyle(startPrintButton);
                }
                else
                {
                    startPrintButton.BackgroundColor = theme.MinimalShade;
                }

                if (hasErrorsOrWarnings)
                {
                    var errorsPanel = new ValidationErrorsPanel(errors, menuTheme);

                    // Conditional layout for right or bottom errors panel alignment
                    var layoutStyle = FlowDirection.TopToBottom;

                    if (layoutStyle == FlowDirection.LeftToRight)
                    {
                        errorsPanel.HAnchor         = HAnchor.Absolute;
                        errorsPanel.VAnchor         = VAnchor.Fit | VAnchor.Top;
                        errorsPanel.BackgroundColor = theme.ResolveColor(menuTheme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30));
                        errorsPanel.Width           = 350;

                        errorsPanel.Load += (s, e) =>
                        {
                            errorsPanel.Parent.BackgroundColor = Color.Transparent;
                        };
                    }
                    else
                    {
                        errorsPanel.HAnchor = HAnchor.Stretch;
                        errorsPanel.VAnchor = VAnchor.Fit;
                        errorsPanel.Margin  = 3;
                    }

                    // Instead of the typical case where the print panel is returned, wrap and append validation errors panel
                    var errorsContainer = new FlowLayoutWidget(layoutStyle)
                    {
                        HAnchor         = HAnchor.Fit,
                        VAnchor         = VAnchor.Fit,
                        BackgroundColor = layoutStyle == FlowDirection.TopToBottom ? printPanel.BackgroundColor : Color.Transparent
                    };

                    // Clear bottom padding
                    printPanel.Padding = printPanel.Padding.Clone(bottom: 2);

                    errorsContainer.AddChild(printPanel);
                    errorsContainer.AddChild(errorsPanel);

                    return(errorsContainer);
                }

                return(printPanel);
            };

            this.AddChild(new TextButton("Print".Localize(), theme)
            {
                Selectable = false,
                Padding    = theme.TextButtonPadding.Clone(right: 5)
            });

            // Register listeners
            printer.Settings.SettingChanged += Printer_SettingChanged;
        }
        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);
            }
        }
Beispiel #12
0
 public SelectionShadow(IObject3DControlContext context)
     : base(context)
 {
     theme       = AppContext.Theme;
     shadowColor = theme.ResolveColor(theme.BackgroundColor, Color.Black.WithAlpha(80)).WithAlpha(110);
 }
        public ExportSlaPopupMenu(PrinterConfig printer, ThemeConfig theme)
            : base(theme)
        {
            this.printer         = printer;
            this.DrawArrow       = true;
            this.BackgroundColor = theme.ToolbarButtonBackground;
            this.HoverColor      = theme.ToolbarButtonHover;
            this.MouseDownColor  = theme.ToolbarButtonDown;
            this.Name            = "ExportSlaPopupMenu";
            this.HAnchor         = HAnchor.Fit;
            this.VAnchor         = VAnchor.Fit;

            settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All);

            this.PopupHAnchor   = HAnchor.Fit;
            this.PopupVAnchor   = VAnchor.Fit;
            this.MakeScrollable = false;

            this.DynamicPopupContent = () =>
            {
                var menuTheme = ApplicationController.Instance.MenuTheme;

                int tabIndex = 0;

                allUiFields.Clear();

                var exportPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
                {
                    Padding         = theme.DefaultContainerPadding,
                    BackgroundColor = menuTheme.BackgroundColor
                };

                exportPanel.AddChild(new TextWidget("Options".Localize(), textColor: menuTheme.TextColor, pointSize: theme.DefaultFontSize)
                {
                    HAnchor = HAnchor.Left
                });

                var optionsPanel = new IgnoredFlowLayout()
                {
                    Name        = "ExportSlaPopupMenu Panel",
                    HAnchor     = HAnchor.Fit | HAnchor.Left,
                    VAnchor     = VAnchor.Fit,
                    Padding     = 5,
                    MinimumSize = new Vector2(400 * GuiWidget.DeviceScale, 65 * GuiWidget.DeviceScale),
                };
                exportPanel.AddChild(optionsPanel);

                var settingsToAdd = new[]
                {
                    SettingsKey.sla_layer_height,
                    SettingsKey.sla_create_raft,
                    SettingsKey.sla_auto_support
                };

                foreach (var key in settingsToAdd)
                {
                    var settingsData = PrinterSettings.SettingsData[key];
                    var row          = SliceSettingsTabView.CreateItemRow(settingsData, settingsContext, printer, menuTheme, ref tabIndex, allUiFields);

                    if (row is SliceSettingsRow settingsRow)
                    {
                        settingsRow.ArrowDirection = ArrowDirection.Left;
                    }

                    optionsPanel.AddChild(row);
                }

                // add the export print button
                var setupRow = new FlowLayoutWidget()
                {
                    HAnchor = HAnchor.Stretch
                };

                // Perform validation before popup
                var errors = printer.Validate();

                var hasErrors   = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Error);
                var hasWarnings = errors.Any(e => e.ErrorLevel == ValidationErrorLevel.Warning &&
                                             UserSettings.Instance.get($"Ignore_{e.ID}") != "true");

                var hasErrorsOrWarnings = hasErrors || hasWarnings;
                if (hasErrorsOrWarnings)
                {
                    string label = hasErrors ? "Action Required".Localize() : "Action Recommended".Localize();

                    setupRow.AddChild(new TextWidget(label, textColor: hasErrors ? Color.Red : theme.PrimaryAccentColor, pointSize: theme.DefaultFontSize)
                    {
                        VAnchor = VAnchor.Bottom,
                        AutoExpandBoundsToText = true,
                    });
                }

                setupRow.AddChild(new HorizontalSpacer());

                // Export button {{
                var exportPlugins = PluginFinder.CreateInstancesOf <IExportPlugin>();
                // set target as SLA export
                var targetPluginType = typeof(GCodeExport);

                // Find the first export plugin with the target type
                if (exportPlugins.FirstOrDefault(p => p.GetType() == targetPluginType) is IExportPlugin exportPlugin)
                {
                    string exportType = "Export Photon File".Localize();

                    exportPlugin.Initialize(printer);

                    var exportButton = menuTheme.CreateDialogButton("Export".Localize());
                    theme.ApplyPrimaryActionStyle(exportButton);

                    exportButton.Name        = "Export SLA Button";
                    exportButton.Enabled     = exportPlugin.Enabled;
                    exportButton.ToolTipText = exportPlugin.Enabled ? exportType : exportPlugin.DisabledReason;

                    exportButton.Click += (s, e) =>
                    {
                        this.CloseMenu();
                        ExportPrintItemPage.DoExport(
                            new[] { new InMemoryLibraryItem(printer.Bed.Scene) },
                            printer,
                            exportPlugin);
                    };

                    setupRow.AddChild(exportButton);
                }

                // Export button

                exportPanel.AddChild(setupRow);

                if (hasErrorsOrWarnings)
                {
                    var errorsPanel = new ValidationErrorsPanel(errors, menuTheme);

                    // Conditional layout for right or bottom errors panel alignment
                    var layoutStyle = FlowDirection.TopToBottom;

                    if (layoutStyle == FlowDirection.LeftToRight)
                    {
                        errorsPanel.HAnchor         = HAnchor.Absolute;
                        errorsPanel.VAnchor         = VAnchor.Fit | VAnchor.Top;
                        errorsPanel.BackgroundColor = theme.ResolveColor(menuTheme.BackgroundColor, theme.PrimaryAccentColor.WithAlpha(30));
                        errorsPanel.Width           = 350;

                        errorsPanel.Load += (s, e) =>
                        {
                            errorsPanel.Parent.BackgroundColor = Color.Transparent;
                        };
                    }
                    else
                    {
                        errorsPanel.HAnchor = HAnchor.Stretch;
                        errorsPanel.VAnchor = VAnchor.Fit;
                        errorsPanel.Margin  = 3;
                    }

                    // Instead of the typical case where the print panel is returned, wrap and append validation errors panel
                    var errorsContainer = new FlowLayoutWidget(layoutStyle)
                    {
                        HAnchor         = HAnchor.Fit,
                        VAnchor         = VAnchor.Fit,
                        BackgroundColor = layoutStyle == FlowDirection.TopToBottom ? exportPanel.BackgroundColor : Color.Transparent
                    };

                    // Clear bottom padding
                    exportPanel.Padding = exportPanel.Padding.Clone(bottom: 2);

                    errorsContainer.AddChild(exportPanel);
                    errorsContainer.AddChild(errorsPanel);

                    return(errorsContainer);
                }

                return(exportPanel);
            };

            this.AddChild(new TextButton("Export".Localize(), theme)
            {
                Selectable = false,
                Padding    = theme.TextButtonPadding.Clone(right: 5)
            });
        }
Beispiel #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);
            }
        }