From 91cb4eb4331f1985d7ffa99bac072fdbf31452a5 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 18 Nov 2009 15:27:00 +0000 Subject: [PATCH] AvalonEdit: When VisualColumn validation has to change the caret position, prefer to move the caret into the direction that does not cause a caret offset change. This fixes issues with text selection when tabs are visible and the user clicks between the tab marker and the whitespace of the tab. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5264 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ICSharpCode.AvalonEdit/Editing/Caret.cs | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs index 55b83fb2cc..d4b27e5c81 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs @@ -289,16 +289,48 @@ namespace ICSharpCode.AvalonEdit.Editing } } } - // search possible caret position (first try forwards) - int newVisualColumn = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal); - if (newVisualColumn < 0) { - // then try backwards - newVisualColumn = visualLine.GetNextCaretPosition(position.VisualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.Normal); - } - if (newVisualColumn < 0) - throw ThrowUtil.NoValidCaretPosition(); - if (newVisualColumn != position.VisualColumn) { - int newOffset = visualLine.GetRelativeOffset(newVisualColumn) + firstDocumentLineOffset; + // search possible caret positions + int newVisualColumnForwards = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal); + // If position.VisualColumn was valid, we're done with validation. + if (newVisualColumnForwards != position.VisualColumn) { + // also search backwards so that we can pick the better match + int newVisualColumnBackwards = visualLine.GetNextCaretPosition(position.VisualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.Normal); + + if (newVisualColumnForwards < 0 && newVisualColumnBackwards < 0) + throw ThrowUtil.NoValidCaretPosition(); + + // determine offsets for new visual column positions + int newOffsetForwards; + if (newVisualColumnForwards >= 0) + newOffsetForwards = visualLine.GetRelativeOffset(newVisualColumnForwards) + firstDocumentLineOffset; + else + newOffsetForwards = -1; + int newOffsetBackwards; + if (newVisualColumnBackwards >= 0) + newOffsetBackwards = visualLine.GetRelativeOffset(newVisualColumnBackwards) + firstDocumentLineOffset; + else + newOffsetBackwards = -1; + + int newVisualColumn, newOffset; + // if there's only one valid position, use it + if (newVisualColumnForwards < 0) { + newVisualColumn = newVisualColumnBackwards; + newOffset = newOffsetBackwards; + } else if (newVisualColumnBackwards < 0) { + newVisualColumn = newVisualColumnForwards; + newOffset = newOffsetForwards; + } else { + // two valid positions: find the better match + if (Math.Abs(newOffsetBackwards - caretOffset) < Math.Abs(newOffsetForwards - caretOffset)) { + // backwards is better + newVisualColumn = newVisualColumnBackwards; + newOffset = newOffsetBackwards; + } else { + // forwards is better + newVisualColumn = newVisualColumnForwards; + newOffset = newOffsetForwards; + } + } this.Position = new TextViewPosition(textView.Document.GetLocation(newOffset), newVisualColumn); } }