Beispiel #1
0
 public XYZColors(ThemeConfig theme)
 {
     this.EColor = theme.GetBorderColor(40);             // new Color(180, 180, 180);
     this.XColor = theme.GetBorderColor(40);             // new Color(180, 180, 180);
     this.YColor = theme.GetBorderColor(40);             //new Color(255, 255, 255);
     this.ZColor = theme.GetBorderColor(40);             //new Color(255, 255, 255);
 }
Beispiel #2
0
        public override void Initialize(int tabIndex)
        {
            dropdownList = new DropDownList("None".Localize(), theme.Colors.PrimaryTextColor, maxHeight: 200, pointSize: theme.DefaultFontSize)
            {
                ToolTipText = this.HelpText,
                TabIndex    = tabIndex,
                Margin      = new BorderDouble(),
                BorderColor = theme.GetBorderColor(75)
            };

            foreach (string listItem in this.ListItems)
            {
                MenuItem newItem = dropdownList.AddItem(listItem);
                if (newItem.Text == this.Value)
                {
                    dropdownList.SelectedLabel = this.Value;
                }

                newItem.Selected += (sender, e) =>
                {
                    if (sender is MenuItem menuItem)
                    {
                        this.SetValue(
                            menuItem.Text,
                            userInitiated: true);
                    }
                };
            }

            this.Content = dropdownList;
        }
Beispiel #3
0
        public override void Initialize(int tabIndex)
        {
            // Enum keyed on name to friendly name
            var enumItems = Enum.GetNames(property.PropertyType).Select(enumName =>
            {
                return(new
                {
                    Key = enumName,
                    Value = enumName.Replace('_', ' ')
                });
            });

            dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize)
            {
                BorderColor = theme.GetBorderColor(75)
            };

            var sortableAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType <SortableAttribute>().FirstOrDefault();
            var orderedItems      = sortableAttribute != null?enumItems.OrderBy(n => n.Value) : enumItems;

            foreach (var orderItem in orderedItems)
            {
                MenuItem newItem = dropDownList.AddItem(orderItem.Value, orderItem.Key);

                var localOrderedItem = orderItem;
                newItem.Selected += (sender, e) =>
                {
                    this.SetValue(localOrderedItem.Key, true);
                };
            }

            dropDownList.SelectedLabel = property.Value.ToString().Replace('_', ' ');

            this.Content = dropDownList;
        }
            public DockingTabButton(string tabTitle, ThemeConfig theme)
            {
                this.grayBorder       = theme.GetBorderColor(theme.IsDarkTheme ? 45 : 55);
                this.theme            = theme;
                this.HAnchor          = HAnchor.Fit;
                this.VAnchor          = VAnchor.Fit | VAnchor.Center;
                this.AlignToRightEdge = true;
                this.MakeScrollable   = false;
                this.Border           = new BorderDouble(right: 6);
                this.BorderColor      = grayBorder;
                this.Margin           = new BorderDouble(2, 8, 0, 0);
                this.HoverColor       = Color.Transparent;

                var printer      = new TypeFacePrinter(tabTitle, theme.DefaultFontSize * GuiWidget.DeviceScale);
                var rotatedLabel = new VertexSourceApplyTransform(
                    printer,
                    Affine.NewRotation(MathHelper.DegreesToRadians(-90)));

                var textBounds = rotatedLabel.GetBounds();
                var bounds     = new RectangleDouble(printer.TypeFaceStyle.DescentInPixels, textBounds.Bottom, printer.TypeFaceStyle.AscentInPixels, textBounds.Top);

                rotatedLabel.Transform = ((Affine)rotatedLabel.Transform)
                                         * Affine.NewTranslation(new Vector2(-printer.TypeFaceStyle.DescentInPixels, -bounds.Bottom));

                this.AddChild(buttonView = new GuiWidget(bounds.Width, bounds.Height)
                {
                    DoubleBuffer = true,
                    Margin       = new BorderDouble(3, 1),
                    Selectable   = false
                });
                buttonView.AfterDraw += (s, e) =>
                {
                    e.Graphics2D.Render(rotatedLabel, theme.TextColor);
                };
            }
        public ThemeColorPanel(ThemeConfig activeTheme)
            : base(FlowDirection.TopToBottom)
        {
            string currentProviderName = UserSettings.Instance.get(UserSettingsKey.ThemeName) ?? "";

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

            this.SelectionColor = activeTheme.GetBorderColor(80);

            // Add color selector
            this.AddChild(colorSelector = new AccentColorsWidget(this)
            {
                Margin = new BorderDouble(activeTheme.DefaultContainerPadding, 0)
            });

            this.AddChild(previewButtonPanel = new FlowLayoutWidget()
            {
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Fit,
                BackgroundColor = this.SelectionColor,
                Padding         = new BorderDouble(left: colorSelector.ColorButtons.First().Border.Left)
            });

            this.CreateThemeModeButtons();
        }
Beispiel #6
0
        public override void Initialize(int tabIndex)
        {
            EventHandler unregisterEvents = null;

            base.Initialize(tabIndex);
            bool canChangeComPort = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect;
            //This setting defaults to Manual
            var selectedMachine = printer.Settings.GetValue(SettingsKey.selector_ip_address);

            dropdownList = new DropDownList(selectedMachine, theme.Colors.PrimaryTextColor, maxHeight: 200, pointSize: theme.DefaultFontSize)
            {
                ToolTipText = HelpText,
                Margin      = new BorderDouble(),
                TabIndex    = tabIndex,

                Enabled     = canChangeComPort,
                TextColor   = canChangeComPort ? theme.Colors.PrimaryTextColor : new Color(theme.Colors.PrimaryTextColor, 150),
                BorderColor = theme.GetBorderColor(75)
            };

            //Create default option
            MenuItem defaultOption = dropdownList.AddItem("Manual", "127.0.0.1:23");

            defaultOption.Selected += (sender, e) =>
            {
                printer.Settings.SetValue(SettingsKey.selector_ip_address, defaultOption.Text);
            };
            UiThread.RunOnIdle(RebuildMenuItems);

            // Prevent droplist interaction when connected
            printer.Connection.CommunicationStateChanged.RegisterEvent((s, e) =>
            {
                canChangeComPort         = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect;
                dropdownList.Enabled     = canChangeComPort;
                dropdownList.TextColor   = canChangeComPort ? theme.Colors.PrimaryTextColor : new Color(theme.Colors.PrimaryTextColor, 150);
                dropdownList.BorderColor = canChangeComPort ? theme.Colors.SecondaryTextColor : new Color(theme.Colors.SecondaryTextColor, 150);
            }, ref unregisterEvents);

            // Release event listener on close
            dropdownList.Closed += (s, e) =>
            {
                unregisterEvents?.Invoke(null, null);
            };

            var widget = new FlowLayoutWidget();

            widget.AddChild(dropdownList);
            refreshButton = new IconButton(AggContext.StaticData.LoadIcon("fa-refresh_14.png", theme.InvertIcons), theme)
            {
                Margin = new BorderDouble(left: 5)
            };

            refreshButton.Click += (s, e) => RebuildMenuItems();
            widget.AddChild(refreshButton);

            this.Content = widget;
        }
Beispiel #7
0
        public SettingsRow(string title, string helpText, ThemeConfig theme, ImageBuffer icon = null, bool enforceGutter = false, bool fullRowSelect = false)
        {
            using (this.LayoutLock())
            {
                this.theme         = theme;
                this.fullRowSelect = fullRowSelect;

                this.HAnchor     = HAnchor.Stretch;
                this.VAnchor     = VAnchor.Fit;
                this.MinimumSize = new Vector2(0, theme.ButtonHeight);
                this.Border      = new BorderDouble(bottom: 1);
                this.BorderColor = theme.GetBorderColor(theme.IsDarkTheme ? 20 : 35);

                hoverColor = theme.MinimalShade;

                if (icon != null)
                {
                    this.AddChild(
                        imageWidget = new ImageWidget(icon)
                    {
                        Margin  = new BorderDouble(right: 6, left: 6),
                        VAnchor = VAnchor.Center
                    });
                }
                else if (enforceGutter)
                {
                    // Add an icon placeholder to get consistent label indenting on items lacking icons
                    this.AddChild(new GuiWidget()
                    {
                        Width  = 24 + 12,
                        Height = 24,
                        Margin = new BorderDouble(0)
                    });
                }
                else
                {
                    this.AddChild(overrideIndicator = new GuiWidget()
                    {
                        VAnchor = VAnchor.Stretch,
                        HAnchor = HAnchor.Absolute,
                        Width   = 3,
                        Margin  = new BorderDouble(right: 6)
                    });
                }

                this.AddChild(settingsLabel = SettingsRow.CreateSettingsLabel(title, helpText, theme.Colors.PrimaryTextColor));

                this.AddChild(new HorizontalSpacer());
            }

            this.PerformLayout();

            if (fullRowSelect)
            {
                this.Cursor = Cursors.Hand;
            }
        }
