Browse Source

First implementation of GUI for editor context actions.

A WPF Popup is shown over the editor when some actions are available. Can be opened by mouse click (TODO open by shortcut).
A Popup is probably not the best solution: it is not "tied" to current editor line anyhow so it stays open when region is collapsed, active ViewContent changes etc. (for active ViewContent change I added explicit handling). It should be probably part of editor's visual tree, in a special layer. Alternatively it could be displayed in the bookmark margin, but that would make it too small. This way it resembles ReSharper.
Have to consult this with Daniel.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6290 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Martin Koníček 15 years ago
parent
commit
53f53a3320
  1. 40
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs
  2. 2
      src/AddIns/Misc/SharpRefactoring/Project/Src/GenerateCode.cs
  3. 4
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHeaderedControl.xaml
  4. 33
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHeaderedControl.xaml.cs
  5. 4
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs
  6. 1
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsService.cs
  7. 6
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs

40
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs

@ -8,8 +8,10 @@ using System; @@ -8,8 +8,10 @@ using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Threading;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.AvalonEdit;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.AvalonEdit.AddIn
@ -44,11 +46,34 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -44,11 +46,34 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMilliseconds) };
this.delayMoveTimer.Stop();
this.delayMoveTimer.Tick += TimerMoveTick;
WorkbenchSingleton.Workbench.ViewClosed += WorkbenchSingleton_Workbench_ViewClosed;
WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchSingleton_Workbench_ActiveViewContentChanged;
}
void WorkbenchSingleton_Workbench_ViewClosed(object sender, ViewContentEventArgs e)
{
try {
// prevent memory leaks
if (e.Content.PrimaryFileName == this.Editor.FileName) {
WorkbenchSingleton.Workbench.ViewClosed -= WorkbenchSingleton_Workbench_ViewClosed;
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchSingleton_Workbench_ActiveViewContentChanged;
}
} catch {}
}
void WorkbenchSingleton_Workbench_ActiveViewContentChanged(object sender, EventArgs e)
{
ClosePopup();
try {
// open the popup again if in current file
if (((IViewContent)WorkbenchSingleton.Workbench.ActiveContent).PrimaryFileName == this.Editor.FileName)
CaretPositionChanged(this, EventArgs.Empty);
} catch {}
}
void ScrollChanged(object sender, EventArgs e)
{
this.popup.Close();
ClosePopup();
}
void TimerMoveTick(object sender, EventArgs e)
@ -62,7 +87,8 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -62,7 +87,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
return;
this.popup.Actions = new ContextActionsViewModel {
Title = "A",
Title = "#",
//Image = ClassBrowserIconService.Class.ImageSource,
Actions = availableActionsVM
};
this.popup.OpenAtLineStart(this.Editor);
@ -72,11 +98,17 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -72,11 +98,17 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
if (this.popup.IsOpen)
{
this.popup.Close();
this.popup.Actions = null;
ClosePopup();
}
this.delayMoveTimer.Stop();
this.delayMoveTimer.Start();
}
void ClosePopup()
{
this.popup.Close();
this.popup.IsDropdownOpen = false;
this.popup.Actions = null;
}
}
}

2
src/AddIns/Misc/SharpRefactoring/Project/Src/GenerateCode.cs

@ -330,4 +330,4 @@ namespace SharpRefactoring @@ -330,4 +330,4 @@ namespace SharpRefactoring
}
}
#endregion
}
}

4
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHeaderedControl.xaml

@ -18,8 +18,8 @@ @@ -18,8 +18,8 @@
</Grid.ColumnDefinitions>
<!-- Header -->
<Border Grid.Row="0" Grid.Column="0" Padding="4" BorderThickness="1 1 1 0"
BorderBrush="{StaticResource OuterBorderBrush}" HorizontalAlignment="Left">
<Border x:Name="Header" Grid.Row="0" Grid.Column="0" Padding="4" BorderThickness="1"
BorderBrush="{StaticResource OuterBorderBrush}" HorizontalAlignment="Left" MouseUp="Header_MouseUp">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#D6E9FF" Offset="0"/>

