// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// Purpose: Utility class that conatins properties and methods
// for chart printing.
//
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
namespace FastReport.DataVisualization.Charting
{
///
/// Chart printing class.
///
public class PrintingManager : IDisposable
{
#region Private fields
// Reference to the service container
private IServiceContainer _serviceContainer;
// Reference to the chart image object
private ChartImage _chartImage;
// Chart printing document
private PrintDocument _printDocument;
#endregion
#region Constructors and Service Provider methods
///
/// Public constructor is unavailable
///
private PrintingManager()
{
}
///
/// Public constructor
///
/// Service container reference.
public PrintingManager(IServiceContainer container)
{
if(container == null)
{
throw(new ArgumentNullException(SR.ExceptionInvalidServiceContainer));
}
_serviceContainer = container;
}
///
/// Returns Printing Manager service object
///
/// Requested service type.
/// Printing Manager sevice object.
internal object GetService(Type serviceType)
{
if(serviceType == typeof(PrintingManager))
{
return this;
}
throw (new ArgumentException( SR.ExceptionChartSerializerUnsupportedType( serviceType.ToString() ) ) );
}
#endregion
#region Printing methods
///
/// Draws chart on the printer graphics.
///
/// Printer graphics.
/// Position to draw in the graphics.
public void PrintPaint(Graphics graphics, Rectangle position)
{
PrintPaint(new FastReport.GdiGraphics(graphics, false), position);
}
///
/// Draws chart on the graphics using graphics wrapper.
///
/// Graphics wrapper.
/// Position to draw in the graphics.
public void PrintPaint(IGraphics graphics, Rectangle position)
{
// Get a reference to the chart image object
if(_chartImage == null && _serviceContainer != null)
{
_chartImage = (ChartImage)_serviceContainer.GetService(typeof(ChartImage));
}
// Draw chart
if(_chartImage != null)
{
// Change chart size to fit the new position
int oldWidth = _chartImage.Width;
int oldHeight = _chartImage.Height;
_chartImage.Width = position.Width;
_chartImage.Height = position.Height;
// Save graphics state.
IGraphicsState transState = graphics.Save();
// Set required transformation
graphics.TranslateTransform(position.X, position.Y);
// Set printing indicator
_chartImage.isPrinting = true;
// Draw chart
_chartImage.Paint(graphics, false);
// Clear printing indicator
_chartImage.isPrinting = false;
// Restore graphics state.
graphics.Restore(transState);
// Restore old chart position
_chartImage.Width = oldWidth;
_chartImage.Height = oldHeight;
}
}
#if PRINTING
///
/// Chart printing document.
///
[
Bindable(false),
SRDescription("DescriptionAttributePrintingManager_PrintDocument"),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Utilities.SerializationVisibilityAttribute(Utilities.SerializationVisibility.Hidden)
]
public PrintDocument PrintDocument
{
set
{
_printDocument = value;
}
get
{
if(_printDocument == null)
{
// Create new object
_printDocument = new PrintDocument();
// Hook up to the PrintPage event of the document
this.PrintDocument.PrintPage += new PrintPageEventHandler(pd_PrintPage);
}
return _printDocument;
}
}
///
/// Shows Page Setup dialog.
///
public void PageSetup()
{
// Create print preview dialog
PageSetupDialog pageSetupDialog = new PageSetupDialog();
// Initialize printing document
pageSetupDialog.Document = this.PrintDocument;
// Show page setup dialog
pageSetupDialog.ShowDialog();
}
///
/// Print preview the chart.
///
public void PrintPreview()
{
// Create print preview dialog
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
// Initialize printing document
printPreviewDialog.Document = this.PrintDocument;
// Show print preview
printPreviewDialog.ShowDialog();
}
///
/// Prints chart.
///
/// Indicates if printing dialog should be shown.
public void Print(bool showPrintDialog)
{
// Show Print dialog
if(showPrintDialog)
{
// Create and show Print dialog
PrintDialog printDialog = new PrintDialog();
printDialog.UseEXDialog = true;
printDialog.Document = this.PrintDocument;
DialogResult dialogResult = printDialog.ShowDialog();
// Do not proceed with printing if OK button was not pressed
if(dialogResult != DialogResult.OK && dialogResult != DialogResult.Yes)
{
return;
}
}
// Print chart
this.PrintDocument.Print();
}
///
/// Handles PrintPage event of the document.
///
/// Sender object.
/// Event parameters.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
// Get a reference to the chart image object
if(_chartImage == null && _serviceContainer != null)
{
_chartImage = (ChartImage)_serviceContainer.GetService(typeof(ChartImage));
}
if(_chartImage != null)
{
// Save graphics state.
GraphicsState transState = ev.Graphics.Save();
try
{
Rectangle marginPixel = ev.MarginBounds;
// Display units mean different thing depending if chart is rendered on the display or printed.
// Typically pixels for video displays, and 1/100 inch for printers.
if (ev.Graphics.PageUnit != GraphicsUnit.Pixel)
{
ev.Graphics.PageUnit = GraphicsUnit.Pixel;
marginPixel.X = (int)(marginPixel.X * (ev.Graphics.DpiX / 100.0f));
marginPixel.Y = (int)(marginPixel.Y * (ev.Graphics.DpiY / 100.0f));
marginPixel.Width = (int)(marginPixel.Width * (ev.Graphics.DpiX / 100.0f));
marginPixel.Height = (int)(marginPixel.Height * (ev.Graphics.DpiY / 100.0f));
}
// Calculate chart position rectangle
Rectangle chartPosition = new Rectangle(marginPixel.X, marginPixel.Y, _chartImage.Width, _chartImage.Height);
// Make sure chart corretly fits the margin area
float chartWidthScale = ((float)marginPixel.Width) / ((float)chartPosition.Width);
float chartHeightScale = ((float)marginPixel.Height) / ((float)chartPosition.Height);
chartPosition.Width = (int)(chartPosition.Width * Math.Min(chartWidthScale, chartHeightScale));
chartPosition.Height = (int)(chartPosition.Height * Math.Min(chartWidthScale, chartHeightScale));
// Calculate top left position so that chart is aligned in the center
chartPosition.X += (marginPixel.Width - chartPosition.Width) / 2;
chartPosition.Y += (marginPixel.Height - chartPosition.Height) / 2;
// Draw chart on the printer graphisc
this.PrintPaint(ev.Graphics, chartPosition);
}
finally
{
// Restore graphics state.
ev.Graphics.Restore(transState);
}
}
}
#endif
#endregion
#region IDisposable Members
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
//Free managed resources
if (_printDocument != null)
{
_printDocument.Dispose();
_printDocument = null;
}
}
}
///
/// Performs freeing, releasing, or resetting managed resources.
///
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}