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