Represents a visual line in the document. A visual line usually corresponds to one DocumentLine, but it can span multiple lines if all but the first are collapsed.
Esempio n. 1
0
 /// <summary>
 /// Creates a visual line text element with the specified length.
 /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
 /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
 /// </summary>
 public VisualLineText(VisualLine parentVisualLine, int length)
     : base(length, length)
 {
     if (parentVisualLine == null)
         throw new ArgumentNullException("parentVisualLine");
     this.parentVisualLine = parentVisualLine;
 }
        public void Render(DrawingContext drawingContext, VisualLine line, Size pixelSize)
        {
            var lineMiddle = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextMiddle) -
                                 _textView.VerticalOffset;

            // Draw the error line
            drawingContext.DrawLine(new Pen(Brushes.DarkGoldenrod, 4), new Point(0, lineMiddle), new Point(20, lineMiddle));
        }
Esempio n. 3
0
		internal void RemoveInlineObjects(VisualLine visualLine)
		{
			// Delay removing inline objects:
			// A document change immediately invalidates affected visual lines, but it does not
			// cause an immediate redraw.
			// To prevent inline objects from flickering when they are recreated, we delay removing
			// inline objects until the next redraw.
			visualLinesWithOutstandingInlineObjects.Add(visualLine);
		}
Esempio n. 4
0
        /// <summary>
        /// Validates the visual column of the caret using the specified visual line.
        /// The visual line must contain the caret offset.
        /// </summary>
        void RevalidateVisualColumn(VisualLine visualLine)
        {
            if (visualLine == null)
                throw new ArgumentNullException("visualLine");

            // mark column as validated
            visualColumnValid = true;

            int caretOffset = textView.Document.GetOffset(position.Location);
            int firstDocumentLineOffset = visualLine.FirstDocumentLine.Offset;
            position.VisualColumn = visualLine.ValidateVisualColumn(position, textArea.Selection.EnableVirtualSpace);

            // search possible caret positions
            int newVisualColumnForwards = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal, textArea.Selection.EnableVirtualSpace);
            // 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, textArea.Selection.EnableVirtualSpace);

                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);
            }
        }
Esempio n. 5
0
 double GetVisualPos(VisualLine vl, TextLine tl)
 {
     double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) + tl.Height / 2 - TextView.VerticalOffset;
     return Math.Round(pos) + 0.5;
 }
Esempio n. 6
0
		/// <summary>
		/// Creates a visual line text element with the specified length.
		/// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
		/// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
		/// </summary>
		public VisualLineLinkText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length)
		{
			this.RequireControlModifierForClick = true;
		}
