// 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 } }