// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (C) 2009 Jakob Christensen
//
//
// Represents the base of a context action.
//
// --------------------------------------------------------------------------------------------------------------------
namespace AgentJohnson
{
using System;
using JetBrains.Annotations;
using JetBrains.Application;
using JetBrains.DocumentModel;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Intentions.CSharp.DataProviders;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.TextControl;
using JetBrains.Util;
/// Represents the base of a context action.
public abstract class ContextActionBase : IBulbItem, IContextAction
{
#region Constants and Fields
///
/// The current provider.
///
private readonly IContextActionDataProvider provider;
///
/// Indicates if transactions should be started.
///
private bool startTransaction = true;
#endregion
#region Constructors and Destructors
/// Initializes a new instance of the class.
/// The provider.
protected ContextActionBase([NotNull] ICSharpContextActionDataProvider provider)
{
this.provider = provider;
}
#endregion
#region Implemented Interfaces
#region IBulbAction
///
/// Gets the items.
///
/// The items.
public IBulbItem[] Items
{
get
{
return new[]
{
this
};
}
}
#endregion
#region IBulbItem
///
/// Gets the text.
///
/// The bulb text.
string IBulbItem.Text
{
get
{
return this.GetText();
}
}
#endregion
#endregion
#region Properties
///
/// Gets the provider.
///
/// The provider.
[NotNull]
public IContextActionDataProvider Provider
{
get
{
return this.provider;
}
}
///
/// Gets the solution.
///
/// The solution.
protected ISolution Solution
{
get
{
return this.provider.Solution;
}
}
///
/// Gets or sets a value indicating whether [start transaction].
///
/// true if [start transaction]; otherwise, false.
protected bool StartTransaction
{
get
{
return this.startTransaction;
}
set
{
this.startTransaction = value;
}
}
///
/// Gets the text control.
///
/// The text control.
protected ITextControl TextControl
{
get
{
return this.provider.TextControl;
}
}
#endregion
#region Public Methods
/// Determines whether this instance is available.
/// The element.
/// true if this instance is available; otherwise, false.
public abstract bool IsAvailable(IElement element);
#endregion
#region Implemented Interfaces
#region IBulbAction
///
/// Check if this action is available at the constructed context.
/// Actions could store precalculated info in to share it between different actions
///
/// The cache.
/// The is available.
public bool IsAvailable(IUserDataHolder cache)
{
return this.IsAvailableInternal();
}
#endregion
#region IBulbItem
/// Executes the specified solution.
/// The solution.
/// The text control.
void IBulbItem.Execute(ISolution solution, ITextControl textControl)
{
if (this.Solution != solution || this.TextControl != textControl)
{
throw new InvalidOperationException();
}
var element = this.provider.SelectedElement;
if (element == null)
{
return;
}
if (this.StartTransaction)
{
this.Modify(() => this.Execute(element));
}
else
{
this.Execute(element);
}
this.PostExecute();
}
#endregion
#endregion
#region Methods
/// Returns the Modification Cookie.
/// The cookie.
[NotNull]
protected ModificationCookie EnsureWritable()
{
if (this.Solution != null)
{
return DocumentManager.GetInstance(this.Solution).EnsureWritable(this.TextControl.Document);
}
return new ModificationCookie(EnsureWritableResult.FAILURE);
}
/// Executes this instance.
/// The element.
protected abstract void Execute(IElement element);
/// Called to apply context action. No locks is taken before call
/// The parameters.
protected void ExecuteInternal(params object[] param)
{
var element = param[0] as IElement;
if (this.startTransaction)
{
this.Modify(() => this.Execute(element));
}
else
{
this.Execute(element);
}
this.PostExecute();
}
/// Gets the text.
/// The context action text.
protected abstract string GetText();
/// Called to check if ContextAction is available.
/// ReadLock is taken
/// Will not be called if PsiManager, ProjectFile of Solution == null
/// The is available internal.
protected bool IsAvailableInternal()
{
var element = this.provider.SelectedElement;
if (element == null)
{
return false;
}
return this.IsAvailable(element);
}
/// Posts the execute.
protected virtual void PostExecute()
{
}
/// Modifies the specified handler.
/// The handler.
private void Modify(Action handler)
{
var psiManager = PsiManager.GetInstance(this.Solution);
if (psiManager == null)
{
return;
}
using (var cookie = this.EnsureWritable())
{
if (cookie.EnsureWritableResult != EnsureWritableResult.SUCCESS)
{
return;
}
using (CommandCookie.Create(string.Format("Context Action {0}", this.GetText())))
{
psiManager.DoTransaction(handler);
}
}
}
#endregion
}
}