diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj index 8b59e7cce0..ec0cd2f2be 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj @@ -89,6 +89,7 @@ + diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index 05f43f274c..f0132e621b 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -180,17 +180,17 @@ namespace ICSharpCode.AvalonEdit.AddIn protected virtual CodeEditorView CreateTextEditor() { - CodeEditorView textEditor = new CodeEditorView(); - CodeEditorAdapter adapter = new CodeEditorAdapter(this, textEditor); - textEditor.Adapter = adapter; - TextView textView = textEditor.TextArea.TextView; + CodeEditorView codeEditorView = new CodeEditorView(); + CodeEditorAdapter adapter = new CodeEditorAdapter(this, codeEditorView); + codeEditorView.Adapter = adapter; + TextView textView = codeEditorView.TextArea.TextView; textView.Services.AddService(typeof(ITextEditor), adapter); textView.Services.AddService(typeof(CodeEditor), this); - textEditor.TextArea.TextEntering += TextAreaTextEntering; - textEditor.TextArea.TextEntered += TextAreaTextEntered; - textEditor.TextArea.Caret.PositionChanged += TextAreaCaretPositionChanged; - textEditor.TextArea.DefaultInputHandler.CommandBindings.Add( + codeEditorView.TextArea.TextEntering += TextAreaTextEntering; + codeEditorView.TextArea.TextEntered += TextAreaTextEntered; + codeEditorView.TextArea.Caret.PositionChanged += TextAreaCaretPositionChanged; + codeEditorView.TextArea.DefaultInputHandler.CommandBindings.Add( new CommandBinding(CustomCommands.CtrlSpaceCompletion, OnCodeCompletion)); textView.BackgroundRenderers.Add(textMarkerService); @@ -200,16 +200,16 @@ namespace ICSharpCode.AvalonEdit.AddIn textView.Services.AddService(typeof(IEditorUIService), new AvalonEditEditorUIService(textView)); textView.Services.AddService(typeof(IBookmarkMargin), iconBarManager); - textEditor.TextArea.LeftMargins.Insert(0, new IconBarMargin(iconBarManager)); + codeEditorView.TextArea.LeftMargins.Insert(0, new IconBarMargin(iconBarManager)); textView.Services.AddService(typeof(ISyntaxHighlighter), new AvalonEditSyntaxHighlighterAdapter(textView)); - textEditor.TextArea.MouseRightButtonDown += TextAreaMouseRightButtonDown; - textEditor.TextArea.ContextMenuOpening += TextAreaContextMenuOpening; - textEditor.TextArea.TextCopied += textEditor_TextArea_TextCopied; - textEditor.GotFocus += textEditor_GotFocus; + codeEditorView.TextArea.MouseRightButtonDown += TextAreaMouseRightButtonDown; + codeEditorView.TextArea.ContextMenuOpening += TextAreaContextMenuOpening; + codeEditorView.TextArea.TextCopied += textEditor_TextArea_TextCopied; + codeEditorView.GotFocus += textEditor_GotFocus; - return textEditor; + return codeEditorView; } public event EventHandler TextCopied; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs index f028b2a49a..98f7b9de67 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs @@ -42,6 +42,7 @@ namespace ICSharpCode.AvalonEdit.AddIn BracketHighlightRenderer bracketRenderer; CaretReferencesRenderer caretReferencesRenderer; + ContextActionsRenderer contextActionsRenderer; public CodeEditorView() { @@ -51,6 +52,7 @@ namespace ICSharpCode.AvalonEdit.AddIn this.bracketRenderer = new BracketHighlightRenderer(this.TextArea.TextView); this.caretReferencesRenderer = new CaretReferencesRenderer(this); + this.contextActionsRenderer = new ContextActionsRenderer(this); this.MouseHover += TextEditorMouseHover; this.MouseHoverStopped += TextEditorMouseHoverStopped; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs new file mode 100644 index 0000000000..ddbf4de945 --- /dev/null +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs @@ -0,0 +1,79 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Threading; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace ICSharpCode.AvalonEdit.AddIn +{ + /// + /// Renders Popup with context actions on the left side of the current line in the editor. + /// + public class ContextActionsRenderer + { + readonly CodeEditorView editorView; + ITextEditor Editor { get { return this.editorView.Adapter; } } + /// + /// This popup is reused (closed and opened again). + /// + ContextActionsPopup popup = new ContextActionsPopup() { StaysOpen = true }; + + /// + /// Delays the available actions resolution so that it does not get called too often when user holds an arrow. + /// + DispatcherTimer delayMoveTimer; + const int delayMoveMilliseconds = 100; + + public ContextActionsRenderer(CodeEditorView editor) + { + if (editor == null) + throw new ArgumentNullException("editor"); + this.editorView = editor; + + this.editorView.TextArea.Caret.PositionChanged += CaretPositionChanged; + + editor.TextArea.TextView.ScrollOffsetChanged += ScrollChanged; + this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMilliseconds) }; + this.delayMoveTimer.Stop(); + this.delayMoveTimer.Tick += TimerMoveTick; + } + + void ScrollChanged(object sender, EventArgs e) + { + this.popup.Close(); + } + + void TimerMoveTick(object sender, EventArgs e) + { + this.delayMoveTimer.Stop(); + + var availableActions = ContextActionsService.Instance.GetAvailableActions(this.Editor); + var availableActionsVM = new ObservableCollection( + availableActions.Select(a => new ContextActionViewModel(a))); + if (availableActionsVM.Count == 0) + return; + + this.popup.Actions = new ContextActionsViewModel { + Title = "Actions", + Actions = availableActionsVM + }; + this.popup.OpenAtLineStart(this.Editor); + } + + void CaretPositionChanged(object sender, EventArgs e) + { + this.popup.Close(); + this.popup.Actions = null; + this.delayMoveTimer.Stop(); + this.delayMoveTimer.Start(); + } + } +} diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs index aef79a9993..d9cc61dd16 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs @@ -38,6 +38,12 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets Text = "foreach (${var} ${element} in ${collection}) {\n\t${Selection}\n}", Keyword = "foreach" }, + /*new CodeSnippet { + Name = "ff", + Description = "foreach loop", + Text = "foreach (var ${toElementName(items)} in ${items}) {\n\t${Selection}\n}", + Keyword = "foreach" + },*/ new CodeSnippet { Name = "if", Description = "if statement", diff --git a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin index bfadd7271d..23737f3f32 100644 --- a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin +++ b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin @@ -48,7 +48,14 @@ - + + + + + + + + diff --git a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj index bea5762751..76716212fd 100644 --- a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj +++ b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj @@ -70,6 +70,10 @@ + + + + @@ -122,6 +126,7 @@ + diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs new file mode 100644 index 0000000000..cc163d6e06 --- /dev/null +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs @@ -0,0 +1,29 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace SharpRefactoring.ContextActions +{ + /// + /// Description of AddUsing. + /// + public class AddUsingProvider : IContextActionsProvider + { + public IEnumerable GetAvailableActions(ITextEditor editor) + { + yield break; + } + } + + public class AddUsingAction + { + } +} diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/GenerateMember.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/GenerateMember.cs new file mode 100644 index 0000000000..a8d1ace3cb --- /dev/null +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/GenerateMember.cs @@ -0,0 +1,29 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace SharpRefactoring.ContextActions +{ + /// + /// Description of GenerateMember. + /// + public class GenerateMemberProvider : IContextActionsProvider + { + public IEnumerable GetAvailableActions(ITextEditor editor) + { + yield break; + } + } + + public class GenerateMemberAction + { + } +} \ No newline at end of file diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementAbstractClass.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementAbstractClass.cs new file mode 100644 index 0000000000..2f5baeb07e --- /dev/null +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementAbstractClass.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using System.Windows; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace SharpRefactoring.ContextActions +{ + /// + /// Description of ImplementAbstractClass. + /// + public class ImplementAbstractClassProvider : IContextActionsProvider + { + public IEnumerable GetAvailableActions(ITextEditor editor) + { + var currentLine = editor.Document.GetLine(editor.Caret.Line); + yield break; + } + } + + public class ImplementAbstractClassAction : IContextAction + { + public string Title { + get { return "Dummy implement abstract class"; } + } + + public void Execute() + { + MessageBox.Show("Dummy implement abstract class"); + } + } +} diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementInterface.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementInterface.cs new file mode 100644 index 0000000000..bfa5ede3e9 --- /dev/null +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementInterface.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using System.Windows; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace SharpRefactoring.ContextActions +{ + /// + /// Description of ImplementInterface. + /// + public class ImplementInterfaceProvider : IContextActionsProvider + { + public IEnumerable GetAvailableActions(ITextEditor editor) + { + var currentLine = editor.Document.GetLine(editor.Caret.Line); + yield break; + } + } + + public class ImplementInterfaceAction : IContextAction + { + public string Title { + get { return "Dummy implement interface"; } + } + + public void Execute() + { + MessageBox.Show("Dummy implement interface"); + } + } +} diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/SwitchSnippetProvider.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/SwitchSnippetProvider.cs index 5e9cbcc3d5..6dcb5cca75 100644 --- a/src/AddIns/Misc/SharpRefactoring/Project/Src/SwitchSnippetProvider.cs +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/SwitchSnippetProvider.cs @@ -11,7 +11,8 @@ using ICSharpCode.SharpDevelop.Editor.AvalonEdit; namespace SharpRefactoring { /// - /// Description of SwitchSnippetProvider. + /// Registers refactoring:switchbody snippet tag. + /// (path /SharpDevelop/ViewContent/AvalonEdit/SnippetElementProviders) /// public class SwitchSnippetProvider : ISnippetElementProvider { diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index d830c39fb7..26b3188a5a 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -89,6 +89,8 @@ + + @@ -103,7 +105,7 @@ - + diff --git a/src/Main/Base/Project/Src/Editor/AvalonEdit/ContextActionsService.cs b/src/Main/Base/Project/Src/Editor/AvalonEdit/ContextActionsService.cs new file mode 100644 index 0000000000..2bd86743d6 --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/AvalonEdit/ContextActionsService.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit +{ + /// + /// Provides context actions available for current line of the editor. + /// + public sealed class ContextActionsService + { + private static ContextActionsService instance = new ContextActionsService(); + + public static ContextActionsService Instance { + get { + return instance; + } + } + + List providers; + + private ContextActionsService() + { + this.providers = AddInTree.BuildItems("/SharpDevelop/ViewContent/AvalonEdit/ContextActionProviders", null, false); + } + + /// + /// Gets actions available for current line of the editor. + /// + public IEnumerable GetAvailableActions(ITextEditor editor) + { + // could run providers in parallel + foreach (var provider in this.providers) { + foreach (var action in provider.GetAvailableActions(editor)) { + yield return action; + } + } + } + } +} diff --git a/src/Main/Base/Project/Src/Editor/AvalonEdit/IContextActionsProvider.cs b/src/Main/Base/Project/Src/Editor/AvalonEdit/IContextActionsProvider.cs new file mode 100644 index 0000000000..0c055fd317 --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/AvalonEdit/IContextActionsProvider.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision: $ +// +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Refactoring; + +namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit +{ + /// + /// Provides s to appear in a popup on the left side of the editor. + /// + public interface IContextActionsProvider + { + /// + /// Gets actions available for current line of the editor. + /// + IEnumerable GetAvailableActions(ITextEditor editor); + } +} diff --git a/src/Main/Base/Project/Src/Editor/Commands/FindBaseClasses.cs b/src/Main/Base/Project/Src/Editor/Commands/FindBaseClasses.cs index 24a25aaa3c..9a3bc45b31 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/FindBaseClasses.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/FindBaseClasses.cs @@ -14,14 +14,14 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands /// /// Description of FindBaseClasses. /// - public class FindBaseClasses : SymbolUnderCaretCommand + public class FindBaseClasses : SymbolUnderCaretMenuCommand { protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) { var classUnderCaret = GetClass(symbol); if (classUnderCaret != null) { - ContextActionsHelper.MakePopupWithBaseClasses(classUnderCaret).Open(editor); + ContextActionsHelper.MakePopupWithBaseClasses(classUnderCaret).OpenAtCaretAndFocus(editor); return; } MessageService.ShowError("${res:ICSharpCode.Refactoring.NoClassUnderCursorError}"); diff --git a/src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs b/src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs index 98bf5cdcca..94278a693a 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs @@ -14,19 +14,19 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands /// /// Description of FindDerivedClassesOrOverrides. /// - public class FindDerivedClassesOrOverrides : SymbolUnderCaretCommand + public class FindDerivedClassesOrOverrides : SymbolUnderCaretMenuCommand { protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) { var classUnderCaret = GetClass(symbol); if (classUnderCaret != null) { - ContextActionsHelper.MakePopupWithDerivedClasses(classUnderCaret).Open(editor); + ContextActionsHelper.MakePopupWithDerivedClasses(classUnderCaret).OpenAtCaretAndFocus(editor); return; } var memberUnderCaret = GetMember(symbol); if (memberUnderCaret != null && memberUnderCaret.IsOverridable) { - ContextActionsHelper.MakePopupWithOverrides(memberUnderCaret).Open(editor); + ContextActionsHelper.MakePopupWithOverrides(memberUnderCaret).OpenAtCaretAndFocus(editor); return; } MessageService.ShowError("${res:ICSharpCode.Refactoring.NoClassOrOverridableSymbolUnderCursorError}"); diff --git a/src/Main/Base/Project/Src/Editor/Commands/FindReferences.cs b/src/Main/Base/Project/Src/Editor/Commands/FindReferences.cs index 9ac795f323..2cd30ae39e 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/FindReferences.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/FindReferences.cs @@ -13,7 +13,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands /// /// Description of FindReferences. /// - public class FindReferences : SymbolUnderCaretCommand + public class FindReferences : SymbolUnderCaretMenuCommand { protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) { diff --git a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs index 91e21b139b..1ca01c3b56 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs @@ -12,7 +12,7 @@ using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.SharpDevelop.Editor.Commands { - public class GoToDefinition : SymbolUnderCaretCommand + public class GoToDefinition : SymbolUnderCaretMenuCommand { protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) { diff --git a/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretCommand.cs b/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs similarity index 95% rename from src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretCommand.cs rename to src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs index cc7630d55b..58b829fc44 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretCommand.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs @@ -14,7 +14,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands /// /// A menu command that uses the symbol under the editor's caret. /// - public abstract class SymbolUnderCaretCommand : AbstractMenuCommand + public abstract class SymbolUnderCaretMenuCommand : AbstractMenuCommand { public override void Run() { @@ -30,6 +30,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands RunImpl(editor, caretOffset, resolveResult); } + protected abstract void RunImpl(ITextEditor editor, int caretOffset, ResolveResult symbol); + public IClass GetClass(ResolveResult symbol) { if (symbol == null || !(symbol is TypeResolveResult)) { @@ -45,7 +47,5 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands } return ((MemberResolveResult)symbol).ResolvedMember; } - - protected abstract void RunImpl(ITextEditor editor, int caretOffset, ResolveResult symbol); } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionCommand.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionCommand.cs index 935e5ace2e..aeaaf6cc17 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionCommand.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionCommand.cs @@ -10,7 +10,7 @@ using System.Windows.Input; namespace ICSharpCode.SharpDevelop.Refactoring { /// - /// Description of ContextActionCommand. + /// Just wraps inside a WPF Command to be used in XAML. /// public class ContextActionCommand : ICommand { @@ -25,6 +25,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring public event EventHandler CanExecuteChanged { + // not supported - Context actions can always be executed add { } remove { } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs index 49def88ea6..d0e7ed16f1 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs @@ -18,7 +18,18 @@ namespace ICSharpCode.SharpDevelop.Refactoring /// public class ContextActionViewModel { - public string Name { get; set; } + public ContextActionViewModel() + { + } + + public ContextActionViewModel(IContextAction action) + { + if (action == null) + throw new ArgumentNullException("action"); + this.Action = action; + } + + public string Name { get { return this.action.Title; } } public string Comment { get; set; } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs index 31faf1b0bf..88b9ddf928 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs @@ -35,13 +35,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring Close(); } - private ContextActionsControl ActionsControl + private ContextActionsControl ActionsControl { get { return (ContextActionsControl)this.Child; } set { this.Child = value; } } - public ContextActionsViewModel Actions + public ContextActionsViewModel Actions { get { return (ContextActionsViewModel)ActionsControl.DataContext; } set { ActionsControl.DataContext = value; } @@ -62,30 +62,49 @@ namespace ICSharpCode.SharpDevelop.Refactoring this.IsOpen = false; } - public void Open(ITextEditor editor) + public void OpenAtCaretAndFocus(ITextEditor editor) + { + OpenAtPosition(editor, editor.Caret.Line, editor.Caret.Column, true); + this.Focus(); + } + + public void OpenAtLineStart(ITextEditor editor) + { + OpenAtPosition(editor, editor.Caret.Line, 1, false); + } + + void OpenAtPosition(ITextEditor editor, int line, int column, bool openAtWordStart) { var editorUIService = editor.GetService(typeof(IEditorUIService)) as IEditorUIService; if (editorUIService != null) { var document = editor.Document; - int line = editor.Caret.Line; - int column = editor.Caret.Column; int offset = document.PositionToOffset(line, column); - int wordStart = document.FindPrevWordStart(offset); - if (wordStart != -1) { - var wordStartLocation = document.OffsetToPosition(wordStart); - line = wordStartLocation.Line; - column = wordStartLocation.Column; + if (openAtWordStart) { + int wordStart = document.FindPrevWordStart(offset); + if (wordStart != -1) { + var wordStartLocation = document.OffsetToPosition(wordStart); + line = wordStartLocation.Line; + column = wordStartLocation.Column; + } } - var caretScreenPos = editorUIService.GetScreenPosition(line, column); this.Placement = PlacementMode.Absolute; - this.HorizontalOffset = caretScreenPos.X; - this.VerticalOffset = caretScreenPos.Y; + try + { + var caretScreenPos = editorUIService.GetScreenPosition(line, column); + this.HorizontalOffset = caretScreenPos.X; + this.VerticalOffset = caretScreenPos.Y; + } + catch + { + this.HorizontalOffset = 200; + this.VerticalOffset = 200; + } + } else { this.HorizontalOffset = 200; this.VerticalOffset = 200; } this.Open(); - this.Focus(); } } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs index d8fbf89bc9..721dab7e24 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs @@ -14,6 +14,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring /// public interface IContextAction { + string Title { get; } void Execute(); } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs index 80938d47c8..08fe044ca6 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs @@ -65,10 +65,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring protected ContextActionViewModel MakeGoToClassAction(IClass @class, ObservableCollection childActions) { return new ContextActionViewModel { - Name = this.LabelAmbience.Convert(@class), + Action = new GoToClassAction(@class, this.LabelAmbience), Image = ClassBrowserIconService.GetIcon(@class).ImageSource, Comment = string.Format("(in {0})", @class.Namespace), - Action = new GoToClassAction(@class), ChildActions = childActions }; } @@ -111,10 +110,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring return null; return new ContextActionViewModel { - Name = this.LabelAmbience.Convert(overridenMember), + Action = new GoToMemberAction(overridenMember, this.LabelAmbience), Image = ClassBrowserIconService.GetIcon(overridenMember).ImageSource, Comment = string.Format("(in {0})", containingClass.FullyQualifiedName), - Action = new GoToMemberAction(overridenMember), ChildActions = childActions }; } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs b/src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs index be2f633731..d005fec788 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs @@ -14,20 +14,24 @@ namespace ICSharpCode.SharpDevelop.Refactoring /// public class GoToClassAction : IContextAction { + public string Title { get; private set; } public IClass Class { get; private set; } - public GoToClassAction(IClass c) + public GoToClassAction(IClass c, IAmbience ambience) { + if (ambience == null) + throw new ArgumentNullException("ambience"); if (c == null) throw new ArgumentNullException("c"); this.Class = c; + this.Title = ambience.Convert(c); } public void Execute() { var cu = this.Class.CompilationUnit; var region = this.Class.Region; - if (cu == null || cu.FileName == null || this.Class.Region.IsEmpty) + if (cu == null || cu.FileName == null || region == null || region.IsEmpty) return; FileService.JumpToFilePosition(cu.FileName, region.BeginLine, region.BeginColumn); } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs b/src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs index 969ef1898c..f5888e0cfc 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs @@ -14,20 +14,24 @@ namespace ICSharpCode.SharpDevelop.Refactoring /// public class GoToMemberAction : IContextAction { + public string Title { get; private set; } public IMember Member { get; private set; } - public GoToMemberAction(IMember member) + public GoToMemberAction(IMember member, IAmbience ambience) { + if (ambience == null) + throw new ArgumentNullException("ambience"); if (member == null) throw new ArgumentNullException("member"); this.Member = member; + this.Title = ambience.Convert(member); } public void Execute() { var cu = this.Member.CompilationUnit; var region = this.Member.Region; - if (cu == null || cu.FileName == null || region.IsEmpty) + if (cu == null || cu.FileName == null || region == null || region.IsEmpty) return; FileService.JumpToFilePosition(cu.FileName, region.BeginLine, region.BeginColumn); } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs index 992e59990b..620e3c607d 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs @@ -195,7 +195,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring item.Icon = ClassBrowserIconService.Class.CreateImage(); item.InputGestureText = new KeyGesture(Key.F9).GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); item.Click += delegate { - ContextActionsHelper.MakePopupWithDerivedClasses(baseClass).Open(context.Editor); + ContextActionsHelper.MakePopupWithDerivedClasses(baseClass).OpenAtCaretAndFocus(context.Editor); }; return item; } @@ -208,7 +208,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring item.Icon = ClassBrowserIconService.Interface.CreateImage(); //item.InputGestureText = new KeyGesture(Key.F10).GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); item.Click += delegate { - ContextActionsHelper.MakePopupWithBaseClasses(@class).Open(context.Editor); + ContextActionsHelper.MakePopupWithBaseClasses(@class).OpenAtCaretAndFocus(context.Editor); }; return item; } @@ -221,7 +221,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring item.Icon = ClassBrowserIconService.Method.CreateImage(); item.InputGestureText = new KeyGesture(Key.F9).GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); item.Click += delegate { - ContextActionsHelper.MakePopupWithOverrides(member).Open(context.Editor); + ContextActionsHelper.MakePopupWithOverrides(member).OpenAtCaretAndFocus(context.Editor); }; return item; }