Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / PtsHost / BreakRecordTable.cs / 1 / BreakRecordTable.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// Description: BreakRecordTable manages cached informaion bout pages and
// break records of FlowDocument contnet.
//
// History:
// 01/24/2004 : [....] - Created
//
//---------------------------------------------------------------------------
using System; // WeakReference, ...
using System.Collections.Generic; // List
using System.Collections.ObjectModel; // ReadOnlyCollection
using System.Windows.Documents; // FlowDocument, TextPointer
using MS.Internal.Documents; // TextDocumentView
namespace MS.Internal.PtsHost
{
///
/// BreakRecordTable manages cached informaion bout pages and break
/// records of FlowDocument contnet.
///
internal sealed class BreakRecordTable
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Constructor.
///
/// Ownder of the BreakRecordTable.
internal BreakRecordTable(FlowDocumentPaginator owner)
{
_owner = owner;
_breakRecords = new List();
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
///
/// Retrieves input BreakRecord for given PageNumber.
///
///
/// Page index indicating which input BreakRecord should be retrieved.
/// Input BreakRecord for given PageNumber.
internal PageBreakRecord GetPageBreakRecord(int pageNumber)
{
PageBreakRecord breakRecord = null;
Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber.");
// Input BreakRecord for the first page is always NULL.
// For the rest of pages, go to the entry preceding requested index and
// return the output BreakRecord.
if (pageNumber > 0)
{
Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry.");
breakRecord = _breakRecords[pageNumber - 1].BreakRecord;
Invariant.Assert(breakRecord != null, "BreakRecord can be null only for the first page.");
}
return breakRecord;
}
///
/// Retrieves cached DocumentPage for given PageNumber.
///
///
/// Page index indicating which cached DocumentPage should be retrieved.
///
/// Cached DocumentPage for given PageNumber.
internal FlowDocumentPage GetCachedDocumentPage(int pageNumber)
{
WeakReference pageRef;
FlowDocumentPage documentPage = null;
if (pageNumber < _breakRecords.Count)
{
Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry.");
pageRef = _breakRecords[pageNumber].DocumentPage;
if (pageRef != null)
{
documentPage = pageRef.Target as FlowDocumentPage;
if (documentPage != null && documentPage.IsDisposed)
{
documentPage = null;
}
}
}
return documentPage;
}
///
/// Retrieves PageNumber for specified ContentPosition.
///
///
/// Represents content position for which PageNumber is requested.
/// Starting index for search process.
///
/// Returns true, if successfull. 'pageNumber' is updated with actual
/// page number that contains specified ContentPosition.
/// Returns false, if BreakRecordTable is missing information about
/// page that contains specified ContentPosition. 'pageNumber'
/// is updated with the last investigated page number.
///
internal bool GetPageNumberForContentPosition(TextPointer contentPosition, ref int pageNumber)
{
bool foundPageNumber = false;
ReadOnlyCollection textSegments;
Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber.");
// Iterate through entries in the BreakRecordTable (starting from specified index)
// and look for page that contains specified ContentPosition.
// NOTE: For each cached page collection of TextSegments is stored to
// optimize this search.
while (pageNumber < _breakRecords.Count)
{
Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry.");
textSegments = _breakRecords[pageNumber].TextSegments;
if (textSegments != null)
{
if (TextDocumentView.Contains(contentPosition, textSegments))
{
foundPageNumber = true;
break;
}
}
else
{
// There is no information about this page.
break;
}
++pageNumber;
}
return foundPageNumber;
}
///
/// Layout of entire content has been affected.
///
internal void OnInvalidateLayout()
{
if (_breakRecords.Count > 0)
{
// Destroy all affected BreakRecords.
InvalidateBreakRecords(0, _breakRecords.Count);
// Initiate the next async operation.
_owner.InitiateNextAsyncOperation();
// Raise PagesChanged event. Start with the first page and set
// count to Int.Max/2, because somebody might want to display a page
// that wasn't available before, but will be right now.
_owner.OnPagesChanged(0, int.MaxValue/2);
}
}
///
/// Layout for specified range has been affected.
///
/// Start of the affected content range.
/// End of the affected content range.
internal void OnInvalidateLayout(ITextPointer start, ITextPointer end)
{
int pageStart, pageCount;
if (_breakRecords.Count > 0)
{
// Get range of affected pages and dispose them
GetAffectedPages(start, end, out pageStart, out pageCount);
// Currently there is no possibility to do partial invalidation
// of BreakRecordTable, so always extend pageCount to the end
// of BreakRecordTable.
pageCount = _breakRecords.Count - pageStart;
if (pageCount > 0)
{
// Destroy all affected BreakRecords.
InvalidateBreakRecords(pageStart, pageCount);
// Initiate the next async operation.
_owner.InitiateNextAsyncOperation();
// Raise PagesChanged event. Start with the first affected page and set
// count to Int.Max/2, because somebody might want to display a page
// that wasn't available before, but will be right now.
_owner.OnPagesChanged(pageStart, int.MaxValue/2);
}
}
}
///
/// Rendering of entire content has been affected.
///
internal void OnInvalidateRender()
{
if (_breakRecords.Count > 0)
{
// Dispose all existing pages.
DisposePages(0, _breakRecords.Count);
// Raise PagesChanged event. Start with the first page and set
// count to this.Count (number of pages have not been changed).
_owner.OnPagesChanged(0, _breakRecords.Count);
}
}
///
/// Rendering for specified range has been affected.
///
/// Start of the affected content range.
/// End of the affected content range.
internal void OnInvalidateRender(ITextPointer start, ITextPointer end)
{
int pageStart, pageCount;
if (_breakRecords.Count > 0)
{
// Get range of affected pages and dispose them.
GetAffectedPages(start, end, out pageStart, out pageCount);
if (pageCount > 0)
{
// Dispose all affected pages.
DisposePages(pageStart, pageCount);
// Raise PagesChanged event.
_owner.OnPagesChanged(pageStart, pageCount);
}
}
}
///
/// Updates entry of BreakRecordTable with new data.
///
/// Index of the entry to update.
/// DocumentPage object that has been just created.
/// Output BreakRecord for created page.
/// Last content position that can affect the output break record.
internal void UpdateEntry(int pageNumber, FlowDocumentPage page, PageBreakRecord brOut, TextPointer dependentMax)
{
ITextView textView;
BreakRecordTableEntry entry;
bool isClean;
Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "The previous BreakRecord does not exist.");
Invariant.Assert(page != null && page != DocumentPage.Missing, "Cannot update BRT with an invalid document page.");
// Get TextView for DocumentPage. This TextView is used to access list of
// content ranges. Those serve as optimalization in finding affeceted pages.
textView = (ITextView)((IServiceProvider)page).GetService(typeof(ITextView));
Invariant.Assert(textView != null, "Cannot access ITextView for FlowDocumentPage.");
// Get current state of BreakRecordTable
isClean = this.IsClean;
// Add new entry into BreakRecordTable
entry = new BreakRecordTableEntry();
entry.BreakRecord = brOut;
entry.DocumentPage = new WeakReference(page);
entry.TextSegments = textView.TextSegments;
entry.DependentMax = dependentMax;
if (pageNumber == _breakRecords.Count)
{
_breakRecords.Add(entry);
// Raise PaginationProgress event only if we did not have valid
// entry for specified page number.
_owner.OnPaginationProgress(pageNumber, 1);
}
else
{
// If old Page and/or BreakRecord are not changing, do not dispose them.
if (_breakRecords[pageNumber].BreakRecord != null &&
_breakRecords[pageNumber].BreakRecord != entry.BreakRecord)
{
_breakRecords[pageNumber].BreakRecord.Dispose();
}
if (_breakRecords[pageNumber].DocumentPage != null &&
_breakRecords[pageNumber].DocumentPage.Target != null &&
_breakRecords[pageNumber].DocumentPage.Target != entry.DocumentPage.Target)
{
((FlowDocumentPage)_breakRecords[pageNumber].DocumentPage.Target).Dispose();
}
_breakRecords[pageNumber] = entry;
}
// Raise PaginationCompleted event only if the BreakRecordTable just
// become clean.
if (!isClean && this.IsClean)
{
_owner.OnPaginationCompleted();
}
}
///
/// Determines whenever input BreakRecord for given page number exists.
///
/// Page index.
/// true, if BreakRecord for given page number exists.
internal bool HasPageBreakRecord(int pageNumber)
{
Invariant.Assert(pageNumber >= 0, "Page number cannot be negative.");
// For the first page, the input break record is always NULL.
// For the rest of pages, it exists if the preceding entry has
// non-NULL output BreakRecord.
if (pageNumber == 0)
return true;
if (pageNumber > _breakRecords.Count)
return false;
Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry.");
return (_breakRecords[pageNumber - 1].BreakRecord != null);
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//--------------------------------------------------------------------
#region Internal Properties
///
/// Current count reflecting number of known pages.
///
internal int Count
{
get { return _breakRecords.Count; }
}
///
/// Whether BreakRecordTable is clean.
///
internal bool IsClean
{
get
{
if (_breakRecords.Count == 0)
return false;
Invariant.Assert(_breakRecords[_breakRecords.Count - 1] != null, "Invalid BreakRecordTable entry.");
return (_breakRecords[_breakRecords.Count - 1].BreakRecord == null);
}
}
#endregion Internal Properties
//-------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------
#region Private Methods
///
/// Dispose all alive pages for specified range.
///
/// Index of the first page to dispose.
/// Number of pages to dispose.
private void DisposePages(int start, int count)
{
WeakReference pageRef;
int index = start + count - 1; // Start from the end of BreakRecordTable
Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation.");
Invariant.Assert(start + count <= _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed.");
while (index >= start)
{
Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry.");
pageRef = _breakRecords[index].DocumentPage;
if (pageRef != null && pageRef.Target != null)
{
((FlowDocumentPage)pageRef.Target).Dispose();
}
_breakRecords[index].DocumentPage = null;
index--;
}
}
///
/// Destroy BreakRecordsTable entries for specified range.
///
/// Index of the first entry to destroy.
/// Nmber of entries to destroy.
private void InvalidateBreakRecords(int start, int count)
{
WeakReference pageRef;
int index = start + count - 1; // Start from the end of BreakRecordTable
Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation.");
Invariant.Assert(start + count == _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed.");
while (index >= start)
{
Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry.");
// Dispose Page and BreakRecord before removing the entry.
pageRef = _breakRecords[index].DocumentPage;
if (pageRef != null && pageRef.Target != null)
{
((FlowDocumentPage)pageRef.Target).Dispose();
}
if (_breakRecords[start].BreakRecord != null)
{
_breakRecords[start].BreakRecord.Dispose();
}
// Remov the entry.
_breakRecords.RemoveAt(index);
index--;
}
}
///
/// Retrieves indices of affected pages by specified content range.
///
/// Content change start position.
/// Content change end position.
/// The first affected page.
/// Number of affected pages.
private void GetAffectedPages(ITextPointer start, ITextPointer end, out int pageStart, out int pageCount)
{
bool affects;
ReadOnlyCollection textSegments;
TextPointer dependentMax;
// Find the first affected page.
pageStart = 0;
while (pageStart < _breakRecords.Count)
{
Invariant.Assert(_breakRecords[pageStart] != null, "Invalid BreakRecordTable entry.");
// If the start position is before last position affecting the output break record,
// this page is affected.
dependentMax = _breakRecords[pageStart].DependentMax;
if (dependentMax != null)
{
if (start.CompareTo(dependentMax) <= 0)
break;
}
textSegments = _breakRecords[pageStart].TextSegments;
if (textSegments != null)
{
affects = false;
foreach (TextSegment textSegment in textSegments)
{
if (start.CompareTo(textSegment.End) <= 0)
{
affects = true;
break;
}
}
if (affects)
break;
}
else
{
// There is no information about this page, so assume that it is
// affected.
break;
}
++pageStart;
}
// Find the last affected page
// For now assume that all following pages are affected.
pageCount = _breakRecords.Count - pageStart;
}
#endregion Private Methods
//-------------------------------------------------------------------
//
// Private Fields
//
//-------------------------------------------------------------------
#region Private Fields
///
/// Owner of the BreakRecordTable.
///
private FlowDocumentPaginator _owner;
///
/// Array of entries in the BreakRecordTable.
///
private List _breakRecords;
///
/// BreakRecordTableEntry
///
private class BreakRecordTableEntry
{
public PageBreakRecord BreakRecord;
public ReadOnlyCollection TextSegments;
public WeakReference DocumentPage;
public TextPointer DependentMax;
}
#endregion Private Fields
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AsnEncodedData.cs
- Choices.cs
- Zone.cs
- DataGridItemEventArgs.cs
- ResXResourceWriter.cs
- ThousandthOfEmRealPoints.cs
- DbConnectionInternal.cs
- TranslateTransform.cs
- BindingExpressionUncommonField.cs
- PropertyGridView.cs
- HandlerBase.cs
- CorrelationInitializer.cs
- TimeSpanConverter.cs
- BitmapPalette.cs
- RequestCacheEntry.cs
- NominalTypeEliminator.cs
- ExtendedPropertyDescriptor.cs
- MemberPathMap.cs
- KeyBinding.cs
- ConfigXmlSignificantWhitespace.cs
- BackgroundWorker.cs
- IfAction.cs
- LinearGradientBrush.cs
- TeredoHelper.cs
- InvokeProviderWrapper.cs
- _HelperAsyncResults.cs
- CompositeCollectionView.cs
- CmsInterop.cs
- Single.cs
- BaseProcessProtocolHandler.cs
- ApplicationId.cs
- SecureConversationSecurityTokenParameters.cs
- MarkupExtensionReturnTypeAttribute.cs
- IncrementalHitTester.cs
- XmlUtilWriter.cs
- ImportedNamespaceContextItem.cs
- SoapSchemaExporter.cs
- Canvas.cs
- DataMember.cs
- COMException.cs
- XmlSchemaCompilationSettings.cs
- TransactionsSectionGroup.cs
- UTF7Encoding.cs
- OLEDB_Util.cs
- TransformCollection.cs
- Vector3D.cs
- DescendentsWalkerBase.cs
- XmlNamespaceManager.cs
- ImageConverter.cs
- XpsS0ValidatingLoader.cs
- Expression.cs
- RichTextBoxAutomationPeer.cs
- WorkflowTimerService.cs
- CounterCreationData.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- XmlWriter.cs
- SerializationStore.cs
- WebPartConnectionsConfigureVerb.cs
- ConversionContext.cs
- MimeObjectFactory.cs
- BuildManager.cs
- CompositeFontParser.cs
- ArithmeticException.cs
- SQLInt64Storage.cs
- InkCanvasInnerCanvas.cs
- SessionStateUtil.cs
- XmlSchemas.cs
- FlowDocumentScrollViewer.cs
- DataGridViewCellValidatingEventArgs.cs
- TextTreeObjectNode.cs
- SoapServerMethod.cs
- ListenerConnectionModeReader.cs
- OleDbTransaction.cs
- TypedDatasetGenerator.cs
- FullTextLine.cs
- SmiXetterAccessMap.cs
- Bold.cs
- ProcessThreadCollection.cs
- HighlightOverlayGlyph.cs
- TabletDeviceInfo.cs
- XXXOnTypeBuilderInstantiation.cs
- SystemResources.cs
- InProcStateClientManager.cs
- embossbitmapeffect.cs
- SqlWebEventProvider.cs
- ResourceIDHelper.cs
- CounterCreationDataConverter.cs
- Stroke.cs
- RequestSecurityTokenResponse.cs
- XmlSchemaAnnotated.cs
- WindowsScroll.cs
- ContentWrapperAttribute.cs
- TemplateEditingFrame.cs
- WindowsAuthenticationModule.cs
- BooleanSwitch.cs
- MemoryMappedView.cs
- StringSource.cs
- querybuilder.cs
- ButtonAutomationPeer.cs
- SafeCryptContextHandle.cs