Browse Source

patch from Troy Simpson improving texteditor gutter selection behaviour

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1854 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Markus Palme 20 years ago
parent
commit
b0d238f8c8
  1. 122
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
  2. 8
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
  3. 140
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaMouseHandler.cs

122
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs

@ -93,83 +93,63 @@ namespace ICSharpCode.TextEditor
} }
} }
Point selectionStartPos;
bool selectionComeFromGutter = false;
bool selectionGutterDirectionDown = false; // direction of gutter selection affects whether a selection starts at the start of a line or at the end of a line
public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons) public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons)
{ {
selectionComeFromGutter = true; SelectFrom.where = WhereFrom.Gutter;
int realline = textArea.TextView.GetLogicalLine(mousepos); int realline = textArea.TextView.GetLogicalLine(mousepos);
if (realline >= 0 && realline < textArea.Document.TotalNumberOfLines) { if (realline >= 0 && realline < textArea.Document.TotalNumberOfLines) {
if((Control.ModifierKeys & Keys.Shift) != 0 && textArea.SelectionManager.HasSomethingSelected) { if((Control.ModifierKeys & Keys.Shift) != 0) {
// let MouseMove handle a shift-click in a gutter if(!textArea.SelectionManager.HasSomethingSelected && realline != textArea.Caret.Position.Y) {
HandleMouseMove(mousepos, mouseButtons); if (realline >= textArea.Caret.Position.Y)
{ // at or below starting selection, place the cursor on the next line
// nothing is selected so make a new selection from cursor
TextAreaMouseHandler.selectionStartPos = textArea.Caret.Position;
textArea.SelectionManager.ClearSelection();
// whole line selection - start of line to start of next line
if (realline < textArea.Document.TotalNumberOfLines - 1)
{
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, TextAreaMouseHandler.selectionStartPos, new Point(0, realline + 1)));
textArea.Caret.Position = new Point(0, realline + 1);
}
else
{
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, TextAreaMouseHandler.selectionStartPos, new Point(textArea.Document.GetLineSegment(realline).Length + 1, realline)));
textArea.Caret.Position = new Point(textArea.Document.GetLineSegment(realline).Length + 1, realline);
}
}
else
{ // prior lines to starting selection, place the cursor on the same line as the new selection
// nothing is selected so make a new selection from cursor
TextAreaMouseHandler.selectionStartPos = textArea.Caret.Position;
textArea.SelectionManager.ClearSelection();
// whole line selection - start of line to start of next line
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, TextAreaMouseHandler.selectionStartPos, new Point(TextAreaMouseHandler.selectionStartPos.X, TextAreaMouseHandler.selectionStartPos.Y)));
textArea.SelectionManager.ExtendSelection(new Point(TextAreaMouseHandler.selectionStartPos.X, TextAreaMouseHandler.selectionStartPos.Y), new Point(0, realline));
textArea.Caret.Position = new Point(0, realline);
}
}
else
{
// let MouseMove handle a shift-click in a gutter
MouseEventArgs e = new MouseEventArgs(mouseButtons, 1, mousepos.X, mousepos.Y, 0);
textArea.doMouseMove(e);
}
} else { } else {
selectionGutterDirectionDown = false; // reset the flag for handling in mousemove TextAreaMouseHandler.selectionStartPos = new Point(0, realline);
selectionStartPos = new Point(0, realline);
textArea.SelectionManager.ClearSelection(); textArea.SelectionManager.ClearSelection();
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(textArea.Document.GetLineSegment(realline).Length + 1, realline))); // whole line selection - start of line to start of next line
textArea.Caret.Position = selectionStartPos; if (realline < textArea.Document.TotalNumberOfLines - 1)
} {
} textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, TextAreaMouseHandler.selectionStartPos, new Point(TextAreaMouseHandler.selectionStartPos.X, TextAreaMouseHandler.selectionStartPos.Y + 1)));
} textArea.Caret.Position = new Point(TextAreaMouseHandler.selectionStartPos.X, TextAreaMouseHandler.selectionStartPos.Y + 1);
}
public override void HandleMouseLeave(EventArgs e) else
{ {
selectionComeFromGutter = false; textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, new Point(0, realline), new Point(textArea.Document.GetLineSegment(realline).Length + 1, TextAreaMouseHandler.selectionStartPos.Y)));
} textArea.Caret.Position = new Point(textArea.Document.GetLineSegment(realline).Length + 1, TextAreaMouseHandler.selectionStartPos.Y);
}
public override void HandleMouseMove(Point mousepos, MouseButtons mouseButtons) }
{
if (mouseButtons == MouseButtons.Left) {
if (selectionComeFromGutter) {
//TODO: Fix handling of mouse moving off to the left of the gutter before moving the selection down. Behaviour of selection changes after mouse moves left of gutter while selecting lines
int realline = textArea.TextView.GetLogicalLine(mousepos);
Point realmousepos = new Point(0, realline);
if (realmousepos.Y < textArea.Document.TotalNumberOfLines) {
if (selectionStartPos.Y == realmousepos.Y) {
// this setselection defaults for a upward moving selection
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, realmousepos, new Point(0, realmousepos.Y + 1)));
selectionGutterDirectionDown = false;
} else if (selectionStartPos.Y < realmousepos.Y && textArea.SelectionManager.HasSomethingSelected) {
// this fixes the selection for moving the selection down
if (! selectionGutterDirectionDown) { //realmousepos.Y - selectionStartPos.Y == 1) {
selectionGutterDirectionDown = true;
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(0, selectionStartPos.Y)));
// this enforces the screen area update
textArea.SelectionManager.ExtendSelection(textArea.SelectionManager.SelectionCollection[0].EndPosition, new Point(0, realmousepos.Y + 1));
} else {
// selection is extended to the end of the current line
textArea.SelectionManager.ExtendSelection(textArea.SelectionManager.SelectionCollection[0].EndPosition, new Point(0, realmousepos.Y + 1));
}
} else {
if(textArea.SelectionManager.HasSomethingSelected) {
// this fixes the selection for moving the selection up
if (selectionGutterDirectionDown) { // selectionStartPos.Y - realmousepos.Y == 1) { // only fix for first line movement
selectionGutterDirectionDown = false;
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(0, realmousepos.Y + 1)));
// move the extendselection to here to fix textarea update issues
textArea.SelectionManager.ExtendSelection(selectionStartPos, realmousepos);
} else {
textArea.SelectionManager.ExtendSelection(textArea.Caret.Position, realmousepos);
}
}
}
textArea.Caret.Position = realmousepos;
}
} else {
if (textArea.SelectionManager.HasSomethingSelected) {
selectionStartPos = textArea.Document.OffsetToPosition(textArea.SelectionManager.SelectionCollection[0].Offset);
int realline = textArea.TextView.GetLogicalLine(mousepos);
Point realmousepos = new Point(0, realline);
if (realmousepos.Y < textArea.Document.TotalNumberOfLines) {
textArea.SelectionManager.ExtendSelection(textArea.Caret.Position, realmousepos);
}
textArea.Caret.Position = realmousepos;
}
}
} }
} }
} }
} }

