File: WinForm\Utilities\Printing.cs
Project: ndp\fx\src\DataVisualization\System.Windows.Forms.DataVisualization.csproj (System.Windows.Forms.DataVisualization)
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
//   Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
//  File:		Printing.cs
//
//  Namespace:	DataVisualization.Charting.Utilities
//
//	Classes:	PrintingManager
//
//  Purpose:	Utility class that conatins properties and methods
//				for chart printing.
//
//	Reviewed:	
//
//===================================================================
 
 
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Printing;
using System.Windows.Forms;
 
 
 
#if WINFORMS_CONTROL
using System.Windows.Forms.DataVisualization.Charting;
 
namespace System.Windows.Forms.DataVisualization.Charting
{
	/// <summary>
	/// Chart printing class.
	/// </summary>
	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
 
		/// <summary>
		/// Public constructor is unavailable
		/// </summary>
		private PrintingManager()
		{
		}
 
		/// <summary>
		/// Public constructor
		/// </summary>
		/// <param name="container">Service container reference.</param>
		public PrintingManager(IServiceContainer container)
		{
			if(container == null)
			{
				throw(new ArgumentNullException(SR.ExceptionInvalidServiceContainer));
			}
			_serviceContainer = container;
		}
 
		/// <summary>
		/// Returns Printing Manager service object
		/// </summary>
		/// <param name="serviceType">Requested service type.</param>
		/// <returns>Printing Manager sevice object.</returns>
		internal object GetService(Type serviceType)
		{
			if(serviceType == typeof(PrintingManager))
			{
				return this;
			}
			throw (new ArgumentException( SR.ExceptionChartSerializerUnsupportedType( serviceType.ToString() ) ) );
		}
		#endregion
 
		#region Printing properties
		/// <summary>
		/// Chart printing document.
		/// </summary>
		[
		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;
			}
		}
 
		#endregion
 
		#region Printing methods
 
		/// <summary>
		/// Draws chart on the printer graphics.
		/// </summary>
        /// <param name="graphics">Printer graphics.</param>
		/// <param name="position">Position to draw in the graphics.</param>
        public void PrintPaint(Graphics 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.
				GraphicsState 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;
			}
		}
 
		/// <summary>
		/// Shows Page Setup dialog.
		/// </summary>
		public void PageSetup()
		{
			// Create print preview dialog
			PageSetupDialog	pageSetupDialog = new PageSetupDialog();
 
			// Initialize printing document
			pageSetupDialog.Document = this.PrintDocument;
 
			// Show page setup dialog
			pageSetupDialog.ShowDialog();
		}
 
 
		/// <summary>
		/// Print preview the chart.
		/// </summary>
		public void PrintPreview()
		{
			// Create print preview dialog
			PrintPreviewDialog	printPreviewDialog = new PrintPreviewDialog();
 
			// Initialize printing document
			printPreviewDialog.Document = this.PrintDocument;
 
			// Show print preview
			printPreviewDialog.ShowDialog();
		}
 
		/// <summary>
		/// Prints chart.
		/// </summary>
		/// <param name="showPrintDialog">Indicates if printing dialog should be shown.</param>
		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();
		}
 
		/// <summary>
		/// Handles PrintPage event of the document.
		/// </summary>
		/// <param name="sender">Sender object.</param>
		/// <param name="ev">Event parameters.</param>
		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);
                }
            }
		}
 
		#endregion
 
        #region IDisposable Members
 
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //Free managed resources
                if (_printDocument != null)
                {
                    _printDocument.Dispose();
                    _printDocument = null;
                }
            }
        }
 
        /// <summary>
        /// Performs freeing, releasing, or resetting managed resources.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        #endregion
	}
}
 
#endif	//#if WINFORMS_CONTROL