33
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHeaderedControl.xaml.cs

@ -24,6 +24,31 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -24,6 +24,31 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public ContextActionsHeaderedControl()
{
InitializeComponent();
this.IsAlwaysOpen = false;
this.IsOpen = false;
}
bool isAlwaysOpen;
public bool IsAlwaysOpen {
get { return isAlwaysOpen; }
set {
isAlwaysOpen = value;
if (value)
IsOpen = true;
}
}
bool isOpen;
public bool IsOpen {
get { return isOpen; }
set {
if (IsAlwaysOpen && !value)
throw new InvalidOperationException("Cannot set IsOpen to false when IsAlwaysOpen is true");
isOpen = value;
this.Header.Opacity = isOpen ? 1.0 : 0.5;
this.Header.BorderThickness = isOpen ? new Thickness(1, 1, 1, 0) : new Thickness(1);
this.ActionsTreeView.Visibility = isOpen ? Visibility.Visible : Visibility.Collapsed;
}
}
public event EventHandler ActionExecuted
@ -37,5 +62,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -37,5 +62,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring
if (this.ActionsTreeView != null)
this.ActionsTreeView.Focus();
}
void Header_MouseUp(object sender, MouseButtonEventArgs e)
{
if (!this.IsAlwaysOpen)
{
this.IsOpen = !this.IsOpen;
}
}
}
}

4
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsPopup.cs

@ -35,6 +35,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -35,6 +35,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring
Close();
}
public bool IsDropdownOpen { get { return ActionsControl.IsOpen; } set {ActionsControl.IsOpen = value; } }
public bool IsDropdownAlwaysOpen { get { return ActionsControl.IsAlwaysOpen; } set {ActionsControl.IsAlwaysOpen = value; } }
ContextActionsHeaderedControl ActionsControl
{
get { return (ContextActionsHeaderedControl)this.Child; }
@ -73,6 +76,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -73,6 +76,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public void OpenAtLineStart(ITextEditor editor)
{
OpenAtPosition(editor, editor.Caret.Line, 1, false);
this.VerticalOffset -= 16;
}
void OpenAtPosition(ITextEditor editor, int line, int column, bool openAtWordStart)

1
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsService.cs

@ -39,7 +39,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -39,7 +39,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary>
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
{
yield break;
var editorContext = new EditorContext(editor);
// could run providers in parallel
foreach (var provider in this.providers) {

6
src/Main/Base/Project/Src/Services/RefactoringService/ContextActionsHelper.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.ClassesDerivingFrom}", new StringTagPair("Name", baseClass.Name)))};
popupViewModel.Actions = new PopupTreeViewModelBuilder().BuildTreeViewModel(derivedClassesTree);
return new ContextActionsPopup { Actions = popupViewModel };
return new ContextActionsPopup { Actions = popupViewModel, IsDropdownAlwaysOpen = true };
}
public static ContextActionsPopup MakePopupWithBaseClasses(IClass @class)
@ -40,7 +40,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -40,7 +40,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.BaseClassesOf}", new StringTagPair("Name", @class.Name)))};
popupViewModel.Actions = new PopupListViewModelBuilder().BuildListViewModel(baseClassList);
return new ContextActionsPopup { Actions = popupViewModel };
return new ContextActionsPopup { Actions = popupViewModel, IsDropdownAlwaysOpen = true };
}
public static ContextActionsPopup MakePopupWithOverrides(IMember member)
@ -49,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -49,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.OverridesOf}", new string[,] {{ "Name", member.FullyQualifiedName }}))};
popupViewModel.Actions = new OverridesPopupTreeViewModelBuilder(member).BuildTreeViewModel(derivedClassesTree);
return new ContextActionsPopup { Actions = popupViewModel };
return new ContextActionsPopup { Actions = popupViewModel, IsDropdownAlwaysOpen = true };
}
class PopupViewModelBuilder

Loading…
Cancel
Save