| File: MS\Internal\Documents\DocumentGridPage.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: DocumentGridPage displays a graphical representation of an // DocumentPaginator page including drop-shadow // and is used by DocumentGrid. // using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Media; namespace MS.Internal.Documents { /// <summary> /// /// </summary> internal class DocumentGridPage : FrameworkElement, IDisposable { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors /// <summary> /// Standard constructor. /// </summary> public DocumentGridPage(DocumentPaginator paginator) : base() { _paginator = paginator; //Attach the GetPageCompleted event handler to the paginator so we can //use it to keep track of whether our page has been loaded yet. _paginator.GetPageCompleted += new GetPageCompletedEventHandler(OnGetPageCompleted); //Set up the static elements of our Visual Tree. Init(); } #endregion //------------------------------------------------------------------- // // Public Properties // //------------------------------------------------------------------- #region Public Properties /// <summary> /// The DocumentPage for the displayed page. /// </summary> public DocumentPage DocumentPage { get { CheckDisposed(); return _documentPageView.DocumentPage; } } /// <summary> /// The page number displayed. /// </summary> public int PageNumber { get { CheckDisposed(); return _documentPageView.PageNumber; } set { CheckDisposed(); if (_documentPageView.PageNumber != value) { _documentPageView.PageNumber = value; } } } /// <summary> /// The DocumentPageView displayed by this DocumentGridPage /// </summary> public DocumentPageView DocumentPageView { get { CheckDisposed(); return _documentPageView; } } /// <summary> /// Whether to show the border and drop shadow around the page. /// </summary> /// <value></value> public bool ShowPageBorders { get { CheckDisposed(); return _showPageBorders; } set { CheckDisposed(); if (_showPageBorders != value) { _showPageBorders = value; InvalidateMeasure(); } } } /// <summary> /// Whether the requested page is loaded. /// </summary> public bool IsPageLoaded { get { CheckDisposed(); return _loaded; } } //------------------------------------------------------------------- // // Public Events // //------------------------------------------------------------------- #region Public Events /// <summary> /// Fired when the document is finished paginating. /// </summary> public event EventHandler PageLoaded; #endregion Public Events #endregion Public Properties //------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------- #region Protected Methods /// <summary> /// Derived class must implement to support Visual children. The method must return /// the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1. /// /// By default a Visual does not have any children. /// /// Remark: /// During this virtual call it is not valid to modify the Visual tree. /// </summary> protected override Visual GetVisualChild(int index) { CheckDisposed(); // count is either 0 or 1 if (VisualChildrenCount != 0) { switch (index) { case 0: return _documentContainer; default: throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange); } } throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange); } /// <summary> /// Derived classes override this property to enable the Visual code to enumerate /// the Visual children. Derived classes need to return the number of children /// from this method. /// /// By default a Visual does not have any children. /// /// Remark: During this virtual method the Visual tree must not be modified. /// </summary> protected override int VisualChildrenCount { get { if (!_disposed && hasAddedChildren) return 1; else return 0; } } /// <summary> /// Content measurement. /// </summary> /// <param name="availableSize">Available size that parent can give to the child. This is soft constraint.</param> /// <returns>The DocumentGridPage's desired size.</returns> protected sealed override Size MeasureOverride(Size availableSize) { CheckDisposed(); if (!hasAddedChildren) { this.AddVisualChild(_documentContainer); hasAddedChildren = true; } //Show / hide the border and drop shadow based on the current //state of the ShowPageBorders property. if (ShowPageBorders) { var key = new ComponentResourceKey(typeof(FrameworkElement), "DocumentGridPageContainerWithBorder"); _documentContainer.SetCurrentValue(StyleProperty, TryFindResource(key)); } else { _documentContainer.SetCurrentValue(StyleProperty, TryFindResource(typeof(ContentControl))); } //Measure our children. _documentContainer.Measure(availableSize); //Set the Page Zoom on the DocumentPageView to the ratio between our measure constraint //and the actual size of the page; this will cause the DPV to scale our page appropriately. if (DocumentPage.Size != Size.Empty && DocumentPage.Size.Width != 0.0) { _documentPageView.SetPageZoom(availableSize.Width / DocumentPage.Size.Width); } return availableSize; } /// <summary> /// Content arrangement. /// </summary> /// <param name="arrangeSize">The final size that element should use to arrange itself and its children.</param> protected sealed override Size ArrangeOverride(Size arrangeSize) { CheckDisposed(); //Arrange the page container, no offset. _documentContainer.Arrange(new Rect(new Point(0.0, 0.0), arrangeSize)); base.ArrangeOverride(arrangeSize); return arrangeSize; } #endregion Protected Methods //------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods /// <summary> /// Creates the static members of DocumentGridPage's Visual Tree. /// </summary> private void Init() { //Create the DocumentPageView, which will display our //content. _documentPageView = new DocumentPageView { ClipToBounds = true, StretchDirection = StretchDirection.Both, PageNumber = int.MaxValue }; //Create the content control that contains the page content. _documentContainer = new ContentControl { Content = _documentPageView }; _loaded = false; } /// <summary> /// Handles the GetPageCompleted event raised by the DocumentPaginator. /// At this point, we'll set the _loaded flag to indicate the page is loaded /// and fire the PageLoaded event. /// </summary> /// <param name="sender">Source of the event.</param> /// <param name="e">Details about this event.</param> private void OnGetPageCompleted(object sender, GetPageCompletedEventArgs e) { //If the GetPageCompleted action completed successfully //and is our page then we'll set the flag and fire the event. if (!_disposed && e != null && !e.Cancelled && e.Error == null && e.PageNumber != int.MaxValue && e.PageNumber == this.PageNumber && e.DocumentPage != null && e.DocumentPage != DocumentPage.Missing) { _loaded = true; if (PageLoaded != null) { PageLoaded(this, EventArgs.Empty); } } } /// <summary> /// Dispose the object. /// </summary> protected void Dispose() { if (!_disposed) { _disposed = true; //Detach the GetPageCompleted event from the content. _paginator?.GetPageCompleted -= new GetPageCompletedEventHandler(OnGetPageCompleted); _paginator = null; //Dispose our DocumentPageView. IDisposable dpv = _documentPageView as IDisposable; dpv?.Dispose(); } } /// <summary> /// Checks if the instance is already disposed, throws if so. /// </summary> private void CheckDisposed() { ObjectDisposedException.ThrowIf(_disposed, typeof(DocumentPageView)); } #endregion Private Methods #region IDisposable Members /// <summary> /// Dispose the object. /// </summary> void IDisposable.Dispose() { GC.SuppressFinalize(this); this.Dispose(); } #endregion IDisposable Members //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields private bool hasAddedChildren; private DocumentPaginator _paginator; private DocumentPageView _documentPageView; private ContentControl _documentContainer; private bool _showPageBorders; private bool _loaded; private bool _disposed; #endregion Private Fields } }