From d08ff2c7c36786ce0130adf85ea7da4b4fe690a7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 18 Aug 2013 18:52:16 +0200 Subject: [PATCH] implement Popup to let user choose a part (if there are more than one) to jump to in GoToDefinition --- .../Src/AvalonEditEditorUIService.cs | 2 +- .../AvalonEdit.AddIn/Src/CodeEditorView.cs | 10 +++ .../Src/ContextActions/ContextActionsPopup.cs | 7 +++ .../Project/Refactoring/IContextAction.cs | 3 +- .../Src/Editor/Commands/GoToDefinition.cs | 62 ++++++++++++++++++- 5 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs index 5bdf41c02e..aff0f599f9 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.AvalonEdit.AddIn /// public void ShowContextActionsPopup(ContextActionsPopupViewModel viewModel) { - new ContextActionsPopup { Actions = viewModel }.OpenAtCaretAndFocus(); + new ContextActionsPopup { Actions = viewModel }.OpenAtCursorAndFocus(); } } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs index 0b55bd4fcf..b42a62e93b 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs @@ -68,6 +68,7 @@ namespace ICSharpCode.AvalonEdit.AddIn this.MouseLeave += TextEditorMouseLeave; this.Unloaded += OnUnloaded; this.TextArea.TextView.MouseDown += TextViewMouseDown; + this.TextArea.TextView.MouseUp += TextViewMouseUp; this.TextArea.Caret.PositionChanged += HighlightBrackets; this.TextArea.TextView.VisualLinesChanged += CodeEditorView_VisualLinesChanged; @@ -400,10 +401,13 @@ namespace ICSharpCode.AvalonEdit.AddIn #endregion #region Ctrl+Click Go To Definition + bool ctrlClickExecuted = false; + void TextViewMouseDown(object sender, MouseButtonEventArgs e) { // close existing debugger popup immediately on text editor mouse down TryCloseExistingPopup(false); + ctrlClickExecuted = false; if (options.CtrlClickGoToDefinition && e.ChangedButton == MouseButton.Left && Keyboard.Modifiers == ModifierKeys.Control) { // Ctrl+Click Go to definition @@ -415,8 +419,14 @@ namespace ICSharpCode.AvalonEdit.AddIn var goToDefinitionCommand = new GoToDefinition(); goToDefinitionCommand.Run(resolveResult); e.Handled = true; + ctrlClickExecuted = true; } } + + void TextViewMouseUp(object sender, MouseButtonEventArgs e) + { + e.Handled = options.CtrlClickGoToDefinition && ctrlClickExecuted; + } #endregion public void JumpTo(int line, int column) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/ContextActionsPopup.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/ContextActionsPopup.cs index 32d76c88fd..5d60f884fb 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/ContextActionsPopup.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/ContextActionsPopup.cs @@ -68,6 +68,13 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions this.Focus(); } + public void OpenAtCursorAndFocus() + { + this.Placement = PlacementMode.MousePoint; + this.IsOpen = true; + this.Focus(); + } + public static void SetPosition(Popup popup, ITextEditor editor, int line, int column, bool openAtWordStart = false) { var editorUIService = editor == null ? null : editor.GetService(typeof(IEditorUIService)) as IEditorUIService; diff --git a/src/Main/Base/Project/Refactoring/IContextAction.cs b/src/Main/Base/Project/Refactoring/IContextAction.cs index 562417b9c0..9faac967e4 100644 --- a/src/Main/Base/Project/Refactoring/IContextAction.cs +++ b/src/Main/Base/Project/Refactoring/IContextAction.cs @@ -18,10 +18,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring IContextActionProvider Provider { get; } /// - /// Name displayed in the context action's popup. + /// Returns the name displayed in the context action's popup. /// /// Refactoring context that can be used by the context action to create the display name. - /// string GetDisplayName(EditorRefactoringContext context); /// diff --git a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs index efbb94ed47..6b57307b7a 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs @@ -2,12 +2,16 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.ObjectModel; using System.IO; +using System.Linq; +using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.Core; +using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Editor.ContextActions; +using ICSharpCode.SharpDevelop.Refactoring; namespace ICSharpCode.SharpDevelop.Editor.Commands { @@ -18,6 +22,13 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands if (symbol == null) return; + var trr = symbol as TypeResolveResult; + var def = symbol.Type.GetDefinition(); + if (trr != null && def != null && def.Parts.Count > 1) { + ShowPopupWithPartialClasses(def); + return; + } + DomRegion pos = symbol.GetDefinitionRegion(); if (string.IsNullOrEmpty(pos.FileName)) { IEntity entity = GetEntity(symbol); @@ -35,5 +46,52 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands } } } + + void ShowPopupWithPartialClasses(ITypeDefinition definition) + { + var popupViewModel = new ContextActionsPopupViewModel(); + popupViewModel.Title = MenuService.ConvertLabel(StringParser.Parse( + "${res:SharpDevelop.Refactoring.PartsOfClass}", new StringTagPair("Name", definition.Name))); + popupViewModel.Actions = new ObservableCollection(definition.Parts.Where(p => !p.Region.IsEmpty).Select(MakeViewModel)); + var uiService = SD.GetActiveViewContentService(); + if (uiService != null) + uiService.ShowContextActionsPopup(popupViewModel); + } + + ContextActionViewModel MakeViewModel(IUnresolvedTypeDefinition entity) + { + var ambience = AmbienceService.GetCurrentAmbience(); + ambience.ConversionFlags = ConversionFlags.ShowDeclaringType | ConversionFlags.ShowTypeParameterList; + return new ContextActionViewModel { + Action = new GoToDomRegionAction(entity.Region), + Image = CompletionImage.GetImage(entity), + Comment = string.Format("(in {0})", Path.GetDirectoryName(entity.Region.FileName)), + ChildActions = null + }; + } + + class GoToDomRegionAction : IContextAction + { + DomRegion target; + + public GoToDomRegionAction(DomRegion target) + { + this.target = target; + } + + public string GetDisplayName(EditorRefactoringContext context) + { + return Path.GetFileName(target.FileName); + } + + public void Execute(EditorRefactoringContext context) + { + SD.FileService.JumpToFilePosition(new FileName(target.FileName), target.BeginLine, target.BeginColumn); + } + + IContextActionProvider IContextAction.Provider { + get { return null; } + } + } } }