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 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 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 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 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 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()); } }
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; } }
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()); } }