Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / MS / Internal / documents / FlowDocumentFormatter.cs / 1 / FlowDocumentFormatter.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// File: FlowDocumentFormatter.cs
//
// Description: Bottomless content formatter associated with FlowDocument.
//
// History:
// 11/07/2005 : grzegorz - created.
//
//---------------------------------------------------------------------------
using System; // Object
using System.Windows; // Size
using System.Windows.Documents; // FlowDocument
using System.Windows.Media; // Visual
using System.Windows.Threading; // DispatcherOperationCallback
using MS.Internal.PtsHost; // FlowDocumentPage
using MS.Internal.PtsHost.UnsafeNativeMethods; // PTS
namespace MS.Internal.Documents
{
///
/// Bottomless content formatter associated with FlowDocument.
///
internal class FlowDocumentFormatter : IFlowDocumentFormatter
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Constructor
///
internal FlowDocumentFormatter(FlowDocument document)
{
_document = document;
_documentPage = new FlowDocumentPage(_document.StructuralCache);
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
///
/// Formatts content.
///
/// Constraint size.
internal void Format(Size constraint)
{
Thickness pageMargin;
Size pageSize;
// Reentrancy check.
if (_document.StructuralCache.IsFormattingInProgress)
{
throw new InvalidOperationException(SR.Get(SRID.FlowDocumentFormattingReentrancy));
}
if (_document.StructuralCache.IsContentChangeInProgress)
{
throw new InvalidOperationException(SR.Get(SRID.TextContainerChangingReentrancyInvalid));
}
// Check if we can continue with formatting without nuking incremental udpate info.
if (_document.StructuralCache.IsFormattedOnce)
{
if (!_lastFormatSuccessful)
{
// We cannot resolve update info if last formatting was unsuccessful.
_document.StructuralCache.InvalidateFormatCache(true);
}
if (!_arrangedAfterFormat && (!_document.StructuralCache.ForceReformat || !_document.StructuralCache.NukeStructure))
{
// Need to clear update info by running arrange process.
// This is necessary, because Format may be called more than once
// before Arrange is called. But PTS is not able to merge update info.
// To protect against loosing incremental changes delta, need
// to arrange the page and create all necessary visuals.
_documentPage.Arrange(_documentPage.ContentSize);
_documentPage.EnsureValidVisuals();
}
}
_arrangedAfterFormat = false;
_lastFormatSuccessful = false;
_isContentFormatValid = false;
pageSize = ComputePageSize(constraint);
pageMargin = ComputePageMargin();
// Disable processing of the queue during blocking operations to prevent unrelated reentrancy.
using (_document.Dispatcher.DisableProcessing())
{
_document.StructuralCache.IsFormattingInProgress = true; // Set reentrancy flag.
try
{
_document.StructuralCache.BackgroundFormatInfo.ViewportHeight = constraint.Height;
_documentPage.FormatBottomless(pageSize, pageMargin);
}
finally
{
_document.StructuralCache.IsFormattingInProgress = false; // Clear reentrancy flag.
}
}
_lastFormatSuccessful = true;
}
///
/// Arranges content.
///
/// Size that element should use to arrange itself and its children.
/// Viewport for visible content.
internal void Arrange(Size arrangeSize, Rect viewport)
{
Invariant.Assert(_document.StructuralCache.DtrList == null || _document.StructuralCache.DtrList.Length == 0 ||
(_document.StructuralCache.DtrList.Length == 1 && _document.StructuralCache.BackgroundFormatInfo.DoesFinalDTRCoverRestOfText));
// Arrange the content and create visual tree.
_documentPage.Arrange(arrangeSize);
_documentPage.EnsureValidVisuals();
_arrangedAfterFormat = true;
// Render content only for the current viewport.
if (viewport.IsEmpty)
{
viewport = new Rect(0, 0, arrangeSize.Width, _document.StructuralCache.BackgroundFormatInfo.ViewportHeight);
}
PTS.FSRECT fsrectViewport = new PTS.FSRECT(viewport);
_documentPage.UpdateViewport(ref fsrectViewport, true);
_isContentFormatValid = true;
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
///
/// DocumentPage representing formatted content.
///
internal FlowDocumentPage DocumentPage
{
get
{
return _documentPage;
}
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Internal Events
//
//--------------------------------------------------------------------
#region Internal Events
///
/// Fired when content has been invalidated.
///
internal event EventHandler ContentInvalidated;
///
/// Fired when formatter has been suspended.
///
internal event EventHandler Suspended;
#endregion Internal Events
//-------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------
#region Private Methods
///
/// Compute size for the page.
///
private Size ComputePageSize(Size constraint)
{
double max, min;
Size pageSize = new Size(_document.PageWidth, double.PositiveInfinity);
if (DoubleUtil.IsNaN(pageSize.Width))
{
pageSize.Width = constraint.Width;
max = _document.MaxPageWidth;
if (pageSize.Width > max)
{
pageSize.Width = max;
}
min = _document.MinPageWidth;
if (pageSize.Width < min)
{
pageSize.Width = min;
}
}
// If the width is Double.PositiveInfinity, crop it to predefined value.
if (double.IsPositiveInfinity(pageSize.Width))
{
pageSize.Width = _defaultWidth;
}
return pageSize;
}
///
/// Compute margin for the page.
///
private Thickness ComputePageMargin()
{
double lineHeight = MS.Internal.Text.DynamicPropertyReader.GetLineHeightValue(_document);
Thickness pageMargin = _document.PagePadding;
// If Padding value is 'Auto', treat it as 1*LineHeight.
if (DoubleUtil.IsNaN(pageMargin.Left))
{
pageMargin.Left = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Top))
{
pageMargin.Top = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Right))
{
pageMargin.Right = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Bottom))
{
pageMargin.Bottom = lineHeight;
}
return pageMargin;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
///
/// FlowDocument associated with the paginator.
///
private readonly FlowDocument _document;
///
/// DocumentPage representing formatted content.
///
private FlowDocumentPage _documentPage;
///
/// Whether Arrange was called after formatting.
///
private bool _arrangedAfterFormat;
///
/// Whether last formatting was succesful.
///
private bool _lastFormatSuccessful;
///
/// Width used when no width is specified.
///
private const double _defaultWidth = 500.0;
///
/// Whether the current format for the content is valid
///
private bool _isContentFormatValid = false;
#endregion Private Fields
//-------------------------------------------------------------------
//
// IFlowDocumentFormatter Members
//
//--------------------------------------------------------------------
#region IFlowDocumentFormatter Members
///
/// Responds to change affecting entire content of associated FlowDocument.
///
/// Whether change affects layout.
void IFlowDocumentFormatter.OnContentInvalidated(bool affectsLayout)
{
// If change happens before we've been arranged, we need to do a full reformat
if (affectsLayout)
{
if(!_arrangedAfterFormat)
{
_document.StructuralCache.InvalidateFormatCache(true);
}
_isContentFormatValid = false;
}
if (ContentInvalidated != null)
{
ContentInvalidated(this, EventArgs.Empty);
}
}
///
/// Responds to change affecting entire content of associated FlowDocument.
///
/// Whether change affects layout.
/// Start of the affected content range.
/// End of the affected content range.
void IFlowDocumentFormatter.OnContentInvalidated(bool affectsLayout, ITextPointer start, ITextPointer end)
{
((IFlowDocumentFormatter)this).OnContentInvalidated(affectsLayout);
}
///
/// Suspend formatting.
///
void IFlowDocumentFormatter.Suspend()
{
if (Suspended != null)
{
Suspended(this, EventArgs.Empty);
}
}
///
/// Is layout data in a valid state.
///
bool IFlowDocumentFormatter.IsLayoutDataValid
{
get
{
// Layout is clean only when the page is calculated and it
// is in the clean state - there are no pending changes that affect layout.
//
// Hittest can be called with invalid arrange. This happens in
// following situation:
// Something is causing to call InvalidateTree and eventually
// InvalidateAllProperties will be called in such case. In responce
// to that following properties are invalidated:
// * ClipToBounds - invalidates arrange
// * IsEnabled - calls MouseDevice.Synchronize and it will eventually
// do hittesting.
//
// OR
// TextContainer sends Changing event, which invalidates measure,
// but we have not yet received a matching Changed event.
//
// So, it is possible to receive hittesting request on dirty layout.
bool layoutValid = _documentPage != null &&
_document.StructuralCache.IsFormattedOnce &&
!_document.StructuralCache.ForceReformat &&
_isContentFormatValid &&
!_document.StructuralCache.IsContentChangeInProgress &&
!_document.StructuralCache.IsFormattingInProgress;
return layoutValid;
}
}
#endregion IFlowDocumentFormatter 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.
//
// File: FlowDocumentFormatter.cs
//
// Description: Bottomless content formatter associated with FlowDocument.
//
// History:
// 11/07/2005 : grzegorz - created.
//
//---------------------------------------------------------------------------
using System; // Object
using System.Windows; // Size
using System.Windows.Documents; // FlowDocument
using System.Windows.Media; // Visual
using System.Windows.Threading; // DispatcherOperationCallback
using MS.Internal.PtsHost; // FlowDocumentPage
using MS.Internal.PtsHost.UnsafeNativeMethods; // PTS
namespace MS.Internal.Documents
{
///
/// Bottomless content formatter associated with FlowDocument.
///
internal class FlowDocumentFormatter : IFlowDocumentFormatter
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Constructor
///
internal FlowDocumentFormatter(FlowDocument document)
{
_document = document;
_documentPage = new FlowDocumentPage(_document.StructuralCache);
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
///
/// Formatts content.
///
/// Constraint size.
internal void Format(Size constraint)
{
Thickness pageMargin;
Size pageSize;
// Reentrancy check.
if (_document.StructuralCache.IsFormattingInProgress)
{
throw new InvalidOperationException(SR.Get(SRID.FlowDocumentFormattingReentrancy));
}
if (_document.StructuralCache.IsContentChangeInProgress)
{
throw new InvalidOperationException(SR.Get(SRID.TextContainerChangingReentrancyInvalid));
}
// Check if we can continue with formatting without nuking incremental udpate info.
if (_document.StructuralCache.IsFormattedOnce)
{
if (!_lastFormatSuccessful)
{
// We cannot resolve update info if last formatting was unsuccessful.
_document.StructuralCache.InvalidateFormatCache(true);
}
if (!_arrangedAfterFormat && (!_document.StructuralCache.ForceReformat || !_document.StructuralCache.NukeStructure))
{
// Need to clear update info by running arrange process.
// This is necessary, because Format may be called more than once
// before Arrange is called. But PTS is not able to merge update info.
// To protect against loosing incremental changes delta, need
// to arrange the page and create all necessary visuals.
_documentPage.Arrange(_documentPage.ContentSize);
_documentPage.EnsureValidVisuals();
}
}
_arrangedAfterFormat = false;
_lastFormatSuccessful = false;
_isContentFormatValid = false;
pageSize = ComputePageSize(constraint);
pageMargin = ComputePageMargin();
// Disable processing of the queue during blocking operations to prevent unrelated reentrancy.
using (_document.Dispatcher.DisableProcessing())
{
_document.StructuralCache.IsFormattingInProgress = true; // Set reentrancy flag.
try
{
_document.StructuralCache.BackgroundFormatInfo.ViewportHeight = constraint.Height;
_documentPage.FormatBottomless(pageSize, pageMargin);
}
finally
{
_document.StructuralCache.IsFormattingInProgress = false; // Clear reentrancy flag.
}
}
_lastFormatSuccessful = true;
}
///
/// Arranges content.
///
/// Size that element should use to arrange itself and its children.
/// Viewport for visible content.
internal void Arrange(Size arrangeSize, Rect viewport)
{
Invariant.Assert(_document.StructuralCache.DtrList == null || _document.StructuralCache.DtrList.Length == 0 ||
(_document.StructuralCache.DtrList.Length == 1 && _document.StructuralCache.BackgroundFormatInfo.DoesFinalDTRCoverRestOfText));
// Arrange the content and create visual tree.
_documentPage.Arrange(arrangeSize);
_documentPage.EnsureValidVisuals();
_arrangedAfterFormat = true;
// Render content only for the current viewport.
if (viewport.IsEmpty)
{
viewport = new Rect(0, 0, arrangeSize.Width, _document.StructuralCache.BackgroundFormatInfo.ViewportHeight);
}
PTS.FSRECT fsrectViewport = new PTS.FSRECT(viewport);
_documentPage.UpdateViewport(ref fsrectViewport, true);
_isContentFormatValid = true;
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
///
/// DocumentPage representing formatted content.
///
internal FlowDocumentPage DocumentPage
{
get
{
return _documentPage;
}
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Internal Events
//
//--------------------------------------------------------------------
#region Internal Events
///
/// Fired when content has been invalidated.
///
internal event EventHandler ContentInvalidated;
///
/// Fired when formatter has been suspended.
///
internal event EventHandler Suspended;
#endregion Internal Events
//-------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------
#region Private Methods
///
/// Compute size for the page.
///
private Size ComputePageSize(Size constraint)
{
double max, min;
Size pageSize = new Size(_document.PageWidth, double.PositiveInfinity);
if (DoubleUtil.IsNaN(pageSize.Width))
{
pageSize.Width = constraint.Width;
max = _document.MaxPageWidth;
if (pageSize.Width > max)
{
pageSize.Width = max;
}
min = _document.MinPageWidth;
if (pageSize.Width < min)
{
pageSize.Width = min;
}
}
// If the width is Double.PositiveInfinity, crop it to predefined value.
if (double.IsPositiveInfinity(pageSize.Width))
{
pageSize.Width = _defaultWidth;
}
return pageSize;
}
///
/// Compute margin for the page.
///
private Thickness ComputePageMargin()
{
double lineHeight = MS.Internal.Text.DynamicPropertyReader.GetLineHeightValue(_document);
Thickness pageMargin = _document.PagePadding;
// If Padding value is 'Auto', treat it as 1*LineHeight.
if (DoubleUtil.IsNaN(pageMargin.Left))
{
pageMargin.Left = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Top))
{
pageMargin.Top = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Right))
{
pageMargin.Right = lineHeight;
}
if (DoubleUtil.IsNaN(pageMargin.Bottom))
{
pageMargin.Bottom = lineHeight;
}
return pageMargin;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
///
/// FlowDocument associated with the paginator.
///
private readonly FlowDocument _document;
///
/// DocumentPage representing formatted content.
///
private FlowDocumentPage _documentPage;
///
/// Whether Arrange was called after formatting.
///
private bool _arrangedAfterFormat;
///
/// Whether last formatting was succesful.
///
private bool _lastFormatSuccessful;
///
/// Width used when no width is specified.
///
private const double _defaultWidth = 500.0;
///
/// Whether the current format for the content is valid
///
private bool _isContentFormatValid = false;
#endregion Private Fields
//-------------------------------------------------------------------
//
// IFlowDocumentFormatter Members
//
//--------------------------------------------------------------------
#region IFlowDocumentFormatter Members
///
/// Responds to change affecting entire content of associated FlowDocument.
///
/// Whether change affects layout.
void IFlowDocumentFormatter.OnContentInvalidated(bool affectsLayout)
{
// If change happens before we've been arranged, we need to do a full reformat
if (affectsLayout)
{
if(!_arrangedAfterFormat)
{
_document.StructuralCache.InvalidateFormatCache(true);
}
_isContentFormatValid = false;
}
if (ContentInvalidated != null)
{
ContentInvalidated(this, EventArgs.Empty);
}
}
///
/// Responds to change affecting entire content of associated FlowDocument.
///
/// Whether change affects layout.
/// Start of the affected content range.
/// End of the affected content range.
void IFlowDocumentFormatter.OnContentInvalidated(bool affectsLayout, ITextPointer start, ITextPointer end)
{
((IFlowDocumentFormatter)this).OnContentInvalidated(affectsLayout);
}
///
/// Suspend formatting.
///
void IFlowDocumentFormatter.Suspend()
{
if (Suspended != null)
{
Suspended(this, EventArgs.Empty);
}
}
///
/// Is layout data in a valid state.
///
bool IFlowDocumentFormatter.IsLayoutDataValid
{
get
{
// Layout is clean only when the page is calculated and it
// is in the clean state - there are no pending changes that affect layout.
//
// Hittest can be called with invalid arrange. This happens in
// following situation:
// Something is causing to call InvalidateTree and eventually
// InvalidateAllProperties will be called in such case. In responce
// to that following properties are invalidated:
// * ClipToBounds - invalidates arrange
// * IsEnabled - calls MouseDevice.Synchronize and it will eventually
// do hittesting.
//
// OR
// TextContainer sends Changing event, which invalidates measure,
// but we have not yet received a matching Changed event.
//
// So, it is possible to receive hittesting request on dirty layout.
bool layoutValid = _documentPage != null &&
_document.StructuralCache.IsFormattedOnce &&
!_document.StructuralCache.ForceReformat &&
_isContentFormatValid &&
!_document.StructuralCache.IsContentChangeInProgress &&
!_document.StructuralCache.IsFormattingInProgress;
return layoutValid;
}
}
#endregion IFlowDocumentFormatter 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
- EntityContainerEntitySetDefiningQuery.cs
- DataSourceCollectionBase.cs
- MetadataElement.cs
- DocumentViewerConstants.cs
- InstanceKey.cs
- Html32TextWriter.cs
- DetailsViewPagerRow.cs
- SqlIdentifier.cs
- GridEntry.cs
- GradientStop.cs
- XmlTypeAttribute.cs
- CorrelationResolver.cs
- DockPanel.cs
- RoutedCommand.cs
- HMACSHA512.cs
- NavigateEvent.cs
- TextPattern.cs
- SapiAttributeParser.cs
- ManagementOptions.cs
- _IPv6Address.cs
- FrameSecurityDescriptor.cs
- BitmapEncoder.cs
- XXXOnTypeBuilderInstantiation.cs
- HtmlTableRow.cs
- SystemThemeKey.cs
- ProxyWebPart.cs
- Pick.cs
- SoapHeaderAttribute.cs
- BoolLiteral.cs
- CachedCompositeFamily.cs
- EncoderReplacementFallback.cs
- WindowsFormsHostPropertyMap.cs
- FileBasedResourceGroveler.cs
- UITypeEditor.cs
- OracleParameterBinding.cs
- formatter.cs
- CodeTypeMemberCollection.cs
- PagedControl.cs
- CompilerGeneratedAttribute.cs
- LabelAutomationPeer.cs
- Function.cs
- CFGGrammar.cs
- NativeCppClassAttribute.cs
- ReturnType.cs
- RelationshipType.cs
- IntSecurity.cs
- SpotLight.cs
- AssociatedControlConverter.cs
- RequestSecurityTokenForRemoteTokenFactory.cs
- DataTableTypeConverter.cs
- QuaternionValueSerializer.cs
- Style.cs
- CodeDirectoryCompiler.cs
- SmiXetterAccessMap.cs
- RMEnrollmentPage2.cs
- DataGridViewAdvancedBorderStyle.cs
- Number.cs
- InfocardChannelParameter.cs
- Point3DIndependentAnimationStorage.cs
- GlobalDataBindingHandler.cs
- OleDbSchemaGuid.cs
- GenericIdentity.cs
- HandoffBehavior.cs
- AccessDataSourceDesigner.cs
- Visitor.cs
- GPPOINT.cs
- XmlSchemaDatatype.cs
- ConfigPathUtility.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- Vertex.cs
- DocumentViewerAutomationPeer.cs
- InProcStateClientManager.cs
- KeyedQueue.cs
- EncoderParameter.cs
- DataViewManager.cs
- ActivationWorker.cs
- DateBoldEvent.cs
- Token.cs
- EncodedStreamFactory.cs
- ErrorWrapper.cs
- WebReferencesBuildProvider.cs
- TextReader.cs
- QuotedStringFormatReader.cs
- DragDeltaEventArgs.cs
- LiteralTextContainerControlBuilder.cs
- InputReport.cs
- WsiProfilesElement.cs
- StrokeFIndices.cs
- UidManager.cs
- TableCell.cs
- DataStorage.cs
- Binding.cs
- __FastResourceComparer.cs
- FileUtil.cs
- TreeIterators.cs
- BinaryFormatterWriter.cs
- ContentPlaceHolder.cs
- PolyLineSegment.cs
- WebHttpBehavior.cs
- ReturnValue.cs