Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / PtsHost / BreakRecordTable.cs / 1305600 / 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; // Listusing 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; ReadOnlyCollectiontextSegments; 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[index].BreakRecord != null) { _breakRecords[index].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; ReadOnlyCollectiontextSegments; 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 ReadOnlyCollectionTextSegments; 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
- formatter.cs
- DataGridViewCellStyleChangedEventArgs.cs
- UserPreferenceChangedEventArgs.cs
- AddInDeploymentState.cs
- DataGridViewRowContextMenuStripNeededEventArgs.cs
- LookupNode.cs
- BatchWriter.cs
- SqlBinder.cs
- ColumnClickEvent.cs
- GenericWebPart.cs
- SiteMapHierarchicalDataSourceView.cs
- CompilerError.cs
- CodeStatement.cs
- NativeMethods.cs
- _TransmitFileOverlappedAsyncResult.cs
- ProtocolsConfigurationEntry.cs
- ElementHost.cs
- Expander.cs
- HttpsHostedTransportConfiguration.cs
- ImpersonateTokenRef.cs
- XmlSortKeyAccumulator.cs
- PixelShader.cs
- MultipleViewPattern.cs
- BrowserTree.cs
- StrokeRenderer.cs
- Point4DConverter.cs
- WindowsListViewGroup.cs
- _UriTypeConverter.cs
- ObjectAnimationBase.cs
- ConfigXmlAttribute.cs
- XamlReader.cs
- DurableServiceAttribute.cs
- EllipticalNodeOperations.cs
- TaskDesigner.cs
- _NetworkingPerfCounters.cs
- ReverseComparer.cs
- HtmlLinkAdapter.cs
- TextServicesDisplayAttributePropertyRanges.cs
- LocationUpdates.cs
- _emptywebproxy.cs
- ParameterEditorUserControl.cs
- InlineUIContainer.cs
- FileEnumerator.cs
- AutomationProperty.cs
- FrameworkContextData.cs
- SqlSelectClauseBuilder.cs
- DbDeleteCommandTree.cs
- WorkflowDefinitionDispenser.cs
- WebConfigurationManager.cs
- RegexTree.cs
- BufferedGraphics.cs
- PageRequestManager.cs
- Canvas.cs
- TypeLibConverter.cs
- DataGridViewLinkCell.cs
- ReadOnlyDictionary.cs
- WebPartManager.cs
- WindowsRegion.cs
- DataGridViewTopLeftHeaderCell.cs
- SqlException.cs
- shaperfactoryquerycacheentry.cs
- RuleDefinitions.cs
- Cursor.cs
- Number.cs
- IPipelineRuntime.cs
- ToolboxItemSnapLineBehavior.cs
- TextTreeNode.cs
- InputLanguageEventArgs.cs
- QilFunction.cs
- ZipFileInfoCollection.cs
- WrappedReader.cs
- EnlistmentTraceIdentifier.cs
- StateMachineExecutionState.cs
- QueueProcessor.cs
- Point3D.cs
- ClientData.cs
- TransformConverter.cs
- Item.cs
- TemplatedAdorner.cs
- CDSsyncETWBCLProvider.cs
- SqlFunctionAttribute.cs
- StateManagedCollection.cs
- EventMappingSettings.cs
- WpfXamlLoader.cs
- ClearTypeHintValidation.cs
- dtdvalidator.cs
- _TransmitFileOverlappedAsyncResult.cs
- DataPointer.cs
- MgmtConfigurationRecord.cs
- OutputCacheProfile.cs
- Random.cs
- CallContext.cs
- AnimationTimeline.cs
- GridViewRowPresenter.cs
- InvalidBodyAccessException.cs
- BooleanToSelectiveScrollingOrientationConverter.cs
- Equal.cs
- DoubleCollection.cs
- ToolStripSeparatorRenderEventArgs.cs
- ConditionalExpression.cs