diff --git a/MatterControlLib/ActionBar/PrinterSelector.cs b/MatterControlLib/ActionBar/PrinterSelector.cs index 27ce0b475..f59c67cf6 100644 --- a/MatterControlLib/ActionBar/PrinterSelector.cs +++ b/MatterControlLib/ActionBar/PrinterSelector.cs @@ -159,5 +159,10 @@ namespace MatterHackers.MatterControl unregisterEvents?.Invoke(this, null); base.OnClosed(e); } + + public bool KeepMenuOpen() + { + return false; + } } } \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index ce7a11405..7fce87b13 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -168,24 +168,25 @@ 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) + popupMenu.CreateSubMenu("Modify".Localize(), ApplicationController.Instance.MenuTheme, (modifyMenu) => { - foreach (var type in nodeOperation.MappedTypes) + foreach (var nodeOperation in ApplicationController.Instance.Graph.Operations) { - if (type.IsAssignableFrom(selectedItemType) - && (nodeOperation.IsVisible?.Invoke(selectedItem) != false) - && nodeOperation.IsEnabled?.Invoke(selectedItem) != false) + foreach (var type in nodeOperation.MappedTypes) { - var subMenuItem = modifyMenu.CreateMenuItem(nodeOperation.Title, nodeOperation.IconCollector?.Invoke(menuTheme)); - subMenuItem.Click += (s2, e2) => + if (type.IsAssignableFrom(selectedItemType) + && (nodeOperation.IsVisible?.Invoke(selectedItem) != false) + && nodeOperation.IsEnabled?.Invoke(selectedItem) != false) { - nodeOperation.Operation(selectedItem, scene).ConfigureAwait(false); - }; + var subMenuItem = modifyMenu.CreateMenuItem(nodeOperation.Title, nodeOperation.IconCollector?.Invoke(menuTheme)); + subMenuItem.Click += (s2, e2) => + { + nodeOperation.Operation(selectedItem, scene).ConfigureAwait(false); + }; + } } } - } + }); }; return popupMenu; diff --git a/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs b/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs index 35441c750..cef79fa2a 100644 --- a/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs +++ b/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs @@ -342,6 +342,11 @@ namespace MatterHackers.MatterControl.ConfigurationPage this.AddSettingsRow(aboutMatterControl); } + public bool KeepMenuOpen() + { + return false; + } + private void AddMenuItem(string title, Action callback) { var newItem = new SettingsItem(title, theme); diff --git a/MatterControlLib/CustomWidgets/DockingTabControl.cs b/MatterControlLib/CustomWidgets/DockingTabControl.cs index 63734262a..0eb40279a 100644 --- a/MatterControlLib/CustomWidgets/DockingTabControl.cs +++ b/MatterControlLib/CustomWidgets/DockingTabControl.cs @@ -398,6 +398,11 @@ namespace MatterHackers.MatterControl.CustomWidgets AddChild(topToBottom); } + + public bool KeepMenuOpen() + { + return false; + } } } diff --git a/MatterControlLib/PartPreviewWindow/MaterialControls.cs b/MatterControlLib/PartPreviewWindow/MaterialControls.cs index 3fa9a3579..e6ee6a45d 100644 --- a/MatterControlLib/PartPreviewWindow/MaterialControls.cs +++ b/MatterControlLib/PartPreviewWindow/MaterialControls.cs @@ -149,5 +149,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow scene.SelectionChanged -= Scene_SelectionChanged; base.OnClosed(e); } + + public bool KeepMenuOpen() + { + return false; + } } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/PopupButton.cs b/MatterControlLib/PartPreviewWindow/PopupButton.cs index 32aa70f87..46ed2d9ea 100644 --- a/MatterControlLib/PartPreviewWindow/PopupButton.cs +++ b/MatterControlLib/PartPreviewWindow/PopupButton.cs @@ -146,5 +146,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { this.BeforePopup?.Invoke(this, null); } + + public bool KeepMenuOpen() + { + return false; + } } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/PopupMenu.cs b/MatterControlLib/PartPreviewWindow/PopupMenu.cs index 07959685c..8dfb9f66d 100644 --- a/MatterControlLib/PartPreviewWindow/PopupMenu.cs +++ b/MatterControlLib/PartPreviewWindow/PopupMenu.cs @@ -108,6 +108,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow Image = icon }; + menuItem.Click += (s, e) => + { + Unfocus(); + }; + this.AddChild(menuItem); return menuItem; @@ -115,10 +120,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public class SubMenuItemButton : MenuItem, IIgnoredPopupChild { - public PopupMenu PopupMenu { get; set; } - public SubMenuItemButton(GuiWidget content, ThemeConfig theme, PopupMenu menu) : base(content, theme) + public PopupMenu SubMenu { get; set; } + + public SubMenuItemButton(GuiWidget content, ThemeConfig theme) : base(content, theme) { - PopupMenu = menu; } public override void OnDraw(Graphics2D graphics2D) @@ -136,48 +141,16 @@ namespace MatterHackers.MatterControl.PartPreviewWindow 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) + public bool KeepMenuOpen() { - Padding = MenuPadding, - }; - - if (shortCut != null) - { - content = new GuiWidget() + if (SubMenu != null) { - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit - }; + return SubMenu.ContainsFocus; + } - content.AddChild(new TextWidget(shortCut, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) - { - HAnchor = HAnchor.Right - }); - - content.AddChild(textWidget); + return false; } - 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 @@ -198,6 +171,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow base.OnLoad(args); } + public bool KeepMenuOpen() + { + return false; + } + public bool Checked { get => _checked; @@ -267,6 +245,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow base.OnLoad(args); } + public bool KeepMenuOpen() + { + return false; + } + public IList SiblingRadioButtonList { get; set; } public bool Checked @@ -295,15 +278,32 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public event EventHandler CheckedStateChanged; } - public PopupMenu CreateSubMenu(string menuTitle, ThemeConfig menuTheme) + public void CreateSubMenu(string menuTitle, ThemeConfig menuTheme, Action populateSubMenu) { - var subMenu = new PopupMenu(menuTheme); - var subMenuItemButton = this.CreateSubMenuButton(menuTitle, subMenu); + GuiWidget content = new TextWidget(menuTitle, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) + { + Padding = MenuPadding, + }; + + content.Selectable = false; + + var subMenuItemButton = new SubMenuItemButton(content, theme) + { + Name = menuTitle + " Menu Item", + //Image = icon + }; + + this.AddChild(subMenuItemButton); subMenuItemButton.Click += (s, e) => { + var subMenu = new PopupMenu(menuTheme); + subMenuItemButton.SubMenu = subMenu; + UiThread.RunOnIdle(() => { + populateSubMenu(subMenu); + var systemWindow = this.Parents().FirstOrDefault(); systemWindow.ShowPopup( new MatePoint(subMenuItemButton) @@ -322,10 +322,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow subMenu.Closed += (s1, e1) => { subMenu.ClearRemovedFlag(); + subMenuItemButton.SubMenu = null; + if(!this.ContainsFocus) + { + this.Close(); + } }; }; - - return subMenu; } public MenuItem CreateBoolMenuItem(string name, Func getter, Action setter, bool useRadioStyle = false, IList siblingRadioButtonList = null) diff --git a/MatterControlLib/PartPreviewWindow/SectionWidget.cs b/MatterControlLib/PartPreviewWindow/SectionWidget.cs index 6e01d5a2d..4d9ed1c72 100644 --- a/MatterControlLib/PartPreviewWindow/SectionWidget.cs +++ b/MatterControlLib/PartPreviewWindow/SectionWidget.cs @@ -183,5 +183,10 @@ namespace MatterHackers.MatterControl.CustomWidgets base.OnDrawBackground(graphics2D); } } + + public bool KeepMenuOpen() + { + return false; + } } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs b/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs index b5832e8bc..3b9928145 100644 --- a/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs +++ b/MatterControlLib/PartPreviewWindow/SystemWindowExtension.cs @@ -88,9 +88,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { var hookedParents = new HashSet(); - var ignoredWidgets = popup.Widget.Children.Where(c => c is IIgnoredPopupChild).ToList(); - - bool checkIfNeedScrollBar = true; + List ignoredWidgets = popup.Widget.Children.OfType().ToList(); void widgetRelativeTo_PositionChanged(object sender, EventArgs e) { @@ -158,16 +156,14 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - void FocusChanged(object sender, EventArgs e) + void FocusChanged(object s, EventArgs e) { UiThread.RunOnIdle(() => { - var send = sender; - // Fired any time focus changes. Traditionally we closed the menu if the we weren't focused. + // Fired any time focus changes. Traditionally we closed the menu if 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.PopupMenu.ContainsFocus); + bool specialChildHasFocus = ignoredWidgets.Any(w => w.ContainsFocus || w.Focused || w.KeepMenuOpen()) + || popup.Widget.DescendantsAndSelf().Any(w => w.IsOpen); // If the focused changed and we've lost focus and no special cases permit, close the menu if (!popup.Widget.ContainsFocus diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/ImageEditor.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/ImageEditor.cs index 3ab415ac2..bc337e409 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/ImageEditor.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/ImageEditor.cs @@ -116,8 +116,6 @@ namespace MatterHackers.MatterControl.DesignTools column.Invalidate(); imageObject.Invalidate(new InvalidateArgs(imageObject, InvalidateType.Image)); - - popupMenu.Unfocus(); }; pasteMenu.Enabled = Clipboard.Instance.ContainsImage; @@ -126,7 +124,6 @@ namespace MatterHackers.MatterControl.DesignTools copyMenu.Click += (s2, e2) => { Clipboard.Instance.SetImage(thumbnailWidget.Image); - popupMenu.Unfocus(); }; var popupBounds = new RectangleDouble(e.X + 1, e.Y + 1, e.X + 1, e.Y + 1); diff --git a/MatterControlLib/PartPreviewWindow/View3D/GridOptionsPanel.cs b/MatterControlLib/PartPreviewWindow/View3D/GridOptionsPanel.cs index ff5289935..39aa91648 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/GridOptionsPanel.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/GridOptionsPanel.cs @@ -81,5 +81,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } this.AddChild(dropDownList); } + + public bool KeepMenuOpen() + { + return false; + } } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs index 49787168b..e8e153506 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs @@ -212,6 +212,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow : base(FlowDirection.TopToBottom) { } + + public bool KeepMenuOpen() + { + return false; + } } } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index 3577e5c5c..6bbf29ff9 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -1320,7 +1320,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow Action = () => { Scene.Paste(); - popupMenu.Unfocus(); }, IsEnabled = () => Clipboard.Instance.ContainsImage || Clipboard.Instance.GetText() == "!--IObjectSelection--!" }, diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index b59a1957e..6b893b449 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit b59a1957eb2fbdbffe3b21306f124cd48e438d75 +Subproject commit 6b893b449e604a6294a2abd7ca7bda43400e3adb