Ejemplo n.º 1
0
        /// <summary>
        /// Returns an ArrayList of rectangles (Rect) that form the bounds of the region specified between
        /// the start and end points
        /// </summary>
        /// <param name="cp"></param>
        /// int offset indicating the starting point of the region for which bounds are required
        /// <param name="cch">
        /// Length in characters of the region for which bounds are required
        /// </param>
        /// <param name="xOffset">
        /// Offset of line in x direction, to be added to line bounds to get actual rectangle for line
        /// </param>
        /// <param name="yOffset">
        /// Offset of line in y direction, to be added to line bounds to get actual rectangle for line
        /// </param>
        /// <remarks>
        /// This function calls GetTextBounds for the line, and then checks if there are text run bounds. If they exist,
        /// it uses those as the bounding rectangles. If not, it returns the rectangle for the first (and only) element
        /// of the text bounds.
        /// </remarks>
        internal List <Rect> GetRangeBounds(int cp, int cch, double xOffset, double yOffset)
        {
            List <Rect> rectangles = new List <Rect>();

            // Adjust x offset for trailing spaces
            double delta           = CalculateXOffsetShift();
            double adjustedXOffset = xOffset + delta;

            IList <TextBounds> textBounds;

            if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
            {
                // We should not shift offset in this case
                Invariant.Assert(DoubleUtil.AreClose(delta, 0));
                System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
                Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
                textBounds = line.GetTextBounds(cp, cch);
            }
            else
            {
                textBounds = _line.GetTextBounds(cp, cch);
            }
            Invariant.Assert(textBounds.Count > 0);


            for (int boundIndex = 0; boundIndex < textBounds.Count; boundIndex++)
            {
                Rect rect = textBounds[boundIndex].Rectangle;
                rect.X += adjustedXOffset;
                rect.Y += yOffset;
                rectangles.Add(rect);
            }
            return(rectangles);
        }
Ejemplo n.º 2
0
        // ------------------------------------------------------------------
        // Get length of content hidden by ellipses.
        //
        //      wrappingWidth - Wrapping width for the line.
        //
        // Returns: Length of collapsed content (number of characters hidden
        //          by ellipses).
        // ------------------------------------------------------------------
        internal int GetEllipsesLength()
        {
            // There are no ellipses, if:
            // * there is no overflow in the line
            // * text trimming is turned off
            if (!_line.HasOverflowed)
            {
                return(0);
            }
            if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None)
            {
                return(0);
            }

            // Create collapsed text line to get length of collapsed content.
            System.Windows.Media.TextFormatting.TextLine collapsedLine = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
            Debug.Assert(collapsedLine.HasCollapsed, "Line has not been collapsed");
            IList <TextCollapsedRange> collapsedRanges = collapsedLine.GetTextCollapsedRanges();

            if (collapsedRanges != null)
            {
                Debug.Assert(collapsedRanges.Count == 1, "Multiple collapsed ranges are not supported.");
                TextCollapsedRange collapsedRange = collapsedRanges[0];
                return(collapsedRange.Length);
            }
            return(0);
        }
Ejemplo n.º 3
0
		/// <summary>
		/// Creates a new FormattedTextElement that displays the specified text
		/// and occupies the specified length in the document.
		/// </summary>
		public FormattedTextElement(TextLine text, int documentLength) : base(1, documentLength)
		{
			if (text == null)
				throw new ArgumentNullException("text");
			this.textLine = text;
			this.BreakBefore = LineBreakCondition.BreakPossible;
			this.BreakAfter = LineBreakCondition.BreakPossible;
		}
Ejemplo n.º 4
0
		/// <inheritdoc/>
		public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)
		{
			if (textLine == null) {
				var formatter = TextFormatterFactory.Create(context.TextView);
				textLine = PrepareText(formatter, this.text, this.TextRunProperties);
				this.text = null;
			}
			return new FormattedTextRun(this, this.TextRunProperties);
		}
Ejemplo n.º 5
0
        internal LineNumberVisual(WpfTextLine textLine)
        {
            _textLine = textLine
                        ?? throw new ArgumentNullException(nameof(textLine));

            _renderTargets = new List <Point>();

            IsHitTestVisible = false;
        }