Beispiel #8
0
        public GridOptionsPanel(InteractionLayer interactionLayer, ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor = HAnchor.MaxFitOrStretch;

            this.AddChild(new TextWidget("Snap Grid".Localize())
            {
                Margin    = new BorderDouble(35, 2, 8, 8),
                TextColor = Color.Gray,
                HAnchor   = HAnchor.Left
            });

            var snapSettings = new Dictionary <double, string>()
            {
                { 0, "Off" },
                { .1, "0.1" },
                { .25, "0.25" },
                { .5, "0.5" },
                { 1, "1" },
                { 2, "2" },
                { 5, "5" },
            };

            var dropDownList = new DropDownList("Custom", theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize)
            {
                TextColor   = Color.Black,
                Margin      = new BorderDouble(35, 15, 35, 5),
                HAnchor     = HAnchor.Left,
                BorderColor = theme.GetBorderColor(75)
            };

            foreach (var snapSetting in snapSettings)
            {
                MenuItem newItem = dropDownList.AddItem(snapSetting.Value);
                if (interactionLayer.SnapGridDistance == snapSetting.Key)
                {
                    dropDownList.SelectedLabel = snapSetting.Value;
                }

                newItem.Selected += (sender, e) =>
                {
                    interactionLayer.SnapGridDistance = snapSetting.Key;
                };
            }
            this.AddChild(dropDownList);
        }
        public override void Initialize(int tabIndex)
        {
            dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize)
            {
                BorderColor = theme.GetBorderColor(75)
            };

            dropDownList.AddItem(
                "Back".Localize(),
                JsonConvert.SerializeObject(
                    new DirectionVector()
            {
                Normal = Vector3.UnitY
            }));

            dropDownList.AddItem(
                "Up".Localize(),
                JsonConvert.SerializeObject(
                    new DirectionVector()
            {
                Normal = Vector3.UnitZ
            }));

            dropDownList.AddItem(
                "Right".Localize(),
                JsonConvert.SerializeObject(
                    new DirectionVector()
            {
                Normal = Vector3.UnitX
            }));

            dropDownList.SelectedLabel = "Right";

            dropDownList.SelectionChanged += (s, e) =>
            {
                if (this.Value != dropDownList.SelectedValue)
                {
                    this.SetValue(
                        dropDownList.SelectedValue,
                        userInitiated: true);
                }
                ;
            };

            this.Content = dropDownList;
        }
Beispiel #10
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))
            };
        }
        public override void Initialize(int tabIndex)
        {
            // Enum keyed on name to friendly name
            List <(string key, string value)> names = null;
            var selectedName = "";

            if (property.source is AlignObject3D item)
            {
                names = item.Children.Select(child => (child.ID, child.Name)).ToList();
                if (item.AnchorObjectSelector.Count == 1)
                {
                    var selectedKey = item.AnchorObjectSelector[0];
                    foreach (var name in names)
                    {
                        if (name.key == selectedKey)
                        {
                            selectedName = name.value;
                        }
                    }
                }
            }

            dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize)
            {
                BorderColor = theme.GetBorderColor(75)
            };

            var orderedItems = names.OrderBy(n => n.value);

            foreach (var orderItem in orderedItems)
            {
                MenuItem newItem = dropDownList.AddItem(orderItem.value, orderItem.key);

                var localOrderedItem = orderItem;
                newItem.Selected += (sender, e) =>
                {
                    this.SetValue(localOrderedItem.key, true);
                };
            }

            dropDownList.SelectedLabel = selectedName;

            this.Content = dropDownList;
        }
Beispiel #12
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 #13
0
        public ItemColorButton(ThemeConfig theme, Color selectedColor)
        {
            this.ToolTipText = "Color".Localize();
            var scaledButtonSize = 14 * GuiWidget.DeviceScale;

            Width  = 30 * GuiWidget.DeviceScale;
            Height = 30 * GuiWidget.DeviceScale;

            this.DynamicPopupContent = () =>
            {
                return(new ColorSwatchSelector(theme, buttonSize: 16, buttonSpacing: new BorderDouble(1, 1, 0, 0), colorNotifier: (newColor) => colorButton.BackgroundColor = newColor)
                {
                    Padding = theme.DefaultContainerPadding,
                    BackgroundColor = this.HoverColor,
                    HAnchor = HAnchor.Fit,
                    VAnchor = VAnchor.Fit
                });
            };

            colorButton = new ColorButton(selectedColor == Color.Transparent ? theme.SlightShade : selectedColor)
            {
                Width         = scaledButtonSize,
                Height        = scaledButtonSize,
                HAnchor       = HAnchor.Center,
                VAnchor       = VAnchor.Center,
                DisabledColor = theme.MinimalShade,
                Border        = new BorderDouble(1),
                BorderColor   = theme.GetBorderColor(75),
                Selectable    = false
            };

            colorButton.BackgroundColorChanged += (s, e) =>
            {
                ColorChanged?.Invoke(this, null);
            };

            this.AddChild(colorButton);
        }
Beispiel #14
0
        public PartTabPage(PrinterConfig printer, BedConfig sceneContext, ThemeConfig theme, string tabTitle)
            : base(tabTitle)
        {
            this.sceneContext    = sceneContext;
            this.theme           = theme;
            this.BackgroundColor = theme.ActiveTabColor;
            this.Padding         = 0;
            this.printer         = printer;

            bool isPrinterType = this is PrinterTabPage;

            var favoritesBarAndView3DWidget = new FlowLayoutWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch
            };

            viewControls3D = new ViewControls3D(sceneContext, theme, sceneContext.Scene.UndoBuffer, isPrinterType, !(this is PrinterTabPage))
            {
                VAnchor = VAnchor.Top | VAnchor.Fit,
                HAnchor = HAnchor.Left | HAnchor.Stretch,
                Visible = true,
            };
            theme.ApplyBottomBorder(viewControls3D, shadedBorder: (this is PrinterTabPage));             // Shade border if toolbar is secondary rather than primary

            viewControls3D.ResetView += (sender, e) =>
            {
                if (view3DWidget.Visible)
                {
                    this.view3DWidget.ResetView();
                }
            };
            viewControls3D.ExtendOverflowMenu  = this.GetViewControls3DOverflowMenu;
            viewControls3D.OverflowButton.Name = "View3D Overflow Menu";

            // The 3D model view
            view3DWidget = new View3DWidget(
                printer,
                sceneContext,
                viewControls3D,
                theme,
                this,
                editorType: (isPrinterType) ? MeshViewerWidget.EditorType.Printer : MeshViewerWidget.EditorType.Part);

            viewControls3D.SetView3DWidget(view3DWidget);

            // Construct and store dictionary of menu actions accessible at workspace level
            view3DWidget.WorkspaceActions = viewControls3D.MenuActions.Where(o => !string.IsNullOrEmpty(o.ID)).ToDictionary(o => o.ID, o => o);

            this.AddChild(topToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch
            });

            topToBottom.AddChild(leftToRight = new FlowLayoutWidget()
            {
                Name    = "View3DContainerParent",
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch
            });

            view3DContainer = new GuiWidget()
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch
            };

            var toolbarAndView3DWidget = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
                VAnchor = VAnchor.Stretch
            };

            toolbarAndView3DWidget.AddChild(viewControls3D);

            var dummyContext = new LibraryConfig()
            {
                ActiveContainer = ApplicationController.Instance.Library.ActiveContainer
            };

            var favoritesBar = new ListView(dummyContext, theme)
            {
                Name = "LibraryView",
                // Drop containers
                ContainerFilter  = (container) => false,
                BackgroundColor  = theme.ActiveTabColor,
                ListContentView  = new IconListView(theme, 22),
                Border           = new BorderDouble(top: 1, right: 1),
                BorderColor      = theme.GetBorderColor(15),
                HAnchor          = HAnchor.Absolute,
                Width            = 33,
                AllowContextMenu = false
            };

            favoritesBarAndView3DWidget.AddChild(favoritesBar);
            favoritesBarAndView3DWidget.AddChild(view3DWidget);
            toolbarAndView3DWidget.AddChild(favoritesBarAndView3DWidget);

            view3DContainer.AddChild(toolbarAndView3DWidget);

            leftToRight.AddChild(view3DContainer);

            if (sceneContext.World.RotationMatrix == Matrix4X4.Identity)
            {
                this.view3DWidget.ResetView();
            }

            this.AnchorAll();
        }
