diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index a5047ea1d..ce7a11405 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -141,7 +141,7 @@ namespace MatterHackers.MatterControl { var popupMenu = new PopupMenu(ApplicationController.Instance.MenuTheme); - var menuItem = popupMenu.CreateMenuItem("Rename"); + var menuItem = popupMenu.CreateMenuItem("Rename".Localize()); menuItem.Click += (s, e) => { DialogWindow.Show( @@ -168,6 +168,8 @@ namespace MatterHackers.MatterControl var menuTheme = ApplicationController.Instance.MenuTheme; + PopupMenu modifyMenu = popupMenu.CreateSubMenu("Modify".Localize(), ApplicationController.Instance.MenuTheme); + foreach (var nodeOperation in ApplicationController.Instance.Graph.Operations) { foreach (var type in nodeOperation.MappedTypes) @@ -176,27 +178,15 @@ namespace MatterHackers.MatterControl && (nodeOperation.IsVisible?.Invoke(selectedItem) != false) && nodeOperation.IsEnabled?.Invoke(selectedItem) != false) { - var button = popupMenu.CreateMenuItem(nodeOperation.Title, nodeOperation.IconCollector?.Invoke(menuTheme)); - button.Click += (s, e) => + var subMenuItem = modifyMenu.CreateMenuItem(nodeOperation.Title, nodeOperation.IconCollector?.Invoke(menuTheme)); + subMenuItem.Click += (s2, e2) => { nodeOperation.Operation(selectedItem, scene).ConfigureAwait(false); }; } } } - - if (selectedItem.Ancestors().OfType().FirstOrDefault() is ComponentObject3D componentAncestor - && !componentAncestor.Finalized) - { - var button = popupMenu.CreateMenuItem("Copy Path".Localize()); - button.Click += (s, e) => - { - var selector = "$." + string.Join(".", selectedItem.AncestorsAndSelf().TakeWhile(o => !(o is ComponentObject3D)).Select(o => $"Children<{o.GetType().Name.ToString()}>").Reverse().ToArray()); - - Clipboard.Instance.SetText(selector); - }; - } - } + }; return popupMenu; } diff --git a/MatterControlLib/Library/Widgets/ExpandCheckboxButton.cs b/MatterControlLib/Library/Widgets/ExpandCheckboxButton.cs index 22661334d..22fddf8e8 100644 --- a/MatterControlLib/Library/Widgets/ExpandCheckboxButton.cs +++ b/MatterControlLib/Library/Widgets/ExpandCheckboxButton.cs @@ -53,11 +53,12 @@ namespace MatterHackers.MatterControl.CustomWidgets arrowRight = AggContext.StaticData.LoadIcon("fa-angle-right_12.png", theme.InvertIcons); arrowDown = AggContext.StaticData.LoadIcon("fa-angle-down_12.png", theme.InvertIcons); - imageButton = new IconButton(expandable ? arrowRight : new ImageBuffer(), theme) + imageButton = new IconButton(arrowRight, theme) { - MinimumSize = new Vector2((expandable) ? theme.ButtonHeight : 10, theme.ButtonHeight), + MinimumSize = new Vector2(theme.ButtonHeight, theme.ButtonHeight), VAnchor = VAnchor.Center, - Selectable = false + Selectable = false, + Enabled = expandable }; this.AddChild(imageButton); @@ -91,7 +92,7 @@ namespace MatterHackers.MatterControl.CustomWidgets _expandable = value; imageButton.SetIcon(_expandable ? arrowRight : new ImageBuffer()); - this.MinimumSize = new Vector2((double)((_expandable) ? this.MinimumSize.X : 10), (double)this.MinimumSize.Y); + this.MinimumSize = new Vector2((_expandable) ? this.MinimumSize.X : 10, this.MinimumSize.Y); } } } @@ -109,7 +110,11 @@ namespace MatterHackers.MatterControl.CustomWidgets public override void OnClick(MouseEventArgs mouseEvent) { - UiThread.RunOnIdle(() => this.Checked = !this.Checked); + if (this.Expandable) + { + UiThread.RunOnIdle(() => this.Checked = !this.Checked); + } + base.OnClick(mouseEvent); } diff --git a/MatterControlLib/PartPreviewWindow/PopupMenu.cs b/MatterControlLib/PartPreviewWindow/PopupMenu.cs index b7b7138d6..07959685c 100644 --- a/MatterControlLib/PartPreviewWindow/PopupMenu.cs +++ b/MatterControlLib/PartPreviewWindow/PopupMenu.cs @@ -34,6 +34,7 @@ using MatterHackers.Agg; using MatterHackers.Agg.Image; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; +using MatterHackers.Agg.VertexSource; using MatterHackers.ImageProcessing; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.Library; @@ -112,6 +113,73 @@ namespace MatterHackers.MatterControl.PartPreviewWindow return menuItem; } + public class SubMenuItemButton : MenuItem, IIgnoredPopupChild + { + public PopupMenu PopupMenu { get; set; } + public SubMenuItemButton(GuiWidget content, ThemeConfig theme, PopupMenu menu) : base(content, theme) + { + PopupMenu = menu; + } + + public override void OnDraw(Graphics2D graphics2D) + { + base.OnDraw(graphics2D); + + // draw the right arrow + var x = this.LocalBounds.Right - this.LocalBounds.Height / 2; + var y = this.Size.Y / 2 + 2; + + var arrow = new VertexStorage(); + arrow.MoveTo(x + 3, y); + arrow.LineTo(x - 3, y + 5); + arrow.LineTo(x - 3, y - 5); + + graphics2D.Render(arrow, this.Enabled ? Color.Black : Color.Gray); + } + } + + private SubMenuItemButton CreateSubMenuButton(string name, PopupMenu popupMenu, ImageBuffer icon = null, string shortCut = null) + { + GuiWidget content; + + var textWidget = new TextWidget(name, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) + { + Padding = MenuPadding, + }; + + if (shortCut != null) + { + content = new GuiWidget() + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }; + + content.AddChild(new TextWidget(shortCut, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) + { + HAnchor = HAnchor.Right + }); + + content.AddChild(textWidget); + } + else + { + content = textWidget; + } + + content.Selectable = false; + + var menuItem = new SubMenuItemButton(content, theme, popupMenu) + { + Name = name + " Menu Item", + Image = icon + }; + + this.AddChild(menuItem); + + return menuItem; + } + public class CheckboxMenuItem : MenuItem, IIgnoredPopupChild, ICheckbox { private bool _checked; @@ -158,7 +226,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private ImageBuffer radioIconUnchecked; public RadioMenuItem(GuiWidget widget, ThemeConfig theme) - : base (widget, theme) + : base(widget, theme) { } @@ -227,6 +295,39 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public event EventHandler CheckedStateChanged; } + public PopupMenu CreateSubMenu(string menuTitle, ThemeConfig menuTheme) + { + var subMenu = new PopupMenu(menuTheme); + var subMenuItemButton = this.CreateSubMenuButton(menuTitle, subMenu); + + subMenuItemButton.Click += (s, e) => + { + UiThread.RunOnIdle(() => + { + var systemWindow = this.Parents().FirstOrDefault(); + systemWindow.ShowPopup( + new MatePoint(subMenuItemButton) + { + Mate = new MateOptions(MateEdge.Right, MateEdge.Top), + AltMate = new MateOptions(MateEdge.Left, MateEdge.Top) + }, + new MatePoint(subMenu) + { + Mate = new MateOptions(MateEdge.Left, MateEdge.Top), + AltMate = new MateOptions(MateEdge.Right, MateEdge.Top) + } + );// altBounds: new RectangleDouble(mouseEvent.X + 1, mouseEvent.Y + 1, mouseEvent.X + 1, mouseEvent.Y + 1)); + }); + + subMenu.Closed += (s1, e1) => + { + subMenu.ClearRemovedFlag(); + }; + }; + + return subMenu; + } + public MenuItem CreateBoolMenuItem(string name, Func getter, Action setter, bool useRadioStyle = false, IList siblingRadioButtonList = null) { var textWidget = new TextWidget(name, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) diff --git a/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs b/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs index f5069df97..b5832e8bc 100644 --- a/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs +++ b/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs @@ -162,10 +162,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { UiThread.RunOnIdle(() => { + var send = sender; // Fired any time focus changes. Traditionally we closed the menu if the we weren't focused. // To accommodate children (or external widgets) having focus we also query for and consider special cases bool specialChildHasFocus = ignoredWidgets.Any(w => w.ContainsFocus || w.Focused) - || popup.Widget.DescendantsAndSelf().Any(w => w.IsOpen); + || popup.Widget.DescendantsAndSelf().Any(w => w.IsOpen) + || popup.Widget.DescendantsAndSelf().Any(w => w.PopupMenu.ContainsFocus); // If the focused changed and we've lost focus and no special cases permit, close the menu if (!popup.Widget.ContainsFocus @@ -176,15 +178,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }); } - void MouseUp(object sender, EventArgs e) - { - bool mouseUpOnIgnoredChild = ignoredWidgets.Any(w => w.MouseCaptured || w.ChildHasMouseCaptured); - if (!mouseUpOnIgnoredChild) - { - UiThread.RunOnIdle(CloseMenu); - } - } - void anchor_Closed(object sender, EventArgs e) { // If the owning widget closed, so should we diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index 1f0b50303..3577e5c5c 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -174,7 +174,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow // add the tree view treeView = new TreeView(theme) { - Margin = new BorderDouble(left: 18), + Margin = new BorderDouble(left: theme.DefaultContainerPadding, top: theme.DefaultContainerPadding), }; treeView.AfterSelect += (s, e) => {