// <copyright file="FlowDocumentPaginator.cs" company="GoalBook">
// Copyright © 2009 Mark Brownsword. All rights reserved.
// This source code and supporting files are licensed under The Code Project
// Open License (CPOL) as detailed at http://www.codeproject.com/info/cpol10.aspx.
// </copyright>
namespace GoalBook.Infrastructure
{
#region Using Statements
using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using GoalBook.Infrastructure.Constants;
using GoalBook.Infrastructure.Printing;
#endregion
/// <summary>
/// Print Document Paginator.
/// </summary>
public class FlowDocumentPaginator : DocumentPaginator
{
#region Constants and Enums
#endregion
#region Instance and Shared Fields
/// <summary>
/// Declaration for pageSize.
/// </summary>
private Size pageSize;
/// <summary>
/// Declaration for paginator.
/// </summary>
private DocumentPaginator paginator;
/// <summary>
/// Declaration for pageDefinition.
/// </summary>
private PageDefinition pageDefinition;
/// <summary>
/// Real total page count number.
/// </summary>
private int pageCount;
/// <summary>
/// Declaration for offSet.
/// </summary>
private double offSet = 55;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the FlowDocumentPaginator class.
/// </summary>
/// <param name="pageDefinition">pageDefinition parameter</param>
/// <param name="flowDocument">flowDocument parameter</param>
public FlowDocumentPaginator(PageDefinition pageDefinition, FlowDocument flowDocument)
{
this.paginator = (flowDocument as IDocumentPaginatorSource).DocumentPaginator;
this.pageSize = pageDefinition.PageSize;
this.pageDefinition = pageDefinition;
// Set paginator page size (allowing for header/footer).
this.paginator.PageSize = new Size(
this.pageDefinition.PageSize.Width,
this.pageDefinition.PageSize.Height - (this.pageDefinition.HeaderHeight + this.pageDefinition.FooterHeight));
}
#endregion
#region Delegates and Events
#endregion
#region Properties
/// <summary>
/// Gets IsPageCountValid.
/// </summary>
public override bool IsPageCountValid
{
get { return this.paginator.IsPageCountValid; }
}
/// <summary>
/// Gets PageCount.
/// </summary>
public override int PageCount
{
get { return this.paginator.PageCount; }
}
/// <summary>
/// Gets or Sets PageSize.
/// </summary>
public override Size PageSize
{
get { return this.pageSize; }
set { this.pageSize = value; }
}
/// <summary>
/// Get Source.
/// </summary>
public override IDocumentPaginatorSource Source
{
get { return this.paginator.Source; }
}
#endregion
#region Public and internal Methods
/// <summary>
/// Get the Document Page for specified page number.
/// </summary>
/// <param name="pageNumber">pageNumber parameter</param>
/// <returns>DocumentPage instance</returns>
public override DocumentPage GetPage(int pageNumber)
{
DocumentPage originalPage = this.paginator.GetPage(pageNumber);
ContainerVisual newPage = new ContainerVisual();
// Compute Page Count.
if (pageNumber == 0)
{
this.paginator.ComputePageCount();
this.pageCount = this.paginator.PageCount;
}
// Header.
if (this.pageDefinition.HeaderTemplate != null)
{
ContainerVisual header = this.GetHeaderVisual(pageNumber);
header.Offset = new Vector(0, this.pageDefinition.HeaderHeight);
newPage.Children.Add(header);
}
// Content.
ContainerVisual content = new ContainerVisual();
content.Children.Add(originalPage.Visual);
content.Offset = new Vector(0, this.pageDefinition.HeaderHeight);
newPage.Children.Add(content);
// Footer.
if (this.pageDefinition.FooterTemplate != null)
{
ContainerVisual footer = this.GetFooterVisual();
footer.Offset = new Vector(0, this.pageSize.Height - this.pageDefinition.FooterHeight - this.offSet);
newPage.Children.Add(footer);
}
// Create the new DocumentPage.
return new DocumentPage(
newPage,
new Size(this.pageSize.Width, this.pageSize.Height),
originalPage.BleedBox,
originalPage.ContentBox);
}
#endregion
#region Base Class Overrides
#endregion
#region Private and Protected Methods
/// <summary>
/// Get Header Visual.
/// </summary>
/// <param name="pageNo">Current page number</param>
/// <returns>ContainerVisual header</returns>
private ContainerVisual GetHeaderVisual(int pageNo)
{
Table content = this.GetTable(
this.pageDefinition.HeaderFontFamily,
this.pageDefinition.HeaderFontSize,
new Thickness(0, 0, 0, 1), // Line below header
this.pageDefinition.HeaderTemplate,
string.Format(Properties.Resources.PrintingPageFormat, pageNo + 1, this.pageCount));
return this.GetPartVisual(
this.pageDefinition.HeaderHeight,
this.paginator.PageSize.Width,
this.pageDefinition.HeaderPadding,
content);
}
/// <summary>
/// Get Footer Visual.
/// </summary>
/// <returns>ContainerVisual footer</returns>
private ContainerVisual GetFooterVisual()
{
Table content = this.GetTable(
this.pageDefinition.FooterFontFamily,
this.pageDefinition.FooterFontSize,
new Thickness(0, 1, 0, 0), // Line above footer
this.pageDefinition.FooterTemplate,
DateTime.Now.ToShortDateString());
return this.GetPartVisual(
this.pageDefinition.FooterHeight,
this.paginator.PageSize.Width,
this.pageDefinition.FooterPadding,
content);
}
/// <summary>
/// Get table formatted for Header/Footer.
/// </summary>
/// <param name="fontFamily">fontFamily parameter</param>
/// <param name="fontSize">fontSize parameter</param>
/// <param name="borderPadding">borderPadding parameter</param>
/// <param name="leftCellText">leftCellText parameter</param>
/// <param name="rightCellText">rightCellText parameter</param>
/// <returns>Formatted table</returns>
private Table GetTable(FontFamily fontFamily, double fontSize, Thickness borderPadding, string leftCellText, string rightCellText)
{
// Initialise Table.
Table table = new Table();
table.BorderThickness = borderPadding;
table.BorderBrush = Brushes.Black;
table.CellSpacing = 0;
table.Columns.Add(new TableColumn());
table.Columns.Add(new TableColumn());
table.Columns[0].Width = new GridLength(3, GridUnitType.Star);
table.Columns[1].Width = new GridLength(1, GridUnitType.Star);
table.RowGroups.Add(new TableRowGroup());
// Initialise Row.
table.RowGroups[0].Rows.Add(new TableRow());
TableRow currentRow = table.RowGroups[0].Rows[0];
currentRow.FontFamily = fontFamily;
currentRow.FontSize = fontSize;
currentRow.Cells.Add(new TableCell(new Paragraph(new Run(leftCellText))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run(rightCellText))));
currentRow.Cells[1].TextAlignment = TextAlignment.Right;
return table;
}
/// <summary>
/// GetPartVisual. Initialise the Header/Footer.
/// </summary>
/// <param name="height">height parameter</param>
/// <param name="width">width parameter</param>
/// <param name="padding">padding parameter</param>
/// <param name="table">table parameter</param>
/// <returns>ContainerVisual for Header/Footer</returns>
private ContainerVisual GetPartVisual(double height, double width, Thickness padding, Table table)
{
FlowDocument flowDocument = new FlowDocument();
flowDocument.ColumnWidth = double.PositiveInfinity;
flowDocument.PageWidth = this.paginator.PageSize.Width;
flowDocument.PageHeight = height;
flowDocument.PagePadding = padding;
flowDocument.Blocks.Add(table);
DocumentPage dp = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator.GetPage(0);
return (ContainerVisual)dp.Visual;
}
#endregion
#region Event Handlers
#endregion
}
}