8
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs

@ -404,7 +404,13 @@ namespace ICSharpCode.TextEditor
} }
} }
protected override void OnMouseMove(MouseEventArgs e) // external interface to the attached event
public void doMouseMove(System.Windows.Forms.MouseEventArgs e)
{
OnMouseMove(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{ {
base.OnMouseMove(e); base.OnMouseMove(e);
if (!toolTipRectangle.Contains(e.Location)) { if (!toolTipRectangle.Contains(e.Location)) {

140
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaMouseHandler.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.TextEditor
static readonly Point nilPoint = new Point(-1, -1); static readonly Point nilPoint = new Point(-1, -1);
Point mousedownpos = nilPoint; Point mousedownpos = nilPoint;
Point lastmousedownpos = nilPoint; Point lastmousedownpos = nilPoint;
Point selectionStartPos = nilPoint; public static Point selectionStartPos = nilPoint;
bool gotmousedown = false; bool gotmousedown = false;
bool dodragdrop = false; bool dodragdrop = false;
@ -138,7 +138,17 @@ namespace ICSharpCode.TextEditor
void TextAreaMouseMove(object sender, MouseEventArgs e) void TextAreaMouseMove(object sender, MouseEventArgs e)
{ {
ShowHiddenCursor(); // honour the starting selection strategy
switch(SelectFrom.where) {
case WhereFrom.Gutter:
moveGutter(sender, e);
break;
case WhereFrom.TArea:
break;
}
ShowHiddenCursor();
if (dodragdrop) { if (dodragdrop) {
dodragdrop = false; dodragdrop = false;
return; return;
@ -251,7 +261,7 @@ namespace ICSharpCode.TextEditor
DateTime lastTime = DateTime.Now; DateTime lastTime = DateTime.Now;
void OnMouseDown(object sender, MouseEventArgs e) void OnMouseDown(object sender, MouseEventArgs e)
{ {
if (dodragdrop) { if (dodragdrop) {
return; return;
} }
@ -262,6 +272,7 @@ namespace ICSharpCode.TextEditor
if (textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y)) { if (textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y)) {
gotmousedown = true; gotmousedown = true;
SelectFrom.where = WhereFrom.TArea;
button = e.Button; button = e.Button;
if (button == MouseButtons.Left && (DateTime.Now - lastTime).Milliseconds < SystemInformation.DoubleClickTime) { if (button == MouseButtons.Left && (DateTime.Now - lastTime).Milliseconds < SystemInformation.DoubleClickTime) {
@ -412,5 +423,128 @@ namespace ICSharpCode.TextEditor
doubleclick = true; doubleclick = true;
} }
bool selectionGutterDirectionDown = true; // direction of gutter selection affects whether a selection starts at the start of a line or at the end of a line
int gutterlastmoveline = -1; // last gutter movement line
public int gutterxstart = 0; // if initial selection is made from the gutter then set to zero, otherwise take the original starting position (from a mouse or keyboard select)
void moveGutter(object sender, MouseEventArgs e)
{
MouseButtons mouseButtons = e.Button;
if (mouseButtons == MouseButtons.Left)
{
bool directionChanged = false; // gone from a downward moving selection to an upward, or vice-versa
int realline = textArea.TextView.GetLogicalLine(mousepos);
Point realmousepos = new Point(0, realline);
// avoid reprocessing the same selected line (prevent flicker)
if (gutterlastmoveline == realmousepos.Y)
return;
else
{
if (realmousepos.Y < selectionStartPos.Y)
{
// we need to record when the behaviour changes
// used down further
if (selectionGutterDirectionDown)
directionChanged = true;
// determine the selection strategy
selectionGutterDirectionDown = false;
}
else
{
// we need to record when the behaviour changes
// used down further
if (!selectionGutterDirectionDown)
directionChanged = true;
// determine the selection strategy
selectionGutterDirectionDown = true;
}
gutterlastmoveline = realmousepos.Y;
}
// between 1st and last lines - last line is handled differently
if (realmousepos.Y < textArea.Document.TotalNumberOfLines - 1)
{
if (selectionStartPos.Y == realmousepos.Y)
{
// this setselection defaults for a upward moving selection
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, realmousepos, new Point(selectionStartPos.X, realmousepos.Y + 1)));
}
else if (selectionStartPos.Y < realmousepos.Y && textArea.SelectionManager.HasSomethingSelected)
{
// this fixes the selection for moving the selection down
if (directionChanged)
{
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(selectionStartPos.X, selectionStartPos.Y)));
// this enforces the screen area update
textArea.SelectionManager.ExtendSelection(textArea.SelectionManager.SelectionCollection[0].EndPosition, new Point(0, realmousepos.Y + 1));
}
else
{
// selection is extended to the end of the current line
textArea.SelectionManager.ExtendSelection(textArea.SelectionManager.SelectionCollection[0].EndPosition, new Point(0, realmousepos.Y + 1));
}
}
else
{
// when something is already selected we must repect the existing selection
if (textArea.SelectionManager.HasSomethingSelected)
{
// this fixes the selection for moving the selection up
if (realmousepos.Y < selectionStartPos.Y && directionChanged) // the first time an upward selection moves above the first selection line
{
textArea.SelectionManager.ClearSelection();
selectionStartPos = new Point(selectionStartPos.X, TextAreaMouseHandler.selectionStartPos.Y);
if ((Control.ModifierKeys & Keys.Shift) != 0 && selectionStartPos.X != 0)
{
// shift-click
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(selectionStartPos.X, selectionStartPos.Y)));
}
else
{
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new Point(selectionStartPos.X, selectionStartPos.Y + 1)));
}
textArea.SelectionManager.ExtendSelection(new Point(selectionStartPos.X, selectionStartPos.Y), new Point(realmousepos.X, realmousepos.Y));
}
else
{
textArea.SelectionManager.ExtendSelection(textArea.Caret.Position, realmousepos);
}
}
}
if (realmousepos.Y >= selectionStartPos.Y) // at or below starting selection, place the cursor on the next line
textArea.Caret.Position = new Point(0, realmousepos.Y + 1);
else // prior lines to starting selection, place the cursor on the same line as the new selection
textArea.Caret.Position = new Point(0, realmousepos.Y);
}
else
{
if (realmousepos.Y == textArea.Document.TotalNumberOfLines - 1)
{
// selection is last line of text
textArea.SelectionManager.ClearSelection();
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, new Point(selectionStartPos.X, selectionStartPos.Y), new Point(textArea.Document.GetLineSegment(realline).Length + 1, realline)));
textArea.Caret.Position = new Point(textArea.Document.GetLineSegment(realline).Length + 1, realline);
}
}
}
else
gutterlastmoveline = -1;
}
} }
public class SelectFrom {
public static int where = WhereFrom.None;
}
public class WhereFrom {
public const int None = 0;
public const int Gutter = 1;
public const int TArea = 2;
}
} }

Loading…
Cancel
Save