/*
i-net software provides programming examples for illustration only, without warranty
either expressed or implied, including, but not limited to, the implied warranties
of merchantability and/or fitness for a particular purpose. This programming example
assumes that you are familiar with the programming language being demonstrated and
the tools used to create and debug procedures. i-net software support professionals
can help explain the functionality of a particular procedure, but they will not modify
these examples to provide added functionality or construct procedures to meet your
specific needs.
© i-net software 1998-2013
*/
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using System.Threading;
using Inet.Viewer.Resources;
using Inet.Viewer.WinForms;
namespace Inet.Viewer.Data
{
/// <summary>
/// Progress implementation for printing a report.
/// </summary>
public class PrintProgress : Progress
{
private PrintDocument printDoc;
private int currentPage;
private ReportDataCache reportDataCache;
private int pageCount;
private PrinterSettings printerSettings;
/// <summary>
/// Creates a print progress for the specified render data.
/// </summary>
/// <param name="renderData">the report to print</param>
/// <param name="printerSettings">printing settings</param>
/// <param name="errorDelegate">a delegate which will be called on failures during the progress</param>
public PrintProgress(IRenderData renderData, PrinterSettings printerSettings, Action<Exception> errorDelegate) :
this(new ReportDataCache(renderData), printerSettings, errorDelegate)
{
}
/// <summary>
/// Creates a print progress for the specified ReportDataCache instance.
/// </summary>
/// <param name="reportDataCache">the report to print as ReportDataCache instance</param>
/// <param name="printerSettings">printing settings</param>
/// <param name="errorDelegate">a delegate which will be called on failures during the progress</param>
internal PrintProgress(ReportDataCache reportDataCache, PrinterSettings printerSettings, Action<Exception> errorDelegate) :
base(errorDelegate, ProgressType.Print)
{
this.reportDataCache = reportDataCache;
this.printerSettings = printerSettings;
printDoc = new PrintDocument();
printDoc.PrinterSettings = printerSettings;
printDoc.QueryPageSettings += new QueryPageSettingsEventHandler(printDoc_QueryPageSettings);
printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
}
/// <summary>
/// Gets or sets the report info instance. When the report and the page info instances are set both, no
/// additional request to the report data cache is needed before printing.
/// </summary>
internal ReportInfo ReportInfo
{
get;
set;
}
/// <summary>
/// Gets or sets the page info instance. When the report and the page info instances are set both, no
/// additional request to the report data cache is needed before printing.
/// </summary>
internal PageInfo PageInfo
{
get;
set;
}
/// <summary>
/// Gets or sets the current page of the viewer. Used when the user selects "Current Page" in the
/// printing dialog.
/// </summary>
internal int CurrentViewPage
{
set;
get;
}
/// <inheritdoc />
protected override void Run()
{
try
{
pageCount = reportDataCache.PageCount();
PrintRange rangeType = printerSettings.PrintRange;
if (rangeType == PrintRange.SomePages)
{
currentPage = printerSettings.FromPage;
}
else if (rangeType == PrintRange.CurrentPage)
{
currentPage = CurrentViewPage;
}
else
{
currentPage = 1;
}
LoadMetaDataIfRequired();
printDoc.DocumentName = ReportInfo.Title;
printDoc.Print();
Status = ProgressStatus.Completed;
}
catch (Exception e)
{
ShowError(e);
}
}
/// <summary>
/// Called before printing a page. Sets the page settings.
/// </summary>
/// <param name="sender">not used</param>
/// <param name="e">event args which include page settings</param>
private void printDoc_QueryPageSettings(object sender, QueryPageSettingsEventArgs e)
{
e.PageSettings.Margins = PageInfo.PrintMargins;
}
/// <summary>
/// Called when printing the next page. Does the actual output on the printer graphics.
/// </summary>
/// <param name="sender"></param>
/// <param name="ev"></param>
private void printDoc_PrintPage(object sender, PrintPageEventArgs ev)
{
Graphics2DPainter painter = new Graphics2DPainter(true);
PrinterPageView pageView = new PrinterPageView(ErrorDelegate, reportDataCache, ev);
byte[] pageData = reportDataCache.PageData(currentPage, false);
pageView.Page = currentPage;
PageLoader pLoader = new PageLoader(painter, pageView);
pLoader.PaintPage(pageData);
currentPage++;
PrintRange rangeType = ev.PageSettings.PrinterSettings.PrintRange;
if (rangeType == PrintRange.SomePages)
{
ev.HasMorePages = currentPage <= Math.Min( pageCount, ev.PageSettings.PrinterSettings.ToPage);
}
else if (rangeType == PrintRange.CurrentPage)
{
ev.HasMorePages = false;
}
else
{
ev.HasMorePages = currentPage <= pageCount;
}
ev.Cancel = Status == ProgressStatus.Canceled;
}
/// <inheritdoc/>
public override string Name
{
get { return strings.Print; }
}
/// <inheritdoc/>
public override void Cancel()
{
Status = ProgressStatus.Canceled;
}
/// <summary>
/// Updates the default page settings of the printer settings. This will change the PrinterSettings
/// instance specified via the constructor when creating this progress.
/// If no meta data (ReportInfo / PageInfo) was set manually, the required properties are loaded
/// directly from the underlying IRenderData instance.
/// Since this method may invoke blocking I/O operations, it should not be called form a UI thread.
/// </summary>
public void UpdatePageSettings()
{
LoadMetaDataIfRequired();
printerSettings.DefaultPageSettings.Landscape = PageInfo.PageAlign == (int)PageOrientation.Landscape;
printerSettings.DefaultPageSettings.Margins = PageInfo.PrintMargins;
}
/// <summary>
/// Loads the meta data if not set yet.
/// </summary>
private void LoadMetaDataIfRequired()
{
if (ReportInfo == null || PageInfo == null)
{
// meta data not set yet => parse the first page
PageMetaReceiver pageMetaReceiver = new PageMetaReceiver();
PageLoader loader = new PageLoader(null, pageMetaReceiver);
loader.Data = reportDataCache.PageData(1, false);
loader.ReadTokens();
if (pageMetaReceiver.Error != null)
{
ShowError(pageMetaReceiver.Error);
return;
}
ReportInfo = pageMetaReceiver.ReportInfo;
PageInfo = pageMetaReceiver.PageInfo;
}
}
}
}