Beispiel #15
0
        public override void Initialize(int tabIndex)
        {
            EventHandler unregisterEvents = null;

            bool canChangeComPort = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect;

            var panel = new FlowLayoutWidget();

            // 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
            dropdownList = new DropDownList("None".Localize(), ActiveTheme.Instance.PrimaryTextColor, maxHeight: 200, pointSize: theme.DefaultFontSize)
            {
                ToolTipText = this.HelpText,
                Margin      = new BorderDouble(),
                TabIndex    = tabIndex,
                Name        = "com_port Field",
                // Prevent droplist interaction when connected
                Enabled     = canChangeComPort,
                TextColor   = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new Color(ActiveTheme.Instance.PrimaryTextColor, 150),
                BorderColor = theme.GetBorderColor(75)
            };

            dropdownList.Click += (s, e) =>
            {
                // TODO: why doesn't this blow up without runonidle?
                RebuildMenuItems();
            };

            RebuildMenuItems();

            // Prevent droplist interaction when connected
            printer.Connection.CommunicationStateChanged.RegisterEvent((s, e) =>
            {
                canChangeComPort       = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect;
                dropdownList.Enabled   = canChangeComPort;
                dropdownList.TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new Color(ActiveTheme.Instance.PrimaryTextColor, 150);

                if (printer.Connection.ComPort != dropdownList.SelectedLabel)
                {
                    dropdownList.SelectedLabel = printer.Connection.ComPort;
                }
            }, ref unregisterEvents);

            // Release event listener on close
            dropdownList.Closed += (s, e) =>
            {
                unregisterEvents?.Invoke(null, null);
            };

            var configureIcon = new IconButton(AggContext.StaticData.LoadIcon("fa-cog_16.png", theme.InvertIcons), theme)
            {
                VAnchor     = VAnchor.Center,
                Margin      = theme.ButtonSpacing,
                ToolTipText = "Port Wizard".Localize()
            };

            configureIcon.Click += (s, e) =>
            {
                DialogWindow.Show(new SetupStepComPortOne(printer));
            };

            panel.AddChild(configureIcon);

            panel.AddChild(dropdownList);

            this.Content = panel;
        }
        public ViewToolBarControls(PartWorkspace workspace, ThemeConfig theme, UndoBuffer undoBuffer, bool isPrinterType, bool showPrintButton)
        {
            this.undoBuffer    = undoBuffer;
            this.IsPrinterMode = isPrinterType;
            this.sceneContext  = workspace.SceneContext;
            this.workspace     = workspace;

            this.RowPadding      = 0;
            this.RowBoarder      = new BorderDouble(0, 0, 0, 1);
            this.RowBoarderColor = theme.GetBorderColor(50);

            var openLibraryButton = CreateOpenLibraryButton(sceneContext, theme);

            this.AddChild(CreateOpenFileButton(openLibraryButton, theme));

            this.AddChild(CreateSaveButton(theme));

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            bedMenuButton = new PopupMenuButton("Bed".Localize(), StaticData.Instance.LoadIcon("bed.png", 16, 16).SetToColor(theme.TextColor), theme)
            {
                Name      = "Bed Options Menu",
                Enabled   = true,
                Margin    = theme.ButtonSpacing,
                VAnchor   = VAnchor.Center,
                DrawArrow = true
            };

            this.AddChild(bedMenuButton);

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            undoButton = new IconButton(StaticData.Instance.LoadIcon("undo.png", 16, 16).SetToColor(theme.TextColor), theme)
            {
                Name        = "3D View Undo",
                ToolTipText = "Undo".Localize(),
                Enabled     = false,
                Margin      = theme.ButtonSpacing,
                VAnchor     = VAnchor.Center
            };
            undoButton.Click += (sender, e) =>
            {
                sceneContext.Scene.Undo();
                view3DWidget.Object3DControlLayer.Focus();
            };
            this.AddChild(undoButton);

            redoButton = new IconButton(StaticData.Instance.LoadIcon("redo.png", 16, 16).SetToColor(theme.TextColor), theme)
            {
                Name        = "3D View Redo",
                Margin      = theme.ButtonSpacing,
                ToolTipText = "Redo".Localize(),
                Enabled     = false,
                VAnchor     = VAnchor.Center
            };
            redoButton.Click += (sender, e) =>
            {
                sceneContext.Scene.Redo();
                view3DWidget.Object3DControlLayer.Focus();
            };
            this.AddChild(redoButton);

            if (showPrintButton)
            {
                var printButton = new TextButton("Print", theme)
                {
                    Name            = "Print Button",
                    BackgroundColor = theme.AccentMimimalOverlay
                };
                printButton.Click += (s, e) =>
                {
                    view3DWidget.PushToPrinterAndPrint();
                };
                this.AddChild(printButton);
            }

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            undoButton.Enabled = undoBuffer.UndoCount > 0;
            redoButton.Enabled = undoBuffer.RedoCount > 0;

            operationButtons = new Dictionary <GuiWidget, SceneOperation>();

            // Add Selected IObject3D -> Operations to toolbar
            foreach (var namedAction in SceneOperations.All)
            {
                if (namedAction is SceneSelectionSeparator)
                {
                    this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                    continue;
                }

                // add the create support before the align
                if (namedAction is OperationGroup group &&
                    group.Id == "Transform")
                {
                    this.AddChild(CreateSupportButton(theme));
                    this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                }

                if (namedAction is OperationGroup operationGroup)
                {
                    var expandoSet = new FlowLayoutWidget();

                    var actionDropDown       = CreateActionDropDown(theme, operationGroup);
                    var operationButtonGroup = CreateOperationButtonGroup(theme, operationGroup);

                    void UpdateVisability(object s, EventArgs e)
                    {
                        if (operationGroup.Visible)
                        {
                            if (operationGroup.Collapse)
                            {
                                actionDropDown.Visible       = true;
                                operationButtonGroup.Visible = false;

                                DoWrappingLayout();
                            }
                            else
                            {
                                actionDropDown.Visible       = false;
                                operationButtonGroup.Visible = true;

                                DoWrappingLayout();
                            }
                        }
                        else
                        {
                            actionDropDown.Visible       = false;
                            operationButtonGroup.Visible = false;

                            DoWrappingLayout();
                        }
                    }

                    UserSettings.Instance.SettingChanged += UpdateVisability;
                    operationGroup.CollapseChanged       += UpdateVisability;
                    operationGroup.VisibleChanged        += UpdateVisability;
                    this.Closed += (s, e) =>
                    {
                        UserSettings.Instance.SettingChanged -= UpdateVisability;
                        operationGroup.CollapseChanged       -= UpdateVisability;
                        operationGroup.VisibleChanged        -= UpdateVisability;
                    };

                    UpdateVisability(operationGroup, null);

                    expandoSet.AddChild(actionDropDown);
                    expandoSet.AddChild(operationButtonGroup);

                    this.AddChild(expandoSet);
                }
                else
                {
                    GuiWidget button;

                    if (namedAction.Icon != null)
                    {
                        button = new IconButton(namedAction.Icon(theme), theme)
                        {
                            Name            = namedAction.Title + " Button",
                            ToolTipText     = namedAction.Title,
                            Margin          = theme.ButtonSpacing,
                            BackgroundColor = theme.ToolbarButtonBackground,
                            HoverColor      = theme.ToolbarButtonHover,
                            MouseDownColor  = theme.ToolbarButtonDown,
                        };
                    }
                    else
                    {
                        button = new TextButton(namedAction.Title, theme)
                        {
                            Name            = namedAction.Title + " Button",
                            Margin          = theme.ButtonSpacing,
                            BackgroundColor = theme.ToolbarButtonBackground,
                            HoverColor      = theme.ToolbarButtonHover,
                            MouseDownColor  = theme.ToolbarButtonDown,
                        };
                    }

                    operationButtons.Add(button, namedAction);

                    button.Click += (s, e) => UiThread.RunOnIdle(() =>
                    {
                        namedAction.Action.Invoke(sceneContext);
                        var partTab = button.Parents <PartTabPage>().FirstOrDefault();
                        var view3D  = partTab.Descendants <View3DWidget>().FirstOrDefault();
                        view3D.Object3DControlLayer.Focus();
                    });

                    this.AddChild(button);
                }
            }

            // add the options menu
            this.AddChild(new HorizontalSpacer());

            var overflowIcon  = StaticData.Instance.LoadIcon(Path.Combine("ViewTransformControls", "overflow.png"), 32, 32).SetToColor(theme.TextColor);
            var optionsButton = new PopupMenuButton(overflowIcon, theme)
            {
                AlignToRightEdge = true
            };

            this.AddChild(optionsButton);
            optionsButton.Name                = "ToolBar Overflow Menu";
            optionsButton.ToolTipText         = "Tool Bar Options".Localize();
            optionsButton.DynamicPopupContent = () => GenerateToolBarOptionsMenu(theme);

            // Register listeners
            undoBuffer.Changed += UndoBuffer_Changed;
            sceneContext.Scene.SelectionChanged += UpdateToolbarButtons;
            sceneContext.Scene.ItemsModified    += UpdateToolbarButtons;

            // Run on load
            UpdateToolbarButtons(null, null);
        }
        public ViewControls3D(PartWorkspace workspace, ThemeConfig theme, UndoBuffer undoBuffer, bool isPrinterType, bool showPrintButton)
            : base(theme)
        {
            this.theme             = theme;
            this.undoBuffer        = undoBuffer;
            this.ActionArea.Click += (s, e) =>
            {
                view3DWidget.Object3DControlLayer.Focus();
            };

            this.OverflowButton.ToolTipText = "Tool Bar Overflow".Localize();

            this.OverflowButton.DynamicPopupContent = () =>
            {
                bool IncludeInMenu(SceneOperation operation)
                {
                    foreach (var widget in this.ActionArea.Children.Where(c => !c.Visible && !ignoredInMenuTypes.Contains(c.GetType())))
                    {
                        if (operationButtons.TryGetValue(widget, out SceneOperation buttonOperation) &&
                            buttonOperation == operation)
                        {
                            return(true);
                        }
                    }

                    return(false);
                }

                return(SceneOperations.GetToolbarOverflowMenu(AppContext.MenuTheme, sceneContext, IncludeInMenu));
            };

            this.IsPrinterMode = isPrinterType;
            this.sceneContext  = workspace.SceneContext;
            this.workspace     = workspace;

            string iconPath;

            this.AddChild(CreateAddButton(sceneContext, theme));

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            bedMenuButton = new PopupMenuButton(StaticData.Instance.LoadIcon("bed.png", 16, 16, theme.InvertIcons), theme)
            {
                Name        = "Bed Options Menu",
                ToolTipText = "Bed",
                Enabled     = true,
                Margin      = theme.ButtonSpacing,
                VAnchor     = VAnchor.Center,
                DrawArrow   = true
            };

            this.AddChild(bedMenuButton);

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            this.AddChild(CreateOpenButton(theme));

            this.AddChild(CreateSaveButton(theme));

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            undoButton = new IconButton(StaticData.Instance.LoadIcon("Undo_grey_16x.png", 16, 16, theme.InvertIcons), theme)
            {
                Name        = "3D View Undo",
                ToolTipText = "Undo".Localize(),
                Enabled     = false,
                Margin      = theme.ButtonSpacing,
                VAnchor     = VAnchor.Center
            };
            undoButton.Click += (sender, e) =>
            {
                sceneContext.Scene.Undo();
                view3DWidget.Object3DControlLayer.Focus();
            };
            this.AddChild(undoButton);

            redoButton = new IconButton(StaticData.Instance.LoadIcon("Redo_grey_16x.png", 16, 16, theme.InvertIcons), theme)
            {
                Name        = "3D View Redo",
                Margin      = theme.ButtonSpacing,
                ToolTipText = "Redo".Localize(),
                Enabled     = false,
                VAnchor     = VAnchor.Center
            };
            redoButton.Click += (sender, e) =>
            {
                sceneContext.Scene.Redo();
                view3DWidget.Object3DControlLayer.Focus();
            };
            this.AddChild(redoButton);

            if (showPrintButton)
            {
                var printButton = new TextButton("Print", theme)
                {
                    Name            = "Print Button",
                    BackgroundColor = theme.AccentMimimalOverlay
                };
                printButton.Click += (s, e) =>
                {
                    view3DWidget.PushToPrinterAndPrint();
                };
                this.AddChild(printButton);
            }

            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

            undoButton.Enabled = undoBuffer.UndoCount > 0;
            redoButton.Enabled = undoBuffer.RedoCount > 0;

            var buttonGroupA = new ObservableCollection <GuiWidget>();

            if (UserSettings.Instance.IsTouchScreen)
            {
                iconPath     = Path.Combine("ViewTransformControls", "rotate.png");
                rotateButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 32, 32, theme.InvertIcons), theme)
                {
                    SiblingRadioButtonList = buttonGroupA,
                    ToolTipText            = "Rotate (Alt + Left Mouse)".Localize(),
                    Margin = theme.ButtonSpacing
                };
                rotateButton.Click += (s, e) => this.ActiveButton = ViewControls3DButtons.Rotate;
                buttonGroupA.Add(rotateButton);
                AddChild(rotateButton);

                iconPath        = Path.Combine("ViewTransformControls", "translate.png");
                translateButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 32, 32, theme.InvertIcons), theme)
                {
                    SiblingRadioButtonList = buttonGroupA,
                    ToolTipText            = "Move (Shift + Left Mouse)".Localize(),
                    Margin = theme.ButtonSpacing
                };
                translateButton.Click += (s, e) => this.ActiveButton = ViewControls3DButtons.Translate;
                buttonGroupA.Add(translateButton);
                AddChild(translateButton);

                iconPath    = Path.Combine("ViewTransformControls", "scale.png");
                scaleButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 32, 32, theme.InvertIcons), theme)
                {
                    SiblingRadioButtonList = buttonGroupA,
                    ToolTipText            = "Zoom (Ctrl + Left Mouse)".Localize(),
                    Margin = theme.ButtonSpacing
                };
                scaleButton.Click += (s, e) => this.ActiveButton = ViewControls3DButtons.Scale;
                buttonGroupA.Add(scaleButton);
                AddChild(scaleButton);

                rotateButton.Checked = true;

                // Add vertical separator
                this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));

                iconPath         = Path.Combine("ViewTransformControls", "partSelect.png");
                partSelectButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 32, 32, theme.InvertIcons), theme)
                {
                    SiblingRadioButtonList = buttonGroupA,
                    ToolTipText            = "Select Part".Localize(),
                    Margin = theme.ButtonSpacing
                };
                partSelectButton.Click += (s, e) => this.ActiveButton = ViewControls3DButtons.PartSelect;
                buttonGroupA.Add(partSelectButton);
                AddChild(partSelectButton);
            }

            operationButtons = new Dictionary <GuiWidget, SceneOperation>();

            // Add Selected IObject3D -> Operations to toolbar
            foreach (var namedAction in SceneOperations.All)
            {
                if (namedAction is SceneSelectionSeparator)
                {
                    this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                    continue;
                }

                // add the create support before the align
                if (namedAction is OperationGroup group &&
                    group.Id == "Transform")
                {
                    this.AddChild(CreateSupportButton(theme));
                    this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                }

                GuiWidget button = null;

                if (namedAction is OperationGroup operationGroup)
                {
                    if (operationGroup.Collapse)
                    {
                        var defaultOperation = operationGroup.GetDefaultOperation();

                        PopupMenuButton groupButton = null;

                        groupButton = theme.CreateSplitButton(
                            new SplitButtonParams()
                        {
                            Icon          = defaultOperation.Icon(theme.InvertIcons),
                            DefaultAction = (menuButton) =>
                            {
                                defaultOperation.Action.Invoke(sceneContext);
                            },
                            DefaultActionTooltip = defaultOperation.HelpText ?? defaultOperation.Title,
                            ButtonName           = defaultOperation.Title,
                            ExtendPopupMenu      = (PopupMenu popupMenu) =>
                            {
                                foreach (var operation in operationGroup.Operations)
                                {
                                    var operationMenu = popupMenu.CreateMenuItem(operation.Title, operation.Icon?.Invoke(theme.InvertIcons));

                                    operationMenu.Enabled     = operation.IsEnabled(sceneContext);
                                    operationMenu.ToolTipText = operation.Title;

                                    if (!operationMenu.Enabled &&
                                        !string.IsNullOrEmpty(operation.HelpText))
                                    {
                                        operationMenu.ToolTipText += "\n\n" + operation.HelpText;
                                    }

                                    operationMenu.Click += (s, e) => UiThread.RunOnIdle(() =>
                                    {
                                        if (defaultOperation != operation)
                                        {
                                            // Update button
                                            var iconButton = groupButton.Children.OfType <IconButton>().First();
                                            iconButton.SetIcon(operation.Icon(theme.InvertIcons));
                                            iconButton.ToolTipText = operation.HelpText ?? operation.Title;

                                            UserSettings.Instance.set(operationGroup.GroupRecordId, operationGroup.Operations.IndexOf(operation).ToString());

                                            defaultOperation = operation;

                                            iconButton.Invalidate();
                                        }

                                        operation.Action?.Invoke(sceneContext);
                                    });
                                }
                            }
                        },
                            operationGroup);

                        button = groupButton;
                    }
                    else
                    {
                        if (!(this.ActionArea.Children.LastOrDefault() is ToolbarSeparator))
                        {
                            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                        }

                        foreach (var operation in operationGroup.Operations)
                        {
                            var operationButton = new OperationIconButton(operation, sceneContext, theme);
                            operationButtons.Add(operationButton, operation);

                            this.AddChild(operationButton);
                        }

                        this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
                    }
                }
                else if (namedAction.Icon != null)
                {
                    button = new IconButton(namedAction.Icon(theme.InvertIcons), theme)
                    {
                        Name            = namedAction.Title + " Button",
                        ToolTipText     = namedAction.Title,
                        Margin          = theme.ButtonSpacing,
                        BackgroundColor = theme.ToolbarButtonBackground,
                        HoverColor      = theme.ToolbarButtonHover,
                        MouseDownColor  = theme.ToolbarButtonDown,
                    };
                }
                else
                {
                    button = new TextButton(namedAction.Title, theme)
                    {
                        Name            = namedAction.Title + " Button",
                        Margin          = theme.ButtonSpacing,
                        BackgroundColor = theme.ToolbarButtonBackground,
                        HoverColor      = theme.ToolbarButtonHover,
                        MouseDownColor  = theme.ToolbarButtonDown,
                    };
                }

                if (button != null)
                {
                    operationButtons.Add(button, namedAction);

                    // Only bind Click event if not a SplitButton
                    if (!(button is PopupMenuButton))
                    {
                        button.Click += (s, e) => UiThread.RunOnIdle(() =>
                        {
                            namedAction.Action.Invoke(sceneContext);
                            var partTab = button.Parents <PartTabPage>().FirstOrDefault();
                            var view3D  = partTab.Descendants <View3DWidget>().FirstOrDefault();
                            view3D.Object3DControlLayer.Focus();
                        });
                    }

                    this.AddChild(button);
                }
            }

            // Register listeners
            undoBuffer.Changed += UndoBuffer_Changed;
            sceneContext.Scene.SelectionChanged += UpdateToolbarButtons;
            sceneContext.Scene.ItemsModified    += UpdateToolbarButtons;

            // Run on load
            UpdateToolbarButtons(null, null);
        }
