/// /// 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 JetBrains.Omea.GUIControls; using JetBrains.Omea.OpenAPI; using System.Collections; namespace JetBrains.Omea { /** * An action which is composed of multiple actions contributed by different * plugins, and invokes the registered actions in order until one of them * matches the current context. */ public class CompositeAction: IAction { private class ActionComponent { public string ResourceType; public IAction Action; public IActionStateFilter[] Filters; internal ActionComponent( string resourceType, IAction action, IActionStateFilter[] filters ) { ResourceType = resourceType; Action = action; Filters = filters; } } private string _id; private ArrayList _components = new ArrayList(); public CompositeAction( string id ) { _id = id; ActionManager actionManager = ICore.Instance.ActionManager as ActionManager; if ( actionManager != null ) { actionManager.RegisterCompositeAction( id, this ); } } /** * Adds a component to the composite action. */ internal void AddComponent( string resType, IAction action, IActionStateFilter[] filters ) { _components.Add( new ActionComponent( resType, action, filters ) ); } /** * Polls the components of the action until the enabled one is found and executes it. */ public void Execute( IActionContext context ) { if ( !ExecuteActionComponents( context ) ) { SplitExecute( context ); } } /** * Polls the components of the action and determines the aggregate state of the * action. */ public void Update( IActionContext context, ref ActionPresentation presentation ) { string[] resTypes = null; if ( _components.Count == 0 ) { presentation.Visible = false; return; } bool isVisible = false; bool isDisabled = false; bool tabMatched = false; UpdateActionComponents( context, ref presentation, ref resTypes, ref isVisible, ref isDisabled, ref tabMatched ); if ( isVisible ) return; // if the resource types were never checked, none of the components are // resource type dependent if ( resTypes != null && resTypes.Length > 1 ) { SplitUpdate( resTypes, context, ref presentation, ref tabMatched ); if ( presentation.Visible && presentation.Enabled ) return; } if ( context.Kind == ActionContextKind.Toolbar && !tabMatched ) { presentation.Visible = false; } else if ( isDisabled || context.Kind == ActionContextKind.MainMenu || context.Kind == ActionContextKind.Toolbar ) { presentation.Visible = true; presentation.Enabled = false; } else { presentation.Visible = false; } } private bool ExecuteActionComponents( IActionContext context ) { string[] resTypes = null; ActionPresentation presentation = new ActionPresentation(); foreach( ActionComponent component in _components ) { bool tabMatched = false; UpdateComponentPresentation( component, context, ref presentation, ref resTypes, ref tabMatched ); if ( presentation.Visible && presentation.Enabled ) { component.Action.Execute( context ); return true; } } return false; } private void UpdateActionComponents( IActionContext context, ref ActionPresentation presentation, ref string[] resTypes, ref bool isVisible, ref bool isDisabled, ref bool tabMatched ) { foreach( ActionComponent component in _components ) { UpdateComponentPresentation( component, context, ref presentation, ref resTypes, ref tabMatched ); if ( presentation.Visible && presentation.Enabled ) { isVisible = true; return; } if ( !presentation.Enabled ) isDisabled = true; } } /// /// Splits the resource list in multiple resource lists, each of which has only a /// single type, and tries to enable the action components with the split lists /// private void SplitUpdate( string[] resTypes, IActionContext context, ref ActionPresentation presentation, ref bool tabMatched ) { IResourceList[] resLists = SplitResourceList( resTypes, context.SelectedResources ); for( int i=0; i 1 ) { IResourceList[] resLists = SplitResourceList( resTypes, context.SelectedResources ); for( int i=0; i