Browse Source

Move InsertionCursorLayer to its own file.

pull/341/head
Daniel Grunwald 12 years ago
parent
commit
d6f82bb28b
  1. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 280
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs
  3. 305
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertionCursorLayer.cs

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -103,6 +103,7 @@ @@ -103,6 +103,7 @@
<DependentUpon>InsertCtorDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Src\Refactoring\InsertCtorSnippetRefactoring.cs" />
<Compile Include="Src\Refactoring\InsertionCursorLayer.cs" />
<Compile Include="Src\Refactoring\InsertionPoint.cs" />
<Compile Include="Src\Refactoring\IssueOptions.xaml.cs">
<DependentUpon>IssueOptions.xaml</DependentUpon>

280
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs

@ -18,21 +18,11 @@ @@ -18,21 +18,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Snippets;
using ICSharpCode.AvalonEdit.Utils;
using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
@ -41,7 +31,6 @@ using ICSharpCode.NRefactory.Editor; @@ -41,7 +31,6 @@ using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding.Refactoring
{
@ -298,273 +287,4 @@ namespace CSharpBinding.Refactoring @@ -298,273 +287,4 @@ namespace CSharpBinding.Refactoring
}
}
}
class InsertionCursorLayer : Canvas, IDisposable
{
readonly string operation;
readonly InsertionPoint[] insertionPoints;
readonly TextArea editor;
public int CurrentInsertionPoint { get; set; }
int insertionPointNextToMouse = -1;
public event EventHandler<InsertionCursorEventArgs> Exited;
public static readonly RoutedCommand ExitCommand = new RoutedCommand(
"Exit", typeof(InsertionCursorLayer),
new InputGestureCollection { new KeyGesture(Key.Escape) }
);
public InsertionCursorLayer(TextArea editor, string operation, IList<InsertionPoint> insertionPoints)
{
if (editor == null)
throw new ArgumentNullException("editor");
this.editor = editor;
this.operation = operation;
this.insertionPoints = insertionPoints.ToArray();
this.editor.ActiveInputHandler = new InputHandler(this);
this.editor.TextView.InsertLayer(this, KnownLayer.Text, LayerInsertionPosition.Above);
this.editor.TextView.ScrollOffsetChanged += TextViewScrollOffsetChanged;
AddGroupBox();
ScrollToInsertionPoint();
}
static readonly Pen markerPen = new Pen(Brushes.Blue, 1);
static readonly Pen tempMarkerPen = new Pen(Brushes.Gray, 1);
protected override void OnRender(DrawingContext drawingContext)
{
DrawLineForInsertionPoint(CurrentInsertionPoint, markerPen, drawingContext);
if (insertionPointNextToMouse > -1 && insertionPointNextToMouse != CurrentInsertionPoint)
DrawLineForInsertionPoint(insertionPointNextToMouse, tempMarkerPen, drawingContext);
SetGroupBoxPosition(); // HACK
}
void DrawLineForInsertionPoint(int index, Pen pen, DrawingContext drawingContext)
{
var currentInsertionPoint = insertionPoints[index];
var pos = editor.TextView.GetVisualPosition(new TextViewPosition(currentInsertionPoint.Location), VisualYPosition.LineTop);
var endPos = new Point(pos.X + editor.TextView.ActualWidth * 0.6, pos.Y);
pos -= editor.TextView.ScrollOffset;
endPos -= editor.TextView.ScrollOffset;
var pixelSize = PixelSnapHelpers.GetPixelSize(this);
drawingContext.DrawLine(pen, PixelSnapHelpers.Round(pos, pixelSize), PixelSnapHelpers.Round(endPos, pixelSize));
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
protected override void OnMouseMove(MouseEventArgs e)
{
insertionPointNextToMouse = FindNextInsertionPoint(e.GetPosition(this));
// don't set e.Handled = true; so that the event continues bubbling
InvalidateVisual();
base.OnMouseMove(e);
}
protected override void OnQueryCursor(QueryCursorEventArgs e)
{
if (FindNextInsertionPoint(e.GetPosition(this)) >= 0)
e.Cursor = Cursors.UpArrow;
else
e.Cursor = Cursors.Arrow;
e.Handled = true;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed) {
if (e.ClickCount > 1) {
FireExited(true);
} else {
insertionPointNextToMouse = FindNextInsertionPoint(e.GetPosition(this));
if (insertionPointNextToMouse >= 0)
CurrentInsertionPoint = insertionPointNextToMouse;
InvalidateVisual();
}
e.Handled = true;
}
base.OnMouseDown(e);
}
int FindNextInsertionPoint(Point point)
{
var position = editor.TextView.GetPosition(point + editor.TextView.ScrollOffset);
if (position == null) return -1;
int insertionPoint = -1;
int mouseLocationLine = position.Value.Location.Line;
int currentLocationLine = -10;
for (int i = 0; i < insertionPoints.Length; i++) {
var line = insertionPoints[i].Location.Line;
var diff = Math.Abs(line - mouseLocationLine);
if (Math.Abs(currentLocationLine - mouseLocationLine) > diff && diff < 2) {
insertionPoint = i;
currentLocationLine = line;
}
}
return insertionPoint;
}
void TextViewScrollOffsetChanged(object sender, EventArgs e)
{
InvalidateVisual();
}
class InputHandler : TextAreaDefaultInputHandler
{
readonly InsertionCursorLayer layer;
internal InputHandler(InsertionCursorLayer layer)
: base(layer.editor)
{
this.layer = layer;
AddBinding(EditingCommands.MoveDownByLine, ModifierKeys.None, Key.Down, MoveMarker(false));
AddBinding(EditingCommands.MoveUpByLine, ModifierKeys.None, Key.Up, MoveMarker(true));
AddBinding(EditingCommands.MoveDownByPage, ModifierKeys.None, Key.PageDown, MoveMarkerPage(false));
AddBinding(EditingCommands.MoveUpByPage, ModifierKeys.None, Key.PageUp, MoveMarkerPage(true));
AddBinding(EditingCommands.MoveToLineStart, ModifierKeys.None, Key.Home, MoveMarkerFull(true));
AddBinding(EditingCommands.MoveToLineEnd, ModifierKeys.None, Key.End, MoveMarkerFull(false));
AddBinding(EditingCommands.EnterParagraphBreak, ModifierKeys.None, Key.Enter, layer.InsertCode);
AddBinding(ExitCommand, ModifierKeys.None, Key.Escape, layer.Cancel);
}
ExecutedRoutedEventHandler MoveMarker(bool up)
{
return (sender, e) => {
if (up)
layer.CurrentInsertionPoint = Math.Max(0, layer.CurrentInsertionPoint - 1);
else
layer.CurrentInsertionPoint = Math.Min(layer.insertionPoints.Length - 1, layer.CurrentInsertionPoint + 1);
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
ExecutedRoutedEventHandler MoveMarkerPage(bool up)
{
return (sender, e) => {
TextLocation current = layer.insertionPoints[layer.CurrentInsertionPoint].Location;
double currentVPos = layer.editor.TextView.GetVisualTopByDocumentLine(current.Line);
int newIndex = layer.CurrentInsertionPoint;
double newVPos;
do {
if (up) {
newIndex--;
if (newIndex < 0) {
newIndex = 0;
break;
}
} else {
newIndex++;
if (newIndex >= layer.insertionPoints.Length) {
newIndex = layer.insertionPoints.Length - 1;
break;
}
}
newVPos = layer.editor.TextView.GetVisualTopByDocumentLine(layer.insertionPoints[newIndex].Location.Line);
} while (Math.Abs(currentVPos - newVPos) < layer.editor.ActualHeight);
layer.CurrentInsertionPoint = newIndex;
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
ExecutedRoutedEventHandler MoveMarkerFull(bool up)
{
return (sender, e) => {
if (up)
layer.CurrentInsertionPoint = 0;
else
layer.CurrentInsertionPoint = layer.insertionPoints.Length - 1;
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
}
public void Dispose()
{
editor.TextView.Layers.Remove(this);
editor.ActiveInputHandler = editor.DefaultInputHandler;
editor.TextView.ScrollOffsetChanged -= TextViewScrollOffsetChanged;
}
void InsertCode(object sender, ExecutedRoutedEventArgs e)
{
FireExited(true);
}
void ScrollToInsertionPoint()
{
var location = insertionPoints[CurrentInsertionPoint].Location;
editor.GetService<TextEditor>().ScrollTo(location.Line, location.Column);
SetGroupBoxPosition();
}
void SetGroupBoxPosition()
{
var location = insertionPoints[CurrentInsertionPoint].Location;
var boxPosition = editor.TextView.GetVisualPosition(new TextViewPosition(location), VisualYPosition.LineMiddle) - editor.TextView.ScrollOffset + new Vector(editor.TextView.ActualWidth * 0.6 - 5, -groupBox.ActualHeight / 2.0);
Canvas.SetTop(groupBox, boxPosition.Y);
Canvas.SetLeft(groupBox, boxPosition.X);
}
void Cancel(object sender, ExecutedRoutedEventArgs e)
{
FireExited(false);
}
void FireExited(bool success)
{
if (Exited != null) {
Exited(this, new InsertionCursorEventArgs(insertionPoints[CurrentInsertionPoint], success));
}
}
GroupBox groupBox;
void AddGroupBox()
{
var content = new StackPanel {
Children = {
new TextBlock {
Text = "Use Up/Down to move to another location.\r\n" +
"Press Enter to select the location.\r\n" +
"Press Esc to cancel this operation."
}
}
};
groupBox = new GroupBox {
Background = Brushes.White,
BorderBrush = Brushes.Blue,
BorderThickness = new Thickness(1),
Header = operation,
Content = content
};
Children.Add(groupBox);
}
}
public class InsertionCursorEventArgs : EventArgs
{
public InsertionPoint InsertionPoint { get; private set; }
public bool Success { get; private set; }
public InsertionCursorEventArgs(InsertionPoint insertionPoint, bool success)
{
if (insertionPoint == null)
throw new ArgumentNullException("insertionPoint");
this.InsertionPoint = insertionPoint;
this.Success = success;
}
}
}

305
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertionCursorLayer.cs

@ -0,0 +1,305 @@ @@ -0,0 +1,305 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
namespace CSharpBinding.Refactoring
{
class InsertionCursorLayer : Canvas, IDisposable
{
readonly string operation;
readonly InsertionPoint[] insertionPoints;
readonly TextArea editor;
public int CurrentInsertionPoint {
get;
set;
}
int insertionPointNextToMouse = -1;
public event EventHandler<InsertionCursorEventArgs> Exited;
public static readonly RoutedCommand ExitCommand = new RoutedCommand("Exit", typeof(InsertionCursorLayer), new InputGestureCollection {
new KeyGesture(Key.Escape)
});
public InsertionCursorLayer(TextArea editor, string operation, IList<InsertionPoint> insertionPoints)
{
if (editor == null)
throw new ArgumentNullException("editor");
this.editor = editor;
this.operation = operation;
this.insertionPoints = insertionPoints.ToArray();
this.editor.ActiveInputHandler = new InputHandler(this);
this.editor.TextView.InsertLayer(this, KnownLayer.Text, LayerInsertionPosition.Above);
this.editor.TextView.ScrollOffsetChanged += TextViewScrollOffsetChanged;
AddGroupBox();
ScrollToInsertionPoint();
}
static readonly Pen markerPen = new Pen(Brushes.Blue, 1);
static readonly Pen tempMarkerPen = new Pen(Brushes.Gray, 1);
protected override void OnRender(DrawingContext drawingContext)
{
DrawLineForInsertionPoint(CurrentInsertionPoint, markerPen, drawingContext);
if (insertionPointNextToMouse > -1 && insertionPointNextToMouse != CurrentInsertionPoint)
DrawLineForInsertionPoint(insertionPointNextToMouse, tempMarkerPen, drawingContext);
SetGroupBoxPosition();
// HACK
}
void DrawLineForInsertionPoint(int index, Pen pen, DrawingContext drawingContext)
{
var currentInsertionPoint = insertionPoints[index];
var pos = editor.TextView.GetVisualPosition(new TextViewPosition(currentInsertionPoint.Location), VisualYPosition.LineTop);
var endPos = new Point(pos.X + editor.TextView.ActualWidth * 0.6, pos.Y);
pos -= editor.TextView.ScrollOffset;
endPos -= editor.TextView.ScrollOffset;
var pixelSize = PixelSnapHelpers.GetPixelSize(this);
drawingContext.DrawLine(pen, PixelSnapHelpers.Round(pos, pixelSize), PixelSnapHelpers.Round(endPos, pixelSize));
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
protected override void OnMouseMove(MouseEventArgs e)
{
insertionPointNextToMouse = FindNextInsertionPoint(e.GetPosition(this));
// don't set e.Handled = true; so that the event continues bubbling
InvalidateVisual();
base.OnMouseMove(e);
}
protected override void OnQueryCursor(QueryCursorEventArgs e)
{
if (FindNextInsertionPoint(e.GetPosition(this)) >= 0)
e.Cursor = Cursors.UpArrow;
else
e.Cursor = Cursors.Arrow;
e.Handled = true;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed) {
if (e.ClickCount > 1) {
FireExited(true);
}
else {
insertionPointNextToMouse = FindNextInsertionPoint(e.GetPosition(this));
if (insertionPointNextToMouse >= 0)
CurrentInsertionPoint = insertionPointNextToMouse;
InvalidateVisual();
}
e.Handled = true;
}
base.OnMouseDown(e);
}
int FindNextInsertionPoint(Point point)
{
var position = editor.TextView.GetPosition(point + editor.TextView.ScrollOffset);
if (position == null)
return -1;
int insertionPoint = -1;
int mouseLocationLine = position.Value.Location.Line;
int currentLocationLine = -10;
for (int i = 0; i < insertionPoints.Length; i++) {
var line = insertionPoints[i].Location.Line;
var diff = Math.Abs(line - mouseLocationLine);
if (Math.Abs(currentLocationLine - mouseLocationLine) > diff && diff < 2) {
insertionPoint = i;
currentLocationLine = line;
}
}
return insertionPoint;
}
void TextViewScrollOffsetChanged(object sender, EventArgs e)
{
InvalidateVisual();
}
class InputHandler : TextAreaDefaultInputHandler
{
readonly InsertionCursorLayer layer;
internal InputHandler(InsertionCursorLayer layer) : base(layer.editor)
{
this.layer = layer;
AddBinding(EditingCommands.MoveDownByLine, ModifierKeys.None, Key.Down, MoveMarker(false));
AddBinding(EditingCommands.MoveUpByLine, ModifierKeys.None, Key.Up, MoveMarker(true));
AddBinding(EditingCommands.MoveDownByPage, ModifierKeys.None, Key.PageDown, MoveMarkerPage(false));
AddBinding(EditingCommands.MoveUpByPage, ModifierKeys.None, Key.PageUp, MoveMarkerPage(true));
AddBinding(EditingCommands.MoveToLineStart, ModifierKeys.None, Key.Home, MoveMarkerFull(true));
AddBinding(EditingCommands.MoveToLineEnd, ModifierKeys.None, Key.End, MoveMarkerFull(false));
AddBinding(EditingCommands.EnterParagraphBreak, ModifierKeys.None, Key.Enter, layer.InsertCode);
AddBinding(ExitCommand, ModifierKeys.None, Key.Escape, layer.Cancel);
}
ExecutedRoutedEventHandler MoveMarker(bool up)
{
return (sender, e) => {
if (up)
layer.CurrentInsertionPoint = Math.Max(0, layer.CurrentInsertionPoint - 1);
else
layer.CurrentInsertionPoint = Math.Min(layer.insertionPoints.Length - 1, layer.CurrentInsertionPoint + 1);
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
ExecutedRoutedEventHandler MoveMarkerPage(bool up)
{
return (sender, e) => {
TextLocation current = layer.insertionPoints[layer.CurrentInsertionPoint].Location;
double currentVPos = layer.editor.TextView.GetVisualTopByDocumentLine(current.Line);
int newIndex = layer.CurrentInsertionPoint;
double newVPos;
do {
if (up) {
newIndex--;
if (newIndex < 0) {
newIndex = 0;
break;
}
}
else {
newIndex++;
if (newIndex >= layer.insertionPoints.Length) {
newIndex = layer.insertionPoints.Length - 1;
break;
}
}
newVPos = layer.editor.TextView.GetVisualTopByDocumentLine(layer.insertionPoints[newIndex].Location.Line);
}
while (Math.Abs(currentVPos - newVPos) < layer.editor.ActualHeight);
layer.CurrentInsertionPoint = newIndex;
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
ExecutedRoutedEventHandler MoveMarkerFull(bool up)
{
return (sender, e) => {
if (up)
layer.CurrentInsertionPoint = 0;
else
layer.CurrentInsertionPoint = layer.insertionPoints.Length - 1;
layer.InvalidateVisual();
layer.ScrollToInsertionPoint();
};
}
}
public void Dispose()
{
editor.TextView.Layers.Remove(this);
editor.ActiveInputHandler = editor.DefaultInputHandler;
editor.TextView.ScrollOffsetChanged -= TextViewScrollOffsetChanged;
}
void InsertCode(object sender, ExecutedRoutedEventArgs e)
{
FireExited(true);
}
void ScrollToInsertionPoint()
{
var location = insertionPoints[CurrentInsertionPoint].Location;
editor.GetService<TextEditor>().ScrollTo(location.Line, location.Column);
SetGroupBoxPosition();
}
void SetGroupBoxPosition()
{
var location = insertionPoints[CurrentInsertionPoint].Location;
var boxPosition = editor.TextView.GetVisualPosition(new TextViewPosition(location), VisualYPosition.LineMiddle) - editor.TextView.ScrollOffset + new Vector(editor.TextView.ActualWidth * 0.6 - 5, -groupBox.ActualHeight / 2.0);
Canvas.SetTop(groupBox, boxPosition.Y);
Canvas.SetLeft(groupBox, boxPosition.X);
}
void Cancel(object sender, ExecutedRoutedEventArgs e)
{
FireExited(false);
}
void FireExited(bool success)
{
if (Exited != null) {
Exited(this, new InsertionCursorEventArgs(insertionPoints[CurrentInsertionPoint], success));
}
}
GroupBox groupBox;
void AddGroupBox()
{
var content = new StackPanel {
Children = {
new TextBlock {
Text = "Use Up/Down to move to another location.\r\n" + "Press Enter to select the location.\r\n" + "Press Esc to cancel this operation."
}
}
};
groupBox = new GroupBox {
Background = Brushes.White,
BorderBrush = Brushes.Blue,
BorderThickness = new Thickness(1),
Header = operation,
Content = content
};
Children.Add(groupBox);
}
}
class InsertionCursorEventArgs : EventArgs
{
public InsertionPoint InsertionPoint { get; private set; }
public bool Success { get; private set; }
public InsertionCursorEventArgs(InsertionPoint insertionPoint, bool success)
{
if (insertionPoint == null)
throw new ArgumentNullException("insertionPoint");
this.InsertionPoint = insertionPoint;
this.Success = success;
}
}
}
Loading…
Cancel
Save