Ejemplo n.º 6
0
        //-------------------------------------------------------------------
        // Retrieve text position index from the distance.
        //
        //      distance - distance relative to the beginning of the line
        //
        // Returns: Text position index.
        //-------------------------------------------------------------------
        internal CharacterHit GetTextPositionFromDistance(double distance)
        {
            // Adjust distance to account for a line shift due to rendering of trailing spaces
            double delta = CalculateXOffsetShift();

            if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
            {
                System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
                Invariant.Assert(DoubleUtil.AreClose(delta, 0));
                Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
                return(line.GetCharacterHitFromDistance(distance));
            }
            return(_line.GetCharacterHitFromDistance(distance - delta));
        }
Ejemplo n.º 7
0
        // ------------------------------------------------------------------
        // Render formatted line.
        //
        //      ctx - Drawing context to be used for rendering.
        //      lineOffset - Offset of the line.
        //      wrappingWidth - Wrapping width for the line.
        // ------------------------------------------------------------------
        internal void Render(DrawingContext ctx, Point lineOffset)
        {
            Debug.Assert(_line != null, "Rendering line that has not been measured yet.");

            // Handle text trimming.
            System.Windows.Media.TextFormatting.TextLine line = _line;
            if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
            {
                line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
                Debug.Assert(line.HasCollapsed, "Line has not been collapsed");
            }

            double delta = CalculateXOffsetShift();

            line.Draw(ctx, new Point(lineOffset.X + delta, lineOffset.Y), (_mirror ? InvertAxes.Horizontal : InvertAxes.None));
        }
Ejemplo n.º 8
0
        // ------------------------------------------------------------------
        // Gets width of content, collapsed at wrappingWidth (if necessary)
        //
        //      wrappingWidth - Wrapping width for the line.
        //
        // Returns: Width of content, after collapse (may be greater than wrappingWidth)
        //
        // ------------------------------------------------------------------
        internal double GetCollapsedWidth()
        {
            // There are no ellipses, if:
            // * there is no overflow in the line
            // * text trimming is turned off
            if (!_line.HasOverflowed)
            {
                return(Width);
            }
            if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None)
            {
                return(Width);
            }

            // Create collapsed text line to get length of collapsed content.
            System.Windows.Media.TextFormatting.TextLine collapsedLine = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
            Debug.Assert(collapsedLine.HasCollapsed, "Line has not been collapsed");

            return(collapsedLine.Width);
        }
Ejemplo n.º 9
0
        //-------------------------------------------------------------------
        //
        //  Protected Methods
        //
        //-------------------------------------------------------------------

        #region Protected Methods

        // ------------------------------------------------------------------
        // Retrieve bounds of an object/character at specified text index.
        //
        //      cp - character index of an object/character
        //      cch - number of positions occupied by object/character
        //      flowDirection - flow direction of object/character
        //
        // Returns: Bounds of an object/character.
        // ------------------------------------------------------------------
        protected Rect GetBoundsFromPosition(int cp, int cch, out FlowDirection flowDirection)
        {
            Rect rect;

            // Adjust x offset for trailing spaces
            double             delta = CalculateXOffsetShift();
            IList <TextBounds> textBounds;

            if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
            {
                // We should not shift offset in this case
                Invariant.Assert(DoubleUtil.AreClose(delta, 0));
                System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
                Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
                textBounds = line.GetTextBounds(cp, cch);
            }
            else
            {
                textBounds = _line.GetTextBounds(cp, cch);
            }
            Invariant.Assert(textBounds != null && textBounds.Count == 1, "Expecting exactly one TextBounds for a single text position.");

            IList <TextRunBounds> runBounds = textBounds[0].TextRunBounds;

            if (runBounds != null)
            {
                Debug.Assert(runBounds.Count == 1, "Expecting exactly one TextRunBounds for a single text position.");
                rect = runBounds[0].Rectangle;
            }
            else
            {
                rect = textBounds[0].Rectangle;
            }

            rect.X       += delta;
            flowDirection = textBounds[0].FlowDirection;
            return(rect);
        }
Ejemplo n.º 10
0
 /// <summary>
 /// Sets the enumerator to its initial position,
 /// which is before the first element in the collection
 /// </summary>
 public void Reset()
 {
     _textStorePosition = 0;
     _lineCount = 0;
     _totalHeight = 0;
     _currentLine = null;
     _nextLine = null;
 }