Beispiel #18
0
        public SectionWidget(string sectionTitle, GuiWidget sectionContent, ThemeConfig theme, GuiWidget rightAlignedContent = null, int headingPointSize = -1, bool expandingContent = true, bool expanded = true, string serializationKey = null, bool defaultExpansion = false, bool setContentVAnchor = true)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor     = HAnchor.Stretch;
            this.VAnchor     = VAnchor.Fit;
            this.Border      = new BorderDouble(bottom: 1);
            this.BorderColor = theme.GetBorderColor(50);

            this.setContentVAnchor = setContentVAnchor;

            if (!string.IsNullOrEmpty(sectionTitle))
            {
                // Add heading
                var pointSize = (headingPointSize) == -1 ? theme.DefaultFontSize : headingPointSize;

                if (serializationKey != null)
                {
                    string dbValue = UserSettings.Instance.get(serializationKey);
                    expanded = dbValue == "1" || (dbValue == null && defaultExpansion);
                }

                checkbox = new ExpandCheckboxButton(sectionTitle, theme, pointSize: pointSize, expandable: expandingContent)
                {
                    HAnchor = HAnchor.Stretch,
                    Checked = expanded,
                    Padding = 0
                };
                checkbox.CheckedStateChanged += (s, e) =>
                {
                    ContentPanel.Visible = checkbox.Checked;
                    // TODO: Remove this Height = 10 and figure out why the layout engine is not sizing these correctly without this.
                    ContentPanel.Height = 10;
                };

                if (serializationKey != null)
                {
                    checkbox.CheckedStateChanged += (s, e) =>
                    {
                        UserSettings.Instance.set(serializationKey, checkbox.Checked ? "1" : "0");
                    };
                }

                if (rightAlignedContent == null)
                {
                    this.AddChild(checkbox);
                }
                else
                {
                    rightAlignedContent.HAnchor = HAnchor.Right;

                    var headingRow = new GuiWidget()
                    {
                        VAnchor = VAnchor.Fit,
                        HAnchor = HAnchor.Stretch
                    };
                    headingRow.AddChild(checkbox);
                    headingRow.AddChild(rightAlignedContent);
                    this.AddChild(headingRow);
                }
            }

            sectionContent.Visible = expanded;

            this.SetContentWidget(sectionContent);
        }
        public ApplicationSettingsWidget(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.HAnchor         = HAnchor.Stretch;
            this.VAnchor         = VAnchor.Fit;
            this.BackgroundColor = theme.Colors.PrimaryBackgroundColor;
            this.theme           = theme;

            var configureIcon = AggContext.StaticData.LoadIcon("fa-cog_16.png", 16, 16, theme.InvertIcons);

#if __ANDROID__
            // Camera Monitoring
            bool hasCamera = true || ApplicationSettings.Instance.get(ApplicationSettingsKey.HardwareHasCamera) == "true";

            var previewButton = new IconButton(configureIcon, theme)
            {
                ToolTipText = "Configure Camera View".Localize()
            };
            previewButton.Click += (s, e) =>
            {
                AppContext.Platform.OpenCameraPreview();
            };

            this.AddSettingsRow(
                new SettingsItem(
                    "Camera Monitoring".Localize(),
                    theme,
                    new SettingsItem.ToggleSwitchConfig()
            {
                Checked      = ActiveSliceSettings.Instance.GetValue <bool>(SettingsKey.publish_bed_image),
                ToggleAction = (itemChecked) =>
                {
                    ActiveSliceSettings.Instance.SetValue(SettingsKey.publish_bed_image, itemChecked ? "1" : "0");
                }
            },
                    previewButton,
                    AggContext.StaticData.LoadIcon("camera-24x24.png", 24, 24))
                );
#endif

            // Print Notifications
            var configureNotificationsButton = new IconButton(configureIcon, theme)
            {
                Name        = "Configure Notification Settings Button",
                ToolTipText = "Configure Notifications".Localize(),
                Margin      = new BorderDouble(left: 6),
                VAnchor     = VAnchor.Center
            };
            configureNotificationsButton.Click += (s, e) =>
            {
                if (OpenPrintNotification != null)
                {
                    UiThread.RunOnIdle(OpenPrintNotification);
                }
            };

            AddMenuItem("Help".Localize(), () =>
            {
                UiThread.RunOnIdle(() =>
                {
                    DialogWindow.Show(new HelpPage("AllGuides"));
                });
            });

            this.AddSettingsRow(
                new SettingsItem(
                    "Notifications".Localize(),
                    theme,
                    new SettingsItem.ToggleSwitchConfig()
            {
                Checked      = UserSettings.Instance.get(UserSettingsKey.PrintNotificationsEnabled) == "true",
                ToggleAction = (itemChecked) =>
                {
                    UserSettings.Instance.set(UserSettingsKey.PrintNotificationsEnabled, itemChecked ? "true" : "false");
                }
            },
                    configureNotificationsButton,
                    AggContext.StaticData.LoadIcon("notify-24x24.png")));

            // Touch Screen Mode
            this.AddSettingsRow(
                new SettingsItem(
                    "Touch Screen Mode".Localize(),
                    theme,
                    new SettingsItem.ToggleSwitchConfig()
            {
                Checked      = UserSettings.Instance.get(UserSettingsKey.ApplicationDisplayMode) == "touchscreen",
                ToggleAction = (itemChecked) =>
                {
                    string displayMode = itemChecked ? "touchscreen" : "responsive";
                    if (displayMode != UserSettings.Instance.get(UserSettingsKey.ApplicationDisplayMode))
                    {
                        UserSettings.Instance.set(UserSettingsKey.ApplicationDisplayMode, displayMode);
                        ApplicationController.Instance.ReloadAll();
                    }
                }
            }));

            // LanguageControl
            var languageSelector = new LanguageSelector(theme);
            languageSelector.SelectionChanged += (s, e) =>
            {
                UiThread.RunOnIdle(() =>
                {
                    string languageCode = languageSelector.SelectedValue;
                    if (languageCode != UserSettings.Instance.get(UserSettingsKey.Language))
                    {
                        UserSettings.Instance.set(UserSettingsKey.Language, languageCode);

                        if (languageCode == "L10N")
                        {
                            GenerateLocalizationValidationFile();
                        }

                        ApplicationController.Instance.ResetTranslationMap();
                        ApplicationController.Instance.ReloadAll();
                    }
                });
            };

            this.AddSettingsRow(new SettingsItem("Language".Localize(), languageSelector, theme));

#if !__ANDROID__
            {
                // ThumbnailRendering
                var thumbnailsModeDropList = new DropDownList("", theme.Colors.PrimaryTextColor, maxHeight: 200, pointSize: theme.DefaultFontSize)
                {
                    BorderColor = theme.GetBorderColor(75)
                };
                thumbnailsModeDropList.AddItem("Flat".Localize(), "orthographic");
                thumbnailsModeDropList.AddItem("3D".Localize(), "raytraced");

                thumbnailsModeDropList.SelectedValue     = UserSettings.Instance.ThumbnailRenderingMode;
                thumbnailsModeDropList.SelectionChanged += (s, e) =>
                {
                    string thumbnailRenderingMode = thumbnailsModeDropList.SelectedValue;
                    if (thumbnailRenderingMode != UserSettings.Instance.ThumbnailRenderingMode)
                    {
                        UserSettings.Instance.ThumbnailRenderingMode = thumbnailRenderingMode;

                        UiThread.RunOnIdle(() =>
                        {
                            // Ask if the user they would like to rebuild their thumbnails
                            StyledMessageBox.ShowMessageBox(
                                (bool rebuildThumbnails) =>
                            {
                                if (rebuildThumbnails)
                                {
                                    string directoryToRemove = ApplicationController.CacheablePath("ItemThumbnails", "");
                                    try
                                    {
                                        if (Directory.Exists(directoryToRemove))
                                        {
                                            Directory.Delete(directoryToRemove, true);
                                        }
                                    }
                                    catch (Exception)
                                    {
                                        GuiWidget.BreakInDebugger();
                                    }

                                    Directory.CreateDirectory(directoryToRemove);

                                    ApplicationController.Instance.Library.NotifyContainerChanged();
                                }
                            },
                                "You are switching to a different thumbnail rendering mode. If you want, your current thumbnails can be removed and recreated in the new style. You can switch back and forth at any time. There will be some processing overhead while the new thumbnails are created.\n\nDo you want to rebuild your existing thumbnails now?".Localize(),
                                "Rebuild Thumbnails Now".Localize(),
                                StyledMessageBox.MessageType.YES_NO,
                                "Rebuild".Localize());
                        });
                    }
                };

                this.AddSettingsRow(
                    new SettingsItem(
                        "Thumbnails".Localize(),
                        thumbnailsModeDropList,
                        theme));

                // TextSize
                if (!double.TryParse(UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize), out double currentTexSize))
                {
                    currentTexSize = 1.0;
                }

                double sliderThumbWidth = 10 * GuiWidget.DeviceScale;
                double sliderWidth      = 100 * GuiWidget.DeviceScale;
                var    textSizeSlider   = new SolidSlider(new Vector2(), sliderThumbWidth, .7, 1.4)
                {
                    Name               = "Text Size Slider",
                    Margin             = new BorderDouble(5, 0),
                    Value              = currentTexSize,
                    HAnchor            = HAnchor.Stretch,
                    VAnchor            = VAnchor.Center,
                    TotalWidthInPixels = sliderWidth,
                };

                var optionalContainer = new FlowLayoutWidget()
                {
                    VAnchor = VAnchor.Center | VAnchor.Fit,
                    HAnchor = HAnchor.Fit
                };

                TextWidget sectionLabel = null;

                var textSizeApplyButton = new TextButton("Apply".Localize(), theme)
                {
                    VAnchor         = VAnchor.Center,
                    BackgroundColor = theme.SlightShade,
                    Visible         = false,
                    Margin          = new BorderDouble(right: 6)
                };
                textSizeApplyButton.Click += (s, e) =>
                {
                    GuiWidget.DeviceScale = textSizeSlider.Value;
                    ApplicationController.Instance.ReloadAll();
                };
                optionalContainer.AddChild(textSizeApplyButton);

                textSizeSlider.ValueChanged += (s, e) =>
                {
                    double textSizeNew = textSizeSlider.Value;
                    UserSettings.Instance.set(UserSettingsKey.ApplicationTextSize, textSizeNew.ToString("0.0"));
                    sectionLabel.Text           = "Text Size".Localize() + $" : {textSizeNew:0.0}";
                    textSizeApplyButton.Visible = textSizeNew != currentTexSize;
                };

                var section = new SettingsItem(
                    "Text Size".Localize() + $" : {currentTexSize:0.0}",
                    textSizeSlider,
                    theme,
                    optionalContainer);

                sectionLabel = section.Children <TextWidget>().FirstOrDefault();

                this.AddSettingsRow(section);
            }
