Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / PtsHost / FlowDocumentPage.cs / 1305600 / FlowDocumentPage.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// Description: DocumentPage representing bottomless of finite page of
// a PTS host (FlowDocument).
//
// History:
// 09/27/2004 : [....] - created.
//
//---------------------------------------------------------------------------
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Documents;
using System.Windows.Threading; // Dispatcher
using MS.Internal.Documents;
using MS.Internal.Text;
using MS.Internal.PtsHost.UnsafeNativeMethods;
namespace MS.Internal.PtsHost
{
//-----------------------------------------------------------------------
// DocumentPage representing bottomless or finite page of a PTS host.
//-----------------------------------------------------------------------
internal sealed class FlowDocumentPage : DocumentPage, IServiceProvider, IDisposable, IContentHost
{
//--------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
//--------------------------------------------------------------------
// Constructor.
//
// structuralCache - context representing data
//--------------------------------------------------------------------
internal FlowDocumentPage(StructuralCache structuralCache) : base(null)
{
_structuralCache = structuralCache;
_ptsPage = new PtsPage(structuralCache.Section);
}
// -----------------------------------------------------------------
// Finalizer
// ------------------------------------------------------------------
~FlowDocumentPage()
{
Dispose(false);
}
#endregion Constructors
//-------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------
#region Public Methods
//-------------------------------------------------------------------
// Dispose the page.
//--------------------------------------------------------------------
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
base.Dispose();
}
#endregion Public Methods
//-------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------
#region Public Properties
//--------------------------------------------------------------------
// Visual node representing content of the page.
//-------------------------------------------------------------------
public override Visual Visual
{
get
{
if (IsDisposed)
{
return null;
}
UpdateVisual();
return base.Visual;
}
}
#endregion Public Properties
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
//-------------------------------------------------------------------
// Format content into a single bottomless page.
//
// pageSize - size of the page
//-------------------------------------------------------------------
internal void FormatBottomless(Size pageSize, Thickness pageMargin)
{
Invariant.Assert(!IsDisposed);
// Every time full format is done reset formatted lines count to 0.
_formattedLinesCount = 0;
// Make sure that PTS limitations are not exceeded.
TextDpi.EnsureValidPageSize(ref pageSize);
_pageMargin = pageMargin;
SetSize(pageSize);
if(!DoubleUtil.AreClose(_lastFormatWidth, pageSize.Width) || !DoubleUtil.AreClose(_pageMargin.Left, pageMargin.Left) ||
!DoubleUtil.AreClose(_pageMargin.Right, pageMargin.Right))
{
// No incremental update if width changes.
_structuralCache.InvalidateFormatCache(false);
}
_lastFormatWidth = pageSize.Width;
using(_structuralCache.SetDocumentFormatContext(this))
{
OnBeforeFormatPage();
if (_ptsPage.PrepareForBottomlessUpdate())
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, true, false);
_ptsPage.UpdateBottomlessPage();
}
else
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, false, false);
_ptsPage.CreateBottomlessPage();
}
// In bottomless page scenario, need to update PageSize to reflect
// calculated size of the page.
pageSize = _ptsPage.CalculatedSize;
pageSize.Width += pageMargin.Left + pageMargin.Right;
pageSize.Height += pageMargin.Top + pageMargin.Bottom;
SetSize(pageSize);
SetContentBox(new Rect(pageMargin.Left, pageMargin.Top, _ptsPage.CalculatedSize.Width, _ptsPage.CalculatedSize.Height));
_structuralCache.CurrentFormatContext.PopPageData();
OnAfterFormatPage();
_structuralCache.DetectInvalidOperation();
}
}
//--------------------------------------------------------------------
// Format content into a single finite page.
//
// pageSize - size of the page
// pageMargin - margin of the page
// breakRecord - input BreakRecor for the page
//
// Returns: Returns output break record.
//-------------------------------------------------------------------
internal PageBreakRecord FormatFinite(Size pageSize, Thickness pageMargin, PageBreakRecord breakRecord)
{
Invariant.Assert(!IsDisposed);
// Every time full format is done reset formatted lines count to 0.
_formattedLinesCount = 0;
// Make sure that PTS limitations are not exceeded.
TextDpi.EnsureValidPageSize(ref pageSize);
TextDpi.EnsureValidPageMargin(ref pageMargin, pageSize);
double pageMarginAdjustment = PtsHelper.CalculatePageMarginAdjustment(_structuralCache, pageSize.Width - (pageMargin.Left + pageMargin.Right));
if (!DoubleUtil.IsZero(pageMarginAdjustment))
{
// Potentially some FP drift here, as we're anticipating that our column count will now work out exactly. Add a small fraction back to prevent this
pageMargin.Right += pageMarginAdjustment - (pageMarginAdjustment / 100.0);
}
_pageMargin = pageMargin;
SetSize(pageSize);
SetContentBox(new Rect(pageMargin.Left, pageMargin.Top,
pageSize.Width - (pageMargin.Left + pageMargin.Right),
pageSize.Height - (pageMargin.Top + pageMargin.Bottom)));
using(_structuralCache.SetDocumentFormatContext(this))
{
OnBeforeFormatPage();
if (_ptsPage.PrepareForFiniteUpdate(breakRecord))
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, true, true);
_ptsPage.UpdateFinitePage(breakRecord);
}
else
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, false, true);
_ptsPage.CreateFinitePage(breakRecord);
}
_structuralCache.CurrentFormatContext.PopPageData();
OnAfterFormatPage();
_structuralCache.DetectInvalidOperation();
}
return _ptsPage.BreakRecord;
}
//--------------------------------------------------------------------
// Arrange the page contents.
//--------------------------------------------------------------------
internal void Arrange(Size partitionSize)
{
Invariant.Assert(!IsDisposed);
_partitionSize = partitionSize;
using(_structuralCache.SetDocumentArrangeContext(this))
{
_ptsPage.ArrangePage();
_structuralCache.DetectInvalidOperation();
}
ValidateTextView();
}
//-------------------------------------------------------------------
// Page update may be requested more than once before rendering is
// done. But PTS is not able to merge update info.
// To protect against loosing incremental changes delta, need
// to force full formatting for the conent.
//--------------------------------------------------------------------
internal void ForceReformat()
{
Invariant.Assert(!IsDisposed);
// Clear update info for PTS page.
_ptsPage.ClearUpdateInfo();
// Force reformat
_structuralCache.ForceReformat = true;
}
//-------------------------------------------------------------------
// Hit tests to the correct ContentElement within the ContentHost
// that the mouse is over.
//
// point - mouse coordinates relative to the ContentHost
//
// Returns: IInputElement from specified position.
//-------------------------------------------------------------------
internal IInputElement InputHitTestCore(Point point)
{
Invariant.Assert(!IsDisposed);
// Core services require that the IInputElement returned from hittesting
// is a UIElement or it has a parent that is a UIElement.
// When using DocumentPageView.DocumentPaginator directly, we may run
// into case when FlowDocument does not have a logical parent. In
// such case it is better to disable all core services.
DependencyObject frameworkParent = FrameworkElement.GetFrameworkParent(_structuralCache.FormattingOwner);
if (frameworkParent == null)
{
return null;
}
IInputElement ie = null;
if (this.IsLayoutDataValid)
{
// Transform point to PtsPage coordinate system.
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
transform = transform.Inverse;
// Hittest PtsPage only when transform can be inverted in order to calculate
// point within PtsPage. If transform cannot be inverted, return the owner of this page.
if (transform != null)
{
point = transform.Transform(point);
ie = _ptsPage.InputHitTest(point);
}
}
return (ie != null) ? ie : _structuralCache.FormattingOwner as IInputElement;
}
///
/// Returns rectangles for element. First finds element by navigating in FlowDocumentPage.
/// If element is not found or if call to get rectangles from FlowDocumentPage returns null
/// we return an empty collection. If the layout is not valid we return null.
///
///
/// Content element for which rectangles are required
///
///
/// Indicates whether search should be restricted only to those text segments within the page's text view
///
internal ReadOnlyCollection GetRectanglesCore(ContentElement child, bool isLimitedToTextView)
{
Invariant.Assert(!IsDisposed);
List rectangles = new List();
Debug.Assert(child != null);
if (IsLayoutDataValid)
{
TextPointer elementStart = FindElementPosition(child, isLimitedToTextView);
if (elementStart != null)
{
// Element exists within this Page, calculate its length
int elementStartOffset = _structuralCache.TextContainer.Start.GetOffsetToPosition(elementStart);
int elementLength = 1;
if (child is TextElement)
{
TextPointer elementEnd = new TextPointer(((TextElement)child).ElementEnd);
elementLength = elementStart.GetOffsetToPosition(elementEnd);
}
rectangles = _ptsPage.GetRectangles(child, elementStartOffset, elementLength);
}
}
if(this.PageVisual != null && rectangles.Count > 0)
{
List transformedRectangles = new List(rectangles.Count);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
for(int index = 0; index < rectangles.Count; index++)
{
transformedRectangles.Add(transform.TransformBounds(rectangles[index]));
}
rectangles = transformedRectangles;
}
// We should never return null for rectangles from public API, only empty ArrayList
Invariant.Assert(rectangles != null);
return new ReadOnlyCollection(rectangles);
}
///
/// Returns elements hosted by the content host as an enumerator class
///
internal IEnumerator HostedElementsCore
{
get
{
if (IsLayoutDataValid)
{
// At this point, we should create TextView if it doesn't exist
_textView = GetTextView();
Invariant.Assert(_textView != null && ((ITextView)_textView).TextSegments.Count > 0);
return new HostedElements(((ITextView)_textView).TextSegments);
}
else
{
// Return empty collection
return new HostedElements(new ReadOnlyCollection(new List(0)));
}
}
}
// Floating element list
internal ReadOnlyCollection FloatingElementResults
{
get
{
List floatingElements = new List(0);
List floatingElementList = _ptsPage.PageContext.FloatingElementList;
if (floatingElementList != null)
{
for (int i = 0; i < floatingElementList.Count; i++)
{
ParagraphResult paragraphResult = floatingElementList[i].CreateParagraphResult();
floatingElements.Add(paragraphResult);
}
}
return new ReadOnlyCollection(floatingElements);
}
}
///
/// Called when a UIElement-derived class which is hosted by a IContentHost changes it’s DesiredSize
///
///
/// Child element whose DesiredSize has changed
///
internal void OnChildDesiredSizeChangedCore(UIElement child)
{
_structuralCache.FormattingOwner.OnChildDesiredSizeChanged(child);
}
//-------------------------------------------------------------------
// Returns a new collection of ColumnResults for the page. Will always
// have at least one column.
// hasTextContent - True if any column in the page has text
// content, i.e. does not contain only figures/floaters
//--------------------------------------------------------------------
///
/// Critical - as this call Critical functions FsQueryPageDetails, FsQueryTrackDetails,
/// FsQuerySectionDetails and some PtsHelper functions.
/// Safe - as this can't be be used to pass arbitrary parameters. All parameters passed
/// in are either Critical for set or are generated within the function.
///
[SecurityCritical, SecurityTreatAsSafe]
internal ReadOnlyCollection GetColumnResults(out bool hasTextContent)
{
Invariant.Assert(!IsDisposed);
List columnResults = new List(0);
// hasTextContent is set to true if any of the columns in the page has text content. This is determined by checking the columns'
// paragraph collections
hasTextContent = false;
// There are 3 cases:
// (1) PTS page is not created - no columns are available.
// (2) PTS page - use page PTS APIs to get columns.
if (_ptsPage.PageHandle == IntPtr.Zero)
{
// (1) PTS page is not created
}
else
{
// (2) PTS page - use page PTS APIs to get columns.
PTS.FSPAGEDETAILS pageDetails;
PTS.Validate(PTS.FsQueryPageDetails(StructuralCache.PtsContext.Context, _ptsPage.PageHandle, out pageDetails));
// There are 2 different types of PTS page:
// (a) simple page (contains only one track) - 1 column.
// (b) complex page (contains header, page body, footnotes and footer) - get columns
// from the page body.
if (PTS.ToBoolean(pageDetails.fSimple))
{
// (a) simple page (contains only one track) - 1 column.
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pageDetails.u.simple.trackdescr.pfstrack, out trackDetails));
if (trackDetails.cParas > 0)
{
columnResults = new List(1);
ColumnResult columnResult = new ColumnResult(this, ref pageDetails.u.simple.trackdescr, new Vector());
columnResults.Add(columnResult);
if (columnResult.HasTextContent)
{
hasTextContent = true;
}
}
}
else if (pageDetails.u.complex.cSections > 0)
{
// (b) complex page (contains header, page body, footnotes and footer) - get columns
// from the page body.
Debug.Assert(pageDetails.u.complex.cSections == 1); // Only one section is supported right now.
// Retrieve description for each section.
PTS.FSSECTIONDESCRIPTION[] arraySectionDesc;
PtsHelper.SectionListFromPage(StructuralCache.PtsContext, _ptsPage.PageHandle, ref pageDetails, out arraySectionDesc);
// Get section details
PTS.FSSECTIONDETAILS sectionDetails;
PTS.Validate(PTS.FsQuerySectionDetails(StructuralCache.PtsContext.Context, arraySectionDesc[0].pfssection, out sectionDetails));
// There are 2 types of sections:
// (1) with page notes - footnotes in section treated as endnotes
// (2) with column notes - footnotes in section treated as column notes
if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes))
{
// (1) with page notes - footnotes in section treated as endnotes
Debug.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0); // Footnotes are not supported yet.
//
Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0);
Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0);
// cBasicColumns == 0, means that section content is empty.
// In such case there is nothing to render.
if (sectionDetails.u.withpagenotes.cBasicColumns > 0)
{
// Retrieve description for each column.
PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
PtsHelper.TrackListFromSection(StructuralCache.PtsContext, arraySectionDesc[0].pfssection, ref sectionDetails, out arrayColumnDesc);
columnResults = new List(sectionDetails.u.withpagenotes.cBasicColumns);
for (int i = 0; i < arrayColumnDesc.Length; i++)
{
PTS.FSTRACKDESCRIPTION columnDesc = arrayColumnDesc[i];
// Column may have null track, in which case we should not add it
if (columnDesc.pfstrack != IntPtr.Zero)
{
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, columnDesc.pfstrack, out trackDetails));
if (trackDetails.cParas > 0)
{
ColumnResult columnResult = new ColumnResult(this, ref columnDesc, new Vector());
columnResults.Add(columnResult);
if (columnResult.HasTextContent)
{
hasTextContent = true;
}
}
}
}
}
// else; section empty => no columns
}
else
{
// (2) with column notes - footnotes in section treated as column notes
Debug.Assert(false); // Complex columns are not supported yet.
}
}
}
Invariant.Assert(columnResults != null);
return new ReadOnlyCollection(columnResults);
}
//-------------------------------------------------------------------
// Retrieves text range for contents of the column represented
// by 'pfstrack'.
//
// pfstrack - pointer to PTS track representing a column
//
// Returns: text range for contents of the column represented by 'pfstrack'
//--------------------------------------------------------------------
///
/// Critical - as this calls Critical function PTS.FsQueryTrackDetails and
/// passes an IntPtr directly.
///
[SecurityCritical]
internal TextContentRange GetTextContentRangeFromColumn(IntPtr pfstrack)
{
Invariant.Assert(!IsDisposed);
// Get track details
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pfstrack, out trackDetails));
// Combine ranges from all nested paragraphs.
TextContentRange textContentRange = new TextContentRange();
if (trackDetails.cParas != 0)
{
PTS.FSPARADESCRIPTION[] arrayParaDesc;
PtsHelper.ParaListFromTrack(StructuralCache.PtsContext, pfstrack, ref trackDetails, out arrayParaDesc);
// Merge TextContentRanges for all paragraphs
BaseParaClient paraClient;
for (int i = 0; i < arrayParaDesc.Length; i++)
{
paraClient = this.StructuralCache.PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
PTS.ValidateHandle(paraClient);
textContentRange.Merge(paraClient.GetTextContentRange());
}
}
return textContentRange;
}
//--------------------------------------------------------------------
// Returns a collection of ParagraphResults for the column's paragraphs.
//
// pfstrack - pointer to PTS track representing a column
// parentOffset - parent offset from the top of the page
// hasTextContent - true if any paragraph in the column has some text content
//
// Returns: collection of ParagraphResults for the column's paragraphs
//-------------------------------------------------------------------
///
/// Critical - as this calls Critical function PTS.FsQueryTrackDetails and
/// passes an IntPtr directly.
///
[SecurityCritical]
internal ReadOnlyCollection GetParagraphResultsFromColumn(IntPtr pfstrack, Vector parentOffset, out bool hasTextContent)
{
Invariant.Assert(!IsDisposed);
// Get track details
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pfstrack, out trackDetails));
hasTextContent = false;
if (trackDetails.cParas == 0)
{
return new ReadOnlyCollection(new List(0));
}
PTS.FSPARADESCRIPTION[] arrayParaDesc;
PtsHelper.ParaListFromTrack(StructuralCache.PtsContext, pfstrack, ref trackDetails, out arrayParaDesc);
List paragraphResults = new List(arrayParaDesc.Length);
for (int i = 0; i < arrayParaDesc.Length; i++)
{
BaseParaClient paraClient = StructuralCache.PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
PTS.ValidateHandle(paraClient);
ParagraphResult paragraphResult = paraClient.CreateParagraphResult();
if (paragraphResult.HasTextContent)
{
hasTextContent = true;
}
paragraphResults.Add(paragraphResult);
}
return new ReadOnlyCollection(paragraphResults);
}
//--------------------------------------------------------------------
// Notification about new line being formatted.
//-------------------------------------------------------------------
internal void OnFormatLine()
{
Invariant.Assert(!IsDisposed);
++_formattedLinesCount;
}
//-------------------------------------------------------------------
// Ensures visual structure for this document page is clean
//-------------------------------------------------------------------
internal void EnsureValidVisuals()
{
Invariant.Assert(!IsDisposed);
UpdateVisual();
}
//--------------------------------------------------------------------
// Update the viewport
//-------------------------------------------------------------------
internal void UpdateViewport(ref PTS.FSRECT viewport, bool drawBackground)
{
Rect contentViewport;
// Transform point to PtsPage coordinate system.
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
transform = transform.Inverse;
contentViewport = viewport.FromTextDpi();
if (transform != null)
{
contentViewport = transform.TransformBounds(contentViewport);
}
if(!IsDisposed)
{
// Draw background
if (drawBackground)
{
this.PageVisual.DrawBackground((Brush)_structuralCache.PropertyOwner.GetValue(FlowDocument.BackgroundProperty), contentViewport);
}
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
PTS.FSRECT contentViewportTextDpi = new PTS.FSRECT(contentViewport);
_ptsPage.UpdateViewport(ref contentViewportTextDpi);
_structuralCache.DetectInvalidOperation();
}
ValidateTextView();
}
}
#endregion Internal methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
//-------------------------------------------------------------------
// Is being used in a plain text box?
//--------------------------------------------------------------------
internal bool UseSizingWorkaroundForTextBox
{
get { return _ptsPage.UseSizingWorkaroundForTextBox; }
set { _ptsPage.UseSizingWorkaroundForTextBox = value; }
}
//-------------------------------------------------------------------
// Margin of the page.
//-------------------------------------------------------------------
internal Thickness Margin { get { return _pageMargin; } }
//-------------------------------------------------------------------
// Is this page already disposed?
//--------------------------------------------------------------------
internal bool IsDisposed { get { return (_disposed != 0) || _structuralCache.PtsContext.Disposed; } }
//-------------------------------------------------------------------
// Size of content on page.
//--------------------------------------------------------------------
internal Size ContentSize
{
get
{
Size size = _ptsPage.ContentSize;
size.Width += _pageMargin.Left + _pageMargin.Right;
size.Height += _pageMargin.Top + _pageMargin.Bottom;
return size;
}
}
//--------------------------------------------------------------------
// Is it finite page or bottomless?
//-------------------------------------------------------------------
internal bool FinitePage { get { return _ptsPage.FinitePage; } }
//--------------------------------------------------------------------
// Page context
//-------------------------------------------------------------------
internal PageContext PageContext { get { return _ptsPage.PageContext; } }
//-------------------------------------------------------------------
// Is during incremental update mode?
//-------------------------------------------------------------------
internal bool IncrementalUpdate { get { return _ptsPage.IncrementalUpdate; } }
//--------------------------------------------------------------------
// StructuralCache associated with this page.
//-------------------------------------------------------------------
internal StructuralCache StructuralCache { get { return _structuralCache; } }
//--------------------------------------------------------------------
// Number of lines formatted during page formatting.
//--------------------------------------------------------------------
internal int FormattedLinesCount { get { return _formattedLinesCount; } }
//-------------------------------------------------------------------
// Is layout data is in a valid state.
//--------------------------------------------------------------------
internal bool IsLayoutDataValid
{
get
{
bool layoutDataValid = false;
if (!IsDisposed)
{
// In case of any content/properties changes FlowDocument does BreakRecordTable
// management and disposes any affected pages. So it is unnecessary to check
// for DtrList of ForceReformat here, because _disposed flag reflects this fact
// in more granular way.
layoutDataValid = _structuralCache.FormattingOwner.IsLayoutDataValid;
}
return layoutDataValid;
}
}
//-------------------------------------------------------------------
// Save the maximum dcpDepend of the page, for invalidations
// of later pages.
//
// DCPDepend - number of characters past end of page that were
// considered for formatting of this page
//-------------------------------------------------------------------
internal TextPointer DependentMax
{
get
{
return _DependentMax;
}
set
{
if ((_DependentMax == null) || ((value != null) && (value.CompareTo(_DependentMax) > 0)))
{
_DependentMax = value;
}
}
}
//-------------------------------------------------------------------
// Viewport
//--------------------------------------------------------------------
internal Rect Viewport
{
get
{
return new Rect(this.Size);
}
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------
#region Private Methods
///
/// Destroy all unmanaged resources.
///
/// Whether dispose is caused by explicit call to Dispose.
///
/// Finalizer needs to follow rules below:
/// a) Your Finalize method must tolerate partially constructed instances.
/// b) Your Finalize method must consider the consequence of failure.
/// c) Your object is callable after Finalization.
/// d) Your object is callable during Finalization.
/// e) Your Finalizer could be called multiple times.
/// f) Your Finalizer runs in a delicate security context.
/// See: http://blogs.msdn.com/[....]/archive/2004/02/20/77460.aspx
///
private void Dispose(bool disposing)
{
// Do actual dispose only once.
if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0)
{
if (disposing)
{
// Clear content of the root visual
if (this.PageVisual != null)
{
// Disconnect all embedded visuals (UIElements) to make sure that
// they are not part of visual tree when page is destroyed.
// This is necessary for building proper event route, because
// BuildRoute prefers visual tree.
DestroyVisualLinks(this.PageVisual);
// Clear its drawing context and children collection.
this.PageVisual.Children.Clear();
this.PageVisual.ClearDrawingContext();
}
// Dispose PTS page
if (_ptsPage != null)
{
_ptsPage.Dispose();
}
}
try
{
if (disposing)
{
// Notify interested parties about disposal of the page.
OnPageDestroyed(EventArgs.Empty);
}
}
finally
{
_ptsPage = null;
_structuralCache = null;
_textView = null;
_DependentMax = null;
}
}
}
//--------------------------------------------------------------------
// Update visual representation of the page.
//-------------------------------------------------------------------
private void UpdateVisual()
{
if (this.PageVisual == null)
{
SetVisual(new PageVisual(this));
}
if (_visualNeedsUpdate)
{
// Draw background
this.PageVisual.DrawBackground((Brush)_structuralCache.PropertyOwner.GetValue(FlowDocument.BackgroundProperty), new Rect(_partitionSize));
// Connect visual created by PTS page.
ContainerVisual pageVisual = null;
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
pageVisual = _ptsPage.GetPageVisual(); // This method will update the visual tree if necessary.
_structuralCache.DetectInvalidOperation();
}
this.PageVisual.Child = pageVisual; // No-op if already connected.
// DocumentPage.Visual for printing scenarions needs to be always returned
// in LeftToRight FlowDirection. Hence, if the document is RightToLeft,
// mirroring transform need to be applied to the content of DocumentPage.Visual.
FlowDirection flowdirection = (FlowDirection)_structuralCache.PropertyOwner.GetValue(FlowDocument.FlowDirectionProperty);
PtsHelper.UpdateMirroringTransform(FlowDirection.LeftToRight, flowdirection, pageVisual, Size.Width);
// Clear update info for PTS page.
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
_ptsPage.ClearUpdateInfo();
_structuralCache.DetectInvalidOperation();
}
_visualNeedsUpdate = false;
}
}
//--------------------------------------------------------------------
// Prepares for format page process.
//-------------------------------------------------------------------
private void OnBeforeFormatPage()
{
if (_visualNeedsUpdate)
{
// Clear update info for PTS page.
_ptsPage.ClearUpdateInfo();
}
}
//-------------------------------------------------------------------
// Completes format page process.
//-------------------------------------------------------------------
private void OnAfterFormatPage()
{
if (_textView != null)
{
_textView.Invalidate();
}
_visualNeedsUpdate = true;
}
//--------------------------------------------------------------------
// IContentHost Helpers
//-------------------------------------------------------------------
///
/// Searches for an element in the _structuralCache.TextContainer. If the element is found, returns the
/// position at which it is found. Otherwise returns null.
///
///
/// Element to be found.
///
///
/// bool value indicating whether the search should only be limited to the text view of the page,
/// in which case we search only text segments in the text view
///
private TextPointer FindElementPosition(IInputElement e, bool isLimitedToTextView)
{
// Parameter validation
Debug.Assert(e != null);
// Validate that this function is only called when a TextContainer exists as complex content
Debug.Assert(_structuralCache.TextContainer is TextContainer);
TextPointer elementPosition = null;
// If e is a TextElement we can optimize by checking its TextContainer
if (e is TextElement)
{
if ((e as TextElement).TextContainer == _structuralCache.TextContainer)
{
// Element found
elementPosition = new TextPointer((e as TextElement).ElementStart);
}
// else: elementPosition stays null
}
else
{
// Else: search for e in the complex content
if (!(_structuralCache.TextContainer.Start is TextPointer) ||
!(_structuralCache.TextContainer.End is TextPointer))
{
// Invalid TextContainer, don't search
return null;
}
TextPointer searchPosition = new TextPointer(_structuralCache.TextContainer.Start as TextPointer);
while (elementPosition == null && ((ITextPointer)searchPosition).CompareTo(_structuralCache.TextContainer.End) < 0)
{
// Search each position in _structuralCache.TextContainer for the element
switch (searchPosition.GetPointerContext(LogicalDirection.Forward))
{
case TextPointerContext.EmbeddedElement:
DependencyObject embeddedObject = searchPosition.GetAdjacentElement(LogicalDirection.Forward);
if (embeddedObject is ContentElement || embeddedObject is UIElement)
{
if (embeddedObject == e as ContentElement || embeddedObject == e as UIElement)
{
// Element found. Stop searching
elementPosition = new TextPointer(searchPosition);
break;
}
}
break;
default:
break;
}
searchPosition.MoveToNextContextPosition(LogicalDirection.Forward);
}
}
// If the element was found, check if we are limited to text view
if (elementPosition != null)
{
if (isLimitedToTextView)
{
// At this point, we should create TextView if it doesn't exist
_textView = GetTextView();
Invariant.Assert(_textView != null);
// Check all segements in text view for position
for (int segmentIndex = 0; segmentIndex < ((ITextView)_textView).TextSegments.Count; segmentIndex++)
{
if (((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].Start) >= 0 &&
((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].End) < 0)
{
// Element lies within a segment. Return position
return elementPosition;
}
}
// Element not found in all segments of TextView. Set position to null
elementPosition = null;
}
}
return elementPosition;
}
//--------------------------------------------------------------------
// Disconnect all embedded visuals (UIElements) to make sure that
// they are not part of visual tree when page is destroyed.
// This is necessary for building proper event route, because
// BuildRoute prefers visual tree.
//--------------------------------------------------------------------
private void DestroyVisualLinks(ContainerVisual visual)
{
VisualCollection vc = visual.Children;
if (vc != null)
{
for (int index = 0; index < vc.Count; index++)
{
if (vc[index] is UIElementIsland)
{
vc.RemoveAt(index);
}
else
{
Invariant.Assert(vc[index] is ContainerVisual, "The children should always derive from ContainerVisual");
DestroyVisualLinks((ContainerVisual)(vc[index]));
}
}
}
}
///
/// Raise TextView.Updated event.
///
private void ValidateTextView()
{
if (_textView != null)
{
_textView.OnUpdated();
}
}
///
/// Gets TextView for this page.
///
private TextDocumentView GetTextView()
{
TextDocumentView textView = (TextDocumentView)((IServiceProvider)this).GetService(typeof(ITextView));
Invariant.Assert(textView != null);
return textView;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Properties
//
//--------------------------------------------------------------------
#region Private Properties
//-------------------------------------------------------------------
// Visual representing content of the page.
//-------------------------------------------------------------------
private PageVisual PageVisual
{
get { return (base.Visual as PageVisual); }
}
#endregion Private Properties
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
//-------------------------------------------------------------------
// Associated PTS page.
//--------------------------------------------------------------------
private PtsPage _ptsPage;
//--------------------------------------------------------------------
// Structural cache.
//-------------------------------------------------------------------
private StructuralCache _structuralCache;
//--------------------------------------------------------------------
// Number of lines formatted during page formatting.
// NOTE: This field is used only internally for layout DRTs.
//-------------------------------------------------------------------
private int _formattedLinesCount;
//-------------------------------------------------------------------
// TextView associated with the document page.
//-------------------------------------------------------------------
private TextDocumentView _textView;
//--------------------------------------------------------------------
// Size of partition for the page.
//-------------------------------------------------------------------
private Size _partitionSize;
//--------------------------------------------------------------------
// Margin of the page.
//--------------------------------------------------------------------
private Thickness _pageMargin;
//-------------------------------------------------------------------
// Is it already disposed?
//--------------------------------------------------------------------
private int _disposed;
//-------------------------------------------------------------------
// Max of dcpDepend for page
//-------------------------------------------------------------------
private TextPointer _DependentMax;
//-------------------------------------------------------------------
// Need to update visual?
//--------------------------------------------------------------------
private bool _visualNeedsUpdate;
//-------------------------------------------------------------------
// Width of page during last format
//--------------------------------------------------------------------
private double _lastFormatWidth;
#endregion Private Fields
//--------------------------------------------------------------------
//
// IServiceProvider Members
//
//-------------------------------------------------------------------
#region IServiceProvider Members
//--------------------------------------------------------------------
// Gets the service object of the specified type. FlowDocumentPage
// currently supports only TextView
//
// serviceType - an object that specifies the type of service
// object to get
//
// Returns: A service object of type serviceType. A null reference
// if there is no service object of type serviceType.
//-------------------------------------------------------------------
object IServiceProvider.GetService(Type serviceType)
{
if (serviceType == null)
{
throw new ArgumentNullException("serviceType");
}
if (serviceType == typeof(ITextView))
{
if (_textView == null)
{
_textView = new TextDocumentView(this, _structuralCache.TextContainer);
}
return _textView;
}
return null;
}
#endregion IServiceProvider Members
//-------------------------------------------------------------------
//
// IContentHost Members
//
//-------------------------------------------------------------------
#region IContentHost Members
///
/// Hit tests to the correct ContentElement
/// within the ContentHost that the mouse
/// is over
///
///
/// Mouse coordinates relative to
/// the ContentHost
///
IInputElement IContentHost.InputHitTest(Point point)
{
return this.InputHitTestCore(point);
}
///
/// Returns rectangles for element. First finds element by navigating in FlowDocumentPage.
/// If element is not found or if call to get rectangles from FlowDocumentPage returns null
/// we return an empty collection. If the layout is not valid we return null.
///
///
/// Content element for which rectangles are required
///
ReadOnlyCollection IContentHost.GetRectangles(ContentElement child)
{
// Restrict search to only the text segments in the page's text view. This is not needed for
// HitTest because it takes only a point
return this.GetRectanglesCore(child, true);
}
///
/// Returns elements hosted by the content host as an enumerator class
///
IEnumerator IContentHost.HostedElements
{
get
{
return this.HostedElementsCore as IEnumerator;
}
}
///
/// Called when a UIElement-derived class which is hosted by a IContentHost changes it’s DesiredSize
///
///
/// Child element whose DesiredSize has changed
///
void IContentHost.OnChildDesiredSizeChanged(UIElement child)
{
this.OnChildDesiredSizeChangedCore(child);
}
#endregion IContentHost Members
}
}
// 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.
//
// Description: DocumentPage representing bottomless of finite page of
// a PTS host (FlowDocument).
//
// History:
// 09/27/2004 : [....] - created.
//
//---------------------------------------------------------------------------
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Documents;
using System.Windows.Threading; // Dispatcher
using MS.Internal.Documents;
using MS.Internal.Text;
using MS.Internal.PtsHost.UnsafeNativeMethods;
namespace MS.Internal.PtsHost
{
//-----------------------------------------------------------------------
// DocumentPage representing bottomless or finite page of a PTS host.
//-----------------------------------------------------------------------
internal sealed class FlowDocumentPage : DocumentPage, IServiceProvider, IDisposable, IContentHost
{
//--------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
//--------------------------------------------------------------------
// Constructor.
//
// structuralCache - context representing data
//--------------------------------------------------------------------
internal FlowDocumentPage(StructuralCache structuralCache) : base(null)
{
_structuralCache = structuralCache;
_ptsPage = new PtsPage(structuralCache.Section);
}
// -----------------------------------------------------------------
// Finalizer
// ------------------------------------------------------------------
~FlowDocumentPage()
{
Dispose(false);
}
#endregion Constructors
//-------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------
#region Public Methods
//-------------------------------------------------------------------
// Dispose the page.
//--------------------------------------------------------------------
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
base.Dispose();
}
#endregion Public Methods
//-------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------
#region Public Properties
//--------------------------------------------------------------------
// Visual node representing content of the page.
//-------------------------------------------------------------------
public override Visual Visual
{
get
{
if (IsDisposed)
{
return null;
}
UpdateVisual();
return base.Visual;
}
}
#endregion Public Properties
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
//-------------------------------------------------------------------
// Format content into a single bottomless page.
//
// pageSize - size of the page
//-------------------------------------------------------------------
internal void FormatBottomless(Size pageSize, Thickness pageMargin)
{
Invariant.Assert(!IsDisposed);
// Every time full format is done reset formatted lines count to 0.
_formattedLinesCount = 0;
// Make sure that PTS limitations are not exceeded.
TextDpi.EnsureValidPageSize(ref pageSize);
_pageMargin = pageMargin;
SetSize(pageSize);
if(!DoubleUtil.AreClose(_lastFormatWidth, pageSize.Width) || !DoubleUtil.AreClose(_pageMargin.Left, pageMargin.Left) ||
!DoubleUtil.AreClose(_pageMargin.Right, pageMargin.Right))
{
// No incremental update if width changes.
_structuralCache.InvalidateFormatCache(false);
}
_lastFormatWidth = pageSize.Width;
using(_structuralCache.SetDocumentFormatContext(this))
{
OnBeforeFormatPage();
if (_ptsPage.PrepareForBottomlessUpdate())
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, true, false);
_ptsPage.UpdateBottomlessPage();
}
else
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, false, false);
_ptsPage.CreateBottomlessPage();
}
// In bottomless page scenario, need to update PageSize to reflect
// calculated size of the page.
pageSize = _ptsPage.CalculatedSize;
pageSize.Width += pageMargin.Left + pageMargin.Right;
pageSize.Height += pageMargin.Top + pageMargin.Bottom;
SetSize(pageSize);
SetContentBox(new Rect(pageMargin.Left, pageMargin.Top, _ptsPage.CalculatedSize.Width, _ptsPage.CalculatedSize.Height));
_structuralCache.CurrentFormatContext.PopPageData();
OnAfterFormatPage();
_structuralCache.DetectInvalidOperation();
}
}
//--------------------------------------------------------------------
// Format content into a single finite page.
//
// pageSize - size of the page
// pageMargin - margin of the page
// breakRecord - input BreakRecor for the page
//
// Returns: Returns output break record.
//-------------------------------------------------------------------
internal PageBreakRecord FormatFinite(Size pageSize, Thickness pageMargin, PageBreakRecord breakRecord)
{
Invariant.Assert(!IsDisposed);
// Every time full format is done reset formatted lines count to 0.
_formattedLinesCount = 0;
// Make sure that PTS limitations are not exceeded.
TextDpi.EnsureValidPageSize(ref pageSize);
TextDpi.EnsureValidPageMargin(ref pageMargin, pageSize);
double pageMarginAdjustment = PtsHelper.CalculatePageMarginAdjustment(_structuralCache, pageSize.Width - (pageMargin.Left + pageMargin.Right));
if (!DoubleUtil.IsZero(pageMarginAdjustment))
{
// Potentially some FP drift here, as we're anticipating that our column count will now work out exactly. Add a small fraction back to prevent this
pageMargin.Right += pageMarginAdjustment - (pageMarginAdjustment / 100.0);
}
_pageMargin = pageMargin;
SetSize(pageSize);
SetContentBox(new Rect(pageMargin.Left, pageMargin.Top,
pageSize.Width - (pageMargin.Left + pageMargin.Right),
pageSize.Height - (pageMargin.Top + pageMargin.Bottom)));
using(_structuralCache.SetDocumentFormatContext(this))
{
OnBeforeFormatPage();
if (_ptsPage.PrepareForFiniteUpdate(breakRecord))
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, true, true);
_ptsPage.UpdateFinitePage(breakRecord);
}
else
{
_structuralCache.CurrentFormatContext.PushNewPageData(pageSize, _pageMargin, false, true);
_ptsPage.CreateFinitePage(breakRecord);
}
_structuralCache.CurrentFormatContext.PopPageData();
OnAfterFormatPage();
_structuralCache.DetectInvalidOperation();
}
return _ptsPage.BreakRecord;
}
//--------------------------------------------------------------------
// Arrange the page contents.
//--------------------------------------------------------------------
internal void Arrange(Size partitionSize)
{
Invariant.Assert(!IsDisposed);
_partitionSize = partitionSize;
using(_structuralCache.SetDocumentArrangeContext(this))
{
_ptsPage.ArrangePage();
_structuralCache.DetectInvalidOperation();
}
ValidateTextView();
}
//-------------------------------------------------------------------
// Page update may be requested more than once before rendering is
// done. But PTS is not able to merge update info.
// To protect against loosing incremental changes delta, need
// to force full formatting for the conent.
//--------------------------------------------------------------------
internal void ForceReformat()
{
Invariant.Assert(!IsDisposed);
// Clear update info for PTS page.
_ptsPage.ClearUpdateInfo();
// Force reformat
_structuralCache.ForceReformat = true;
}
//-------------------------------------------------------------------
// Hit tests to the correct ContentElement within the ContentHost
// that the mouse is over.
//
// point - mouse coordinates relative to the ContentHost
//
// Returns: IInputElement from specified position.
//-------------------------------------------------------------------
internal IInputElement InputHitTestCore(Point point)
{
Invariant.Assert(!IsDisposed);
// Core services require that the IInputElement returned from hittesting
// is a UIElement or it has a parent that is a UIElement.
// When using DocumentPageView.DocumentPaginator directly, we may run
// into case when FlowDocument does not have a logical parent. In
// such case it is better to disable all core services.
DependencyObject frameworkParent = FrameworkElement.GetFrameworkParent(_structuralCache.FormattingOwner);
if (frameworkParent == null)
{
return null;
}
IInputElement ie = null;
if (this.IsLayoutDataValid)
{
// Transform point to PtsPage coordinate system.
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
transform = transform.Inverse;
// Hittest PtsPage only when transform can be inverted in order to calculate
// point within PtsPage. If transform cannot be inverted, return the owner of this page.
if (transform != null)
{
point = transform.Transform(point);
ie = _ptsPage.InputHitTest(point);
}
}
return (ie != null) ? ie : _structuralCache.FormattingOwner as IInputElement;
}
///
/// Returns rectangles for element. First finds element by navigating in FlowDocumentPage.
/// If element is not found or if call to get rectangles from FlowDocumentPage returns null
/// we return an empty collection. If the layout is not valid we return null.
///
///
/// Content element for which rectangles are required
///
///
/// Indicates whether search should be restricted only to those text segments within the page's text view
///
internal ReadOnlyCollection GetRectanglesCore(ContentElement child, bool isLimitedToTextView)
{
Invariant.Assert(!IsDisposed);
List rectangles = new List();
Debug.Assert(child != null);
if (IsLayoutDataValid)
{
TextPointer elementStart = FindElementPosition(child, isLimitedToTextView);
if (elementStart != null)
{
// Element exists within this Page, calculate its length
int elementStartOffset = _structuralCache.TextContainer.Start.GetOffsetToPosition(elementStart);
int elementLength = 1;
if (child is TextElement)
{
TextPointer elementEnd = new TextPointer(((TextElement)child).ElementEnd);
elementLength = elementStart.GetOffsetToPosition(elementEnd);
}
rectangles = _ptsPage.GetRectangles(child, elementStartOffset, elementLength);
}
}
if(this.PageVisual != null && rectangles.Count > 0)
{
List transformedRectangles = new List(rectangles.Count);
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
for(int index = 0; index < rectangles.Count; index++)
{
transformedRectangles.Add(transform.TransformBounds(rectangles[index]));
}
rectangles = transformedRectangles;
}
// We should never return null for rectangles from public API, only empty ArrayList
Invariant.Assert(rectangles != null);
return new ReadOnlyCollection(rectangles);
}
///
/// Returns elements hosted by the content host as an enumerator class
///
internal IEnumerator HostedElementsCore
{
get
{
if (IsLayoutDataValid)
{
// At this point, we should create TextView if it doesn't exist
_textView = GetTextView();
Invariant.Assert(_textView != null && ((ITextView)_textView).TextSegments.Count > 0);
return new HostedElements(((ITextView)_textView).TextSegments);
}
else
{
// Return empty collection
return new HostedElements(new ReadOnlyCollection(new List(0)));
}
}
}
// Floating element list
internal ReadOnlyCollection FloatingElementResults
{
get
{
List floatingElements = new List(0);
List floatingElementList = _ptsPage.PageContext.FloatingElementList;
if (floatingElementList != null)
{
for (int i = 0; i < floatingElementList.Count; i++)
{
ParagraphResult paragraphResult = floatingElementList[i].CreateParagraphResult();
floatingElements.Add(paragraphResult);
}
}
return new ReadOnlyCollection(floatingElements);
}
}
///
/// Called when a UIElement-derived class which is hosted by a IContentHost changes it’s DesiredSize
///
///
/// Child element whose DesiredSize has changed
///
internal void OnChildDesiredSizeChangedCore(UIElement child)
{
_structuralCache.FormattingOwner.OnChildDesiredSizeChanged(child);
}
//-------------------------------------------------------------------
// Returns a new collection of ColumnResults for the page. Will always
// have at least one column.
// hasTextContent - True if any column in the page has text
// content, i.e. does not contain only figures/floaters
//--------------------------------------------------------------------
///
/// Critical - as this call Critical functions FsQueryPageDetails, FsQueryTrackDetails,
/// FsQuerySectionDetails and some PtsHelper functions.
/// Safe - as this can't be be used to pass arbitrary parameters. All parameters passed
/// in are either Critical for set or are generated within the function.
///
[SecurityCritical, SecurityTreatAsSafe]
internal ReadOnlyCollection GetColumnResults(out bool hasTextContent)
{
Invariant.Assert(!IsDisposed);
List columnResults = new List(0);
// hasTextContent is set to true if any of the columns in the page has text content. This is determined by checking the columns'
// paragraph collections
hasTextContent = false;
// There are 3 cases:
// (1) PTS page is not created - no columns are available.
// (2) PTS page - use page PTS APIs to get columns.
if (_ptsPage.PageHandle == IntPtr.Zero)
{
// (1) PTS page is not created
}
else
{
// (2) PTS page - use page PTS APIs to get columns.
PTS.FSPAGEDETAILS pageDetails;
PTS.Validate(PTS.FsQueryPageDetails(StructuralCache.PtsContext.Context, _ptsPage.PageHandle, out pageDetails));
// There are 2 different types of PTS page:
// (a) simple page (contains only one track) - 1 column.
// (b) complex page (contains header, page body, footnotes and footer) - get columns
// from the page body.
if (PTS.ToBoolean(pageDetails.fSimple))
{
// (a) simple page (contains only one track) - 1 column.
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pageDetails.u.simple.trackdescr.pfstrack, out trackDetails));
if (trackDetails.cParas > 0)
{
columnResults = new List(1);
ColumnResult columnResult = new ColumnResult(this, ref pageDetails.u.simple.trackdescr, new Vector());
columnResults.Add(columnResult);
if (columnResult.HasTextContent)
{
hasTextContent = true;
}
}
}
else if (pageDetails.u.complex.cSections > 0)
{
// (b) complex page (contains header, page body, footnotes and footer) - get columns
// from the page body.
Debug.Assert(pageDetails.u.complex.cSections == 1); // Only one section is supported right now.
// Retrieve description for each section.
PTS.FSSECTIONDESCRIPTION[] arraySectionDesc;
PtsHelper.SectionListFromPage(StructuralCache.PtsContext, _ptsPage.PageHandle, ref pageDetails, out arraySectionDesc);
// Get section details
PTS.FSSECTIONDETAILS sectionDetails;
PTS.Validate(PTS.FsQuerySectionDetails(StructuralCache.PtsContext.Context, arraySectionDesc[0].pfssection, out sectionDetails));
// There are 2 types of sections:
// (1) with page notes - footnotes in section treated as endnotes
// (2) with column notes - footnotes in section treated as column notes
if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes))
{
// (1) with page notes - footnotes in section treated as endnotes
Debug.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0); // Footnotes are not supported yet.
//
Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0);
Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0);
// cBasicColumns == 0, means that section content is empty.
// In such case there is nothing to render.
if (sectionDetails.u.withpagenotes.cBasicColumns > 0)
{
// Retrieve description for each column.
PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
PtsHelper.TrackListFromSection(StructuralCache.PtsContext, arraySectionDesc[0].pfssection, ref sectionDetails, out arrayColumnDesc);
columnResults = new List(sectionDetails.u.withpagenotes.cBasicColumns);
for (int i = 0; i < arrayColumnDesc.Length; i++)
{
PTS.FSTRACKDESCRIPTION columnDesc = arrayColumnDesc[i];
// Column may have null track, in which case we should not add it
if (columnDesc.pfstrack != IntPtr.Zero)
{
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, columnDesc.pfstrack, out trackDetails));
if (trackDetails.cParas > 0)
{
ColumnResult columnResult = new ColumnResult(this, ref columnDesc, new Vector());
columnResults.Add(columnResult);
if (columnResult.HasTextContent)
{
hasTextContent = true;
}
}
}
}
}
// else; section empty => no columns
}
else
{
// (2) with column notes - footnotes in section treated as column notes
Debug.Assert(false); // Complex columns are not supported yet.
}
}
}
Invariant.Assert(columnResults != null);
return new ReadOnlyCollection(columnResults);
}
//-------------------------------------------------------------------
// Retrieves text range for contents of the column represented
// by 'pfstrack'.
//
// pfstrack - pointer to PTS track representing a column
//
// Returns: text range for contents of the column represented by 'pfstrack'
//--------------------------------------------------------------------
///
/// Critical - as this calls Critical function PTS.FsQueryTrackDetails and
/// passes an IntPtr directly.
///
[SecurityCritical]
internal TextContentRange GetTextContentRangeFromColumn(IntPtr pfstrack)
{
Invariant.Assert(!IsDisposed);
// Get track details
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pfstrack, out trackDetails));
// Combine ranges from all nested paragraphs.
TextContentRange textContentRange = new TextContentRange();
if (trackDetails.cParas != 0)
{
PTS.FSPARADESCRIPTION[] arrayParaDesc;
PtsHelper.ParaListFromTrack(StructuralCache.PtsContext, pfstrack, ref trackDetails, out arrayParaDesc);
// Merge TextContentRanges for all paragraphs
BaseParaClient paraClient;
for (int i = 0; i < arrayParaDesc.Length; i++)
{
paraClient = this.StructuralCache.PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
PTS.ValidateHandle(paraClient);
textContentRange.Merge(paraClient.GetTextContentRange());
}
}
return textContentRange;
}
//--------------------------------------------------------------------
// Returns a collection of ParagraphResults for the column's paragraphs.
//
// pfstrack - pointer to PTS track representing a column
// parentOffset - parent offset from the top of the page
// hasTextContent - true if any paragraph in the column has some text content
//
// Returns: collection of ParagraphResults for the column's paragraphs
//-------------------------------------------------------------------
///
/// Critical - as this calls Critical function PTS.FsQueryTrackDetails and
/// passes an IntPtr directly.
///
[SecurityCritical]
internal ReadOnlyCollection GetParagraphResultsFromColumn(IntPtr pfstrack, Vector parentOffset, out bool hasTextContent)
{
Invariant.Assert(!IsDisposed);
// Get track details
PTS.FSTRACKDETAILS trackDetails;
PTS.Validate(PTS.FsQueryTrackDetails(StructuralCache.PtsContext.Context, pfstrack, out trackDetails));
hasTextContent = false;
if (trackDetails.cParas == 0)
{
return new ReadOnlyCollection(new List(0));
}
PTS.FSPARADESCRIPTION[] arrayParaDesc;
PtsHelper.ParaListFromTrack(StructuralCache.PtsContext, pfstrack, ref trackDetails, out arrayParaDesc);
List paragraphResults = new List(arrayParaDesc.Length);
for (int i = 0; i < arrayParaDesc.Length; i++)
{
BaseParaClient paraClient = StructuralCache.PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
PTS.ValidateHandle(paraClient);
ParagraphResult paragraphResult = paraClient.CreateParagraphResult();
if (paragraphResult.HasTextContent)
{
hasTextContent = true;
}
paragraphResults.Add(paragraphResult);
}
return new ReadOnlyCollection(paragraphResults);
}
//--------------------------------------------------------------------
// Notification about new line being formatted.
//-------------------------------------------------------------------
internal void OnFormatLine()
{
Invariant.Assert(!IsDisposed);
++_formattedLinesCount;
}
//-------------------------------------------------------------------
// Ensures visual structure for this document page is clean
//-------------------------------------------------------------------
internal void EnsureValidVisuals()
{
Invariant.Assert(!IsDisposed);
UpdateVisual();
}
//--------------------------------------------------------------------
// Update the viewport
//-------------------------------------------------------------------
internal void UpdateViewport(ref PTS.FSRECT viewport, bool drawBackground)
{
Rect contentViewport;
// Transform point to PtsPage coordinate system.
// NOTE: TransformToAncestor is safe (will never throw an exception).
GeneralTransform transform = this.PageVisual.Child.TransformToAncestor(this.PageVisual);
transform = transform.Inverse;
contentViewport = viewport.FromTextDpi();
if (transform != null)
{
contentViewport = transform.TransformBounds(contentViewport);
}
if(!IsDisposed)
{
// Draw background
if (drawBackground)
{
this.PageVisual.DrawBackground((Brush)_structuralCache.PropertyOwner.GetValue(FlowDocument.BackgroundProperty), contentViewport);
}
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
PTS.FSRECT contentViewportTextDpi = new PTS.FSRECT(contentViewport);
_ptsPage.UpdateViewport(ref contentViewportTextDpi);
_structuralCache.DetectInvalidOperation();
}
ValidateTextView();
}
}
#endregion Internal methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
//-------------------------------------------------------------------
// Is being used in a plain text box?
//--------------------------------------------------------------------
internal bool UseSizingWorkaroundForTextBox
{
get { return _ptsPage.UseSizingWorkaroundForTextBox; }
set { _ptsPage.UseSizingWorkaroundForTextBox = value; }
}
//-------------------------------------------------------------------
// Margin of the page.
//-------------------------------------------------------------------
internal Thickness Margin { get { return _pageMargin; } }
//-------------------------------------------------------------------
// Is this page already disposed?
//--------------------------------------------------------------------
internal bool IsDisposed { get { return (_disposed != 0) || _structuralCache.PtsContext.Disposed; } }
//-------------------------------------------------------------------
// Size of content on page.
//--------------------------------------------------------------------
internal Size ContentSize
{
get
{
Size size = _ptsPage.ContentSize;
size.Width += _pageMargin.Left + _pageMargin.Right;
size.Height += _pageMargin.Top + _pageMargin.Bottom;
return size;
}
}
//--------------------------------------------------------------------
// Is it finite page or bottomless?
//-------------------------------------------------------------------
internal bool FinitePage { get { return _ptsPage.FinitePage; } }
//--------------------------------------------------------------------
// Page context
//-------------------------------------------------------------------
internal PageContext PageContext { get { return _ptsPage.PageContext; } }
//-------------------------------------------------------------------
// Is during incremental update mode?
//-------------------------------------------------------------------
internal bool IncrementalUpdate { get { return _ptsPage.IncrementalUpdate; } }
//--------------------------------------------------------------------
// StructuralCache associated with this page.
//-------------------------------------------------------------------
internal StructuralCache StructuralCache { get { return _structuralCache; } }
//--------------------------------------------------------------------
// Number of lines formatted during page formatting.
//--------------------------------------------------------------------
internal int FormattedLinesCount { get { return _formattedLinesCount; } }
//-------------------------------------------------------------------
// Is layout data is in a valid state.
//--------------------------------------------------------------------
internal bool IsLayoutDataValid
{
get
{
bool layoutDataValid = false;
if (!IsDisposed)
{
// In case of any content/properties changes FlowDocument does BreakRecordTable
// management and disposes any affected pages. So it is unnecessary to check
// for DtrList of ForceReformat here, because _disposed flag reflects this fact
// in more granular way.
layoutDataValid = _structuralCache.FormattingOwner.IsLayoutDataValid;
}
return layoutDataValid;
}
}
//-------------------------------------------------------------------
// Save the maximum dcpDepend of the page, for invalidations
// of later pages.
//
// DCPDepend - number of characters past end of page that were
// considered for formatting of this page
//-------------------------------------------------------------------
internal TextPointer DependentMax
{
get
{
return _DependentMax;
}
set
{
if ((_DependentMax == null) || ((value != null) && (value.CompareTo(_DependentMax) > 0)))
{
_DependentMax = value;
}
}
}
//-------------------------------------------------------------------
// Viewport
//--------------------------------------------------------------------
internal Rect Viewport
{
get
{
return new Rect(this.Size);
}
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------
#region Private Methods
///
/// Destroy all unmanaged resources.
///
/// Whether dispose is caused by explicit call to Dispose.
///
/// Finalizer needs to follow rules below:
/// a) Your Finalize method must tolerate partially constructed instances.
/// b) Your Finalize method must consider the consequence of failure.
/// c) Your object is callable after Finalization.
/// d) Your object is callable during Finalization.
/// e) Your Finalizer could be called multiple times.
/// f) Your Finalizer runs in a delicate security context.
/// See: http://blogs.msdn.com/[....]/archive/2004/02/20/77460.aspx
///
private void Dispose(bool disposing)
{
// Do actual dispose only once.
if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0)
{
if (disposing)
{
// Clear content of the root visual
if (this.PageVisual != null)
{
// Disconnect all embedded visuals (UIElements) to make sure that
// they are not part of visual tree when page is destroyed.
// This is necessary for building proper event route, because
// BuildRoute prefers visual tree.
DestroyVisualLinks(this.PageVisual);
// Clear its drawing context and children collection.
this.PageVisual.Children.Clear();
this.PageVisual.ClearDrawingContext();
}
// Dispose PTS page
if (_ptsPage != null)
{
_ptsPage.Dispose();
}
}
try
{
if (disposing)
{
// Notify interested parties about disposal of the page.
OnPageDestroyed(EventArgs.Empty);
}
}
finally
{
_ptsPage = null;
_structuralCache = null;
_textView = null;
_DependentMax = null;
}
}
}
//--------------------------------------------------------------------
// Update visual representation of the page.
//-------------------------------------------------------------------
private void UpdateVisual()
{
if (this.PageVisual == null)
{
SetVisual(new PageVisual(this));
}
if (_visualNeedsUpdate)
{
// Draw background
this.PageVisual.DrawBackground((Brush)_structuralCache.PropertyOwner.GetValue(FlowDocument.BackgroundProperty), new Rect(_partitionSize));
// Connect visual created by PTS page.
ContainerVisual pageVisual = null;
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
pageVisual = _ptsPage.GetPageVisual(); // This method will update the visual tree if necessary.
_structuralCache.DetectInvalidOperation();
}
this.PageVisual.Child = pageVisual; // No-op if already connected.
// DocumentPage.Visual for printing scenarions needs to be always returned
// in LeftToRight FlowDirection. Hence, if the document is RightToLeft,
// mirroring transform need to be applied to the content of DocumentPage.Visual.
FlowDirection flowdirection = (FlowDirection)_structuralCache.PropertyOwner.GetValue(FlowDocument.FlowDirectionProperty);
PtsHelper.UpdateMirroringTransform(FlowDirection.LeftToRight, flowdirection, pageVisual, Size.Width);
// Clear update info for PTS page.
using (_structuralCache.SetDocumentVisualValidationContext(this))
{
_ptsPage.ClearUpdateInfo();
_structuralCache.DetectInvalidOperation();
}
_visualNeedsUpdate = false;
}
}
//--------------------------------------------------------------------
// Prepares for format page process.
//-------------------------------------------------------------------
private void OnBeforeFormatPage()
{
if (_visualNeedsUpdate)
{
// Clear update info for PTS page.
_ptsPage.ClearUpdateInfo();
}
}
//-------------------------------------------------------------------
// Completes format page process.
//-------------------------------------------------------------------
private void OnAfterFormatPage()
{
if (_textView != null)
{
_textView.Invalidate();
}
_visualNeedsUpdate = true;
}
//--------------------------------------------------------------------
// IContentHost Helpers
//-------------------------------------------------------------------
///
/// Searches for an element in the _structuralCache.TextContainer. If the element is found, returns the
/// position at which it is found. Otherwise returns null.
///
///
/// Element to be found.
///
///
/// bool value indicating whether the search should only be limited to the text view of the page,
/// in which case we search only text segments in the text view
///
private TextPointer FindElementPosition(IInputElement e, bool isLimitedToTextView)
{
// Parameter validation
Debug.Assert(e != null);
// Validate that this function is only called when a TextContainer exists as complex content
Debug.Assert(_structuralCache.TextContainer is TextContainer);
TextPointer elementPosition = null;
// If e is a TextElement we can optimize by checking its TextContainer
if (e is TextElement)
{
if ((e as TextElement).TextContainer == _structuralCache.TextContainer)
{
// Element found
elementPosition = new TextPointer((e as TextElement).ElementStart);
}
// else: elementPosition stays null
}
else
{
// Else: search for e in the complex content
if (!(_structuralCache.TextContainer.Start is TextPointer) ||
!(_structuralCache.TextContainer.End is TextPointer))
{
// Invalid TextContainer, don't search
return null;
}
TextPointer searchPosition = new TextPointer(_structuralCache.TextContainer.Start as TextPointer);
while (elementPosition == null && ((ITextPointer)searchPosition).CompareTo(_structuralCache.TextContainer.End) < 0)
{
// Search each position in _structuralCache.TextContainer for the element
switch (searchPosition.GetPointerContext(LogicalDirection.Forward))
{
case TextPointerContext.EmbeddedElement:
DependencyObject embeddedObject = searchPosition.GetAdjacentElement(LogicalDirection.Forward);
if (embeddedObject is ContentElement || embeddedObject is UIElement)
{
if (embeddedObject == e as ContentElement || embeddedObject == e as UIElement)
{
// Element found. Stop searching
elementPosition = new TextPointer(searchPosition);
break;
}
}
break;
default:
break;
}
searchPosition.MoveToNextContextPosition(LogicalDirection.Forward);
}
}
// If the element was found, check if we are limited to text view
if (elementPosition != null)
{
if (isLimitedToTextView)
{
// At this point, we should create TextView if it doesn't exist
_textView = GetTextView();
Invariant.Assert(_textView != null);
// Check all segements in text view for position
for (int segmentIndex = 0; segmentIndex < ((ITextView)_textView).TextSegments.Count; segmentIndex++)
{
if (((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].Start) >= 0 &&
((ITextPointer)elementPosition).CompareTo(((ITextView)_textView).TextSegments[segmentIndex].End) < 0)
{
// Element lies within a segment. Return position
return elementPosition;
}
}
// Element not found in all segments of TextView. Set position to null
elementPosition = null;
}
}
return elementPosition;
}
//--------------------------------------------------------------------
// Disconnect all embedded visuals (UIElements) to make sure that
// they are not part of visual tree when page is destroyed.
// This is necessary for building proper event route, because
// BuildRoute prefers visual tree.
//--------------------------------------------------------------------
private void DestroyVisualLinks(ContainerVisual visual)
{
VisualCollection vc = visual.Children;
if (vc != null)
{
for (int index = 0; index < vc.Count; index++)
{
if (vc[index] is UIElementIsland)
{
vc.RemoveAt(index);
}
else
{
Invariant.Assert(vc[index] is ContainerVisual, "The children should always derive from ContainerVisual");
DestroyVisualLinks((ContainerVisual)(vc[index]));
}
}
}
}
///
/// Raise TextView.Updated event.
///
private void ValidateTextView()
{
if (_textView != null)
{
_textView.OnUpdated();
}
}
///
/// Gets TextView for this page.
///
private TextDocumentView GetTextView()
{
TextDocumentView textView = (TextDocumentView)((IServiceProvider)this).GetService(typeof(ITextView));
Invariant.Assert(textView != null);
return textView;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Properties
//
//--------------------------------------------------------------------
#region Private Properties
//-------------------------------------------------------------------
// Visual representing content of the page.
//-------------------------------------------------------------------
private PageVisual PageVisual
{
get { return (base.Visual as PageVisual); }
}
#endregion Private Properties
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
//-------------------------------------------------------------------
// Associated PTS page.
//--------------------------------------------------------------------
private PtsPage _ptsPage;
//--------------------------------------------------------------------
// Structural cache.
//-------------------------------------------------------------------
private StructuralCache _structuralCache;
//--------------------------------------------------------------------
// Number of lines formatted during page formatting.
// NOTE: This field is used only internally for layout DRTs.
//-------------------------------------------------------------------
private int _formattedLinesCount;
//-------------------------------------------------------------------
// TextView associated with the document page.
//-------------------------------------------------------------------
private TextDocumentView _textView;
//--------------------------------------------------------------------
// Size of partition for the page.
//-------------------------------------------------------------------
private Size _partitionSize;
//--------------------------------------------------------------------
// Margin of the page.
//--------------------------------------------------------------------
private Thickness _pageMargin;
//-------------------------------------------------------------------
// Is it already disposed?
//--------------------------------------------------------------------
private int _disposed;
//-------------------------------------------------------------------
// Max of dcpDepend for page
//-------------------------------------------------------------------
private TextPointer _DependentMax;
//-------------------------------------------------------------------
// Need to update visual?
//--------------------------------------------------------------------
private bool _visualNeedsUpdate;
//-------------------------------------------------------------------
// Width of page during last format
//--------------------------------------------------------------------
private double _lastFormatWidth;
#endregion Private Fields
//--------------------------------------------------------------------
//
// IServiceProvider Members
//
//-------------------------------------------------------------------
#region IServiceProvider Members
//--------------------------------------------------------------------
// Gets the service object of the specified type. FlowDocumentPage
// currently supports only TextView
//
// serviceType - an object that specifies the type of service
// object to get
//
// Returns: A service object of type serviceType. A null reference
// if there is no service object of type serviceType.
//-------------------------------------------------------------------
object IServiceProvider.GetService(Type serviceType)
{
if (serviceType == null)
{
throw new ArgumentNullException("serviceType");
}
if (serviceType == typeof(ITextView))
{
if (_textView == null)
{
_textView = new TextDocumentView(this, _structuralCache.TextContainer);
}
return _textView;
}
return null;
}
#endregion IServiceProvider Members
//-------------------------------------------------------------------
//
// IContentHost Members
//
//-------------------------------------------------------------------
#region IContentHost Members
///
/// Hit tests to the correct ContentElement
/// within the ContentHost that the mouse
/// is over
///
///
/// Mouse coordinates relative to
/// the ContentHost
///
IInputElement IContentHost.InputHitTest(Point point)
{
return this.InputHitTestCore(point);
}
///
/// Returns rectangles for element. First finds element by navigating in FlowDocumentPage.
/// If element is not found or if call to get rectangles from FlowDocumentPage returns null
/// we return an empty collection. If the layout is not valid we return null.
///
///
/// Content element for which rectangles are required
///
ReadOnlyCollection IContentHost.GetRectangles(ContentElement child)
{
// Restrict search to only the text segments in the page's text view. This is not needed for
// HitTest because it takes only a point
return this.GetRectanglesCore(child, true);
}
///
/// Returns elements hosted by the content host as an enumerator class
///
IEnumerator IContentHost.HostedElements
{
get
{
return this.HostedElementsCore as IEnumerator;
}
}
///
/// Called when a UIElement-derived class which is hosted by a IContentHost changes it’s DesiredSize
///
///
/// Child element whose DesiredSize has changed
///
void IContentHost.OnChildDesiredSizeChanged(UIElement child)
{
this.OnChildDesiredSizeChangedCore(child);
}
#endregion IContentHost Members
}
}
// 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
- InfoCardTraceRecord.cs
- CompilerLocalReference.cs
- BreakRecordTable.cs
- ALinqExpressionVisitor.cs
- DataRow.cs
- LookupNode.cs
- CharKeyFrameCollection.cs
- OleServicesContext.cs
- PointAnimation.cs
- XmlSchemaValidator.cs
- CompiledELinqQueryState.cs
- VirtualDirectoryMappingCollection.cs
- Rfc2898DeriveBytes.cs
- DesignTimeData.cs
- LockCookie.cs
- DataGridTableStyleMappingNameEditor.cs
- MinimizableAttributeTypeConverter.cs
- ContextStack.cs
- ParameterCollection.cs
- DynamicValidatorEventArgs.cs
- RadioButtonPopupAdapter.cs
- TextFormatterContext.cs
- ListView.cs
- D3DImage.cs
- StateDesignerConnector.cs
- ChangeBlockUndoRecord.cs
- WindowsFormsSectionHandler.cs
- DefaultPropertiesToSend.cs
- DataFieldCollectionEditor.cs
- LinqDataSourceHelper.cs
- FormParameter.cs
- GetIndexBinder.cs
- FieldAccessException.cs
- SimpleRecyclingCache.cs
- DataGridViewRowCancelEventArgs.cs
- HierarchicalDataSourceControl.cs
- PointCollection.cs
- DesignerValidatorAdapter.cs
- ComEventsMethod.cs
- dtdvalidator.cs
- SQlBooleanStorage.cs
- OuterGlowBitmapEffect.cs
- FileStream.cs
- ReadOnlyDictionary.cs
- CursorConverter.cs
- BehaviorEditorPart.cs
- BindingValueChangedEventArgs.cs
- TripleDESCryptoServiceProvider.cs
- SchemaImporter.cs
- DesignColumnCollection.cs
- DriveInfo.cs
- CodePropertyReferenceExpression.cs
- RegexCapture.cs
- DataGridViewComboBoxColumn.cs
- CodeDomSerializerException.cs
- ListViewEditEventArgs.cs
- EncoderParameter.cs
- PropertyGroupDescription.cs
- WorkflowQueuingService.cs
- TdsParserHelperClasses.cs
- XPathItem.cs
- DesignBinding.cs
- ValueType.cs
- AssemblyResourceLoader.cs
- ApplyTemplatesAction.cs
- BulletChrome.cs
- LogicalExpr.cs
- Contracts.cs
- DrawingImage.cs
- securitymgrsite.cs
- ToolStripMenuItem.cs
- SimpleMailWebEventProvider.cs
- HttpResponseInternalWrapper.cs
- PrintingPermission.cs
- StreamReader.cs
- ToolStripItemEventArgs.cs
- TableCellAutomationPeer.cs
- SqlCachedBuffer.cs
- PeerName.cs
- TextTabProperties.cs
- TextChange.cs
- SpotLight.cs
- ChtmlSelectionListAdapter.cs
- CustomUserNameSecurityTokenAuthenticator.cs
- SerializationInfoEnumerator.cs
- AtomContentProperty.cs
- KeyInstance.cs
- MailBnfHelper.cs
- ValidationHelpers.cs
- Camera.cs
- SortKey.cs
- SqlMultiplexer.cs
- Console.cs
- Renderer.cs
- DoubleLink.cs
- Cursor.cs
- CharacterString.cs
- TextViewSelectionProcessor.cs
- CacheVirtualItemsEvent.cs
- SessionParameter.cs