Ejemplo n.º 11
0
		private void FindSelectedArea(int idx, int txtLen, int txtOffset, double x, TextLine line, ref double start, ref double end)
		{
			int first = Math.Max(txtOffset, this.SelectionStart - idx);
			int last = Math.Min(txtLen - 1 + txtOffset, this.SelectionEnd - idx);
			if (last >= first)
			{
				start = Math.Min(start, line.GetDistanceFromCharacterHit(new CharacterHit(first, 0)) + x);
				end = Math.Max(end, line.GetDistanceFromCharacterHit(new CharacterHit(last, 1)) + x);
			}
		}
		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;
		}
Ejemplo n.º 13
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;
 }
Ejemplo n.º 14
0
		public WpfTextViewLine(IBufferGraph bufferGraph, LinePartsCollection linePartsCollection, int linePartsIndex, int linePartsLength, int startColumn, int endColumn, ITextSnapshotLine bufferLine, SnapshotSpan span, ITextSnapshot visualSnapshot, TextLine textLine, double indentation, double virtualSpaceWidth) {
			if (bufferGraph == null)
				throw new ArgumentNullException(nameof(bufferGraph));
			if (linePartsCollection == null)
				throw new ArgumentNullException(nameof(linePartsCollection));
			if (linePartsIndex < 0)
				throw new ArgumentOutOfRangeException(nameof(linePartsIndex));
			if (linePartsLength < 0)
				throw new ArgumentOutOfRangeException(nameof(linePartsLength));
			if (linePartsIndex + linePartsLength > linePartsCollection.LineParts.Count)
				throw new ArgumentOutOfRangeException(nameof(linePartsLength));
			if (bufferLine == null)
				throw new ArgumentNullException(nameof(bufferLine));
			if (span.Snapshot != bufferLine.Snapshot)
				throw new ArgumentException();
			if (visualSnapshot == null)
				throw new ArgumentNullException(nameof(visualSnapshot));
			if (textLine == null)
				throw new ArgumentNullException(nameof(textLine));

			IsValid = true;
			this.linePartsIndex = linePartsIndex;
			this.linePartsLength = linePartsLength;
			this.bufferGraph = bufferGraph;
			this.linePartsCollection = linePartsCollection;
			this.startColumn = startColumn;
			this.endColumn = endColumn;
			this.visualSnapshot = visualSnapshot;
			textLines = new ReadOnlyCollection<TextLine>(new[] { textLine });
			Debug.Assert(textLines.Count == 1);// Assumed by all code accessing TextLine prop

			realTopSpace = 0;
			realBottomSpace = 0;
			realBaseline = TextLine.Baseline;
			double baseLineHeight = TextLine.TextHeight - TextLine.Baseline;
			var lineParts = linePartsCollection.LineParts;
			for (int i = 0; i < linePartsLength; i++) {
				var adornmentElement = lineParts[linePartsIndex + i].AdornmentElement;
				if (adornmentElement == null)
					continue;
				double adornmentBaseLineHeight = adornmentElement.TextHeight - adornmentElement.Baseline;
				if (adornmentBaseLineHeight > baseLineHeight)
					baseLineHeight = adornmentBaseLineHeight;
				if (adornmentElement.Baseline > realBaseline)
					realBaseline = adornmentElement.Baseline;
				if (adornmentElement.TopSpace > realTopSpace)
					realTopSpace = adornmentElement.TopSpace;
				if (adornmentElement.BottomSpace > realBottomSpace)
					realBottomSpace = adornmentElement.BottomSpace;
			}
			realTextHeight = Math.Ceiling(baseLineHeight + realBaseline);

			isFirstTextViewLineForSnapshotLine = span.Start == bufferLine.Start;
			isLastTextViewLineForSnapshotLine = span.End == bufferLine.EndIncludingLineBreak;
			IsLastVisualLine = bufferLine.LineNumber + 1 == bufferLine.Snapshot.LineCount && IsLastTextViewLineForSnapshotLine;
			lineBreakLength = isLastTextViewLineForSnapshotLine ? bufferLine.LineBreakLength : 0;
			this.virtualSpaceWidth = virtualSpaceWidth;
			textLeft = indentation;
			textWidth = TextLine.WidthIncludingTrailingWhitespace;
			extentIncludingLineBreak = span;
			endOfLineWidth = Math.Floor(realTextHeight * 0.58333333333333337);// Same as VS
			width = textWidth + (lineBreakLength == 0 ? 0 : endOfLineWidth);
			change = TextViewLineChange.NewOrReformatted;
			SetLineTransform(DefaultLineTransform);
		}