#endif

            AddMenuItem("Forums".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://forums.matterhackers.com/category/20/mattercontrol"));
            AddMenuItem("Wiki".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com"));
            AddMenuItem("Guides and Articles".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://www.matterhackers.com/topic/mattercontrol"));
            AddMenuItem("Release Notes".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com/Release_Notes"));
            AddMenuItem("Report a Bug".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://github.com/MatterHackers/MatterControl/issues"));

            var updateMatterControl = new SettingsItem("Check For Update".Localize(), theme);
            updateMatterControl.Click += (s, e) =>
            {
                UiThread.RunOnIdle(() =>
                {
                    UpdateControlData.Instance.CheckForUpdate();
                    DialogWindow.Show <CheckForUpdatesPage>();
                });
            };
            this.AddSettingsRow(updateMatterControl);

            this.AddChild(new SettingsItem("Theme".Localize(), new GuiWidget(), theme));
            this.AddChild(this.GetThemeControl(theme));

            var aboutMatterControl = new SettingsItem("About".Localize() + " " + ApplicationController.Instance.ProductName, theme);
            if (IntPtr.Size == 8)
            {
                // Push right
                aboutMatterControl.AddChild(new HorizontalSpacer());

                // Add x64 adornment
                var blueBox = new FlowLayoutWidget()
                {
                    Margin      = new BorderDouble(10, 0),
                    Padding     = new BorderDouble(2),
                    Border      = new BorderDouble(1),
                    BorderColor = theme.Colors.PrimaryAccentColor,
                    VAnchor     = VAnchor.Center | VAnchor.Fit,
                };
                blueBox.AddChild(new TextWidget("64", pointSize: 8, textColor: theme.Colors.PrimaryAccentColor));

                aboutMatterControl.AddChild(blueBox);
            }
            aboutMatterControl.Click += (s, e) =>
            {
                UiThread.RunOnIdle(() => DialogWindow.Show <AboutPage>());
            };
            this.AddSettingsRow(aboutMatterControl);
        }
Beispiel #20
0
        public PrinterActionsBar(PrinterConfig printer, PrinterTabPage printerTabPage, ThemeConfig theme)
            : base(theme)
        {
            this.printer        = printer;
            this.printerTabPage = printerTabPage;

            this.HAnchor = HAnchor.Stretch;
            this.VAnchor = VAnchor.Fit;

            var defaultMargin = theme.ButtonSpacing;

            var printerType = printer.Settings.Slicer.PrinterType;

            if (printerType == PrinterType.FFF)
            {
                // add the reset button first (if there is one)
                if (printer.Settings.GetValue <bool>(SettingsKey.show_reset_connection))
                {
                    var resetConnectionButton = new TextIconButton(
                        "Reset".Localize(),
                        StaticData.Instance.LoadIcon("e_stop.png", 14, 14).SetToColor(theme.TextColor),
                        theme)
                    {
                        ToolTipText = "Reboots the firmware on the controller".Localize(),
                        Margin      = defaultMargin
                    };
                    resetConnectionButton.Click += (s, e) =>
                    {
                        UiThread.RunOnIdle(printer.Connection.RebootBoard);
                    };
                    this.AddChild(resetConnectionButton);
                }

                this.AddChild(new PrinterConnectButton(printer, theme));

                // add the start print button
                GuiWidget startPrintButton;
                this.AddChild(startPrintButton = new PrintPopupMenu(printer, theme)
                {
                    Margin = theme.ButtonSpacing
                });

                void SetPrintButtonStyle(object s, EventArgs e)
                {
                    switch (printer.Connection.CommunicationState)
                    {
                    case CommunicationStates.FinishedPrint:
                    case CommunicationStates.Connected:
                        theme.ApplyPrimaryActionStyle(startPrintButton);
                        break;

                    default:
                        theme.RemovePrimaryActionStyle(startPrintButton);
                        break;
                    }
                }

                // make sure the buttons state is set correctly
                printer.Connection.CommunicationStateChanged += SetPrintButtonStyle;
                startPrintButton.Closed += (s, e) => printer.Connection.CommunicationStateChanged -= SetPrintButtonStyle;

                // and set the style right now
                SetPrintButtonStyle(this, null);
            }
            else
            {
                var exportButton = new ExportSlaPopupMenu(printer, theme)
                {
                    Margin = theme.ButtonSpacing
                };
                // add the SLA export button
                this.AddChild(exportButton);

                theme.ApplyPrimaryActionStyle(exportButton);
            }

            this.AddChild(new SliceButton(printer, printerTabPage, theme)
            {
                Name   = "Generate Gcode Button",
                Margin = theme.ButtonSpacing,
            });

            // Add vertical separator
            this.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin)
            {
                VAnchor = VAnchor.Absolute,
                Height  = theme.ButtonHeight,
            });

            var buttonGroupB = new ObservableCollection <GuiWidget>();

            var iconPath = Path.Combine("ViewTransformControls", "model.png");

            modelViewButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 16, 16).SetToColor(theme.TextColor), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name             = "Model View Button",
                Checked          = printer?.ViewState.ViewMode == PartViewMode.Model || printer == null,
                ToolTipText      = "Model View".Localize(),
                BackgroundRadius = theme.ButtonRadius * GuiWidget.DeviceScale,
                Margin           = theme.ButtonSpacing
            };
            modelViewButton.Click += SwitchModes_Click;
            buttonGroupB.Add(modelViewButton);
            AddChild(modelViewButton);

            viewModes.Add(PartViewMode.Model, modelViewButton);

            iconPath       = Path.Combine("ViewTransformControls", "gcode_3d.png");
            layers3DButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 16, 16).SetToColor(theme.TextColor), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name             = "Layers3D Button",
                Checked          = printer?.ViewState.ViewMode == PartViewMode.Layers3D,
                ToolTipText      = "3D Layer View".Localize(),
                BackgroundRadius = theme.ButtonRadius * GuiWidget.DeviceScale,
                Margin           = theme.ButtonSpacing
            };
            layers3DButton.Click += SwitchModes_Click;
            buttonGroupB.Add(layers3DButton);

            viewModes.Add(PartViewMode.Layers3D, layers3DButton);

            this.AddChild(layers3DButton);

            iconPath       = Path.Combine("ViewTransformControls", "gcode_2d.png");
            layers2DButton = new RadioIconButton(StaticData.Instance.LoadIcon(iconPath, 16, 16).SetToColor(theme.TextColor), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name             = "Layers2D Button",
                Checked          = printer?.ViewState.ViewMode == PartViewMode.Layers2D,
                ToolTipText      = "2D Layer View".Localize(),
                BackgroundRadius = theme.ButtonRadius * GuiWidget.DeviceScale,
                Margin           = theme.ButtonSpacing,
            };
            layers2DButton.Click += SwitchModes_Click;
            buttonGroupB.Add(layers2DButton);
            this.AddChild(layers2DButton);

            viewModes.Add(PartViewMode.Layers2D, layers2DButton);

            this.AddChild(new HorizontalSpacer());

            if (printerType == PrinterType.FFF)
            {
                int hotendCount = printer.Settings.Helpers.HotendCount();

                for (int extruderIndex = 0; extruderIndex < hotendCount; extruderIndex++)
                {
                    this.AddChild(new TemperatureWidgetHotend(printer, extruderIndex, theme, hotendCount)
                    {
                        Margin = new BorderDouble(right: 10)
                    });
                }

                if (printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed))
                {
                    this.AddChild(new TemperatureWidgetBed(printer, theme));
                }

                // Register listeners
                printer.Connection.ConnectionSucceeded += CheckForPrintRecovery;

                // if we are already connected than check if there is a print recovery right now
                if (printer.Connection.CommunicationState == CommunicationStates.Connected)
                {
                    CheckForPrintRecovery(null, null);
                }
            }

            this.OverflowButton.Name        = "Printer Overflow Menu";
            this.OverflowButton.ToolTipText = "Printer Options".Localize();
            this.ExtendOverflowMenu         = (popupMenu) =>
            {
                this.GeneratePrinterOverflowMenu(popupMenu, ApplicationController.Instance.MenuTheme);
            };

            printer.ViewState.ViewModeChanged += (s, e) =>
            {
                if (viewModes[e.ViewMode] is RadioIconButton activeButton &&
                    viewModes[e.PreviousMode] is RadioIconButton previousButton &&
                    !buttonIsBeingClicked)
                {
                    // Show slide to animation from previous to current, on completion update view to current by setting active.Checked
                    previousButton.SlideToNewState(
                        activeButton,
                        this,
                        () =>
                    {
                        activeButton.Checked = true;
                    },
                        theme);
                }
            };
        }
        public void SetActiveItem(ISceneContext sceneContext)
        {
            var selectedItem = sceneContext?.Scene?.SelectedItem;

            if (this.item == selectedItem)
            {
                return;
            }

            this.item = selectedItem;
            editorPanel.CloseChildren();

            // Allow caller to clean up with passing null for selectedItem
            if (item == null)
            {
                editorSectionWidget.Text = editorTitle;
                return;
            }

            var selectedItemType = selectedItem.GetType();

            primaryActionsPanel.RemoveChildren();

            IEnumerable <SceneOperation> primaryActions;

            if ((primaryActions = SceneOperations.GetPrimaryOperations(selectedItemType)) == null)
            {
                primaryActions = new List <SceneOperation>();
            }
            else
            {
                // Loop over primary actions creating a button for each
                foreach (var primaryAction in primaryActions)
                {
                    // TODO: Run visible/enable rules on actions, conditionally add/enable as appropriate
                    var button = new IconButton(primaryAction.Icon(theme.InvertIcons), theme)
                    {
                        // Name = namedAction.Title + " Button",
                        ToolTipText     = primaryAction.Title,
                        Margin          = theme.ButtonSpacing,
                        BackgroundColor = theme.ToolbarButtonBackground,
                        HoverColor      = theme.ToolbarButtonHover,
                        MouseDownColor  = theme.ToolbarButtonDown,
                    };

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

                    primaryActionsPanel.AddChild(button);
                }
            }

            if (primaryActionsPanel.Children.Any())
            {
                // add in a separator from the apply and cancel buttons
                primaryActionsPanel.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
            }

            editorSectionWidget.Text = selectedItem.Name ?? selectedItemType.Name;

            HashSet <IObject3DEditor> mappedEditors = ApplicationController.Instance.Extensions.GetEditorsForType(selectedItemType);

            var undoBuffer = sceneContext.Scene.UndoBuffer;

            // put in a color edit field
            var colorField = new ColorField(theme, selectedItem.Color);

            colorField.Initialize(0);
            colorField.ValueChanged += (s, e) =>
            {
                if (selectedItem.Color != colorField.Color)
                {
                    undoBuffer.AddAndDo(new ChangeColor(selectedItem, colorField.Color));
                }
            };

            colorField.Content.MouseDown += (s, e) =>
            {
                // make sure the render mode is set to shaded or outline
                if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Shaded &&
                    sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Outlines)
                {
                    // make sure the render mode is set to outline
                    sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Outlines;
                }
            };

            // color row
            var row = new SettingsRow("Color".Localize(), null, colorField.Content, theme);

            // Special top border style for first item in editor
            row.Border = new BorderDouble(0, 1);

            editorPanel.AddChild(row);

            // put in a material edit field
            var materialField = new MaterialIndexField(sceneContext.Printer, theme, selectedItem.MaterialIndex);

            materialField.Initialize(0);
            materialField.ValueChanged += (s, e) =>
            {
                if (selectedItem.MaterialIndex != materialField.MaterialIndex)
                {
                    undoBuffer.AddAndDo(new ChangeMaterial(selectedItem, materialField.MaterialIndex));
                }
            };

            materialField.Content.MouseDown += (s, e) =>
            {
                if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Materials)
                {
                    // make sure the render mode is set to material
                    sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Materials;
                }
            };

            // material row
            editorPanel.AddChild(
                new SettingsRow("Material".Localize(), null, materialField.Content, theme));

            // put in the normal editor
            if (selectedItem is ComponentObject3D componentObject &&
                componentObject.Finalized)
            {
                PublicPropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme);
                foreach (var selector in componentObject.SurfacedEditors)
                {
                    // Get the named property via reflection
                    // Selector example:            '$.Children<CylinderObject3D>'
                    var match = pathResolver.Select(componentObject, selector).ToList();

                    //// TODO: Create editor row for each property
                    //// - Use the type of the property to find a matching editor (ideally all datatype -> editor functionality would resolve consistently)
                    //// - Add editor row for each

                    foreach (var instance in match)
                    {
                        if (instance is IObject3D object3D)
                        {
                            if (ApplicationController.Instance.Extensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is IObject3DEditor editor)
                            {
                                ShowObjectEditor((editor, object3D, object3D.Name), selectedItem);
                            }
                        }
                        else if (JsonPath.JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget)
                        {
                            var context = new PPEContext();

                            if (reflectionTarget.Source is IObject3D editedChild)
                            {
                                context.item = editedChild;
                            }
                            else
                            {
                                context.item = item;
                            }

                            var editableProperty = new EditableProperty(reflectionTarget.PropertyInfo, reflectionTarget.Source);

                            var editor = PublicPropertyEditor.CreatePropertyEditor(editableProperty, undoBuffer, context, theme);
                            if (editor != null)
                            {
                                editorPanel.AddChild(editor);
                            }
                        }
                    }
                }

                // Enforce panel padding
                foreach (var sectionWidget in editorPanel.Descendants <SectionWidget>())
                {
                    sectionWidget.Margin = 0;
                }
            }
