static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; var oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); if (direction < CaretMovementType.MultyLeft) { textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); } else { if (textArea.Selection is RectangleSelection) { textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); } else { textArea.Selection = new RectangleSelection(textArea, oldPosition, textArea.Caret.Position); } } textArea.Caret.BringCaretToView(); } }); }
internal static void MoveCaret(TextArea textArea, CaretMovementType direction) { double desiredXPos = textArea.Caret.DesiredXPos; if (textArea.FlowDirection == FlowDirection.RightToLeft) { if (direction == CaretMovementType.CharLeft) { direction = CaretMovementType.CharRight; } else if (direction == CaretMovementType.CharRight) { direction = CaretMovementType.CharLeft; } else if (direction == CaretMovementType.WordRight) { direction = CaretMovementType.WordLeft; } else if (direction == CaretMovementType.WordLeft) { direction = CaretMovementType.WordRight; } } textArea.Caret.Position = GetNewCaretPosition(textArea.TextView, textArea.Caret.Position, direction, textArea.Selection.EnableVirtualSpace, ref desiredXPos); textArea.Caret.DesiredXPos = desiredXPos; }
static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { switch (direction) { case CaretMovementType.LineUp: case CaretMovementType.LineDown: if (textArea.IsCodeCompleteMode) { return; } break; } args.Handled = true; TextViewPosition oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); if (!textArea.Document.IsInUpdate) // if we're inside a larger update (e.g. called by EditingCommandHandler.OnDelete()), avoid calculating the caret rectangle now { textArea.Caret.BringCaretToView(); } } }); }
internal static void MoveCaret(TextArea textArea, CaretMovementType direction) { double desiredXPos = textArea.Caret.DesiredXPos; textArea.Caret.Position = GetNewCaretPosition(textArea.TextView, textArea.Caret.Position, direction, textArea.Selection.EnableVirtualSpace, ref desiredXPos); textArea.Caret.DesiredXPos = desiredXPos; }
static ExecutedRoutedEventHandler OnMoveCaretBoxSelection(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; // First, convert the selection into a rectangle selection // (this is required so that virtual space gets enabled for the caret movement) if (textArea.Options.EnableRectangularSelection && !(textArea.Selection is RectangleSelection)) { if (textArea.Selection.IsEmpty) { textArea.Selection = new RectangleSelection(textArea, textArea.Caret.Position, textArea.Caret.Position); } else { // Convert normal selection to rectangle selection textArea.Selection = new RectangleSelection(textArea, textArea.Selection.StartPosition, textArea.Caret.Position); } } // Now move the caret and extend the selection TextViewPosition oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); textArea.Caret.BringCaretToView(); } }); }
static void MoveCaret(TextArea textArea, CaretMovementType direction) { DocumentLine caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); VisualLine visualLine = textArea.TextView.GetOrConstructVisualLine(caretLine); TextViewPosition caretPosition = textArea.Caret.Position; TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn); switch (direction) { case CaretMovementType.CharLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.CharRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.WordLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.WordRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: MoveCaretUpDown(textArea, direction, visualLine, textLine, caretPosition.VisualColumn); break; case CaretMovementType.DocumentStart: SetCaretPosition(textArea, 0, 0); break; case CaretMovementType.DocumentEnd: SetCaretPosition(textArea, -1, textArea.Document.TextLength); break; case CaretMovementType.LineStart: MoveCaretToStartOfLine(textArea, visualLine); break; case CaretMovementType.LineEnd: MoveCaretToEndOfLine(textArea, visualLine); break; default: throw new NotSupportedException(direction.ToString()); } }
static ExecutedRoutedEventHandler OnMoveCaret(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; textArea.Selection = Selection.Empty; MoveCaret(textArea, direction); textArea.Caret.BringCaretToView(); } }); }
private static EventHandler <ExecutedRoutedEventArgs> OnMoveCaret(CaretMovementType direction) { return((target, args) => { var textArea = GetTextArea(target); if (textArea?.Document != null) { args.Handled = true; textArea.ClearSelection(); MoveCaret(textArea, direction); textArea.Caret.BringCaretToView(); } }); }
static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; int oldOffset = textArea.Caret.Offset; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldOffset, textArea.Caret.Offset); textArea.Caret.BringCaretToView(); } }); }
private static ExecutedRoutedEventHandler CaretHandler(CaretMovementType caretMovementType, Boolean doSelect) { return((sender, e) => { if (e.Handled) { return; } EditView editor = sender as EditView; editor.MoveCaret(caretMovementType, doSelect); editor.Redraw(); e.Handled = true; }); }
private static EventHandler <ExecutedRoutedEventArgs> OnDelete(CaretMovementType caretMovement) { return((target, args) => { var textArea = GetTextArea(target); if (textArea?.Document != null) { if (textArea.Selection.IsEmpty) { var startPos = textArea.Caret.Position; var enableVirtualSpace = textArea.Options.EnableVirtualSpace; // When pressing delete; don't move the caret further into virtual space - instead delete the newline if (caretMovement == CaretMovementType.CharRight) { enableVirtualSpace = false; } var desiredXPos = textArea.Caret.DesiredXPos; var endPos = CaretNavigationCommandHandler.GetNewCaretPosition( textArea.TextView, startPos, caretMovement, enableVirtualSpace, ref desiredXPos); // GetNewCaretPosition may return (0,0) as new position, // thus we need to validate endPos before using it in the selection. if (endPos.Line < 1 || endPos.Column < 1) { endPos = new TextViewPosition(Math.Max(endPos.Line, 1), Math.Max(endPos.Column, 1)); } // Don't do anything if the number of lines of a rectangular selection would be changed by the deletion. if (textArea.Selection is RectangleSelection && startPos.Line != endPos.Line) { return; } // Don't select the text to be deleted; just reuse the ReplaceSelectionWithText logic // Reuse the existing selection, so that we continue using the same logic textArea.Selection.StartSelectionOrSetEndpoint(startPos, endPos) .ReplaceSelectionWithText(string.Empty); } else { textArea.RemoveSelectedText(); } textArea.Caret.BringCaretToView(); args.Handled = true; } }); }
private static EventHandler <ExecutedRoutedEventArgs> OnDelete(CaretMovementType caretMovement) { return((target, args) => { var textArea = GetTextArea(target); if (textArea?.Document != null) { if (textArea.Selection.IsEmpty) { var startPos = textArea.Caret.Position; var enableVirtualSpace = textArea.Options.EnableVirtualSpace; // When pressing delete; don't move the caret further into virtual space - instead delete the newline if (caretMovement == CaretMovementType.CharRight) { enableVirtualSpace = false; } var desiredXPos = textArea.Caret.DesiredXPos; var endPos = CaretNavigationCommandHandler.GetNewCaretPosition( textArea.TextView, startPos, caretMovement, enableVirtualSpace, ref desiredXPos); // GetNewCaretPosition may return (0,0) as new position, // thus we need to validate endPos before using it in the selection. if (endPos.Line < 1 || endPos.Column < 1) { endPos = new TextViewPosition(Math.Max(endPos.Line, 1), Math.Max(endPos.Column, 1)); } // Don't select the text to be deleted; just reuse the ReplaceSelectionWithText logic var sel = new SimpleSelection(textArea, startPos, endPos); sel.ReplaceSelectionWithText(string.Empty); } else { textArea.RemoveSelectedText(); } textArea.Caret.BringCaretToView(); args.Handled = true; } }); }
static ExecutedRoutedEventHandler OnMoveCaret(CaretMovementType direction) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { switch (direction) { case CaretMovementType.LineUp: case CaretMovementType.LineDown: if (textArea.IsCodeCompleteMode) { return; } break; } args.Handled = true; textArea.ClearSelection(); MoveCaret(textArea, direction); textArea.Caret.BringCaretToView(); } }); }
static ExecutedRoutedEventHandler OnMoveCaretBoxSelection(CaretMovementType direction) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; // First, convert the selection into a rectangle selection // (this is required so that virtual space gets enabled for the caret movement) if (textArea.Options.EnableRectangularSelection && !(textArea.Selection is RectangleSelection)) { if (textArea.Selection.IsEmpty) { textArea.Selection = new RectangleSelection(textArea, textArea.Caret.Position, textArea.Caret.Position); } else { // Convert normal selection to rectangle selection textArea.Selection = new RectangleSelection(textArea, textArea.Selection.StartPosition, textArea.Caret.Position); } } // Now move the caret and extend the selection TextViewPosition oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); textArea.Caret.BringCaretToView(); } }; }
internal static TextViewPosition GetNewCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, bool enableVirtualSpace, ref double desiredXPos) { switch (direction) { case CaretMovementType.None: return caretPosition; case CaretMovementType.DocumentStart: desiredXPos = double.NaN; return new TextViewPosition(0, 0); case CaretMovementType.DocumentEnd: desiredXPos = double.NaN; return new TextViewPosition(textView.Document.GetLocation(textView.Document.TextLength)); } DocumentLine caretLine = textView.Document.GetLineByNumber(caretPosition.Line); VisualLine visualLine = textView.GetOrConstructVisualLine(caretLine); TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn, caretPosition.IsAtEndOfLine); switch (direction) { case CaretMovementType.CharLeft: desiredXPos = double.NaN; return GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace); case CaretMovementType.Backspace: desiredXPos = double.NaN; return GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.EveryCodepoint, enableVirtualSpace); case CaretMovementType.CharRight: desiredXPos = double.NaN; return GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace); case CaretMovementType.WordLeft: desiredXPos = double.NaN; return GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace); case CaretMovementType.WordRight: desiredXPos = double.NaN; return GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace); case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: return GetUpDownCaretPosition(textView, caretPosition, direction, visualLine, textLine, enableVirtualSpace, ref desiredXPos); case CaretMovementType.LineStart: desiredXPos = double.NaN; return GetStartOfLineCaretPosition(caretPosition.VisualColumn, visualLine, textLine, enableVirtualSpace); case CaretMovementType.LineEnd: desiredXPos = double.NaN; return GetEndOfLineCaretPosition(visualLine, textLine); default: throw new NotSupportedException(direction.ToString()); } }
static TextViewPosition GetUpDownCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace, ref double xPos) { // moving up/down happens using the desired visual X position if (double.IsNaN(xPos)) xPos = visualLine.GetTextLineVisualXPosition(textLine, caretPosition.VisualColumn); // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textView.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textView.Document.LineCount) { DocumentLine nextLine = textView.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) yPos -= textView.RenderSize.Height; else yPos += textView.RenderSize.Height; DocumentLine newLine = textView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { double yPos = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle); int newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), enableVirtualSpace); // prevent wrapping to the next line; TODO: could 'IsAtEnd' help here? int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine); if (newVisualColumn >= targetLineStartCol + targetLine.Length) { if (newVisualColumn <= targetVisualLine.VisualLength) newVisualColumn = targetLineStartCol + targetLine.Length - 1; } return targetVisualLine.GetTextViewPosition(newVisualColumn); } else { return caretPosition; } }
static ExecutedRoutedEventHandler OnDelete(CaretMovementType caretMovement) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { if (textArea.Selection.IsEmpty) { TextViewPosition startPos = textArea.Caret.Position; bool enableVirtualSpace = textArea.Options.EnableVirtualSpace; // When pressing delete; don't move the caret further into virtual space - instead delete the newline if (caretMovement == CaretMovementType.CharRight) enableVirtualSpace = false; double desiredXPos = textArea.Caret.DesiredXPos; TextViewPosition endPos = CaretNavigationCommandHandler.GetNewCaretPosition( textArea.TextView, startPos, caretMovement, enableVirtualSpace, ref desiredXPos); // GetNewCaretPosition may return (0,0) as new position, // thus we need to validate endPos before using it in the selection. if (endPos.Line < 1 || endPos.Column < 1) endPos = new TextViewPosition(Math.Max(endPos.Line, 1), Math.Max(endPos.Column, 1)); // Don't select the text to be deleted; just reuse the ReplaceSelectionWithText logic var sel = new SimpleSelection(textArea, startPos, endPos); sel.ReplaceSelectionWithText(string.Empty); } else { textArea.RemoveSelectedText(); } textArea.Caret.BringCaretToView(); args.Handled = true; } }; }
static TextViewPosition GetUpDownCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace, ref double xPos) { // moving up/down happens using the desired visual X position if (double.IsNaN(xPos)) { xPos = visualLine.GetTextLineVisualXPosition(textLine, caretPosition.VisualColumn); } // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textView.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textView.Document.LineCount) { DocumentLine nextLine = textView.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) { yPos -= textView.RenderSize.Height; } else { yPos += textView.RenderSize.Height; } DocumentLine newLine = textView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { double yPos = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle); int newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), enableVirtualSpace); // prevent wrapping to the next line; TODO: could 'IsAtEnd' help here? int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine); if (newVisualColumn >= targetLineStartCol + targetLine.Length) { if (newVisualColumn <= targetVisualLine.VisualLength) { newVisualColumn = targetLineStartCol + targetLine.Length - 1; } } return(targetVisualLine.GetTextViewPosition(newVisualColumn)); } else { return(caretPosition); } }
private static void MoveCaret(TextArea textArea, CaretMovementType direction) { var caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); var visualLine = textArea.TextView.GetOrConstructVisualLine(caretLine); var caretPosition = textArea.Caret.Position; var textLine = visualLine.GetTextLine(caretPosition.VisualColumn); switch (direction) { case CaretMovementType.CharLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.CharRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.WordLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.WordRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: MoveCaretUpDown(textArea, direction, visualLine, textLine, caretPosition.VisualColumn); break; case CaretMovementType.DocumentStart: SetCaretPosition(textArea, 0, 0); break; case CaretMovementType.DocumentEnd: SetCaretPosition(textArea, -1, textArea.Document.TextLength); break; case CaretMovementType.LineStart: MoveCaretToStartOfLine(textArea, visualLine); break; case CaretMovementType.LineEnd: MoveCaretToEndOfLine(textArea, visualLine); break; case CaretMovementType.MultyLeft: textArea.Caret.Position = new TextViewPosition(caretPosition.Line, caretPosition.Column-1); textArea.Caret.DesiredXPos = double.NaN; break; case CaretMovementType.MultyUp: textArea.Caret.Position = new TextViewPosition(caretPosition.Line-1, caretPosition.Column); textArea.Caret.DesiredXPos = double.NaN; break; case CaretMovementType.MultyRight: textArea.Caret.Position = new TextViewPosition(caretPosition.Line, caretPosition.Column+1); textArea.Caret.DesiredXPos = double.NaN; break; case CaretMovementType.MultyDown: textArea.Caret.Position = new TextViewPosition(caretPosition.Line+1, caretPosition.Column); textArea.Caret.DesiredXPos = double.NaN; break; default: throw new NotSupportedException(direction.ToString()); } }
private static EventHandler <ExecutedRoutedEventArgs> OnMoveCaretExtendSelection(CaretMovementType direction) { return((target, args) => { var textArea = GetTextArea(target); if (textArea?.Document != null) { args.Handled = true; var oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); textArea.Caret.BringCaretToView(); } }); }
static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; int oldOffset = textArea.Caret.Offset; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldOffset, textArea.Caret.Offset); textArea.Caret.BringCaretToView(); } }; }
static ExecutedRoutedEventHandler OnMoveCaret(CaretMovementType direction) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; textArea.Selection = Selection.Empty; MoveCaret(textArea, direction); textArea.Caret.BringCaretToView(); } }; }
static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn) { // moving up/down happens using the desired visual X position double xPos = textArea.Caret.DesiredXPos; if (double.IsNaN(xPos)) xPos = textLine.GetDistanceFromCharacterHit(new CharacterHit(caretVisualColumn, 0)); // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textArea.Document.LineCount) { DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) yPos -= textArea.TextView.RenderSize.Height; else yPos += textArea.TextView.RenderSize.Height; DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { CharacterHit ch = targetLine.GetCharacterHitFromDistance(xPos); SetCaretPosition(textArea, targetVisualLine, targetLine, ch, false); textArea.Caret.DesiredXPos = xPos; } }
static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; TextViewPosition oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); if (!textArea.Document.IsInUpdate) // if we're inside a larger update (e.g. called by EditingCommandHandler.OnDelete()), avoid calculating the caret rectangle now textArea.Caret.BringCaretToView(); } }; }
private static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction) { return (target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { args.Handled = true; var oldPosition = textArea.Caret.Position; MoveCaret(textArea, direction); if (direction < CaretMovementType.MultyLeft) textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); else { if (textArea.Selection is RectangleSelection) textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); else textArea.Selection = new RectangleSelection(textArea, oldPosition, textArea.Caret.Position); } textArea.Caret.BringCaretToView(); } }; }
static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn) { // moving up/down happens using the desired visual X position double xPos = textArea.Caret.DesiredXPos; if (double.IsNaN(xPos)) { xPos = textLine.GetDistanceFromCharacterHit(new CharacterHit(caretVisualColumn, 0)); } // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textArea.Document.LineCount) { DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) { yPos -= textArea.TextView.RenderSize.Height; } else { yPos += textArea.TextView.RenderSize.Height; } DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { CharacterHit ch = targetLine.GetCharacterHitFromDistance(xPos); SetCaretPosition(textArea, targetVisualLine, targetLine, ch, false); textArea.Caret.DesiredXPos = xPos; } }
private static ExecutedRoutedEventHandler OnDelete(CaretMovementType caretMovement) { return((target, args) => { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { if (textArea.Selection.IsEmpty) { TextViewPosition startPos = textArea.Caret.Position; bool enableVirtualSpace = textArea.Options.EnableVirtualSpace; // When pressing delete; don't move the caret further into virtual space - instead delete the newline if (caretMovement == CaretMovementType.CharRight) { enableVirtualSpace = false; } double desiredXPos = textArea.Caret.DesiredXPos; TextViewPosition endPos = CaretNavigationCommandHandler.GetNewCaretPosition( textArea.TextView, startPos, caretMovement, enableVirtualSpace, ref desiredXPos); // GetNewCaretPosition may return (0,0) as new position, // thus we need to validate endPos before using it in the selection. if (endPos.Line < 1 || endPos.Column < 1) { endPos = new TextViewPosition(Math.Max(endPos.Line, 1), Math.Max(endPos.Column, 1)); } // Don't select the text to be deleted; just reuse the ReplaceSelectionWithText logic if (endPos.Column == 1) { var a = textArea.Document.GetLineByNumber(textArea.Caret.Line); var b = a.PreviousLine; if (b != null) { var c = b.PreviousLine; if (b.obs != null) { var obs = c.obs; var sa = textArea.Document.Text.Substring(a.Offset, a.Length + a.DelimiterLength); var bs = textArea.Document.Text.Substring(b.Offset, b.Length + b.DelimiterLength); var cs = textArea.Document.Text.Substring(c.Offset, c.Length + c.DelimiterLength); textArea.Document.Remove(c.Offset + c.Length, bs.Length + sa.Length /* + c.DelimiterLength*//* + a.DelimiterLength + b.DelimiterLength*/); textArea.Document.Insert(c.Offset + c.Length, sa); } else { var sel = new SimpleSelection(textArea, startPos, endPos); sel.ReplaceSelectionWithText(string.Empty); } } else { var sel = new SimpleSelection(textArea, startPos, endPos); sel.ReplaceSelectionWithText(string.Empty); } } else { var sel = new SimpleSelection(textArea, startPos, endPos); sel.ReplaceSelectionWithText(string.Empty); } } else { textArea.RemoveSelectedText(); } } textArea.Caret.BringCaretToView(); args.Handled = true; }); }
internal static TextViewPosition GetNewCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, bool enableVirtualSpace, ref double desiredXPos) { switch (direction) { case CaretMovementType.None: return(caretPosition); case CaretMovementType.DocumentStart: desiredXPos = double.NaN; return(new TextViewPosition(0, 0)); case CaretMovementType.DocumentEnd: desiredXPos = double.NaN; return(new TextViewPosition(textView.Document.GetLocation(textView.Document.TextLength))); } DocumentLine caretLine = textView.Document.GetLineByNumber(caretPosition.Line); VisualLine visualLine = textView.GetOrConstructVisualLine(caretLine); TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn, caretPosition.IsAtEndOfLine); switch (direction) { case CaretMovementType.CharLeft: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace)); case CaretMovementType.Backspace: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.EveryCodepoint, enableVirtualSpace)); case CaretMovementType.CharRight: desiredXPos = double.NaN; return(GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace)); case CaretMovementType.WordLeft: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace)); case CaretMovementType.WordRight: desiredXPos = double.NaN; return(GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace)); case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: return(GetUpDownCaretPosition(textView, caretPosition, direction, visualLine, textLine, enableVirtualSpace, ref desiredXPos)); case CaretMovementType.LineStart: desiredXPos = double.NaN; return(GetStartOfLineCaretPosition(caretPosition.VisualColumn, visualLine, textLine, enableVirtualSpace)); case CaretMovementType.LineEnd: desiredXPos = double.NaN; return(GetEndOfLineCaretPosition(visualLine, textLine)); default: throw new NotSupportedException(direction.ToString()); } }