Ejemplo n.º 15
0
 /// <summary>
 /// Gets the start visual column from the specified text line.
 /// </summary>
 public int GetTextLineVisualStartColumn(TextLine textLine)
 {
     if (!TextLines.Contains(textLine))
         throw new ArgumentException("textLine is not a line in this VisualLine");
     int col = 0;
     foreach (TextLine tl in TextLines) {
         if (tl == textLine)
             break;
         else
             col += tl.Length;
     }
     return col;
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Gets the visual top from the specified text line.
 /// </summary>
 /// <returns>Distance in device-independent pixels
 /// from the top of the document to the top of the specified text line.</returns>
 public double GetTextLineVisualYPosition(TextLine textLine, VisualYPosition yPositionMode)
 {
     if (textLine == null)
         throw new ArgumentNullException("textLine");
     double pos = VisualTop;
     foreach (TextLine tl in TextLines) {
         if (tl == textLine) {
             switch (yPositionMode) {
                 case VisualYPosition.LineTop:
                     return pos;
                 case VisualYPosition.LineMiddle:
                     return pos + tl.Height / 2;
                 case VisualYPosition.LineBottom:
                     return pos + tl.Height;
                 case VisualYPosition.TextTop:
                     return pos + tl.Baseline - textView.DefaultBaseline;
                 case VisualYPosition.TextBottom:
                     return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight;
                 case VisualYPosition.TextMiddle:
                     return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight / 2;
                 case VisualYPosition.Baseline:
                     return pos + tl.Baseline;
                 default:
                     throw new ArgumentException("Invalid yPositionMode:" + yPositionMode);
             }
         } else {
             pos += tl.Height;
         }
     }
     throw new ArgumentException("textLine is not a line in this VisualLine");
 }
Ejemplo n.º 17
0
		public int GetTextLineVisualStartColumn(TextLine textLine) 
		{ 
			//TODO: VisualLine.GetTextLineVisualStartColumn()
			throw new NotImplementedException();
		}
Ejemplo n.º 18
0
		public double GetTextLineVisualTop(TextLine textLine) 
		{ 
			//TODO: VisualLine.GetTextLineVisualTop()
			throw new NotImplementedException();
		}
Ejemplo n.º 19
0
            /// <summary>
            /// Advances the enumerator to the next text line of the collection
            /// </summary>
            /// <returns>true if the enumerator was successfully advanced to the next element;
            /// false if the enumerator has passed the end of the collection</returns>
            public bool MoveNext()
            {
                if (_currentLine == null)
                {   // this is the first line

                    if (_that._text.Length == 0)
                        return false;

                    _currentLine = FormatLine(
                        _that._textSourceImpl,
                        _textStorePosition,
                        MaxLineLength(_lineCount),
                        _that._defaultParaProps,
                        null // no previous line break
                        );

                    // check if this line fits the text height
                    if (_totalHeight + _currentLine.Height > _that._maxTextHeight)
                    {
                        _currentLine.Dispose();
                        _currentLine = null;
                        return false;
                    }
                    Debug.Assert(_nextLine == null);
                }
                else
                {
                    // there is no next line or it didn't fit
                    // either way we're finished
                    if (_nextLine == null)
                        return false;

                    _totalHeight += _previousHeight;
                    _textStorePosition += _previousLength;
                    ++_lineCount;

                    _currentLine = _nextLine;
                    _nextLine = null;
                }

                TextLineBreak currentLineBreak = _currentLine.GetTextLineBreak();

                // this line is guaranteed to fit the text height
                Debug.Assert(_totalHeight + _currentLine.Height <= _that._maxTextHeight);

                // now, check if the next line fits, we need to do this on this iteration
                // because we might need to add ellipsis to the current line
                // as a result of the next line measurement

                // maybe there is no next line at all
                if (_textStorePosition + _currentLine.Length < _that._text.Length)
                {
                    bool nextLineFits;

                    if (_lineCount + 1 >= _that._maxLineCount)
                        nextLineFits = false;
                    else
                    {
                        _nextLine = FormatLine(
                            _that._textSourceImpl,
                            _textStorePosition + _currentLine.Length,
                            MaxLineLength(_lineCount + 1),
                            _that._defaultParaProps,
                            currentLineBreak
                            );
                        nextLineFits = (_totalHeight + _currentLine.Height + _nextLine.Height <= _that._maxTextHeight);
                    }                       

                    if (!nextLineFits)
                    {
                        // next line doesn't fit
                        if (_nextLine != null)
                        {
                            _nextLine.Dispose();
                            _nextLine = null;
                        }

                        if (_that._trimming != TextTrimming.None && !_currentLine.HasCollapsed)
                        {
                            // recreate the current line with ellipsis added
                            // Note: Paragraph ellipsis is not supported today. We'll workaround
                            // it here by faking a non-wrap text on finite column width.
                            TextWrapping currentWrap = _that._defaultParaProps.TextWrapping;
                            _that._defaultParaProps.SetTextWrapping(TextWrapping.NoWrap);

                            if (currentLineBreak != null)
                                currentLineBreak.Dispose();

                            _currentLine.Dispose();
                            _currentLine = FormatLine(
                                _that._textSourceImpl,
                                _textStorePosition,
                                MaxLineLength(_lineCount),
                                _that._defaultParaProps,
                                _previousLineBreak
                                );

                            currentLineBreak = _currentLine.GetTextLineBreak();
                            _that._defaultParaProps.SetTextWrapping(currentWrap);
                        }
                    }
                }
                _previousHeight = _currentLine.Height;
                _previousLength = _currentLine.Length;

                if (_previousLineBreak != null)
                    _previousLineBreak.Dispose();

                _previousLineBreak = currentLineBreak;

                return true;
            }
 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);
 }