Beispiel #22
0
        private DropDownList CreateDropdown()
        {
            var dropDownList = new DropDownList(defaultMenuItemText, theme.Colors.PrimaryTextColor, maxHeight: 300, useLeftIcons: true, pointSize: theme.DefaultFontSize)
            {
                HAnchor          = HAnchor.Stretch,
                VAnchor          = VAnchor.Center,
                MenuItemsPadding = new BorderDouble(10, 7, 7, 7),
                BorderColor      = theme.GetBorderColor(75)
            };

            dropDownList.Name        = layerType.ToString() + " DropDown List";
            dropDownList.Margin      = 0;
            dropDownList.MinimumSize = new Vector2(dropDownList.LocalBounds.Width, dropDownList.LocalBounds.Height);

            MenuItem defaultMenuItem = dropDownList.AddItem(defaultMenuItemText, "");

            defaultMenuItem.Selected += MenuItem_Selected;

            var listSource = (layerType == NamedSettingsLayers.Material) ? printer.Settings.MaterialLayers : printer.Settings.QualityLayers;

            foreach (var layer in listSource.OrderBy(l => l.Name))
            {
                MenuItem menuItem = dropDownList.AddItem(layer.Name, layer.LayerID);
                menuItem.Name      = layer.Name + " Menu";
                menuItem.Selected += MenuItem_Selected;
            }

            MenuItem addNewPreset = dropDownList.AddItem(AggContext.StaticData.LoadIcon("icon_plus.png", 16, 16), "Add New Setting".Localize() + "...", "new");

            addNewPreset.Selected += (s, e) =>
            {
                var newLayer = new PrinterSettingsLayer();
                if (layerType == NamedSettingsLayers.Quality)
                {
                    newLayer.Name = "Quality" + printer.Settings.QualityLayers.Count;
                    printer.Settings.QualityLayers.Add(newLayer);
                    printer.Settings.ActiveQualityKey = newLayer.LayerID;
                }
                else
                {
                    newLayer.Name = "Material" + printer.Settings.MaterialLayers.Count;
                    printer.Settings.MaterialLayers.Add(newLayer);
                    printer.Settings.ActiveMaterialKey = newLayer.LayerID;
                }

                RebuildDropDownList();

                editButton.OnClick(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
            };

            try
            {
                string settingsKey;

                if (layerType == NamedSettingsLayers.Material)
                {
                    settingsKey = printer.Settings.ActiveMaterialKey;

                    printer.Settings.MaterialLayers.CollectionChanged += SettingsLayers_CollectionChanged;
                    dropDownList.Closed += (s1, e1) =>
                    {
                        printer.Settings.MaterialLayers.CollectionChanged -= SettingsLayers_CollectionChanged;
                    };
                }
                else
                {
                    settingsKey = printer.Settings.ActiveQualityKey;

                    printer.Settings.QualityLayers.CollectionChanged += SettingsLayers_CollectionChanged;
                    dropDownList.Closed += (s1, e1) =>
                    {
                        printer.Settings.QualityLayers.CollectionChanged -= SettingsLayers_CollectionChanged;
                    };
                }

                if (!string.IsNullOrEmpty(settingsKey))
                {
                    dropDownList.SelectedValue = settingsKey;
                }
            }
            catch (Exception ex)
            {
                GuiWidget.BreakInDebugger(ex.Message);
            }

            return(dropDownList);
        }
        public void SetActiveItem(ISceneContext sceneContext)
        {
            var selectedItem = sceneContext?.Scene?.SelectedItem;

            if (this.item == selectedItem)
            {
                return;
            }

            this.item = selectedItem;
            editorPanel.CloseChildren();

            // Allow caller to clean up with passing null for selectedItem
            if (item == null)
            {
                editorSectionWidget.Text = editorTitle;
                return;
            }

            var selectedItemType = selectedItem.GetType();

            primaryActionsPanel.RemoveChildren();

            IEnumerable <SceneOperation> primaryActions;

            if ((primaryActions = SceneOperations.GetPrimaryOperations(selectedItemType)) == null)
            {
                primaryActions = new List <SceneOperation>();
            }
            else
            {
                // Loop over primary actions creating a button for each
                foreach (var primaryAction in primaryActions)
                {
                    // TODO: Run visible/enable rules on actions, conditionally add/enable as appropriate
                    var button = new IconButton(primaryAction.Icon(theme), theme)
                    {
                        // Name = namedAction.Title + " Button",
                        ToolTipText     = primaryAction.Title,
                        Margin          = theme.ButtonSpacing,
                        BackgroundColor = theme.ToolbarButtonBackground,
                        HoverColor      = theme.ToolbarButtonHover,
                        MouseDownColor  = theme.ToolbarButtonDown,
                    };

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

                    primaryActionsPanel.AddChild(button);
                }
            }

            if (primaryActionsPanel.Children.Any())
            {
                // add in a separator from the apply and cancel buttons
                primaryActionsPanel.AddChild(new ToolbarSeparator(theme.GetBorderColor(50), theme.SeparatorMargin));
            }

            editorSectionWidget.Text = selectedItem.Name ?? selectedItemType.Name;

            HashSet <IObject3DEditor> mappedEditors = ApplicationController.Instance.Extensions.GetEditorsForType(selectedItemType);

            var undoBuffer = sceneContext.Scene.UndoBuffer;

            if (!(selectedItem.GetType().GetCustomAttributes(typeof(HideMeterialAndColor), true).FirstOrDefault() is HideMeterialAndColor))
            {
                // put in a color edit field
                var colorField = new ColorField(theme, selectedItem.Color);
                colorField.Initialize(0);
                colorField.ValueChanged += (s, e) =>
                {
                    if (selectedItem.Color != colorField.Color)
                    {
                        undoBuffer.AddAndDo(new ChangeColor(selectedItem, colorField.Color));
                    }
                };

                colorField.Content.MouseDown += (s, e) =>
                {
                    // make sure the render mode is set to shaded or outline
                    if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Shaded &&
                        sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Outlines)
                    {
                        // make sure the render mode is set to outline
                        sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Outlines;
                    }
                };

                // color row
                var row = new SettingsRow("Color".Localize(), null, colorField.Content, theme);

                // Special top border style for first item in editor
                row.Border = new BorderDouble(0, 1);

                editorPanel.AddChild(row);

                // put in a material edit field
                var materialField = new MaterialIndexField(sceneContext.Printer, theme, selectedItem.MaterialIndex);
                materialField.Initialize(0);
                materialField.ValueChanged += (s, e) =>
                {
                    if (selectedItem.MaterialIndex != materialField.MaterialIndex)
                    {
                        undoBuffer.AddAndDo(new ChangeMaterial(selectedItem, materialField.MaterialIndex));
                    }
                };

                materialField.Content.MouseDown += (s, e) =>
                {
                    if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Materials)
                    {
                        // make sure the render mode is set to material
                        sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Materials;
                    }
                };

                // material row
                editorPanel.AddChild(
                    new SettingsRow("Material".Localize(), null, materialField.Content, theme));
            }

            var rows = new SafeList <SettingsRow>();

            // put in the normal editor
            if (selectedItem is ComponentObject3D componentObject &&
                componentObject.Finalized)
            {
                var context = new PPEContext();
                PublicPropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme);
                foreach (var selector in componentObject.SurfacedEditors)
                {
                    // if it is a reference to a sheet cell
                    if (selector.StartsWith("!"))
                    {
                        var firtSheet = componentObject.Descendants <SheetObject3D>().FirstOrDefault();
                        if (firtSheet != null)
                        {
                            var cellId = selector.Substring(1);
                            var cell   = firtSheet.SheetData[cellId];
                            if (cell != null)
                            {
                                // add an editor for the cell
                                var field = new DoubleField(theme);
                                field.Initialize(0);
                                double.TryParse(firtSheet.SheetData.EvaluateExpression(cellId), out double value);
                                field.DoubleValue = value;
                                field.ClearUndoHistory();

                                field.Content.Descendants <InternalNumberEdit>().First().MaxDecimalsPlaces = 3;
                                field.ValueChanged += (s, e) =>
                                {
                                    cell.Expression = field.Value;
                                    firtSheet.SheetData.Recalculate();
                                };

                                var row = new SettingsRow(cell.Name == null ? cellId : cell.Name, null, field.Content, theme);

                                editorPanel.AddChild(row);
                            }
                        }
                    }
                    else                     // parse it as a path to an object
                    {
                        // Get the named property via reflection
                        // Selector example:            '$.Children<CylinderObject3D>'
                        var match = pathResolver.Select(componentObject, selector).ToList();

                        //// - Add editor row for each
                        foreach (var instance in match)
                        {
                            if (instance is IObject3D object3D)
                            {
                                if (ApplicationController.Instance.Extensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is IObject3DEditor editor)
                                {
                                    ShowObjectEditor((editor, object3D, object3D.Name), selectedItem);
                                }
                            }
                            else if (JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget)
                            {
                                if (reflectionTarget.Source is IObject3D editedChild)
                                {
                                    context.item = editedChild;
                                }
                                else
                                {
                                    context.item = item;
                                }

                                var editableProperty = new EditableProperty(reflectionTarget.PropertyInfo, reflectionTarget.Source);

                                var editor = PublicPropertyEditor.CreatePropertyEditor(rows, editableProperty, undoBuffer, context, theme);
                                if (editor != null)
                                {
                                    editorPanel.AddChild(editor);
                                }

                                // Init with custom 'UpdateControls' hooks
                                (context.item as IPropertyGridModifier)?.UpdateControls(new PublicPropertyChange(context, "Update_Button"));
                            }
                        }
                    }
                }

                // Enforce panel padding
                foreach (var sectionWidget in editorPanel.Descendants <SectionWidget>())
                {
                    sectionWidget.Margin = 0;
                }
            }