Esempio n. 7
0
		Rect CalcCaretOverstrikeRectangle(VisualLine visualLine)
		{
			if (!visualColumnValid) {
				RevalidateVisualColumn(visualLine);
			}
			
			int currentPos = position.VisualColumn;
			// The text being overwritten in overstrike mode is everything up to the next normal caret stop
			int nextPos = visualLine.GetNextCaretPosition(currentPos, LogicalDirection.Forward, CaretPositioningMode.Normal, true);
			TextLine textLine = visualLine.GetTextLine(currentPos);
			
			Rect r;
			if (currentPos < visualLine.VisualLength) {
				// If the caret is within the text, use GetTextBounds() for the text being overwritten.
				// This is necessary to ensure the rectangle is calculated correctly in bidirectional text.
				var textBounds = textLine.GetTextBounds(currentPos, nextPos - currentPos)[0];
				r = textBounds.Rectangle;
				r.Y += visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineTop);
			} else {
				// If the caret is at the end of the line (or in virtual space),
				// use the visual X position of currentPos and nextPos (one or more of which will be in virtual space)
				double xPos = visualLine.GetTextLineVisualXPosition(textLine, currentPos);
				double xPos2 = visualLine.GetTextLineVisualXPosition(textLine, nextPos);
				double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop);
				double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom);
				r = new Rect(xPos, lineTop, xPos2 - xPos, lineBottom - lineTop);
			}
			// If the caret is too small (e.g. in front of zero-width character), ensure it's still visible
			if (r.Width < SystemParameters.CaretWidth)
				r.Width = SystemParameters.CaretWidth;
			return r;
		}
 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 TextViewPosition GetPrevCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace)
		{
			int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode, enableVirtualSpace);
			if (pos >= 0) {
				return visualLine.GetTextViewPosition(pos);
			} else {
				// move to end of previous line
				DocumentLine previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
				if (previousDocumentLine != null) {
					VisualLine previousLine = textView.GetOrConstructVisualLine(previousDocumentLine);
					pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode, enableVirtualSpace);
					if (pos < 0)
						throw ThrowUtil.NoValidCaretPosition();
					return previousLine.GetTextViewPosition(pos);
				} else {
					// at start of document
					Debug.Assert(visualLine.FirstDocumentLine.Offset == 0);
					return new TextViewPosition(0, 0);
				}
			}
		}
		static TextViewPosition GetNextCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace)
		{
			int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Forward, mode, enableVirtualSpace);
			if (pos >= 0) {
				return visualLine.GetTextViewPosition(pos);
			} else {
				// move to start of next line
				DocumentLine nextDocumentLine = visualLine.LastDocumentLine.NextLine;
				if (nextDocumentLine != null) {
					VisualLine nextLine = textView.GetOrConstructVisualLine(nextDocumentLine);
					pos = nextLine.GetNextCaretPosition(-1, LogicalDirection.Forward, mode, enableVirtualSpace);
					if (pos < 0)
						throw ThrowUtil.NoValidCaretPosition();
					return nextLine.GetTextViewPosition(pos);
				} else {
					// at end of document
					Debug.Assert(visualLine.LastDocumentLine.Offset + visualLine.LastDocumentLine.TotalLength == textView.Document.TextLength);
					return new TextViewPosition(textView.Document.GetLocation(textView.Document.TextLength));
				}
			}
		}
		static TextViewPosition GetEndOfLineCaretPosition(VisualLine visualLine, TextLine textLine)
		{
			int newVC = visualLine.GetTextLineVisualStartColumn(textLine) + textLine.Length - textLine.TrailingWhitespaceLength;
			TextViewPosition pos = visualLine.GetTextViewPosition(newVC);
			pos.IsAtEndOfLine = true;
			return pos;
		}
		static TextViewPosition GetStartOfLineCaretPosition(int oldVC, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace)
		{
			int newVC = visualLine.GetTextLineVisualStartColumn(textLine);
			if (newVC == 0)
				newVC = visualLine.GetNextCaretPosition(newVC - 1, LogicalDirection.Forward, CaretPositioningMode.WordStart, enableVirtualSpace);
			if (newVC < 0)
				throw ThrowUtil.NoValidCaretPosition();
			// when the caret is already at the start of the text, jump to start before whitespace
			if (newVC == oldVC)
				newVC = 0;
			return visualLine.GetTextViewPosition(newVC);
		}
Esempio n. 14
0
 public VisualLineTextSource(VisualLine visualLine)
 {
     this.VisualLine = visualLine;
 }
