diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
index 702822c2f6..db074cdfad 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
@@ -44,10 +44,16 @@
3.0
+
+ 3.0
+
+
+ 4.0
+
@@ -58,6 +64,7 @@
+
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
index 69597d0443..98153b951c 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
@@ -2,7 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.ComponentModel.Design;
using CSharpBinding.FormattingStrategy;
+using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
@@ -26,9 +28,16 @@ namespace CSharpBinding
get { return new CSharpBracketSearcher(); }
}
+ CodeManipulation codeManipulation;
+
public override void Attach(ITextEditor editor)
{
- //CSharpBackgroundCompiler.Init();
+ codeManipulation = new CodeManipulation(editor);
+ }
+
+ public override void Detach()
+ {
+ codeManipulation.Dispose();
}
}
}
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeManipulation.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CodeManipulation.cs
similarity index 70%
rename from src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeManipulation.cs
rename to src/AddIns/BackendBindings/CSharpBinding/Project/Src/CodeManipulation.cs
index 335c89cee9..c26d91968b 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeManipulation.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CodeManipulation.cs
@@ -2,9 +2,12 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
+using System.Windows.Input;
+using ICSharpCode.AvalonEdit.Document;
+using ICSharpCode.AvalonEdit.Editing;
+using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
@@ -12,35 +15,125 @@ using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
using Ast = ICSharpCode.NRefactory.Ast;
-namespace ICSharpCode.AvalonEdit.AddIn
+namespace CSharpBinding
{
///
/// Description of ExtendSelection.
///
- public class CodeManipulation
+ public class CodeManipulation : IDisposable
{
enum MoveStatementDirection { Up, Down };
+ ITextEditor editor;
+
+ public static readonly RoutedCommand ExtendSelectionCommand = new RoutedCommand(
+ "ExtendSelection", typeof(CodeManipulation),
+ new InputGestureCollection { new KeyGesture(Key.W, ModifierKeys.Control) }
+ );
+
+ public static readonly RoutedCommand ShrinkSelectionCommand = new RoutedCommand(
+ "ShrinkSelection", typeof(CodeManipulation),
+ new InputGestureCollection { new KeyGesture(Key.W, ModifierKeys.Control | ModifierKeys.Shift) }
+ );
+
+ public static readonly RoutedCommand MoveStatementUpCommand = new RoutedCommand(
+ "MoveStatementUp", typeof(CodeManipulation),
+ new InputGestureCollection { new KeyGesture(Key.Up, ModifierKeys.Alt) }
+ );
+
+ public static readonly RoutedCommand MoveStatementDownCommand = new RoutedCommand(
+ "MoveStatementDown", typeof(CodeManipulation),
+ new InputGestureCollection { new KeyGesture(Key.Down, ModifierKeys.Alt) }
+ );
+
+ IEnumerable bindings;
+
+ public CodeManipulation(ITextEditor editor)
+ {
+ this.editor = editor;
+ this.editor.SelectionChanged += CodeManipulationSelectionChanged;
+
+ TextArea area = (TextArea)editor.GetService(typeof(TextArea));
+
+ bindings = new List {
+ new CommandBinding(ExtendSelectionCommand, ExtendSelectionExecuted),
+ new CommandBinding(ShrinkSelectionCommand, ShrinkSelectionExecuted),
+ new CommandBinding(MoveStatementUpCommand, MoveStatementUpExecuted),
+ new CommandBinding(MoveStatementDownCommand, MoveStatementDownExecuted)
+ };
+
+ area.DefaultInputHandler.CommandBindings.AddRange(bindings);
+ }
+
+ bool internalSelectionChange;
+
+ void ExtendSelectionExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ internalSelectionChange = true;
+ try {
+ ExtendSelection();
+ } finally {
+ internalSelectionChange = false;
+ }
+ }
+
+ void ShrinkSelectionExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ internalSelectionChange = true;
+ try {
+ ShrinkSelection();
+ } finally {
+ internalSelectionChange = false;
+ }
+ }
+
+ void MoveStatementUpExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ MoveStatementUp();
+ }
+
+ void MoveStatementDownExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ MoveStatementDown();
+ }
+
+ readonly Stack previousSelections = new Stack();
+
class Selection
{
public Location Start { get; set; }
public Location End { get; set; }
}
- public static void MoveStatementUp(ITextEditor editor)
+ void CodeManipulationSelectionChanged(object sender, EventArgs e)
+ {
+ if (!internalSelectionChange)
+ previousSelections.Clear();
+ }
+
+ public void Dispose()
+ {
+ this.editor.SelectionChanged -= CodeManipulationSelectionChanged;
+ TextArea area = (TextArea)editor.GetService(typeof(TextArea));
+
+ foreach (var b in bindings)
+ area.DefaultInputHandler.CommandBindings.Remove(b);
+ }
+
+ public void MoveStatementUp()
{
MoveStatement(editor, MoveStatementDirection.Up);
editor.ClearSelection();
}
- public static void MoveStatementDown(ITextEditor editor)
+ public void MoveStatementDown()
{
MoveStatement(editor, MoveStatementDirection.Down);
editor.ClearSelection();
}
// move selection - find outermost node in selection, swap selection with closest child of its parent to the selection
- static void MoveStatement(ITextEditor editor, MoveStatementDirection direction)
+ void MoveStatement(ITextEditor editor, MoveStatementDirection direction)
{
IList commentsBlankLines;
var parsedCU = ParseDocument(editor, out commentsBlankLines);
@@ -81,7 +174,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- static Selection TryExtendSelectionToComments(IDocument document, Selection selection, IList commentsBlankLines)
+ Selection TryExtendSelectionToComments(IDocument document, Selection selection, IList commentsBlankLines)
{
var extendedToComments = ExtendSelectionToComments(document, selection, commentsBlankLines);
if (extendedToComments != null)
@@ -89,20 +182,37 @@ namespace ICSharpCode.AvalonEdit.AddIn
return selection;
}
- public static void ExtendSelection(ITextEditor editor)
+ public void ExtendSelection()
{
INode selectedNode = null;
IList commentsBlankLines;
var parsedCU = ParseDocument(editor, out commentsBlankLines);
if (parsedCU == null) return;
+ ISegment oldSelection = new TextSegment { StartOffset = editor.SelectionStart, Length = editor.SelectionLength };
Selection extendedSelection = ExtendSelection(editor, parsedCU, commentsBlankLines, out selectedNode, new Type[] { typeof(INode) }); // any node type
SelectText(extendedSelection, editor);
+
+ if (previousSelections.Count == 0 || !(previousSelections.Peek().Offset == oldSelection.Offset && previousSelections.Peek().EndOffset == oldSelection.EndOffset)) {
+ previousSelections.Push(oldSelection);
+ LoggingService.Debug("pushed: " + oldSelection);
+ } else {
+ LoggingService.Debug("not accepted: " + oldSelection);
+ }
+ }
+
+ public void ShrinkSelection()
+ {
+ if (previousSelections.Count < 1)
+ return;
+ var selection = previousSelections.Pop();
+ editor.Select(selection.Offset, selection.Length);
+ LoggingService.Debug("popped: " + selection);
}
// could work to extend selection to set of adjacent statements separated by blank lines
- static Selection ExtendSelection(ITextEditor editor, CompilationUnit parsedCU, IList commentsBlankLines, out INode selectedResultNode, Type[] interestingNodeTypes)
+ Selection ExtendSelection(ITextEditor editor, CompilationUnit parsedCU, IList commentsBlankLines, out INode selectedResultNode, Type[] interestingNodeTypes)
{
selectedResultNode = null;
@@ -168,7 +278,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
return new Selection { Start = selectionStart, End = selectionEnd };
}
- static Selection ExtendSelectionToComments(IDocument document, Selection selection, IList commentsBlankLines)
+ Selection ExtendSelectionToComments(IDocument document, Selection selection, IList commentsBlankLines)
{
if (selection == null)
throw new ArgumentNullException("selection");
@@ -178,7 +288,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
///
/// If there is a comment block immediately before selection, or behind selection on the same line, add it to selection.
///
- static Selection ExtendSelectionToComments(IDocument document, Location selectionStart, Location selectionEnd, IList commentsBlankLines)
+ Selection ExtendSelectionToComments(IDocument document, Location selectionStart, Location selectionEnd, IList commentsBlankLines)
{
var comments = commentsBlankLines.Where(s => s is Comment).Cast();
// add "var i = 5; // comments" comments
@@ -194,7 +304,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
///
/// If there is a comment block behind selection on the same line ("var i = 5; // comment"), add it to selection.
///
- static Selection ExtendSelectionToEndOfLineComments(IDocument document, Location selectionStart, Location selectionEnd, IEnumerable commentsBlankLines)
+ Selection ExtendSelectionToEndOfLineComments(IDocument document, Location selectionStart, Location selectionEnd, IEnumerable commentsBlankLines)
{
var lineComment = commentsBlankLines.Where(c => c.StartPosition.Line == selectionEnd.Line && c.StartPosition >= selectionEnd).FirstOrDefault();
if (lineComment == null) {
@@ -213,7 +323,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
///
/// If there is a comment block immediately before selection, add it to selection.
///
- static Selection ExtendSelectionToSeparateComments(IDocument document, Location selectionStart, Location selectionEnd, IEnumerable commentsBlankLines)
+ Selection ExtendSelectionToSeparateComments(IDocument document, Location selectionStart, Location selectionEnd, IEnumerable commentsBlankLines)
{
var comments = commentsBlankLines.Where(c => c.CommentStartsLine).ToList();
int commentIndex = comments.FindIndex(c => c.EndPosition <= selectionStart && IsWhitespaceBetween(document, c.EndPosition, selectionStart));
@@ -234,7 +344,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
///
/// Searches for parent of interesting type. Skips uninteresting parents.
///
- static INode GetInterestingParent(INode node, Type[] interestingNodeTypes)
+ INode GetInterestingParent(INode node, Type[] interestingNodeTypes)
{
var parent = node.Parent;
while(parent != null) {
@@ -245,18 +355,18 @@ namespace ICSharpCode.AvalonEdit.AddIn
return null;
}
- static bool IsNodeTypeInteresting(INode node, Type[] interestingNodeTypes)
+ bool IsNodeTypeInteresting(INode node, Type[] interestingNodeTypes)
{
Type nodeType = node.GetType();
return interestingNodeTypes.Any(interestingType => interestingType.IsAssignableFrom(nodeType) || (nodeType == interestingType));
}
- static bool SelectionContainsBlankLines(Location selectionStart, Location selectionEnd, List blankLines)
+ bool SelectionContainsBlankLines(Location selectionStart, Location selectionEnd, List blankLines)
{
return blankLines.Exists(b => b.StartPosition >= selectionStart && b.EndPosition <= selectionEnd);
}
- static bool IsWhitespaceBetween(IDocument document, Location startPos, Location endPos)
+ bool IsWhitespaceBetween(IDocument document, Location startPos, Location endPos)
{
int startOffset = document.PositionToOffset(startPos);
int endOffset = document.PositionToOffset(endPos);
@@ -270,7 +380,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
/// If the text at startPos is preceded by any of the prefixes, moves the start backwards to include one prefix
/// (the rightmost one).
///
- static Location ExtendLeft(Location startPos, IDocument document, params String[] prefixes)
+ Location ExtendLeft(Location startPos, IDocument document, params String[] prefixes)
{
int startOffset = document.PositionToOffset(startPos);
foreach (string prefix in prefixes) {
@@ -285,7 +395,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
// could depend just on IDocument
- static CompilationUnit ParseDocument(ITextEditor editor, out IList parsedSpecials)
+ CompilationUnit ParseDocument(ITextEditor editor, out IList parsedSpecials)
{
parsedSpecials = null;
var editorLang = EditorContext.GetEditorLanguage(editor);
@@ -308,7 +418,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
///
/// Swaps 2 ranges of text in a document.
///
- static void SwapText(IDocument document, Location start1, Location end1, Location start2, Location end2)
+ void SwapText(IDocument document, Location start1, Location end1, Location start2, Location end2)
{
if (start1 > start2) {
Location sw;
@@ -331,7 +441,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- static void SelectText(Selection selection, ITextEditor editor)
+ void SelectText(Selection selection, ITextEditor editor)
{
if (selection == null)
return;
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
index 68af13281c..1c6ef5f091 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
@@ -101,7 +101,6 @@
Code
-
HiddenDefinitionControl.xaml
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
index 52437a186e..403efc1ece 100755
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
@@ -490,25 +490,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
#endregion
- #region CTRL+W extend selection
- protected override void OnKeyUp(KeyEventArgs e)
- {
- base.OnKeyUp(e);
- if (e.Handled) return;
- if (e.Key == Key.W && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) {
- CodeManipulation.ExtendSelection(this.Adapter);
- }
- if (e.SystemKey == Key.Up && Keyboard.Modifiers.HasFlag(ModifierKeys.Alt)) {
- // Left Alt + Up (probably will have different shortcut)
- CodeManipulation.MoveStatementUp(this.Adapter);
- }
- if (e.SystemKey == Key.Down && Keyboard.Modifiers.HasFlag(ModifierKeys.Alt)) {
- // Left Alt + Down (probably will have different shortcut)
- CodeManipulation.MoveStatementDown(this.Adapter);
- }
- }
- #endregion
-
public void JumpTo(int line, int column)
{
// closes Debugger popup on debugger step