///
/// 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 );
}
}
}