Esempio n. 15
0
 /// <summary>
 /// Creates a visual line text element with the specified length.
 /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
 /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
 /// </summary>
 public VisualLineLinkText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length)
 {
     this.RequireControlModifierForClick = true;
 }
		/// <summary>
		/// Calculates the rectangles for the visual column segment.
		/// This returns one rectangle for each line inside the segment.
		/// </summary>
		public static IEnumerable<Rect> GetRectsFromVisualSegment(TextView textView, VisualLine line, int startVC, int endVC)
		{
			if (textView == null)
				throw new ArgumentNullException("textView");
			if (line == null)
				throw new ArgumentNullException("line");
			return ProcessTextLines(textView, line, startVC, endVC);
		}
        static IEnumerable <Rect> ProcessTextLines(TextView textView, VisualLine visualLine, int segmentStartVC, int segmentEndVC)
        {
            TextLine lastTextLine = visualLine.TextLines.Last();
            Vector   scrollOffset = textView.ScrollOffset;

            for (int i = 0; i < visualLine.TextLines.Count; i++)
            {
                TextLine line           = visualLine.TextLines[i];
                double   y              = visualLine.GetTextLineVisualYPosition(line, VisualYPosition.LineTop);
                int      visualStartCol = visualLine.GetTextLineVisualStartColumn(line);
                int      visualEndCol   = visualStartCol + line.Length;
                if (line == lastTextLine)
                {
                    visualEndCol -= 1;                     // 1 position for the TextEndOfParagraph
                }
                else
                {
                    visualEndCol -= line.TrailingWhitespaceLength;
                }

                if (segmentEndVC < visualStartCol)
                {
                    break;
                }
                if (lastTextLine != line && segmentStartVC > visualEndCol)
                {
                    continue;
                }
                int segmentStartVCInLine = Math.Max(segmentStartVC, visualStartCol);
                int segmentEndVCInLine   = Math.Min(segmentEndVC, visualEndCol);
                y -= scrollOffset.Y;
                Rect lastRect = Rect.Empty;
                if (segmentStartVCInLine == segmentEndVCInLine)
                {
                    // GetTextBounds crashes for length=0, so we'll handle this case with GetDistanceFromCharacterHit
                    // We need to return a rectangle to ensure empty lines are still visible
                    double pos = visualLine.GetTextLineVisualXPosition(line, segmentStartVCInLine);
                    pos -= scrollOffset.X;
                    // The following special cases are necessary to get rid of empty rectangles at the end of a TextLine if "Show Spaces" is active.
                    // If not excluded once, the same rectangle is calculated (and added) twice (since the offset could be mapped to two visual positions; end/start of line), if there is no trailing whitespace.
                    // Skip this TextLine segment, if it is at the end of this line and this line is not the last line of the VisualLine and the selection continues and there is no trailing whitespace.
                    if (segmentEndVCInLine == visualEndCol && i < visualLine.TextLines.Count - 1 && segmentEndVC > segmentEndVCInLine && line.TrailingWhitespaceLength == 0)
                    {
                        continue;
                    }
                    if (segmentStartVCInLine == visualStartCol && i > 0 && segmentStartVC < segmentStartVCInLine && visualLine.TextLines[i - 1].TrailingWhitespaceLength == 0)
                    {
                        continue;
                    }
                    /* Az Add Start 選択時の色の四角形を作成する */
                    yield return(new Rect(pos, y, 1, line.Height));
                    /* Az Add End   */
                }
                else
                {
                    if (segmentStartVCInLine <= visualEndCol)
                    {
                        foreach (TextBounds b in line.GetTextBounds(segmentStartVCInLine, segmentEndVCInLine - segmentStartVCInLine))
                        {
                            double left  = b.Rectangle.Left - scrollOffset.X;
                            double right = b.Rectangle.Right - scrollOffset.X;
                            if (!lastRect.IsEmpty)
                            {
                                yield return(lastRect);
                            }
                            // left>right is possible in RTL languages
                            /* Az Add Start 選択時の色の四角形を作成する */
                            lastRect = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
                            /* Az Add End   */
                        }
                    }
                    if (segmentEndVC >= visualLine.VisualLengthWithEndOfLineMarker)
                    {
                        double left  = (segmentStartVC > visualLine.VisualLengthWithEndOfLineMarker ? visualLine.GetTextLineVisualXPosition(lastTextLine, segmentStartVC) : line.Width) - scrollOffset.X;
                        double right = ((segmentEndVC == int.MaxValue || line != lastTextLine) ? Math.Max(((IScrollInfo)textView).ExtentWidth, ((IScrollInfo)textView).ViewportWidth) : visualLine.GetTextLineVisualXPosition(lastTextLine, segmentEndVC)) - scrollOffset.X;
                        /* Az Add Start 選択時の色の四角形を作成する */
                        Rect extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
                        /* Az Add End   */
                        if (!lastRect.IsEmpty)
                        {
                            if (extendSelection.IntersectsWith(lastRect))
                            {
                                lastRect.Union(extendSelection);
                                yield return(lastRect);
                            }
                            else
                            {
                                // If the end of the line is in an RTL segment, keep lastRect and extendSelection separate.
                                yield return(lastRect);

                                yield return(extendSelection);
                            }
                        }
                        else
                        {
                            yield return(extendSelection);
                        }
                    }
                    else
                    {
                        yield return(lastRect);
                    }
                }
            }
        }
 private static IEnumerable<DocumentLine> DocumentLines(VisualLine visLine)
 {
   var line = visLine.FirstDocumentLine;
   while (line != visLine.LastDocumentLine)
   {
     yield return line;
     line = line.NextLine;
   }
   yield return line;
 }
        static void SetCaretPosition(TextArea textArea, VisualLine targetVisualLine, TextLine targetLine,
		                             CharacterHit ch, bool allowWrapToNextLine)
        {
            int newVisualColumn = ch.FirstCharacterIndex + ch.TrailingLength;
            int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine);
            if (!allowWrapToNextLine && newVisualColumn >= targetLineStartCol + targetLine.Length)
                newVisualColumn = targetLineStartCol + targetLine.Length - 1;
            int newOffset = targetVisualLine.GetRelativeOffset(newVisualColumn) + targetVisualLine.FirstDocumentLine.Offset;
            SetCaretPosition(textArea, newVisualColumn, newOffset);
        }
