Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / documents / DocumentPageTextView.cs / 1305600 / DocumentPageTextView.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// File: DocumentPageTextView.cs
//
// Description: TextView implementation for DocumentPageView.
//
//---------------------------------------------------------------------------
using System; // InvalidOperationException, ...
using System.Collections.Generic; // List
using System.Collections.ObjectModel; // ReadOnlyCollection
using System.Windows; // Point, Rect, ...
using System.Windows.Controls.Primitives; // DocumentPageView
using System.Windows.Documents; // ITextView, ITextContainer
using System.Windows.Media; // VisualTreeHelper
using MS.Internal.PtsHost; // BackgroundFormatInfo
namespace MS.Internal.Documents
{
///
/// TextView implementation for DocumentPageView.
///
internal class DocumentPageTextView : TextViewBase
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Constructor.
///
///
/// Root of layout structure visualizing content of a page.
///
///
/// TextContainer representing content.
///
internal DocumentPageTextView(DocumentPageView owner, ITextContainer textContainer)
{
Invariant.Assert(owner != null && textContainer != null);
_owner = owner;
_page = owner.DocumentPageInternal;
_textContainer = textContainer;
// Retrive inner TextView
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
}
///
/// Constructor.
///
///
/// Root of layout structure visualizing content of a page.
///
///
/// TextContainer representing content.
///
internal DocumentPageTextView(FlowDocumentView owner, ITextContainer textContainer)
{
Invariant.Assert(owner != null && textContainer != null);
_owner = owner;
_page = owner.DocumentPage;
_textContainer = textContainer;
// Retrive inner TextView
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
///
///
///
internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
// Transform to page coordinates.
point = TransformToDescendant(point);
return _pageTextView.GetTextPositionFromPoint(point, snapToText);
}
///
///
///
internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
{
Rect rect;
Transform pageTextViewTransform, ancestorTransform;
// Initialize transform to identity
transform = Transform.Identity;
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return Rect.Empty;
}
rect = _pageTextView.GetRawRectangleFromTextPosition(position, out pageTextViewTransform);
Invariant.Assert(pageTextViewTransform != null);
ancestorTransform = GetTransformToAncestor();
transform = GetAggregateTransform(pageTextViewTransform, ancestorTransform);
return rect;
}
///
///
///
internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition)
{
// verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
Geometry geometry = null;
if (!IsPageMissing)
{
geometry = _pageTextView.GetTightBoundingGeometryFromTextPositions(startPosition, endPosition);
if (geometry != null)
{
Transform transform = GetTransformToAncestor().AffineTransform;
CaretElement.AddTransformToGeometry(geometry, transform);
}
}
return (geometry);
}
///
///
///
internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
{
ITextPointer positionOut;
Point offset;
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
newSuggestedX = suggestedX;
linesMoved = 0;
return position;
}
offset = TransformToDescendant(new Point(suggestedX, 0));
suggestedX = offset.X;
positionOut = _pageTextView.GetPositionAtNextLine(position, suggestedX, count, out newSuggestedX, out linesMoved);
offset = TransformToAncestor(new Point(newSuggestedX, 0));
newSuggestedX = offset.X;
return positionOut;
}
///
///
///
internal override ITextPointer GetPositionAtNextPage(ITextPointer position, Point suggestedOffset, int count, out Point newSuggestedOffset, out int pagesMoved)
{
ITextPointer positionOut = position;
newSuggestedOffset = suggestedOffset;
Point offset = suggestedOffset;
pagesMoved = 0;
if (count == 0)
{
return positionOut;
}
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return position;
}
// Calculate distance from current position
offset.Y = GetYOffsetAtNextPage(offset.Y, count, out pagesMoved);
if (pagesMoved != 0)
{
// Transfrom offset to _pageTextView's coordinate position, obtain position from _pageTextView and convert back
offset = TransformToDescendant(offset);
positionOut = _pageTextView.GetTextPositionFromPoint(offset, true);
Invariant.Assert(positionOut != null);
Rect rect = _pageTextView.GetRectangleFromTextPosition(position);
newSuggestedOffset = TransformToAncestor(new Point(rect.X, rect.Y));
}
return positionOut;
}
///
///
///
internal override bool IsAtCaretUnitBoundary(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return false;
}
return _pageTextView.IsAtCaretUnitBoundary(position);
}
///
///
///
internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
return _pageTextView.GetNextCaretUnitPosition(position, direction);
}
///
///
///
internal override ITextPointer GetBackspaceCaretUnitPosition(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
return _pageTextView.GetBackspaceCaretUnitPosition(position);
}
///
///
///
internal override TextSegment GetLineRange(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return TextSegment.Null;
}
return _pageTextView.GetLineRange(position);
}
///
///
///
internal override ReadOnlyCollection GetGlyphRuns(ITextPointer start, ITextPointer end)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return new ReadOnlyCollection(new List());
}
return _pageTextView.GetGlyphRuns(start, end);
}
///
///
///
internal override bool Contains(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return false;
}
return _pageTextView.Contains(position);
}
///
/// Handler for PageConnected raised by the DocumentPageView.
///
internal void OnPageConnected()
{
OnPageDisconnected();
if (_owner is DocumentPageView)
{
_page = ((DocumentPageView)_owner).DocumentPageInternal;
}
else if (_owner is FlowDocumentView)
{
_page = ((FlowDocumentView)_owner).DocumentPage;
}
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
if (IsValid)
{
OnUpdated(EventArgs.Empty);
}
}
///
/// Handler for PageDisconnected raised by the DocumentPageView.
///
internal void OnPageDisconnected()
{
if (_pageTextView != null)
{
_pageTextView.Updated -= new EventHandler(HandlePageTextViewUpdated);
}
_pageTextView = null;
_page = null;
}
///
/// Handler for TransformChanged raised by the DocumentPageView.
///
internal void OnTransformChanged()
{
if (IsValid)
{
OnUpdated(EventArgs.Empty);
}
}
///
///
///
internal override bool Validate()
{
if (!_owner.IsMeasureValid || !_owner.IsArrangeValid)
{
_owner.UpdateLayout();
}
return (_pageTextView != null && _pageTextView.Validate());
}
///
///
///
internal override bool Validate(ITextPointer position)
{
FlowDocumentView owner = _owner as FlowDocumentView;
bool isValid;
if (owner == null || owner.Document == null)
{
isValid = base.Validate(position);
}
else
{
if (Validate())
{
BackgroundFormatInfo backgroundFormatInfo = owner.Document.StructuralCache.BackgroundFormatInfo;
FlowDocumentFormatter formatter = owner.Document.BottomlessFormatter;
int lastCPInterrupted = -1;
while (this.IsValid && !Contains(position))
{
backgroundFormatInfo.BackgroundFormat(formatter, true /* ignoreThrottle */);
_owner.UpdateLayout(); // May invalidate the view.
// Break if background layout is not progressing.
// There are some edge cases where Validate() == true, but background
// layout will not progress (such as collapsed text in a tree view).
if (backgroundFormatInfo.CPInterrupted <= lastCPInterrupted)
{
// CPInterrupted is reset to -1 when background layout finishes, so
// check explicitly below to see if the position is valid or not.
break;
}
lastCPInterrupted = backgroundFormatInfo.CPInterrupted;
}
}
isValid = this.IsValid && Contains(position);
}
return isValid;
}
///
///
///
internal override void ThrottleBackgroundTasksForUserInput()
{
FlowDocumentView owner = _owner as FlowDocumentView;
if (owner != null && owner.Document != null)
{
owner.Document.StructuralCache.ThrottleBackgroundFormatting();
}
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
///
///
///
internal override UIElement RenderScope
{
get { return _owner; }
}
///
///
///
internal override ITextContainer TextContainer
{
get { return _textContainer; }
}
///
///
///
internal override bool IsValid
{
get
{
if (!_owner.IsMeasureValid || !_owner.IsArrangeValid || _page == null)
{
return false;
}
if (IsPageMissing)
{
return true;
}
return (_pageTextView != null && _pageTextView.IsValid);
}
}
///
///
///
internal override bool RendersOwnSelection
{
get
{
if (_pageTextView != null)
{
return _pageTextView.RendersOwnSelection;
}
return false;
}
}
///
///
///
internal override ReadOnlyCollection TextSegments
{
get
{
if (!IsValid || IsPageMissing)
{
return new ReadOnlyCollection(new List());
}
return _pageTextView.TextSegments;
}
}
///
/// DocumentPageView associated with this TextView.
///
internal DocumentPageView DocumentPageView
{
get { return _owner as DocumentPageView; }
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------
#region Private Methods
///
/// Handler for Updated event raised by the inner TextView.
///
private void HandlePageTextViewUpdated(object sender, EventArgs e)
{
Invariant.Assert(_pageTextView != null);
if (sender == _pageTextView)
{
OnUpdated(EventArgs.Empty);
}
}
///
/// Gets transform to ancestor
///
private Transform GetTransformToAncestor()
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
Transform transform = _page.Visual.TransformToAncestor(_owner) as Transform;
if (transform == null)
{
transform = Transform.Identity;
}
return transform;
}
///
/// Transforms point from inner scope.
///
private Point TransformToAncestor(Point point)
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = _page.Visual.TransformToAncestor(_owner);
if (transform != null)
{
point = transform.Transform(point);
}
return point;
}
///
/// Transforms rectangle from inner scope
///
private Point TransformToDescendant(Point point)
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = _page.Visual.TransformToAncestor(_owner);
if (transform != null)
{
transform = transform.Inverse;
if (transform != null)
{
point = transform.Transform(point);
}
}
return point;
}
///
/// Gets updated offset at next page
///
///
/// Current value of offset
///
/// Number of pages to move
///
///
/// Number of pages actually moved
///
private double GetYOffsetAtNextPage(double offset, int count, out int pagesMoved)
{
double newOffset = offset;
pagesMoved = 0;
if (_owner is IScrollInfo && ((IScrollInfo)_owner).ScrollOwner != null)
{
IScrollInfo scrollInfo = (IScrollInfo)_owner;
double viewportHeight = scrollInfo.ViewportHeight;
double extentHeight = scrollInfo.ExtentHeight;
if (count > 0)
{
while (pagesMoved < count)
{
if (DoubleUtil.LessThanOrClose(offset + viewportHeight, extentHeight))
{
newOffset += viewportHeight;
pagesMoved++;
}
else
{
break;
}
}
}
else
{
while (Math.Abs(pagesMoved) < Math.Abs(count))
{
if (DoubleUtil.GreaterThanOrClose(offset - viewportHeight, 0))
{
newOffset -= viewportHeight;
pagesMoved--;
}
else
{
break;
}
}
}
}
return newOffset;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Properties
//
//-------------------------------------------------------------------
#region Private Properties
///
/// Whether page is missing.
///
private bool IsPageMissing
{
get { return (_page == DocumentPage.Missing); }
}
#endregion Private Properties
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
///
/// Root of layout structure visualizing content.
///
private readonly UIElement _owner;
///
/// TextContainer representing content.
///
private readonly ITextContainer _textContainer;
///
/// DocumentPage associated with this view.
///
private DocumentPage _page;
///
/// TextView associated with DocumentPage.
///
private ITextView _pageTextView;
#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: DocumentPageTextView.cs
//
// Description: TextView implementation for DocumentPageView.
//
//---------------------------------------------------------------------------
using System; // InvalidOperationException, ...
using System.Collections.Generic; // List
using System.Collections.ObjectModel; // ReadOnlyCollection
using System.Windows; // Point, Rect, ...
using System.Windows.Controls.Primitives; // DocumentPageView
using System.Windows.Documents; // ITextView, ITextContainer
using System.Windows.Media; // VisualTreeHelper
using MS.Internal.PtsHost; // BackgroundFormatInfo
namespace MS.Internal.Documents
{
///
/// TextView implementation for DocumentPageView.
///
internal class DocumentPageTextView : TextViewBase
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Constructor.
///
///
/// Root of layout structure visualizing content of a page.
///
///
/// TextContainer representing content.
///
internal DocumentPageTextView(DocumentPageView owner, ITextContainer textContainer)
{
Invariant.Assert(owner != null && textContainer != null);
_owner = owner;
_page = owner.DocumentPageInternal;
_textContainer = textContainer;
// Retrive inner TextView
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
}
///
/// Constructor.
///
///
/// Root of layout structure visualizing content of a page.
///
///
/// TextContainer representing content.
///
internal DocumentPageTextView(FlowDocumentView owner, ITextContainer textContainer)
{
Invariant.Assert(owner != null && textContainer != null);
_owner = owner;
_page = owner.DocumentPage;
_textContainer = textContainer;
// Retrive inner TextView
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
///
///
///
internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
// Transform to page coordinates.
point = TransformToDescendant(point);
return _pageTextView.GetTextPositionFromPoint(point, snapToText);
}
///
///
///
internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
{
Rect rect;
Transform pageTextViewTransform, ancestorTransform;
// Initialize transform to identity
transform = Transform.Identity;
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return Rect.Empty;
}
rect = _pageTextView.GetRawRectangleFromTextPosition(position, out pageTextViewTransform);
Invariant.Assert(pageTextViewTransform != null);
ancestorTransform = GetTransformToAncestor();
transform = GetAggregateTransform(pageTextViewTransform, ancestorTransform);
return rect;
}
///
///
///
internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition)
{
// verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
Geometry geometry = null;
if (!IsPageMissing)
{
geometry = _pageTextView.GetTightBoundingGeometryFromTextPositions(startPosition, endPosition);
if (geometry != null)
{
Transform transform = GetTransformToAncestor().AffineTransform;
CaretElement.AddTransformToGeometry(geometry, transform);
}
}
return (geometry);
}
///
///
///
internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
{
ITextPointer positionOut;
Point offset;
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
newSuggestedX = suggestedX;
linesMoved = 0;
return position;
}
offset = TransformToDescendant(new Point(suggestedX, 0));
suggestedX = offset.X;
positionOut = _pageTextView.GetPositionAtNextLine(position, suggestedX, count, out newSuggestedX, out linesMoved);
offset = TransformToAncestor(new Point(newSuggestedX, 0));
newSuggestedX = offset.X;
return positionOut;
}
///
///
///
internal override ITextPointer GetPositionAtNextPage(ITextPointer position, Point suggestedOffset, int count, out Point newSuggestedOffset, out int pagesMoved)
{
ITextPointer positionOut = position;
newSuggestedOffset = suggestedOffset;
Point offset = suggestedOffset;
pagesMoved = 0;
if (count == 0)
{
return positionOut;
}
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return position;
}
// Calculate distance from current position
offset.Y = GetYOffsetAtNextPage(offset.Y, count, out pagesMoved);
if (pagesMoved != 0)
{
// Transfrom offset to _pageTextView's coordinate position, obtain position from _pageTextView and convert back
offset = TransformToDescendant(offset);
positionOut = _pageTextView.GetTextPositionFromPoint(offset, true);
Invariant.Assert(positionOut != null);
Rect rect = _pageTextView.GetRectangleFromTextPosition(position);
newSuggestedOffset = TransformToAncestor(new Point(rect.X, rect.Y));
}
return positionOut;
}
///
///
///
internal override bool IsAtCaretUnitBoundary(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return false;
}
return _pageTextView.IsAtCaretUnitBoundary(position);
}
///
///
///
internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
return _pageTextView.GetNextCaretUnitPosition(position, direction);
}
///
///
///
internal override ITextPointer GetBackspaceCaretUnitPosition(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return null;
}
return _pageTextView.GetBackspaceCaretUnitPosition(position);
}
///
///
///
internal override TextSegment GetLineRange(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return TextSegment.Null;
}
return _pageTextView.GetLineRange(position);
}
///
///
///
internal override ReadOnlyCollection GetGlyphRuns(ITextPointer start, ITextPointer end)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return new ReadOnlyCollection(new List());
}
return _pageTextView.GetGlyphRuns(start, end);
}
///
///
///
internal override bool Contains(ITextPointer position)
{
// Verify that layout information is valid. Cannot continue if not valid.
if (!IsValid)
{
throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
}
if (IsPageMissing)
{
return false;
}
return _pageTextView.Contains(position);
}
///
/// Handler for PageConnected raised by the DocumentPageView.
///
internal void OnPageConnected()
{
OnPageDisconnected();
if (_owner is DocumentPageView)
{
_page = ((DocumentPageView)_owner).DocumentPageInternal;
}
else if (_owner is FlowDocumentView)
{
_page = ((FlowDocumentView)_owner).DocumentPage;
}
if (_page is IServiceProvider)
{
_pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView;
}
if (_pageTextView != null)
{
_pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
}
if (IsValid)
{
OnUpdated(EventArgs.Empty);
}
}
///
/// Handler for PageDisconnected raised by the DocumentPageView.
///
internal void OnPageDisconnected()
{
if (_pageTextView != null)
{
_pageTextView.Updated -= new EventHandler(HandlePageTextViewUpdated);
}
_pageTextView = null;
_page = null;
}
///
/// Handler for TransformChanged raised by the DocumentPageView.
///
internal void OnTransformChanged()
{
if (IsValid)
{
OnUpdated(EventArgs.Empty);
}
}
///
///
///
internal override bool Validate()
{
if (!_owner.IsMeasureValid || !_owner.IsArrangeValid)
{
_owner.UpdateLayout();
}
return (_pageTextView != null && _pageTextView.Validate());
}
///
///
///
internal override bool Validate(ITextPointer position)
{
FlowDocumentView owner = _owner as FlowDocumentView;
bool isValid;
if (owner == null || owner.Document == null)
{
isValid = base.Validate(position);
}
else
{
if (Validate())
{
BackgroundFormatInfo backgroundFormatInfo = owner.Document.StructuralCache.BackgroundFormatInfo;
FlowDocumentFormatter formatter = owner.Document.BottomlessFormatter;
int lastCPInterrupted = -1;
while (this.IsValid && !Contains(position))
{
backgroundFormatInfo.BackgroundFormat(formatter, true /* ignoreThrottle */);
_owner.UpdateLayout(); // May invalidate the view.
// Break if background layout is not progressing.
// There are some edge cases where Validate() == true, but background
// layout will not progress (such as collapsed text in a tree view).
if (backgroundFormatInfo.CPInterrupted <= lastCPInterrupted)
{
// CPInterrupted is reset to -1 when background layout finishes, so
// check explicitly below to see if the position is valid or not.
break;
}
lastCPInterrupted = backgroundFormatInfo.CPInterrupted;
}
}
isValid = this.IsValid && Contains(position);
}
return isValid;
}
///
///
///
internal override void ThrottleBackgroundTasksForUserInput()
{
FlowDocumentView owner = _owner as FlowDocumentView;
if (owner != null && owner.Document != null)
{
owner.Document.StructuralCache.ThrottleBackgroundFormatting();
}
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
///
///
///
internal override UIElement RenderScope
{
get { return _owner; }
}
///
///
///
internal override ITextContainer TextContainer
{
get { return _textContainer; }
}
///
///
///
internal override bool IsValid
{
get
{
if (!_owner.IsMeasureValid || !_owner.IsArrangeValid || _page == null)
{
return false;
}
if (IsPageMissing)
{
return true;
}
return (_pageTextView != null && _pageTextView.IsValid);
}
}
///
///
///
internal override bool RendersOwnSelection
{
get
{
if (_pageTextView != null)
{
return _pageTextView.RendersOwnSelection;
}
return false;
}
}
///
///
///
internal override ReadOnlyCollection TextSegments
{
get
{
if (!IsValid || IsPageMissing)
{
return new ReadOnlyCollection(new List());
}
return _pageTextView.TextSegments;
}
}
///
/// DocumentPageView associated with this TextView.
///
internal DocumentPageView DocumentPageView
{
get { return _owner as DocumentPageView; }
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------
#region Private Methods
///
/// Handler for Updated event raised by the inner TextView.
///
private void HandlePageTextViewUpdated(object sender, EventArgs e)
{
Invariant.Assert(_pageTextView != null);
if (sender == _pageTextView)
{
OnUpdated(EventArgs.Empty);
}
}
///
/// Gets transform to ancestor
///
private Transform GetTransformToAncestor()
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
Transform transform = _page.Visual.TransformToAncestor(_owner) as Transform;
if (transform == null)
{
transform = Transform.Identity;
}
return transform;
}
///
/// Transforms point from inner scope.
///
private Point TransformToAncestor(Point point)
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = _page.Visual.TransformToAncestor(_owner);
if (transform != null)
{
point = transform.Transform(point);
}
return point;
}
///
/// Transforms rectangle from inner scope
///
private Point TransformToDescendant(Point point)
{
Invariant.Assert(IsValid && !IsPageMissing);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = _page.Visual.TransformToAncestor(_owner);
if (transform != null)
{
transform = transform.Inverse;
if (transform != null)
{
point = transform.Transform(point);
}
}
return point;
}
///
/// Gets updated offset at next page
///
///
/// Current value of offset
///
/// Number of pages to move
///
///
/// Number of pages actually moved
///
private double GetYOffsetAtNextPage(double offset, int count, out int pagesMoved)
{
double newOffset = offset;
pagesMoved = 0;
if (_owner is IScrollInfo && ((IScrollInfo)_owner).ScrollOwner != null)
{
IScrollInfo scrollInfo = (IScrollInfo)_owner;
double viewportHeight = scrollInfo.ViewportHeight;
double extentHeight = scrollInfo.ExtentHeight;
if (count > 0)
{
while (pagesMoved < count)
{
if (DoubleUtil.LessThanOrClose(offset + viewportHeight, extentHeight))
{
newOffset += viewportHeight;
pagesMoved++;
}
else
{
break;
}
}
}
else
{
while (Math.Abs(pagesMoved) < Math.Abs(count))
{
if (DoubleUtil.GreaterThanOrClose(offset - viewportHeight, 0))
{
newOffset -= viewportHeight;
pagesMoved--;
}
else
{
break;
}
}
}
}
return newOffset;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Properties
//
//-------------------------------------------------------------------
#region Private Properties
///
/// Whether page is missing.
///
private bool IsPageMissing
{
get { return (_page == DocumentPage.Missing); }
}
#endregion Private Properties
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
///
/// Root of layout structure visualizing content.
///
private readonly UIElement _owner;
///
/// TextContainer representing content.
///
private readonly ITextContainer _textContainer;
///
/// DocumentPage associated with this view.
///
private DocumentPage _page;
///
/// TextView associated with DocumentPage.
///
private ITextView _pageTextView;
#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
- CheckBox.cs
- HTTPNotFoundHandler.cs
- OleDbReferenceCollection.cs
- DrawingAttributesDefaultValueFactory.cs
- DataBoundLiteralControl.cs
- XmlDomTextWriter.cs
- SspiNegotiationTokenAuthenticatorState.cs
- CommandPlan.cs
- RuntimeConfigLKG.cs
- EdmFunction.cs
- MyContact.cs
- ContentTextAutomationPeer.cs
- IxmlLineInfo.cs
- XmlSchemaInclude.cs
- RoutedEventValueSerializer.cs
- RedirectionProxy.cs
- ResourceReferenceKeyNotFoundException.cs
- ArraySubsetEnumerator.cs
- ThicknessAnimationUsingKeyFrames.cs
- connectionpool.cs
- XmlException.cs
- configsystem.cs
- StaticExtensionConverter.cs
- LinkButton.cs
- DataGridRow.cs
- QuinticEase.cs
- NonParentingControl.cs
- GenericFlowSwitchHelper.cs
- GeometryModel3D.cs
- TypeInfo.cs
- FullTrustAssembly.cs
- PermissionRequestEvidence.cs
- UrlParameterReader.cs
- RoleService.cs
- PerformanceCounters.cs
- SafeArrayTypeMismatchException.cs
- DetailsView.cs
- DataGridViewMethods.cs
- CodeSubDirectory.cs
- SweepDirectionValidation.cs
- RepeatBehavior.cs
- XmlSchemaAny.cs
- StaticResourceExtension.cs
- HorizontalAlignConverter.cs
- SemanticResolver.cs
- DateTimeUtil.cs
- DisplayNameAttribute.cs
- TextModifierScope.cs
- RuleSetCollection.cs
- EmbeddedMailObjectCollectionEditor.cs
- HScrollProperties.cs
- RequestNavigateEventArgs.cs
- _IPv6Address.cs
- DeviceContext.cs
- DbConnectionStringBuilder.cs
- HMACMD5.cs
- ReadOnlyObservableCollection.cs
- EncryptedData.cs
- BitmapMetadataBlob.cs
- HtmlTableRow.cs
- QueryContinueDragEvent.cs
- HttpModuleAction.cs
- FatalException.cs
- FixedTextView.cs
- HeaderedContentControl.cs
- XPathAncestorIterator.cs
- DataGridViewCellPaintingEventArgs.cs
- DeclarativeCatalogPart.cs
- BinaryNode.cs
- QilValidationVisitor.cs
- JavaScriptSerializer.cs
- DesignerSerializationVisibilityAttribute.cs
- AffineTransform3D.cs
- SettingsPropertyWrongTypeException.cs
- CommonRemoteMemoryBlock.cs
- DropDownButton.cs
- Condition.cs
- TypeLoadException.cs
- ServerIdentity.cs
- ListBox.cs
- DataGridViewRowCancelEventArgs.cs
- NavigationFailedEventArgs.cs
- AutoResizedEvent.cs
- VerificationException.cs
- DataGridViewImageColumn.cs
- LZCodec.cs
- XsdValidatingReader.cs
- PersonalizationEntry.cs
- NotFiniteNumberException.cs
- Vector3DAnimationBase.cs
- Span.cs
- MethodInfo.cs
- CodeMethodReturnStatement.cs
- ScrollChangedEventArgs.cs
- TypefaceCollection.cs
- RowTypePropertyElement.cs
- UserPreferenceChangedEventArgs.cs
- Translator.cs
- ParagraphResult.cs
- ProjectionCamera.cs