@ -27,62 +27,18 @@ using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Editor.Commands
namespace ICSharpCode.SharpDevelop.Editor.Commands
{
{
/// <summary>
/// <summary>
/// Build context menu for class members in the text editor.
/// Build context submenu for class members in the text editor.
/// Paths:
/// /SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu, id=MenuBuilder
/// /SharpDevelop/Pads/ClassBrowser/ClassContextMenu, id=MenuBuilder
/// </summary>
/// </summary>
public class ClassBookmarkMenuBuilder : ISubmenuBuilder , IMenuItemBuilder
public class ClassBookmarkSubm enuBuilder : ISubmenuBuilder , IMenuItemBuilder
{
{
public System . Collections . ICollection BuildItems ( Codon codon , object owner )
public System . Collections . ICollection BuildItems ( Codon codon , object owner )
{
{
return BuildSubmenu ( codon , owner ) . TranslateToWpf ( ) ;
return BuildSubmenu ( codon , owner ) . TranslateToWpf ( ) ;
}
}
/// <summary>
/// Gets a specific part of the compound class.
/// </summary>
static IClass GetPart ( IClass possibleCompound , string fileName )
{
CompoundClass compound = possibleCompound as CompoundClass ;
if ( compound = = null )
return possibleCompound ;
IList < IClass > parts = compound . Parts ;
if ( ! string . IsNullOrEmpty ( fileName ) ) {
// get the part with the requested file name
foreach ( IClass part in parts ) {
if ( FileUtility . IsEqualFileName ( fileName , part . CompilationUnit . FileName ) )
return part ;
}
}
// Fallback: get the part with the shortest file name.
// This should prefer non-designer files over designer files.
IClass preferredClass = parts [ 0 ] ;
for ( int i = 1 ; i < parts . Count ; i + + ) {
if ( IsShorterFileName ( parts [ i ] . CompilationUnit . FileName , preferredClass . CompilationUnit . FileName ) )
preferredClass = parts [ i ] ;
}
return preferredClass ;
}
static bool IsShorterFileName ( string a , string b )
{
// Fix forum-17295: compilation unit's file name might be null: prefer the non-null file
if ( a = = null )
return false ;
if ( b = = null )
return true ;
return a . Length < b . Length ;
}
static IClass GetCurrentPart ( IClass possibleCompound )
{
IViewContent viewContent = WorkbenchSingleton . Workbench . ActiveViewContent ;
if ( viewContent ! = null )
return GetPart ( possibleCompound , viewContent . PrimaryFileName ) ;
else
return GetPart ( possibleCompound , null ) ;
}
public ToolStripItem [ ] BuildSubmenu ( Codon codon , object owner )
public ToolStripItem [ ] BuildSubmenu ( Codon codon , object owner )
{
{
MenuCommand cmd ;
MenuCommand cmd ;
@ -106,58 +62,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
List < ToolStripItem > list = new List < ToolStripItem > ( ) ;
List < ToolStripItem > list = new List < ToolStripItem > ( ) ;
// refactoring actions
if ( ! FindReferencesAndRenameHelper . IsReadOnly ( c ) ) {
if ( c . DeclaringType = = null & &
! c . BodyRegion . IsEmpty & &
! c . Name . Equals ( Path . GetFileNameWithoutExtension ( c . CompilationUnit . FileName ) ,
StringComparison . OrdinalIgnoreCase ) )
{
// File name does not match class name
string correctFileName = Path . Combine ( Path . GetDirectoryName ( c . CompilationUnit . FileName ) ,
c . Name + Path . GetExtension ( c . CompilationUnit . FileName ) ) ;
if ( FileUtility . IsValidPath ( correctFileName )
& & Path . IsPathRooted ( correctFileName )
& & ! File . Exists ( correctFileName ) )
{
if ( c . CompilationUnit . Classes . Count = = 1 ) {
// Rename file to ##
cmd = new MenuCommand (
StringParser . Parse ( "${res:SharpDevelop.Refactoring.RenameFileTo}" ,
new string [ , ] { { "FileName" , Path . GetFileName ( correctFileName ) } } ) ,
delegate {
IProject p = ( IProject ) c . ProjectContent . Project ;
RenameFile ( p , c . CompilationUnit . FileName , correctFileName ) ;
if ( p ! = null ) {
p . Save ( ) ;
}
} ) ;
list . Add ( cmd ) ;
} else if ( language . RefactoringProvider . SupportsCreateNewFileLikeExisting & & language . RefactoringProvider . SupportsGetFullCodeRangeForType ) {
// Move class to file ##
cmd = new MenuCommand (
StringParser . Parse ( "${res:SharpDevelop.Refactoring.MoveClassToFile}" ,
new string [ , ] { { "FileName" , Path . GetFileName ( correctFileName ) } } ) ,
delegate {
FindReferencesAndRenameHelper . MoveClassToFile ( c , correctFileName ) ;
} ) ;
list . Add ( cmd ) ;
}
}
}
cmd = new MenuCommand ( "${res:SharpDevelop.Refactoring.RenameCommand}" , Rename ) ;
cmd . ShortcutKeys = MenuCommand . ParseShortcut ( "Control|R" ) ;
cmd . Tag = c ;
list . Add ( cmd ) ;
if ( language . RefactoringProvider . SupportsExtractInterface ) {
cmd = new MenuCommand ( "${res:SharpDevelop.Refactoring.ExtractInterfaceCommand}" , ExtractInterface ) ;
cmd . Tag = c ;
list . Add ( cmd ) ;
}
}
// navigation actions
// navigation actions
if ( c . BaseTypes . Count > 0 ) {
if ( c . BaseTypes . Count > 0 ) {
list . Add ( new MenuSeparator ( ) ) ;
list . Add ( new MenuSeparator ( ) ) ;
@ -182,38 +86,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
return list . ToArray ( ) ;
return list . ToArray ( ) ;
}
}
static void RenameFile ( IProject p , string oldFileName , string newFileName )
{
FileService . RenameFile ( oldFileName , newFileName , false ) ;
if ( p ! = null ) {
string oldPrefix = Path . GetFileNameWithoutExtension ( oldFileName ) + "." ;
string newPrefix = Path . GetFileNameWithoutExtension ( newFileName ) + "." ;
foreach ( ProjectItem item in p . Items ) {
FileProjectItem fileItem = item as FileProjectItem ;
if ( fileItem = = null )
continue ;
string dependentUpon = fileItem . DependentUpon ;
if ( string . IsNullOrEmpty ( dependentUpon ) )
continue ;
string directory = Path . GetDirectoryName ( fileItem . FileName ) ;
dependentUpon = Path . Combine ( directory , dependentUpon ) ;
if ( FileUtility . IsEqualFileName ( dependentUpon , oldFileName ) ) {
fileItem . DependentUpon = FileUtility . GetRelativePath ( directory , newFileName ) ;
string fileName = Path . GetFileName ( fileItem . FileName ) ;
if ( fileName . StartsWith ( oldPrefix ) ) {
RenameFile ( p , fileItem . FileName , Path . Combine ( directory , newPrefix + fileName . Substring ( oldPrefix . Length ) ) ) ;
}
}
}
}
}
void ExtractInterface ( object sender , EventArgs e )
{
MenuCommand item = ( MenuCommand ) sender ;
FindReferencesAndRenameHelper . ExtractInterface ( ( IClass ) item . Tag ) ;
}
void GoToBase ( object sender , EventArgs e )
void GoToBase ( object sender , EventArgs e )
{
{
MenuCommand item = ( MenuCommand ) sender ;
MenuCommand item = ( MenuCommand ) sender ;
@ -227,12 +99,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
}
}
}
}
void Rename ( object sender , EventArgs e )
{
MenuCommand item = ( MenuCommand ) sender ;
FindReferencesAndRenameHelper . RenameClass ( ( IClass ) item . Tag ) ;
}
void FindDerivedClasses ( object sender , EventArgs e )
void FindDerivedClasses ( object sender , EventArgs e )
{
{
MenuCommand item = ( MenuCommand ) sender ;
MenuCommand item = ( MenuCommand ) sender ;
@ -264,5 +130,69 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
IClass c = ( IClass ) item . Tag ;
IClass c = ( IClass ) item . Tag ;
FindReferencesAndRenameHelper . RunFindReferences ( c ) ;
FindReferencesAndRenameHelper . RunFindReferences ( c ) ;
}
}
public static IClass GetClass ( object menuOwner )
{
IClass c ;
ClassNode classNode = menuOwner as ClassNode ;
if ( classNode ! = null ) {
c = classNode . Class ;
} else {
ClassBookmark bookmark = ( ClassBookmark ) menuOwner ;
c = bookmark . Class ;
}
ParserService . ParseCurrentViewContent ( ) ;
c = c . ProjectContent . GetClass ( c . FullyQualifiedName , c . TypeParameters . Count , c . ProjectContent . Language , GetClassOptions . LookForInnerClass ) ;
c = GetCurrentPart ( c ) ;
return c ;
}
static IClass GetCurrentPart ( IClass possibleCompound )
{
IViewContent viewContent = WorkbenchSingleton . Workbench . ActiveViewContent ;
if ( viewContent ! = null )
return GetPart ( possibleCompound , viewContent . PrimaryFileName ) ;
else
return GetPart ( possibleCompound , null ) ;
}
/// <summary>
/// Gets a specific part of the compound class.
/// </summary>
static IClass GetPart ( IClass possibleCompound , string fileName )
{
CompoundClass compound = possibleCompound as CompoundClass ;
if ( compound = = null )
return possibleCompound ;
IList < IClass > parts = compound . Parts ;
if ( ! string . IsNullOrEmpty ( fileName ) ) {
// get the part with the requested file name
foreach ( IClass part in parts ) {
if ( FileUtility . IsEqualFileName ( fileName , part . CompilationUnit . FileName ) )
return part ;
}
}
// Fallback: get the part with the shortest file name.
// This should prefer non-designer files over designer files.
IClass preferredClass = parts [ 0 ] ;
for ( int i = 1 ; i < parts . Count ; i + + ) {
if ( IsShorterFileName ( parts [ i ] . CompilationUnit . FileName , preferredClass . CompilationUnit . FileName ) )
preferredClass = parts [ i ] ;
}
return preferredClass ;
}
static bool IsShorterFileName ( string a , string b )
{
// Fix forum-17295: compilation unit's file name might be null: prefer the non-null file
if ( a = = null )
return false ;
if ( b = = null )
return true ;
return a . Length < b . Length ;
}
}
}
}
}