Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Text / Line.cs / 1305600 / Line.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: Line.cs // // Description: Text line formatter. // // History: // 04/25/2003 : [....] - moving from Avalon branch. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.PtsHost; namespace MS.Internal.Text { // --------------------------------------------------------------------- // Text line formatter. // --------------------------------------------------------------------- internal abstract class Line : TextSource, IDisposable { // ------------------------------------------------------------------ // // IDisposable Implementation // // ----------------------------------------------------------------- #region IDisposable Implementation // ------------------------------------------------------------------ // Free all resources associated with the line. Prepare it for reuse. // ------------------------------------------------------------------ public void Dispose() { // Dispose text line if (_line != null) { _line.Dispose(); _line = null; } GC.SuppressFinalize(this); } #endregion IDisposable Implementation //------------------------------------------------------------------- // // Internal Methods // //-------------------------------------------------------------------- #region Internal Methods // ----------------------------------------------------------------- // Constructor. // // owner - owner of the line. // ----------------------------------------------------------------- internal Line(System.Windows.Controls.TextBlock owner) { _owner = owner; _textAlignment = owner.TextAlignment; _showParagraphEllipsis = false; _wrappingWidth = _owner.RenderSize.Width; } // ----------------------------------------------------------------- // Create and format text line. // // lineStartIndex - index of the first character in the line // width - wrapping width of the line // lineProperties - properties of the line // textRunCache - run cache used by text formatter // showParagraphEllipsis - true if paragraph ellipsis is shown // at the end of the line // ------------------------------------------------------------------ internal void Format(int dcp, double width, TextParagraphProperties lineProperties, TextLineBreak textLineBreak, TextRunCache textRunCache, bool showParagraphEllipsis) { #if TEXTPANELLAYOUTDEBUG TextPanelDebug.IncrementCounter("Line.Format", TextPanelDebug.Category.TextView); #endif _mirror = (lineProperties.FlowDirection == FlowDirection.RightToLeft); _dcp = dcp; _showParagraphEllipsis = showParagraphEllipsis; _wrappingWidth = width; _line = _owner.TextFormatter.FormatLine(this, dcp, width, lineProperties, textLineBreak, textRunCache); } // ----------------------------------------------------------------- // Arrange content of formatted line. // // vc - Visual collection of the parent. // lineOffset - Offset of the line. // ------------------------------------------------------------------ internal virtual void Arrange(VisualCollection vc, Vector lineOffset) { } // ------------------------------------------------------------------ // 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)); } // ------------------------------------------------------------------ // Retrieve bounds of an object/character at specified text position. // // characterIndex - position of an object/character // flowDirection - flow direction of object/character // // Returns: Bounds of an object/character. // ----------------------------------------------------------------- internal Rect GetBoundsFromTextPosition(int characterIndex, out FlowDirection flowDirection) { return GetBoundsFromPosition(characterIndex, 1, out flowDirection); } ////// Returns an ArrayList of rectangles (Rect) that form the bounds of the region specified between /// the start and end points /// /// /// int offset indicating the starting point of the region for which bounds are required /// /// Length in characters of the region for which bounds are required /// /// /// Offset of line in x direction, to be added to line bounds to get actual rectangle for line /// /// /// Offset of line in y direction, to be added to line bounds to get actual rectangle for line /// ////// 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. /// internal ListGetRangeBounds(int cp, int cch, double xOffset, double yOffset) { List rectangles = new List (); // Adjust x offset for trailing spaces double delta = CalculateXOffsetShift(); double adjustedXOffset = xOffset + delta; IList 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; } //------------------------------------------------------------------- // 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); } //-------------------------------------------------------------------- // Retrieve text position for next caret position // // index: CharacterHit for current position // // Returns: Text position index. //------------------------------------------------------------------- internal CharacterHit GetNextCaretCharacterHit(CharacterHit index) { return _line.GetNextCaretCharacterHit(index); } //-------------------------------------------------------------------- // Retrieve text position for previous caret position // // index: CharacterHit for current position // // Returns: Text position index. //-------------------------------------------------------------------- internal CharacterHit GetPreviousCaretCharacterHit(CharacterHit index) { return _line.GetPreviousCaretCharacterHit(index); } //------------------------------------------------------------------- // Retrieve text position for backspace caret position // // index: CharacterHit for current position // // Returns: Text position index. //-------------------------------------------------------------------- internal CharacterHit GetBackspaceCaretCharacterHit(CharacterHit index) { return _line.GetBackspaceCaretCharacterHit(index); } /// /// Returns true of char hit is at caret unit boundary. /// /// /// CharacterHit to be tested. /// internal bool IsAtCaretCharacterHit(CharacterHit charHit) { return _line.IsAtCaretCharacterHit(charHit, _dcp); } // ----------------------------------------------------------------- // Find out if there are any inline objects. // ----------------------------------------------------------------- internal virtual bool HasInlineObjects() { return false; } // ----------------------------------------------------------------- // Hit tests to the correct ContentElement within the line. // // offset - offset within the line. // // Returns: ContentElement which has been hit. // ------------------------------------------------------------------ internal virtual IInputElement InputHitTest(double offset) { return null; } ////// Passes linebreak object back up from contained line /// internal TextLineBreak GetTextLineBreak() { if(_line == null) { return null; } return _line.GetTextLineBreak(); } // ----------------------------------------------------------------- // 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"); IListcollapsedRanges = 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; } // ------------------------------------------------------------------ // 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; } #endregion Internal Methods //-------------------------------------------------------------------- // // Internal Properties // //------------------------------------------------------------------- #region Internal Properties // ----------------------------------------------------------------- // Calculated width of the line. // ----------------------------------------------------------------- internal double Width { get { if (IsWidthAdjusted) { // Trailing spaces add to width return _line.WidthIncludingTrailingWhitespace; } else { return _line.Width; } } } // ------------------------------------------------------------------ // Distance from the beginning of paragraph edge to the line edge. // ----------------------------------------------------------------- internal double Start { get { if (IsXOffsetAdjusted) { return _line.Start + CalculateXOffsetShift(); } else { return _line.Start; } } } // ------------------------------------------------------------------ // Height of the line; line advance distance. // ------------------------------------------------------------------ internal double Height { get { return _line.Height; } } // ----------------------------------------------------------------- // Distance from top to baseline of this text line. // ------------------------------------------------------------------ internal double BaselineOffset { get { return _line.Baseline; } } // ----------------------------------------------------------------- // Is this the last line of the paragraph? // ----------------------------------------------------------------- internal bool EndOfParagraph { get { // If there are no Newline characters, it is not the end of paragraph. if (_line.NewlineLength == 0) { return false; } // Since there are Newline characters in the line, do more expensive and // accurate check. IList > runs = _line.GetTextRunSpans(); return (((TextSpan )runs[runs.Count-1]).Value is TextEndOfParagraph); } } // ----------------------------------------------------------------- // Length of the line excluding any synthetic characters. // ------------------------------------------------------------------ internal int Length { get { return _line.Length - (EndOfParagraph ? _syntheticCharacterLength : 0); } } // ----------------------------------------------------------------- // Length of the line excluding any synthetic characters and line breaks. // ------------------------------------------------------------------ internal int ContentLength { get { return _line.Length - _line.NewlineLength; } } #endregion Internal Properties //-------------------------------------------------------------------- // // 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; 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 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; } // ----------------------------------------------------------------- // Get collapsing properties. // // wrappingWidth - wrapping width for collapsed line. // paraProperties - paragraph properties. // // Returns: Line collapsing properties. // ----------------------------------------------------------------- protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties) { Debug.Assert(paraProperties.TextTrimming != TextTrimming.None, "Text trimming must be enabled."); TextCollapsingProperties collapsingProps; if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis) { collapsingProps = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties); } else { collapsingProps = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties); } return collapsingProps; } /// /// Returns amount of shift for X-offset to render trailing spaces /// protected double CalculateXOffsetShift() { // Assert that textblock autosize is working correctly and that moving the offset back // will not result in the front of the line being taken off rendered area if (IsXOffsetAdjusted) { if (_textAlignment == TextAlignment.Center) { // Return trailing spaces length divided by two so line remains centered return (_line.Width - _line.WidthIncludingTrailingWhitespace) / 2; } else { return (_line.Width - _line.WidthIncludingTrailingWhitespace); } } else { return 0.0; } } #endregion Protected Methods //-------------------------------------------------------------------- // // Protected Properites // //------------------------------------------------------------------- #region Protected Properties ////// True if eliipsis is displayed in the line /// protected bool ShowEllipsis { get { if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None) { return false; } if (_line.HasOverflowed || _showParagraphEllipsis) { return true; } return false; } } ////// True if line ends in hard line break /// protected bool HasLineBreak { get { return (_line.NewlineLength > 0); } } ////// True if line's X-offset needs adjustment to render trailing spaces /// protected bool IsXOffsetAdjusted { get { return ((_textAlignment == TextAlignment.Right || _textAlignment == TextAlignment.Center) && IsWidthAdjusted); } } ////// True if line's width is adjusted to include trailing spaces. For right and center alignment we need to /// adjust line offset as well, but for left alignment we need to only make a width asjustment /// protected bool IsWidthAdjusted { get { bool adjusted = false; // Trailing spaces rendered only around hard breaks if (HasLineBreak || EndOfParagraph) { // Lines with ellipsis are not shifted because ellipsis would not appear after trailing spaces if (!ShowEllipsis) { adjusted = true; } } return adjusted; } } #endregion Protected Properties //-------------------------------------------------------------------- // // Private Fields // //-------------------------------------------------------------------- #region Private Fields // ----------------------------------------------------------------- // Owner of the line. // ------------------------------------------------------------------ protected System.Windows.Controls.TextBlock _owner; // ----------------------------------------------------------------- // Cached text line. // ----------------------------------------------------------------- protected System.Windows.Media.TextFormatting.TextLine _line; // ----------------------------------------------------------------- // Index of the first character in the line. // ------------------------------------------------------------------ protected int _dcp; // ----------------------------------------------------------------- // Synthetic character length. // ------------------------------------------------------------------ protected static int _syntheticCharacterLength = 1; // ------------------------------------------------------------------ // Is text mirrored? // ----------------------------------------------------------------- protected bool _mirror; ////// Alignment direction of line. Set during formatting. /// protected TextAlignment _textAlignment; ////// Does the line habe paragraph ellipsis. This is determined during formatting depending upon /// the type of line properties passed. /// protected bool _showParagraphEllipsis; ////// Wrapping width of line /// protected double _wrappingWidth; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: Line.cs // // Description: Text line formatter. // // History: // 04/25/2003 : [....] - moving from Avalon branch. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.PtsHost; namespace MS.Internal.Text { // --------------------------------------------------------------------- // Text line formatter. // --------------------------------------------------------------------- internal abstract class Line : TextSource, IDisposable { // ------------------------------------------------------------------ // // IDisposable Implementation // // ----------------------------------------------------------------- #region IDisposable Implementation // ------------------------------------------------------------------ // Free all resources associated with the line. Prepare it for reuse. // ------------------------------------------------------------------ public void Dispose() { // Dispose text line if (_line != null) { _line.Dispose(); _line = null; } GC.SuppressFinalize(this); } #endregion IDisposable Implementation //------------------------------------------------------------------- // // Internal Methods // //-------------------------------------------------------------------- #region Internal Methods // ----------------------------------------------------------------- // Constructor. // // owner - owner of the line. // ----------------------------------------------------------------- internal Line(System.Windows.Controls.TextBlock owner) { _owner = owner; _textAlignment = owner.TextAlignment; _showParagraphEllipsis = false; _wrappingWidth = _owner.RenderSize.Width; } // ----------------------------------------------------------------- // Create and format text line. // // lineStartIndex - index of the first character in the line // width - wrapping width of the line // lineProperties - properties of the line // textRunCache - run cache used by text formatter // showParagraphEllipsis - true if paragraph ellipsis is shown // at the end of the line // ------------------------------------------------------------------ internal void Format(int dcp, double width, TextParagraphProperties lineProperties, TextLineBreak textLineBreak, TextRunCache textRunCache, bool showParagraphEllipsis) { #if TEXTPANELLAYOUTDEBUG TextPanelDebug.IncrementCounter("Line.Format", TextPanelDebug.Category.TextView); #endif _mirror = (lineProperties.FlowDirection == FlowDirection.RightToLeft); _dcp = dcp; _showParagraphEllipsis = showParagraphEllipsis; _wrappingWidth = width; _line = _owner.TextFormatter.FormatLine(this, dcp, width, lineProperties, textLineBreak, textRunCache); } // ----------------------------------------------------------------- // Arrange content of formatted line. // // vc - Visual collection of the parent. // lineOffset - Offset of the line. // ------------------------------------------------------------------ internal virtual void Arrange(VisualCollection vc, Vector lineOffset) { } // ------------------------------------------------------------------ // 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)); } // ------------------------------------------------------------------ // Retrieve bounds of an object/character at specified text position. // // characterIndex - position of an object/character // flowDirection - flow direction of object/character // // Returns: Bounds of an object/character. // ----------------------------------------------------------------- internal Rect GetBoundsFromTextPosition(int characterIndex, out FlowDirection flowDirection) { return GetBoundsFromPosition(characterIndex, 1, out flowDirection); } ////// Returns an ArrayList of rectangles (Rect) that form the bounds of the region specified between /// the start and end points /// /// /// int offset indicating the starting point of the region for which bounds are required /// /// Length in characters of the region for which bounds are required /// /// /// Offset of line in x direction, to be added to line bounds to get actual rectangle for line /// /// /// Offset of line in y direction, to be added to line bounds to get actual rectangle for line /// ////// 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. /// internal ListGetRangeBounds(int cp, int cch, double xOffset, double yOffset) { List rectangles = new List (); // Adjust x offset for trailing spaces double delta = CalculateXOffsetShift(); double adjustedXOffset = xOffset + delta; IList 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; } //------------------------------------------------------------------- // 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); } //-------------------------------------------------------------------- // Retrieve text position for next caret position // // index: CharacterHit for current position // // Returns: Text position index. //------------------------------------------------------------------- internal CharacterHit GetNextCaretCharacterHit(CharacterHit index) { return _line.GetNextCaretCharacterHit(index); } //-------------------------------------------------------------------- // Retrieve text position for previous caret position // // index: CharacterHit for current position // // Returns: Text position index. //-------------------------------------------------------------------- internal CharacterHit GetPreviousCaretCharacterHit(CharacterHit index) { return _line.GetPreviousCaretCharacterHit(index); } //------------------------------------------------------------------- // Retrieve text position for backspace caret position // // index: CharacterHit for current position // // Returns: Text position index. //-------------------------------------------------------------------- internal CharacterHit GetBackspaceCaretCharacterHit(CharacterHit index) { return _line.GetBackspaceCaretCharacterHit(index); } /// /// Returns true of char hit is at caret unit boundary. /// /// /// CharacterHit to be tested. /// internal bool IsAtCaretCharacterHit(CharacterHit charHit) { return _line.IsAtCaretCharacterHit(charHit, _dcp); } // ----------------------------------------------------------------- // Find out if there are any inline objects. // ----------------------------------------------------------------- internal virtual bool HasInlineObjects() { return false; } // ----------------------------------------------------------------- // Hit tests to the correct ContentElement within the line. // // offset - offset within the line. // // Returns: ContentElement which has been hit. // ------------------------------------------------------------------ internal virtual IInputElement InputHitTest(double offset) { return null; } ////// Passes linebreak object back up from contained line /// internal TextLineBreak GetTextLineBreak() { if(_line == null) { return null; } return _line.GetTextLineBreak(); } // ----------------------------------------------------------------- // 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"); IListcollapsedRanges = 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; } // ------------------------------------------------------------------ // 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; } #endregion Internal Methods //-------------------------------------------------------------------- // // Internal Properties // //------------------------------------------------------------------- #region Internal Properties // ----------------------------------------------------------------- // Calculated width of the line. // ----------------------------------------------------------------- internal double Width { get { if (IsWidthAdjusted) { // Trailing spaces add to width return _line.WidthIncludingTrailingWhitespace; } else { return _line.Width; } } } // ------------------------------------------------------------------ // Distance from the beginning of paragraph edge to the line edge. // ----------------------------------------------------------------- internal double Start { get { if (IsXOffsetAdjusted) { return _line.Start + CalculateXOffsetShift(); } else { return _line.Start; } } } // ------------------------------------------------------------------ // Height of the line; line advance distance. // ------------------------------------------------------------------ internal double Height { get { return _line.Height; } } // ----------------------------------------------------------------- // Distance from top to baseline of this text line. // ------------------------------------------------------------------ internal double BaselineOffset { get { return _line.Baseline; } } // ----------------------------------------------------------------- // Is this the last line of the paragraph? // ----------------------------------------------------------------- internal bool EndOfParagraph { get { // If there are no Newline characters, it is not the end of paragraph. if (_line.NewlineLength == 0) { return false; } // Since there are Newline characters in the line, do more expensive and // accurate check. IList > runs = _line.GetTextRunSpans(); return (((TextSpan )runs[runs.Count-1]).Value is TextEndOfParagraph); } } // ----------------------------------------------------------------- // Length of the line excluding any synthetic characters. // ------------------------------------------------------------------ internal int Length { get { return _line.Length - (EndOfParagraph ? _syntheticCharacterLength : 0); } } // ----------------------------------------------------------------- // Length of the line excluding any synthetic characters and line breaks. // ------------------------------------------------------------------ internal int ContentLength { get { return _line.Length - _line.NewlineLength; } } #endregion Internal Properties //-------------------------------------------------------------------- // // 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; 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 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; } // ----------------------------------------------------------------- // Get collapsing properties. // // wrappingWidth - wrapping width for collapsed line. // paraProperties - paragraph properties. // // Returns: Line collapsing properties. // ----------------------------------------------------------------- protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties) { Debug.Assert(paraProperties.TextTrimming != TextTrimming.None, "Text trimming must be enabled."); TextCollapsingProperties collapsingProps; if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis) { collapsingProps = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties); } else { collapsingProps = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties); } return collapsingProps; } /// /// Returns amount of shift for X-offset to render trailing spaces /// protected double CalculateXOffsetShift() { // Assert that textblock autosize is working correctly and that moving the offset back // will not result in the front of the line being taken off rendered area if (IsXOffsetAdjusted) { if (_textAlignment == TextAlignment.Center) { // Return trailing spaces length divided by two so line remains centered return (_line.Width - _line.WidthIncludingTrailingWhitespace) / 2; } else { return (_line.Width - _line.WidthIncludingTrailingWhitespace); } } else { return 0.0; } } #endregion Protected Methods //-------------------------------------------------------------------- // // Protected Properites // //------------------------------------------------------------------- #region Protected Properties ////// True if eliipsis is displayed in the line /// protected bool ShowEllipsis { get { if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None) { return false; } if (_line.HasOverflowed || _showParagraphEllipsis) { return true; } return false; } } ////// True if line ends in hard line break /// protected bool HasLineBreak { get { return (_line.NewlineLength > 0); } } ////// True if line's X-offset needs adjustment to render trailing spaces /// protected bool IsXOffsetAdjusted { get { return ((_textAlignment == TextAlignment.Right || _textAlignment == TextAlignment.Center) && IsWidthAdjusted); } } ////// True if line's width is adjusted to include trailing spaces. For right and center alignment we need to /// adjust line offset as well, but for left alignment we need to only make a width asjustment /// protected bool IsWidthAdjusted { get { bool adjusted = false; // Trailing spaces rendered only around hard breaks if (HasLineBreak || EndOfParagraph) { // Lines with ellipsis are not shifted because ellipsis would not appear after trailing spaces if (!ShowEllipsis) { adjusted = true; } } return adjusted; } } #endregion Protected Properties //-------------------------------------------------------------------- // // Private Fields // //-------------------------------------------------------------------- #region Private Fields // ----------------------------------------------------------------- // Owner of the line. // ------------------------------------------------------------------ protected System.Windows.Controls.TextBlock _owner; // ----------------------------------------------------------------- // Cached text line. // ----------------------------------------------------------------- protected System.Windows.Media.TextFormatting.TextLine _line; // ----------------------------------------------------------------- // Index of the first character in the line. // ------------------------------------------------------------------ protected int _dcp; // ----------------------------------------------------------------- // Synthetic character length. // ------------------------------------------------------------------ protected static int _syntheticCharacterLength = 1; // ------------------------------------------------------------------ // Is text mirrored? // ----------------------------------------------------------------- protected bool _mirror; ////// Alignment direction of line. Set during formatting. /// protected TextAlignment _textAlignment; ////// Does the line habe paragraph ellipsis. This is determined during formatting depending upon /// the type of line properties passed. /// protected bool _showParagraphEllipsis; ////// Wrapping width of line /// protected double _wrappingWidth; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EntityViewGenerator.cs
- ZipIOModeEnforcingStream.cs
- XmlAnyAttributeAttribute.cs
- PrintDialog.cs
- ProtocolsConfigurationEntry.cs
- WeakEventTable.cs
- PropertyTabAttribute.cs
- StateValidator.cs
- ContentValidator.cs
- ComNativeDescriptor.cs
- DynamicPropertyHolder.cs
- UnsafeNativeMethods.cs
- PermissionSetEnumerator.cs
- MultiDataTrigger.cs
- WindowsGrip.cs
- TextRunCache.cs
- FilterableAttribute.cs
- DataRelationPropertyDescriptor.cs
- _AutoWebProxyScriptHelper.cs
- PageAdapter.cs
- log.cs
- AppDomainFactory.cs
- SafeEventLogWriteHandle.cs
- WebServiceHostFactory.cs
- JsonUriDataContract.cs
- UnicodeEncoding.cs
- GeneralTransform2DTo3DTo2D.cs
- URLIdentityPermission.cs
- DecimalAnimationBase.cs
- XsltContext.cs
- ClockController.cs
- DBSchemaTable.cs
- WebPartEventArgs.cs
- SqlUserDefinedTypeAttribute.cs
- CheckBoxAutomationPeer.cs
- Configuration.cs
- ReverseQueryOperator.cs
- Int64Storage.cs
- DataTableTypeConverter.cs
- CoTaskMemHandle.cs
- ActiveDocumentEvent.cs
- SMSvcHost.cs
- SubMenuStyleCollection.cs
- WindowsScrollBar.cs
- CompilationPass2TaskInternal.cs
- EventMemberCodeDomSerializer.cs
- ControlPaint.cs
- RtfFormatStack.cs
- RunWorkerCompletedEventArgs.cs
- ObjectHandle.cs
- ExtenderControl.cs
- COM2ColorConverter.cs
- RotationValidation.cs
- Tuple.cs
- ToolStripLocationCancelEventArgs.cs
- RootNamespaceAttribute.cs
- HWStack.cs
- SchemaMapping.cs
- Popup.cs
- XmlWriterSettings.cs
- PlaceHolder.cs
- LayoutSettings.cs
- NotImplementedException.cs
- FontCacheLogic.cs
- KnownBoxes.cs
- BrushValueSerializer.cs
- DefaultDiscoveryService.cs
- _TimerThread.cs
- ToolZone.cs
- ConcurrentBag.cs
- CodeDefaultValueExpression.cs
- ProcessRequestArgs.cs
- Ray3DHitTestResult.cs
- sortedlist.cs
- EventRecord.cs
- ClientTargetSection.cs
- _LazyAsyncResult.cs
- XhtmlBasicPageAdapter.cs
- TaskHelper.cs
- GlobalProxySelection.cs
- ConfigurationValues.cs
- EditCommandColumn.cs
- HtmlButton.cs
- DbConnectionInternal.cs
- EntityDataSourceQueryBuilder.cs
- JulianCalendar.cs
- TransformGroup.cs
- CryptoApi.cs
- DynamicDataResources.Designer.cs
- ServiceReflector.cs
- SqlFacetAttribute.cs
- DocumentViewerAutomationPeer.cs
- DesignerFrame.cs
- DataGridViewCellCollection.cs
- WsatServiceAddress.cs
- WaitHandle.cs
- SchemaLookupTable.cs
- HybridObjectCache.cs
- ConstrainedDataObject.cs
- CalloutQueueItem.cs