Esempio n. 20
0
 protected virtual string GetLineNumberString(VisualLine line)
 {
     return line.FirstDocumentLine.LineNumber.ToString(CultureInfo.CurrentCulture);
 }
Esempio n. 21
0
 /// <summary>
 /// Creates a visual line text element with the specified length.
 /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
 /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
 /// </summary>
 public VisualLineReferenceText(VisualLine parentVisualLine, int length, ReferenceElementGenerator parent, ReferenceSegment referenceSegment)
     : base(parentVisualLine, length)
 {
     this.parent = parent;
     this.referenceSegment = referenceSegment;
 }
 private static void SetCaretPosition(TextArea textArea, VisualLine targetVisualLine, TextLine targetLine, int newVisualColumn, bool allowWrapToNextLine)
 {
     int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine);
     if (!allowWrapToNextLine && newVisualColumn >= targetLineStartCol + targetLine.Length)
     {
         if (newVisualColumn <= targetVisualLine.VisualLength)
             newVisualColumn = targetLineStartCol + targetLine.Length - 1;
     }
     int newOffset = targetVisualLine.GetRelativeOffset(newVisualColumn) + targetVisualLine.FirstDocumentLine.Offset;
     SetCaretPosition(textArea, newVisualColumn, newOffset);
 }
Esempio n. 23
0
		static TextViewPosition GetPrevCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace) {
			int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode, enableVirtualSpace);
			if (pos >= 0)
				return visualLine.GetTextViewPosition(pos);
			var previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
			if (previousDocumentLine != null) {
				var previousLine = textView.GetOrConstructVisualLine(previousDocumentLine);
				pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode, enableVirtualSpace);
				return previousLine.GetTextViewPosition(pos);
			}
			return new TextViewPosition(0, 0);
		}
Esempio n. 24
0
		double GetVisualPos(VisualLine vl, TextLine tl, double pixelHeight)
		{
			double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.TextMiddle) - TextView.VerticalOffset;
			return PixelSnapHelpers.PixelAlign(pos, pixelHeight);
		}
