/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Diagnostics; using JetBrains.Omea.OpenAPI; using JetBrains.Omea.Containers; using System.Collections; using System.Windows.Forms; using JetBrains.DataStructures; namespace JetBrains.Omea { /** * Class for managing a menu consisting of actions. */ public class MenuActionManager { internal class MenuAction { private string _resourceType; private string _name; private IAction _action; private IActionStateFilter[] _filters; public MenuAction( string resourceType, string name, IAction action, IActionStateFilter[] filters ) { _resourceType = resourceType; _name = name; _action = action; _filters = filters; } internal string ResourceType { get { return _resourceType; } } internal string Name { get { return _name; } set { _name = value; } } internal IAction Action { get { return _action; } } internal IActionStateFilter[] Filters { get { return _filters; } } } internal class MenuActionGroup { private string _name; private string _submenuName; private AnchoredList _actions = new AnchoredList(); public MenuActionGroup( string name, string submenuName ) { _actions.AllowDuplicates = true; _name = name; _submenuName = submenuName; } internal void Add( MenuAction action, ListAnchor anchor ) { _actions.Add( action.Action.ToString(), action, anchor ); } internal string Name { get { return _name; } } internal string SubmenuName { get { return _submenuName; } } public IEnumerable Actions { get { return _actions; } } public bool RemoveAction( IAction action ) { foreach( MenuAction menuAction in _actions ) { if ( menuAction.Action == action ) { _actions.Remove( menuAction ); return true; } } return false; } } private Menu.MenuItemCollection _menuItems; private AnchoredList _actionGroups = new AnchoredList(); // private Hashtable _itemToActionMap = new Hashtable(); // MenuItem -> MenuAction private IActionContext _lastContext; private bool _disableUnmatchingTypeActions; private bool _mnemonicsAssigned; private HashSet _usedMnemonics = new HashSet(); private bool _persistentMnemonics = true; private HashSet _suppressedSeparators = new HashSet(); public MenuActionManager( Menu.MenuItemCollection menuItems, bool disableUnmatchingTypeActions ) { _menuItems = menuItems; _disableUnmatchingTypeActions = disableUnmatchingTypeActions; } public bool PersistentMnemonics { get { return _persistentMnemonics; } set { _persistentMnemonics = value; } } public void RegisterGroup( string name, string submenuName, ListAnchor anchor ) { if ( _actionGroups.FindByKey( name ) == null ) { _actionGroups.Add( name, new MenuActionGroup( name, submenuName ), anchor ); } } public bool ContainsGroup( string groupName ) { return _actionGroups.FindByKey( groupName ) != null; } /** * Registers an action in an action group of the menu. */ public void RegisterAction( IAction action, string groupId, ListAnchor anchor, string text, string resourceType, IActionStateFilter[] filters ) { MenuActionGroup group = (MenuActionGroup) _actionGroups.FindByKey( groupId ); if ( group != null ) { _mnemonicsAssigned = false; group.Add( new MenuAction( resourceType, text, action, filters ), anchor ); } else { throw new ArgumentException( "Invalid action group name " + groupId, "groupId" ); } } private void AssignMnemonics() { ResetUsedMnemonics(); foreach( MenuActionGroup group in _actionGroups ) { foreach( MenuAction action in group.Actions ) { action.Name = AssignMnemonic( action.Name ); } } } private void ResetUsedMnemonics() { _usedMnemonics.Clear(); foreach( MenuActionGroup group in _actionGroups ) { foreach( MenuAction action in group.Actions ) { CheckExistingMnemonic( action.Name ); } } } /** * Automatically assigns a mnemonic for a menu action. */ private string AssignMnemonic( string text ) { if ( CheckExistingMnemonic( text ) ) { return text; } // try to assign mnemonics on word start characters for( int i=0; i /// Hides duplicate separators or separators at edges of the visible area. /// private bool UpdateSeparatorVisibility( Menu.MenuItemCollection items ) { if ( items.Count == 0 ) { return true; } bool hadVisible = false; MenuItem lastSeparator = null; foreach( MenuItem item in items ) { if ( item.Text == "-" ) { if ( !hadVisible ) item.Visible = false; else { item.Visible = true; lastSeparator = item; hadVisible = false; } } else { if ( !UpdateSeparatorVisibility( item.MenuItems ) ) { item.Visible = false; } if ( item.Visible ) hadVisible = true; } } if ( lastSeparator != null && !hadVisible ) { lastSeparator.Visible = false; } return hadVisible; } /** * Updates the visible and enabled state of actions in the menu without rebuilding * the menu entirely. */ public void UpdateMenuActions( IActionContext context ) { if ( context == null ) throw new ArgumentNullException( "context" ); bool visibleChanged = false; ActionPresentation presentation = new ActionPresentation(); foreach( DictionaryEntry de in _itemToActionMap ) { presentation.Reset(); MenuItem item = (MenuItem) de.Key; MenuAction menuAction = (MenuAction) de.Value; UpdateAction( menuAction, context, ref presentation ); bool wasVisible = item.Visible; SetActionFlags( item, ref presentation ); if ( wasVisible != item.Visible ) { visibleChanged = true; } } if ( visibleChanged ) { UpdateSeparatorVisibility( _menuItems ); } } public void SuppressGroupSeparator( string groupId1, string groupId2 ) { _suppressedSeparators.Add( groupId1 + ":" + groupId2 ); _suppressedSeparators.Add( groupId2 + ":" + groupId1 ); } private bool IsSeparatorSuppressed( MenuActionGroup group1, MenuActionGroup group2 ) { return _suppressedSeparators.Contains( group1.Name + ":" + group2.Name ); } } }