@ -21,9 +21,8 @@ namespace ICSharpCode.TextEditor
/// </summary>
/// </summary>
public class TextAreaMouseHandler
public class TextAreaMouseHandler
{
{
TextArea textArea ;
TextArea textArea ;
bool doubleclick = false ;
bool doubleclick = false ;
Point mousepos = new Point ( 0 , 0 ) ;
int selbegin ;
int selbegin ;
int selend ;
int selend ;
bool clickedOnSelectedText = false ;
bool clickedOnSelectedText = false ;
@ -33,14 +32,13 @@ 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 ;
public static Point selectionStartPos = nilPoint ;
bool gotmousedown = false ;
bool gotmousedown = false ;
bool dodragdrop = false ;
bool dodragdrop = false ;
public TextAreaMouseHandler ( TextArea textArea )
public TextAreaMouseHandler ( TextArea tt extArea )
{
{
this . textArea = textArea ;
textArea = t textArea;
}
}
public void Attach ( )
public void Attach ( )
@ -115,21 +113,27 @@ namespace ICSharpCode.TextEditor
void OnMouseUp ( object sender , MouseEventArgs e )
void OnMouseUp ( object sender , MouseEventArgs e )
{
{
textArea . SelectionManager . selectFrom . where = WhereFrom . None ;
gotmousedown = false ;
gotmousedown = false ;
mousedownpos = nilPoint ;
mousedownpos = nilPoint ;
}
}
void TextAreaClick ( object sender , EventArgs e )
void TextAreaClick ( object sender , EventArgs e )
{
{
if ( dodragdrop ) {
Point mousepos ;
mousepos = textArea . mousepos ;
if ( dodragdrop )
{
return ;
return ;
}
}
if ( clickedOnSelectedText & & textArea . TextView . DrawingPosition . Contains ( mousepos . X , mousepos . Y ) ) {
if ( clickedOnSelectedText & & textArea . TextView . DrawingPosition . Contains ( mousepos . X , mousepos . Y ) )
{
textArea . SelectionManager . ClearSelection ( ) ;
textArea . SelectionManager . ClearSelection ( ) ;
Point clickPosition = textArea . TextView . GetLogicalPosition ( mousepos . X - textArea . TextView . DrawingPosition . X ,
Point clickPosition = textArea . TextView . GetLogicalPosition ( mousepos . X - textArea . TextView . DrawingPosition . X ,
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
textArea . Caret . Position = clickPosition ;
textArea . Caret . Position = clickPosition ;
textArea . SetDesiredColumn ( ) ;
textArea . SetDesiredColumn ( ) ;
}
}
@ -138,10 +142,15 @@ namespace ICSharpCode.TextEditor
void TextAreaMouseMove ( object sender , MouseEventArgs e )
void TextAreaMouseMove ( object sender , MouseEventArgs e )
{
{
Point mousepos ;
mousepos = textArea . mousepos ;
// honour the starting selection strategy
// honour the starting selection strategy
switch ( SelectFrom . where ) {
switch ( textArea . SelectionManager . selectFrom . where )
{
case WhereFrom . Gutter :
case WhereFrom . Gutter :
moveGutter ( sender , e ) ;
//moveGutter(sender, e);
ExtendSelectionToMouse ( ) ;
break ;
break ;
case WhereFrom . TArea :
case WhereFrom . TArea :
@ -155,11 +164,12 @@ namespace ICSharpCode.TextEditor
}
}
doubleclick = false ;
doubleclick = false ;
mousepos = new Point ( e . X , e . Y ) ;
textArea . mousepos = new Point ( e . X , e . Y ) ;
if ( clickedOnSelectedText ) {
if ( clickedOnSelectedText ) {
if ( Math . Abs ( mousedownpos . X - mousepos . X ) > = SystemInformation . DragSize . Width / 2 | |
if ( Math . Abs ( mousedownpos . X - mousepos . X ) > = SystemInformation . DragSize . Width / 2 | |
Math . Abs ( mousedownpos . Y - mousepos . Y ) > = SystemInformation . DragSize . Height / 2 ) {
Math . Abs ( mousedownpos . Y - mousepos . Y ) > = SystemInformation . DragSize . Height / 2 )
{
clickedOnSelectedText = false ;
clickedOnSelectedText = false ;
ISelection selection = textArea . SelectionManager . GetSelectionAt ( textArea . Caret . Offset ) ;
ISelection selection = textArea . SelectionManager . GetSelectionAt ( textArea . Caret . Offset ) ;
if ( selection ! = null ) {
if ( selection ! = null ) {
@ -178,7 +188,8 @@ namespace ICSharpCode.TextEditor
}
}
if ( e . Button = = MouseButtons . Left ) {
if ( e . Button = = MouseButtons . Left ) {
if ( gotmousedown ) {
if ( gotmousedown & & textArea . SelectionManager . selectFrom . where = = WhereFrom . TArea )
{
ExtendSelectionToMouse ( ) ;
ExtendSelectionToMouse ( ) ;
}
}
}
}
@ -186,15 +197,32 @@ namespace ICSharpCode.TextEditor
void ExtendSelectionToMouse ( )
void ExtendSelectionToMouse ( )
{
{
Point realmousepos = textArea . TextView . GetLogicalPosition ( Math . Max ( 0 , mousepos . X - textArea . TextView . DrawingPosition . X ) ,
Point mousepos ;
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
mousepos = textArea . mousepos ;
Point realmousepos = textArea . TextView . GetLogicalPosition ( Math . Max ( 0 , mousepos . X - textArea . TextView . DrawingPosition . X ) ,
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
int y = realmousepos . Y ;
int y = realmousepos . Y ;
realmousepos = textArea . Caret . ValidatePosition ( realmousepos ) ;
realmousepos = textArea . Caret . ValidatePosition ( realmousepos ) ;
Point oldPos = textArea . Caret . Position ;
Point oldPos = textArea . Caret . Position ;
if ( oldPos = = realmousepos ) {
if ( oldPos = = realmousepos & & textArea . SelectionManager . selectFrom . where ! = WhereFrom . Gutter )
{
return ;
return ;
}
}
textArea . Caret . Position = realmousepos ;
if ( textArea . SelectionManager . selectFrom . where = = WhereFrom . Gutter )
if ( realmousepos . Y < textArea . SelectionManager . selectionStart . Y ) {
// the selection is from the gutter and it has moved above the startpoint
textArea . Caret . Position = new Point ( 0 , realmousepos . Y ) ;
} else {
if ( realmousepos . Y = = textArea . SelectionManager . selectionStart . Y ) {
textArea . Caret . Position = textArea . SelectionManager . NextValidPosition ( realmousepos . Y ) ;
} else {
textArea . Caret . Position = textArea . SelectionManager . NextValidPosition ( realmousepos . Y ) ;
}
}
else
textArea . Caret . Position = realmousepos ;
if ( minSelection ! = nilPoint & & textArea . SelectionManager . SelectionCollection . Count > 0 ) {
if ( minSelection ! = nilPoint & & textArea . SelectionManager . SelectionCollection . Count > 0 ) {
// Extend selection when selection was started with double-click
// Extend selection when selection was started with double-click
ISelection selection = textArea . SelectionManager . SelectionCollection [ 0 ] ;
ISelection selection = textArea . SelectionManager . SelectionCollection [ 0 ] ;
@ -221,10 +249,14 @@ namespace ICSharpCode.TextEditor
void DoubleClickSelectionExtend ( )
void DoubleClickSelectionExtend ( )
{
{
textArea . SelectionManager . ClearSelection ( ) ;
Point mousepos ;
if ( textArea . TextView . DrawingPosition . Contains ( mousepos . X , mousepos . Y ) ) {
mousepos = textArea . mousepos ;
FoldMarker marker = textArea . TextView . GetFoldMarkerFromPosition ( mousepos . X - textArea . TextView . DrawingPosition . X ,
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
textArea . SelectionManager . ClearSelection ( ) ;
if ( textArea . TextView . DrawingPosition . Contains ( mousepos . X , mousepos . Y ) )
{
FoldMarker marker = textArea . TextView . GetFoldMarkerFromPosition ( mousepos . X - textArea . TextView . DrawingPosition . X ,
mousepos . Y - textArea . TextView . DrawingPosition . Y ) ;
if ( marker ! = null & & marker . IsFolded ) {
if ( marker ! = null & & marker . IsFolded ) {
marker . IsFolded = false ;
marker . IsFolded = false ;
textArea . MotherTextAreaControl . AdjustScrollBars ( ) ;
textArea . MotherTextAreaControl . AdjustScrollBars ( ) ;
@ -261,7 +293,11 @@ 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 ) {
Point mousepos ;
mousepos = textArea . mousepos ;
if ( dodragdrop )
{
return ;
return ;
}
}
@ -272,7 +308,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 ;
textArea . SelectionManager . s electFrom . 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 ) {
@ -327,7 +363,7 @@ namespace ICSharpCode.TextEditor
textArea . SetDesiredColumn ( ) ;
textArea . SetDesiredColumn ( ) ;
}
}
}
}
}
}
} else if ( button = = MouseButtons . Right ) {
} else if ( button = = MouseButtons . Right ) {
// Rightclick sets the cursor to the click position unless
// Rightclick sets the cursor to the click position unless
// the previous selection was clicked
// the previous selection was clicked
@ -412,8 +448,6 @@ namespace ICSharpCode.TextEditor
Point minSelection = nilPoint ;
Point minSelection = nilPoint ;
Point maxSelection = nilPoint ;
Point maxSelection = nilPoint ;
void OnDoubleClick ( object sender , System . EventArgs e )
void OnDoubleClick ( object sender , System . EventArgs e )
{
{
if ( dodragdrop ) {
if ( dodragdrop ) {
@ -423,128 +457,5 @@ 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 ;
}
}
}