MenuItemContext InitializeMainSubMenu(MenuItem menuItem, MenuMD md, IInputElement commandTarget) { Reinitialize(menuItem); var guid = new Guid(md.Metadata.Guid); bool b = guidToGroups.TryGetValue(guid, out var groups); Debug.Assert(b); if (b) { BindBackgroundBrush(menuItem, isCtxMenu: false); var ctx = new MenuItemContext(guid, true, new GuidObject(guid, null), null); var firstMenuItem = menuItem.Items.Count == 1 ? menuItem.Items[0] as MenuItem : null; var allItems = CreateMenuItems(ctx, groups, commandTarget, firstMenuItem, false); foreach (var i in allItems) { if (firstMenuItem != i) { menuItem.Items.Add(i); } } return(ctx); } return(null); }
internal bool?ShowContextMenu(object evArgs, FrameworkElement ctxMenuElem, Guid topLevelMenuGuid, Guid ownerMenuGuid, GuidObject creatorObject, IGuidObjectsProvider?provider, IContextMenuInitializer?initCtxMenu, bool openedFromKeyboard) { InitializeMenuItemObjects(); Debug2.Assert(guidToGroups is not null); // There could be nested context menu handler calls, eg. first text editor followed by // the TabControl. We don't wan't the TabControl to disable the text editor's ctx menu. if (prevEventArgs.Target == evArgs) { return(null); } var ctx = new MenuItemContext(topLevelMenuGuid, openedFromKeyboard, creatorObject, provider?.GetGuidObjects(new GuidObjectsProviderArgs(creatorObject, openedFromKeyboard))); bool b = guidToGroups.TryGetValue(ownerMenuGuid, out var groups); if (!b) { return(false); } Debug2.Assert(groups is not null); var menu = new ContextMenu(); BindBackgroundBrush(menu, isCtxMenu: true); // The owner control could be zoomed (eg. text editor) but the context menu isn't, so make // sure we use 100% zoom here (same as the context menu). double defaultZoom = 1.0; DsImage.SetZoom(menu, defaultZoom); // Also make sure we use Display mode. Let MetroWindow handle it since it has some extra checks var window = Window.GetWindow(ctxMenuElem) as MetroWindow; window?.SetScaleTransform(menu, defaultZoom); var allItems = CreateMenuItems(ctx, groups, null, null, true); if (allItems.Count == 0) { return(false); } foreach (var i in allItems) { menu.Items.Add(i); } menu.Closed += (s, e) => { ctx.Dispose(); ctxMenuElem.ContextMenu = new ContextMenu(); }; if (initCtxMenu is not null) { initCtxMenu.Initialize(ctx, menu); } ctxMenuElem.ContextMenu = menu; prevEventArgs.Target = evArgs; return(true); }
public Menu CreateMenu(Guid menuGuid, IInputElement commandTarget) { InitializeMenuItemObjects(); var menu = new Menu(); List <MenuMD> list; if (!guidToMenu.TryGetValue(menuGuid, out list)) { return(menu); } foreach (var md in list) { var guid = new Guid(md.Metadata.Guid); List <MenuItemGroupMD> itemGroups; if (!guidToGroups.TryGetValue(guid, out itemGroups)) { continue; } var topMenuItem = new MenuItem() { Header = ResourceHelper.GetString(md.Menu, md.Metadata.Header) }; topMenuItem.Items.Add(new MenuItem()); var mdTmp = md; MenuItemContext ctxTmp = null; topMenuItem.SubmenuOpened += (s, e) => { if (e.Source == topMenuItem) { ctxTmp?.Dispose(); ctxTmp = InitializeMainSubMenu(topMenuItem, mdTmp, commandTarget); } }; topMenuItem.SubmenuClosed += (s, e) => { if (e.Source == topMenuItem) { Debug.Assert(ctxTmp != null); ctxTmp?.Dispose(); ctxTmp = null; // There must always be exactly one MenuItem in the list when it's not shown. // We must re-use the first one or the first menu item won't be highlighted // when the menu is opened from the keyboard, eg. Alt+F. topMenuItem.Items.Clear(); topMenuItem.Items.Add(new MenuItem()); } }; menu.Items.Add(topMenuItem); } return(menu); }
List <object> CreateMenuItems(MenuItemContext ctx, List <MenuItemGroupMD> groups, IInputElement commandTarget, MenuItem firstMenuItem, bool isCtxMenu) { var allItems = new List <object>(); var items = new List <MenuItemMD>(); bool needSeparator = false; foreach (var group in groups) { items.Clear(); foreach (var item in group.Items) { if (item.MenuItem.IsVisible(ctx)) { items.Add(item); } } if (items.Count == 0) { continue; } if (needSeparator) { allItems.Add(new Separator()); } needSeparator = true; foreach (var item in items) { var itemProvider = item.MenuItem as IMenuItemProvider; if (itemProvider != null) { foreach (var createdItem in itemProvider.Create(ctx)) { var menuItem = Create(createdItem.MenuItem, createdItem.Metadata, ctx, commandTarget, firstMenuItem, isCtxMenu); firstMenuItem = null; allItems.Add(menuItem); } } else { var menuItem = Create(item.MenuItem, item.Metadata, ctx, commandTarget, firstMenuItem, isCtxMenu); firstMenuItem = null; allItems.Add(menuItem); } } } return(allItems); }
internal bool?ShowContextMenu(object evArgs, FrameworkElement ctxMenuElem, Guid topLevelMenuGuid, Guid ownerMenuGuid, GuidObject creatorObject, IGuidObjectsProvider provider, IContextMenuInitializer initCtxMenu, bool openedFromKeyboard) { InitializeMenuItemObjects(); // There could be nested contex menu handler calls, eg. first text editor followed by // the TabControl. We don't wan't the TabControl to disable the text editor's ctx menu. if (prevEventArgs.Target == evArgs) { return(null); } var ctx = new MenuItemContext(topLevelMenuGuid, openedFromKeyboard, creatorObject, provider?.GetGuidObjects(new GuidObjectsProviderArgs(creatorObject, openedFromKeyboard))); List <MenuItemGroupMD> groups; bool b = guidToGroups.TryGetValue(ownerMenuGuid, out groups); if (!b) { return(false); } var menu = new ContextMenu(); BindBackgroundBrush(menu, isCtxMenu: true); var allItems = CreateMenuItems(ctx, groups, null, null, true); if (allItems.Count == 0) { return(false); } foreach (var i in allItems) { menu.Items.Add(i); } menu.Closed += (s, e) => { ctx.Dispose(); ctxMenuElem.ContextMenu = new ContextMenu(); }; if (initCtxMenu != null) { initCtxMenu.Initialize(ctx, menu); } ctxMenuElem.ContextMenu = menu; prevEventArgs.Target = evArgs; return(true); }
void InitializeSubMenu(MenuItem menuItem, MenuItemContext ctx, Guid ownerMenuGuid, IInputElement commandTarget, bool isCtxMenu) { Reinitialize(menuItem); bool b = guidToGroups.TryGetValue(ownerMenuGuid, out var groups); Debug.Assert(b); if (b) { BindBackgroundBrush(menuItem, isCtxMenu); var firstMenuItem = menuItem.Items.Count == 1 ? menuItem.Items[0] as MenuItem : null; var allItems = CreateMenuItems(ctx, groups, commandTarget, firstMenuItem, isCtxMenu); foreach (var i in allItems) { if (firstMenuItem != i) { menuItem.Items.Add(i); } } } }
MenuItem Create(IMenuItem item, IMenuItemMetadata metadata, MenuItemContext ctx, IInputElement commandTarget, MenuItem menuItem, bool isCtxMenu) { if (menuItem == null) { menuItem = new MenuItem(); } menuItem.CommandTarget = commandTarget; string header = ResourceHelper.GetString(item, metadata.Header); string inputGestureText = ResourceHelper.GetString(item, metadata.InputGestureText); ImageReference?iconImgRef = ImageReferenceHelper.GetImageReference(item, metadata.Icon); header = item.GetHeader(ctx) ?? header; inputGestureText = item.GetInputGestureText(ctx) ?? inputGestureText; iconImgRef = item.GetIcon(ctx) ?? iconImgRef; menuItem.IsChecked = item.IsChecked(ctx); menuItem.Header = header; menuItem.InputGestureText = inputGestureText; var cmdHolder = item as ICommandHolder; bool lastIsEnabledCallValue = false; if (iconImgRef != null) { if (cmdHolder == null) { lastIsEnabledCallValue = item.IsEnabled(ctx); } else { var routedCommand = cmdHolder.Command as RoutedCommand; lastIsEnabledCallValue = commandTarget == null || routedCommand == null || routedCommand.CanExecute(ctx, commandTarget); } Add16x16Image(menuItem, iconImgRef.Value, lastIsEnabledCallValue); } if (metadata.Guid != null) { var itemGuid = Guid.Parse(metadata.Guid); if (guidToGroups.ContainsKey(itemGuid)) { menuItem.Items.Add(new MenuItem()); menuItem.SubmenuOpened += (s, e) => { if (e.Source == menuItem) { InitializeSubMenu(menuItem, ctx, itemGuid, commandTarget, isCtxMenu); } }; menuItem.SubmenuClosed += (s, e) => { if (e.Source == menuItem) { menuItem.Items.Clear(); menuItem.Items.Add(new MenuItem()); } }; } } ctx.OnDisposed += (_, __) => { // Buggy automation peers could hold a reference to us, so clear the captured variables (we can't clear the captured 'this') menuItem = null; ctx = null; commandTarget = null; item = null; iconImgRef = null; }; menuItem.Command = cmdHolder != null ? cmdHolder.Command : new RelayCommand(a => { Debug.Assert(!ctx.IsDisposed); if (ctx?.IsDisposed == false) { item.Execute(ctx); ctx?.Dispose(); } }, a => { if (ctx?.IsDisposed != false) { return(false); } bool b = item.IsEnabled(ctx); if (lastIsEnabledCallValue != b && iconImgRef != null) { Add16x16Image(menuItem, iconImgRef.Value, lastIsEnabledCallValue = b); } return(b); }); return(menuItem); }
MenuItem Create(IMenuItem item, IMenuItemMetadata metadata, MenuItemContext ctx, IInputElement commandTarget, MenuItem menuItem, bool isCtxMenu) { if (menuItem == null) { menuItem = new MenuItem(); } menuItem.CommandTarget = commandTarget; string header = ResourceHelper.GetString(item, metadata.Header); string inputGestureText = ResourceHelper.GetString(item, metadata.InputGestureText); ImageReference?iconImgRef = string.IsNullOrEmpty(metadata.Icon) ? (ImageReference?)null : new ImageReference(item.GetType().Assembly, metadata.Icon); var mi2 = item as IMenuItem2; if (mi2 != null) { header = mi2.GetHeader(ctx) ?? header; inputGestureText = mi2.GetInputGestureText(ctx) ?? inputGestureText; iconImgRef = mi2.GetIcon(ctx) ?? iconImgRef; menuItem.IsChecked = mi2.IsChecked(ctx); } menuItem.Header = header; menuItem.InputGestureText = inputGestureText; var cmdHolder = item as ICommandHolder; bool lastIsEnabledCallValue = false; if (iconImgRef != null) { if (cmdHolder == null) { lastIsEnabledCallValue = item.IsEnabled(ctx); } else { var routedCommand = cmdHolder.Command as RoutedCommand; lastIsEnabledCallValue = commandTarget == null || routedCommand == null || routedCommand.CanExecute(ctx, commandTarget); } imageManager.Add16x16Image(menuItem, iconImgRef.Value, isCtxMenu, lastIsEnabledCallValue); } if (metadata.Guid != null) { var itemGuid = Guid.Parse(metadata.Guid); List <MenuItemGroupMD> list; if (guidToGroups.TryGetValue(itemGuid, out list)) { menuItem.Items.Add(new MenuItem()); menuItem.SubmenuOpened += (s, e) => { if (e.Source == menuItem) { InitializeSubMenu(menuItem, ctx, itemGuid, commandTarget, isCtxMenu); } }; menuItem.SubmenuClosed += (s, e) => { if (e.Source == menuItem) { menuItem.Items.Clear(); menuItem.Items.Add(new MenuItem()); } }; } } menuItem.Command = cmdHolder != null ? cmdHolder.Command : new RelayCommand(a => { Debug.Assert(!ctx.IsDisposed); if (!ctx.IsDisposed) { item.Execute(ctx); ctx.Dispose(); } }, a => { if (ctx.IsDisposed) { return(false); } bool b = item.IsEnabled(ctx); if (lastIsEnabledCallValue != b && iconImgRef != null) { imageManager.Add16x16Image(menuItem, iconImgRef.Value, isCtxMenu, lastIsEnabledCallValue = b); } return(b); }); return(menuItem); }