예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
                    }
                }
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }