diff --git a/CADability/MenuResource.cs b/CADability/MenuResource.cs index 3a111d44..85abf613 100644 --- a/CADability/MenuResource.cs +++ b/CADability/MenuResource.cs @@ -304,14 +304,16 @@ static public MenuWithHandler[] CreateContextMenuWithHandler(string[] menuIDs, I /// Name of the menu to load: the "Name" attribute of a "MainMenu" node or the "MenuId" attribute of a "Popup" node /// true to load a main menu, false to load a popup (context) menu /// Command handler which handles the menu commands - /// The menu entries + /// The menu entries, an empty array if there is no menu with this name (e.g. for a null name) static public MenuWithHandler[] LoadMenuDefinition(string MenuName, bool main, ICommandHandler handler) { List result = new List(); ICommandHandler Handler = handler; + if (MenuName == null) return result.ToArray(); // e.g. an object without a context menu of its own, like a picture XmlNode MenuNode; if (main) MenuNode = mMenuDocument.SelectSingleNode("Menus/MainMenu[@Name='" + MenuName + "']"); else MenuNode = mMenuDocument.SelectSingleNode("Menus//Popup[@MenuId='" + MenuName + "']"); + if (MenuNode == null) return result.ToArray(); for (XmlNode nd = MenuNode.FirstChild; nd != null; nd = nd.NextSibling) { LoadMenu(nd, result, Handler); diff --git a/CADability/UnscaledGeoObject.cs b/CADability/UnscaledGeoObject.cs index 6e454eed..4d211e9c 100644 --- a/CADability/UnscaledGeoObject.cs +++ b/CADability/UnscaledGeoObject.cs @@ -343,7 +343,7 @@ IGeoObject IGeoObjectShowProperty.GetGeoObject() string IGeoObjectShowProperty.GetContextMenuId() { - throw new Exception("The method or operation is not implemented."); + return null; // no context menu of its own } #endregion diff --git a/CADability/UnscaledIcon.cs b/CADability/UnscaledIcon.cs index fd6a82f6..639bc6c7 100644 --- a/CADability/UnscaledIcon.cs +++ b/CADability/UnscaledIcon.cs @@ -338,7 +338,7 @@ IGeoObject IGeoObjectShowProperty.GetGeoObject() string IGeoObjectShowProperty.GetContextMenuId() { - throw new Exception("The method or operation is not implemented."); + return null; // no context menu of its own } #endregion diff --git a/tests/CADability.Tests/ContextMenuTests.cs b/tests/CADability.Tests/ContextMenuTests.cs new file mode 100644 index 00000000..f78d77a4 --- /dev/null +++ b/tests/CADability.Tests/ContextMenuTests.cs @@ -0,0 +1,45 @@ +using CADability.GeoObject; +using CADability.UserInterface; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CADability.Tests +{ + /// + /// The context menu of a selected object: loads the menu whose id the object's + /// returns. Pictures, icons and unscaled objects have no menu of their own and + /// return null; a right click on a selected picture threw a NullReferenceException in + /// . + /// + [TestClass] + public class ContextMenuTests + { + [TestMethod] + public void AMissingMenuIsEmpty() + { + Assert.AreEqual(0, MenuResource.LoadMenuDefinition(null, false, null).Length); + Assert.AreEqual(0, MenuResource.LoadMenuDefinition("MenuId.DoesNotExist", false, null).Length); + Assert.AreEqual(0, MenuResource.LoadMenuDefinition("No Such Main Menu", true, null).Length); + } + + [TestMethod] + public void AnExistingMenuIsLoaded() + { + // the context menu of the path of a picture + MenuWithHandler[] menu = MenuResource.LoadMenuDefinition("MenuId.Picture.Path", false, null); + CollectionAssert.AreEqual(new[] { "MenuId.Picture.Path.Reload", "MenuId.Picture.Path.Open" }, menu.Select(m => m.ID).ToArray()); + } + + [TestMethod] + [DataRow(typeof(ShowPropertyPicture))] + [DataRow(typeof(ShowPropertyUnscaledIcon))] + [DataRow(typeof(ShowPropertyUnscaledGeoObject))] + public void TheContextMenuOfObjectsWithoutAMenuOfTheirOwnCanBeLoaded(Type showPropertyType) + { + // what SelectObjectsAction.OnMouseUp does for a single selected object; the id does not depend on the state + // of the property, so an uninitialized one (without a frame) is enough + IGeoObjectShowProperty showProperty = (IGeoObjectShowProperty)System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(showPropertyType); + MenuWithHandler[] menu = MenuResource.LoadMenuDefinition(showProperty.GetContextMenuId(), false, showProperty as ICommandHandler); + Assert.AreEqual(0, menu.Length); + } + } +}