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