Ejemplo n.º 21
0
            public void Dispose()
            {
                if (_currentLine != null)
                {
                    _currentLine.Dispose();
                    _currentLine = null;
                }

                if (_nextLine != null)
                {
                    _nextLine.Dispose();
                    _nextLine = null;
                }
            }
Ejemplo n.º 22
0
            internal LineEnumerator(FormattedText text)
            {
                _previousHeight = 0;
                _previousLength = 0;
                _previousLineBreak = null;

                _textStorePosition = 0;
                _lineCount = 0;
                _totalHeight = 0;
                _currentLine = null;
                _nextLine = null;
                _formatter = TextFormatter.FromCurrentDispatcher(text._textFormattingMode);
                _that = text;
                if (_that._textSourceImpl == null)
                    _that._textSourceImpl = new TextSourceImplementation(_that);
            }
Ejemplo n.º 23
0
 private void AdvanceLineOrigin(ref Point lineOrigin, TextLine currentLine)
 {
     double height = currentLine.Height;
     // advance line origin according to the flow direction
     switch (_defaultParaProps.FlowDirection)
     {
         case FlowDirection.LeftToRight:
         case FlowDirection.RightToLeft:
             lineOrigin.Y += height;
             break;
     }
 }
 public TabTextElement(TextLine text)
     : base(2, 1)
 {
     this.text = text;
 }
Ejemplo n.º 25
0
		double GetVisualPos(VisualLine vl, TextLine tl, double pixelHeight)
		{
			double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.TextMiddle) - TextView.VerticalOffset;
			return PixelSnapHelpers.PixelAlign(pos, pixelHeight);
		}
			public NewLineTextElement(TextLine text) : base(text, 0)
			{
				BreakBefore = LineBreakCondition.BreakPossible;
				BreakAfter = LineBreakCondition.BreakRestrained;
			}
		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);
		}
Ejemplo n.º 28
0
 /// <summary>
 /// Gets the distance to the left border of the text area of the specified visual column.
 /// The visual column must belong to the specified text line.
 /// </summary>
 public double GetTextLineVisualXPosition(TextLine textLine, int visualColumn)
 {
     if (textLine == null)
         throw new ArgumentNullException("textLine");
     double xPos = textLine.GetDistanceFromCharacterHit(
         new CharacterHit(Math.Min(visualColumn, VisualLengthWithEndOfLineMarker), 0));
     if (visualColumn > VisualLengthWithEndOfLineMarker) {
         xPos += (visualColumn - VisualLengthWithEndOfLineMarker) * textView.WideSpaceWidth;
     }
     return xPos;
 }
        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);
        }