Esempio n. 25
0
 public VisualLineDrawingVisual(VisualLine visualLine)
 {
     this.VisualLine = visualLine;
     var drawingContext = RenderOpen();
     double pos = 0;
     foreach (TextLine textLine in visualLine.TextLines) {
         textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None);
         pos += textLine.Height;
     }
     this.Height = pos;
     drawingContext.Close();
 }
 static void MoveCaretLeft(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
 {
     int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode);
     if (pos >= 0) {
         SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
     } else {
         // move to end of previous line
         DocumentLine previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
         if (previousDocumentLine != null) {
             VisualLine previousLine = textArea.TextView.GetOrConstructVisualLine(previousDocumentLine);
             pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode);
             if (pos < 0)
                 throw ThrowUtil.NoValidCaretPosition();
             SetCaretPosition(textArea, pos, previousLine.GetRelativeOffset(pos) + previousLine.FirstDocumentLine.Offset);
         } else {
             // at start of document
             Debug.Assert(visualLine.FirstDocumentLine.Offset == 0);
             SetCaretPosition(textArea, 0, 0);
         }
     }
 }
Esempio n. 27
0
			/// <summary>
			/// Creates a visual line text element with the specified length.
			/// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
			/// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
			/// </summary>
			public VisualLineMessageViewLinkText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length)
			{
				this.RequireControlModifierForClick = false;
			}
 static void MoveCaretRight(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
 {
     int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Forward, mode);
     if (pos >= 0) {
         SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
     } else {
         // move to start of next line
         DocumentLine nextDocumentLine = visualLine.LastDocumentLine.NextLine;
         if (nextDocumentLine != null) {
             VisualLine nextLine = textArea.TextView.GetOrConstructVisualLine(nextDocumentLine);
             pos = nextLine.GetNextCaretPosition(-1, LogicalDirection.Forward, mode);
             if (pos < 0)
                 throw ThrowUtil.NoValidCaretPosition();
             SetCaretPosition(textArea, pos, nextLine.GetRelativeOffset(pos) + nextLine.FirstDocumentLine.Offset);
         } else {
             // at end of document
             Debug.Assert(visualLine.LastDocumentLine.Offset + visualLine.LastDocumentLine.TotalLength == textArea.Document.TextLength);
             SetCaretPosition(textArea, -1, textArea.Document.TextLength);
         }
     }
 }