Ejemplo n.º 30
0
 /// <summary>
 /// Gets the visual column from a document position (relative to top left of the document).
 /// If the user clicks between two visual columns, rounds to the nearest column.
 /// </summary>
 public int GetVisualColumn(TextLine textLine, double xPos, bool allowVirtualSpace)
 {
     if (xPos > textLine.WidthIncludingTrailingWhitespace) {
         if (allowVirtualSpace && textLine == TextLines[TextLines.Count - 1]) {
             int virtualX = (int)Math.Round((xPos - textLine.WidthIncludingTrailingWhitespace) / textView.WideSpaceWidth);
             return VisualLengthWithEndOfLineMarker + virtualX;
         }
     }
     CharacterHit ch = textLine.GetCharacterHitFromDistance(xPos);
     return ch.FirstCharacterIndex + ch.TrailingLength;
 }
Ejemplo n.º 31
0
			public Line(int number, TextLine textLine, double right, double top) {
				if (number <= 0)
					throw new ArgumentOutOfRangeException(nameof(number));
				if (textLine == null)
					throw new ArgumentNullException(nameof(textLine));
				Number = number;
				this.textLine = textLine;
				this.right = right;
				this.top = top;
			}
Ejemplo n.º 32
0
			public FoldingLineElement(FoldingSection fs, TextLine text, int documentLength) : base(text, documentLength)
			{
				this.fs = fs;
			}
Ejemplo n.º 33
0
        void MakeNewText()
        {
            if (fmt == null)
                fmt = TextFormatterFactory.Create(this, provider);

            if (line != null)
                line.Dispose();

            src.UpdateParent(this);
            line = fmt.FormatLine(src.Source, 0, 0, new ParaProps(this), null);
        }
Ejemplo n.º 34
0
        public static void HandleLine(LinkedList <CharInfo> allCharInfos, Point linePosition, TextLine myTextLine,
                                      CustomTextSource4 customTextSource4, int runCount, int nRuns, int lineNo, int textStorePosition,
                                      List <TextRunInfo> runsInfos,
                                      LinkedListNode <CharInfo> curCharInfoNode,
                                      out LinkedListNode <CharInfo> lastCharInfoNode,
                                      RoslynCodeBase.DebugDelegate?debugFn = null, TextChange?change = null,
                                      LineInfo2?curLineInfo = null)
        {
            lastCharInfoNode = null;
            var curPos = linePosition;
            // var positions = new List<Rect>();
            var indexedGlyphRuns = myTextLine.GetIndexedGlyphRuns();

            var runs = customTextSource4.Runs;

            debugFn?.Invoke($"Runs is count is {runs.Count}", 1);
            var textRuns = runs.Skip(runCount).Take(nRuns).ToList();

            debugFn?.Invoke($"{runCount} {nRuns} TextRuns enumerator count is {textRuns.Count}", 1);
            var curCi = curCharInfoNode;

            using (var enum1 = textRuns.GetEnumerator())
            {
                var moveNext      = enum1.MoveNext();
                var lineCharIndex = 0;
                var xOrigin       = linePosition.X;
                if (indexedGlyphRuns == null)
                {
                    return;
                }
                foreach (var glyphRunC in indexedGlyphRuns)
                {
                    var gl         = glyphRunC.GlyphRun;
                    var advanceSum = gl.AdvanceWidths.Sum();
                    var startCi    = curCi;
                    for (var i = 0; i < gl.Characters.Count; i++)
                    {
                        var i0             = gl.ClusterMap?[i] ?? i;
                        var glAdvanceWidth = gl.AdvanceWidths[i0];
                        var glCharacter    = gl.Characters[i];
                        var glCaretStop    = gl.CaretStops?[i0];
                        if (curCi != null && curLineInfo != null)
                        {
                            // ReSharper disable once PossibleInvalidOperationException
#pragma warning disable 8629
                            if (lineCharIndex + curLineInfo.Offset >= change.Value.Span.Start)
#pragma warning restore 8629
                            {
                                curCi.Value.Index        = textStorePosition + lineCharIndex;
                                curCi.Value.RunIndex     = i;
                                curCi.Value.Character    = glCharacter;
                                curCi.Value.AdvanceWidth = glAdvanceWidth;
                                curCi.Value.XOrigin      = xOrigin;
                                if (Math.Abs(curCi.Value.YOrigin - linePosition.Y) > 0.5)
                                {
                                    curCi.Value.YOrigin = linePosition.Y;
                                }
                            }
                            if (curCi.Value.RunIndex != i)
                            {
                                curCi.Value.RunIndex = i;
                            }
                            curCi = curCi.Next;
                        }
                        else
                        {
                            var ci = new CharInfo(lineNo, textStorePosition + lineCharIndex, lineCharIndex, i,
                                                  glCharacter, glAdvanceWidth,
                                                  glCaretStop, xOrigin, linePosition.Y);
                            allCharInfos.AddLast(ci);
                        }

                        lineCharIndex++;
                        xOrigin += glAdvanceWidth;
                    }

                    var item = new Rect(curPos, new Size(advanceSum, myTextLine.Height));
                    if (!moveNext)
                    {
                        StringBuilder sb = new StringBuilder();
                        for (var c = curCharInfoNode; c != null; c = c.Next)
                        {
                            sb.Append(c.Value.Character);
                        }

                        throw new CodeControlException("enumerator empty " + sb);
                    }

                    var enum1Current = enum1.Current;
                    var textRunInfo  = new TextRunInfo(enum1Current, item, startCi);
                    debugFn?.Invoke(textRunInfo.ToString(), 2);
                    runsInfos?.Add(textRunInfo);

                    curPos.X += advanceSum;
                }
            }

#pragma warning disable 8601
            lastCharInfoNode = allCharInfos.Last;
#pragma warning restore 8601
        }
 public SpaceTextElement(TextLine textLine)
     : base(textLine, 1)
 {
     BreakBefore = LineBreakCondition.BreakPossible;
     BreakAfter = LineBreakCondition.BreakDesired;
 }
		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;
			}
		}
 public SpecialCharacterBoxElement(TextLine text)
     : base(text, 1)
 {
 }
 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;
     }
 }
Ejemplo n.º 39
0
        // ------------------------------------------------------------------
        //  Hit tests to the correct ContentElement within the line.
        //
        //      offset - offset within the line.
        //
        // Returns: ContentElement which has been hit.
        // ------------------------------------------------------------------
        internal override IInputElement InputHitTest(double offset)
        {
            TextContainer      tree;
            DependencyObject   element;
            CharacterHit       charHit;
            TextPointer        position;
            TextPointerContext type = TextPointerContext.None;

            element = null;

            // We can only support hittesting text elements in a TextContainer.
            // If the TextContainer is not a TextContainer, return null which higher up the stack
            // will be converted into a reference to the control itself.
            tree = _owner.TextContainer as TextContainer;

            // Adjusted offset for shift due to trailing spaces rendering
            double delta = CalculateXOffsetShift();

            if (tree != null)
            {
                if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
                {
                    // We should not shift offset in this case
                    Invariant.Assert(DoubleUtil.AreClose(delta, 0));
                    System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
                    Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");

                    // Get TextPointer from specified distance.
                    charHit = line.GetCharacterHitFromDistance(offset);
                }
                else
                {
                    charHit = _line.GetCharacterHitFromDistance(offset - delta);
                }

                position = new TextPointer(_owner.ContentStart, CalcPositionOffset(charHit), LogicalDirection.Forward);

                if (position != null)
                {
                    if (charHit.TrailingLength == 0)
                    {
                        // Start of character. Look forward
                        type = position.GetPointerContext(LogicalDirection.Forward);
                    }
                    else
                    {
                        // End of character. Look backward
                        type = position.GetPointerContext(LogicalDirection.Backward);
                    }

                    // Get element only for Text & Start/End element, for all other positions
                    // return null (it means that the line owner has been hit).
                    if (type == TextPointerContext.Text || type == TextPointerContext.ElementEnd)
                    {
                        element = position.Parent as TextElement;
                    }
                    else if (type == TextPointerContext.ElementStart)
                    {
                        element = position.GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                    }
                }
            }

            return(element as IInputElement);
        }