Esempio n. 29
0
        Rect CalcCaretRectangle(VisualLine visualLine)
        {
            if (!visualColumnValid) {
                RevalidateVisualColumn(visualLine);
            }

            TextLine textLine = visualLine.GetTextLine(position.VisualColumn);
            double xPos = visualLine.GetTextLineVisualXPosition(textLine, position.VisualColumn);
            double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop);
            double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineBottom);

            return new Rect(xPos,
                            lineTop,
                            SystemParameters.CaretWidth,
                            lineBottom - lineTop);
        }
 static void MoveCaretToEndOfLine(TextArea textArea, VisualLine visualLine)
 {
     int newVC = visualLine.VisualLength;
     int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);
     SetCaretPosition(textArea, newVC, offset);
 }
 public VisualLineTextSource(VisualLine visualLine)
 {
     this.VisualLine = visualLine;
 }
 static void MoveCaretToStartOfLine(TextArea textArea, VisualLine visualLine)
 {
     int newVC = visualLine.GetNextCaretPosition(-1, LogicalDirection.Forward, CaretPositioningMode.WordStart);
     if (newVC < 0)
         throw ThrowUtil.NoValidCaretPosition();
     // when the caret is already at the start of the text, jump to start before whitespace
     if (newVC == textArea.Caret.VisualColumn)
         newVC = 0;
     int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);
     SetCaretPosition(textArea, newVC, offset);
 }
		static IEnumerable<Rect> ProcessTextLines(TextView textView, VisualLine visualLine, int segmentStartVC, int segmentEndVC)
		{
			TextLine lastTextLine = visualLine.TextLines.Last();
			Vector scrollOffset = textView.ScrollOffset;
			
			for (int i = 0; i < visualLine.TextLines.Count; i++) {
				TextLine line = visualLine.TextLines[i];
				double y = visualLine.GetTextLineVisualYPosition(line, VisualYPosition.LineTop);
				int visualStartCol = visualLine.GetTextLineVisualStartColumn(line);
				int visualEndCol = visualStartCol + line.Length;
				if (line != lastTextLine)
					visualEndCol -= line.TrailingWhitespaceLength;
				
				if (segmentEndVC < visualStartCol)
					break;
				if (lastTextLine != line && segmentStartVC > visualEndCol)
					continue;
				int segmentStartVCInLine = Math.Max(segmentStartVC, visualStartCol);
				int segmentEndVCInLine = Math.Min(segmentEndVC, visualEndCol);
				y -= scrollOffset.Y;
				if (segmentStartVCInLine == segmentEndVCInLine) {
					// GetTextBounds crashes for length=0, so we'll handle this case with GetDistanceFromCharacterHit
					// We need to return a rectangle to ensure empty lines are still visible
					double pos = visualLine.GetTextLineVisualXPosition(line, segmentStartVCInLine);
					pos -= scrollOffset.X;
					// The following special cases are necessary to get rid of empty rectangles at the end of a TextLine if "Show Spaces" is active.
					// If not excluded once, the same rectangle is calculated (and added) twice (since the offset could be mapped to two visual positions; end/start of line), if there is no trailing whitespace.
					// Skip this TextLine segment, if it is at the end of this line and this line is not the last line of the VisualLine and the selection continues and there is no trailing whitespace.
					if (segmentEndVCInLine == visualEndCol && i < visualLine.TextLines.Count - 1 && segmentEndVC > segmentEndVCInLine && line.TrailingWhitespaceLength == 0)
						continue;
					if (segmentStartVCInLine == visualStartCol && i > 0 && segmentStartVC < segmentStartVCInLine && visualLine.TextLines[i - 1].TrailingWhitespaceLength == 0)
						continue;
					yield return new Rect(pos, y, 1, line.Height);
				} else {
					Rect lastRect = Rect.Empty;
					if (segmentStartVCInLine <= visualEndCol) {
						foreach (TextBounds b in line.GetTextBounds(segmentStartVCInLine, segmentEndVCInLine - segmentStartVCInLine)) {
							double left = b.Rectangle.Left - scrollOffset.X;
							double right = b.Rectangle.Right - scrollOffset.X;
							if (!lastRect.IsEmpty)
								yield return lastRect;
							// left>right is possible in RTL languages
							lastRect = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
						}
					}
					if (segmentEndVC >= visualLine.VisualLengthWithEndOfLineMarker) {
						double left = (segmentStartVC > visualLine.VisualLengthWithEndOfLineMarker ? visualLine.GetTextLineVisualXPosition(lastTextLine, segmentStartVC) : line.Width) - scrollOffset.X;
						double right = ((segmentEndVC == int.MaxValue || line != lastTextLine) ? Math.Max(((IScrollInfo)textView).ExtentWidth, ((IScrollInfo)textView).ViewportWidth) : visualLine.GetTextLineVisualXPosition(lastTextLine, segmentEndVC)) - scrollOffset.X;
						Rect extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
						if (!lastRect.IsEmpty) {
							if (extendSelection.IntersectsWith(lastRect)) {
								lastRect.Union(extendSelection);
								yield return lastRect;
							} else {
								yield return lastRect;
								yield return extendSelection;
							}
						} else
							yield return extendSelection;
					} else
						yield return lastRect;
				}
			}
		}
 /// <summary>
 /// Calculates the rectangles for the visual column segment.
 /// This returns one rectangle for each line inside the segment.
 /// </summary>
 public static IEnumerable <Rect> GetRectsFromVisualSegment(TextView textView, VisualLine line, int startVC, int endVC)
 {
     if (textView == null)
     {
         throw new ArgumentNullException("textView");
     }
     if (line == null)
     {
         throw new ArgumentNullException("line");
     }
     return(ProcessTextLines(textView, line, startVC, endVC));
 }