/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.IO; using TBF.Resources; namespace TBF { public class PrintOrderDocument : PrintDocument { const string FontFamilyName = "Arial"; //"Times New Roman"; const int SpacingOne = 18; const int Padding = 10; const int TitleX = 100; const int TitleY = 160; int HdrTop = 220; /// Depends on the size of the title int TableTopFirstPage = 390; /// Depends on the size of the header int TableTopNextPage = TitleY; const int SpacingOneAndHalf = (3 * SpacingOne) / 2; /// /// Property variable for the Font the user wishes to use /// Font font; Font boldFont; Font titleFont; /// /// Data to print /// readonly Entities.Procedure procedure; readonly IList allResults; readonly string tester; readonly DateTime dateTime; readonly int batchMin; readonly int batchMax; /// /// Items to print /// readonly IList testNames; readonly int testsPerMeter; readonly IList resultItems; /// /// Data to print /// readonly int maxNrRows; readonly int nrRows; readonly int nrColumns; string[,] dataToPrint; /// /// Layout and status /// int nrTabLinesOnFirstPage; int nrTabLinesOnNextPage; int nextTableRow; /// nr. of table row to be printed as the first one on the next page int nrPages; int pageNr; /// Page number to be printed at the bottom of the page /// /// Constructor. /// Precalculates some values and dimensions and stores strings for the table /// to be printed into a 2-dimensional array of strings 'dataToprint'. /// /// Procedure belonging to the results /// Results to be printed (multiple batches) public PrintOrderDocument(Entities.Procedure procedure, IList allResults, string tester) { this.procedure = procedure; this.allResults = allResults; this.tester = tester; dateTime = DateTime.Now; batchMin = int.MaxValue; batchMax = int.MinValue; foreach (var tr in allResults) { if (tr.BatchNr < batchMin) batchMin = tr.BatchNr; if (tr.BatchNr > batchMax) batchMax = tr.BatchNr; } resultItems = Forms.ResultItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Printer_SingleWM); testNames = Utils.GetDecoratedTestNames(procedure, 1); testsPerMeter = testNames.Count; maxNrRows = (batchMax - batchMin + 1) * Program.WMsCount; nrColumns = testsPerMeter * resultItems.Count + 2; /// /// Prepare raw data to print /// dataToPrint = new string[maxNrRows, nrColumns]; nrRows = 0; for (int i = batchMin; i <= batchMax; i++) { /// Collect all results belonging to one batch IList unsortedResults = new List(); foreach (var tr in allResults) if (tr.BatchNr == i) unsortedResults.Add(tr); if (unsortedResults.Count == 0) continue; for (int wmNr = 0; wmNr < Program.WMsCount; wmNr++) /// wmNr is 0-based { if (!unsortedResults[0].Meters[wmNr].Disabled) { dataToPrint[nrRows, 0] = (nrRows + 1).ToString(); dataToPrint[nrRows, 1] = unsortedResults[0].Meters[wmNr].SerialNr; IList results = Utils.GetSortedTestResults(procedure, unsortedResults, Utils.PartNr(wmNr + 1, false)); for (int j = 0; j < testsPerMeter; j++) { if (results[j] != null) { int k = 2 + j * resultItems.Count; foreach (var item in resultItems) { string str = item.Print(results[j].Meters[wmNr]); int pos = str.IndexOf('|'); dataToPrint[nrRows, k++] = (pos < 0) ? str : str.Substring(0, pos); } } } nrRows++; } } } pageNr = 1; nextTableRow = 0; } /// /// Override the default onbeginPrint method of the PrintDocument Object /// /// /// protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e) { base.OnBeginPrint(e); if (font == null) { font = new Font(FontFamilyName, 10, FontStyle.Regular); } if (boldFont == null) { boldFont = new Font(FontFamilyName, 10, FontStyle.Bold); } if (titleFont == null) { titleFont = new Font(FontFamilyName, 18, FontStyle.Bold); } } /// /// Override the default OnPrintPage method of the PrintDocument. /// /// /// This provides the print logic for our document protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e) { /// Run base code base.OnPrintPage(e); /// Set print area size and margins (in dots using 80 dpi) int printHeight = base.DefaultPageSettings.PaperSize.Height - base.DefaultPageSettings.Margins.Top - base.DefaultPageSettings.Margins.Bottom; int printWidth = base.DefaultPageSettings.PaperSize.Width - base.DefaultPageSettings.Margins.Left - base.DefaultPageSettings.Margins.Right; int leftMargin = base.DefaultPageSettings.Margins.Left; /// X int topMargin = base.DefaultPageSettings.Margins.Top; /// Y if (base.DefaultPageSettings.Landscape) { /// Landscape mode: we need to swap height/width parameters int tmp = printHeight; printHeight = printWidth; printWidth = tmp; if (File.Exists("C:\\TBF\\header-landscape.png")) { Image img = Image.FromFile("C:\\TBF\\header-landscape.png"); e.Graphics.DrawImage(new Bitmap(img), new Rectangle(0, 0, 1169, 827)); } } else { if (File.Exists("C:\\TBF\\header-portrait.png")) { Image img = Image.FromFile("C:\\TBF\\header-portrait.png"); e.Graphics.DrawImage(new Bitmap(img), new Rectangle(0, 0, 827, 1169)); } } ///--------------- /// Common info ///--------------- if (pageNr == 1) { if (!string.IsNullOrEmpty(allResults[0].ProtocolTitle)) { RectangleF printArea = new RectangleF(TitleX, TitleY, 667, 40); e.Graphics.DrawString(allResults[0].ProtocolTitle, titleFont, Brushes.Black, printArea); } else { TableTopFirstPage -= (HdrTop - TitleY); HdrTop = TitleY; } string[] leftColumn = new string[] { Strings.Purchase_order_, Strings.Date_and_time_, Strings.Procedure_, Strings.Tester_, Strings.Approval_, Strings.Ambient_temperature_, Strings.Ambient_pressure_, Strings.Ambient_humidity_, }; string[] rightColumn = new string[] { allResults[0].PurchaseOrder, //dateTime.ToShortDateString() + " " + dateTime.ToShortTimeString(), string.Format("{0}.{1}.{2} {3}:{4}", dateTime.Year.ToString("D4"), dateTime.Month.ToString("D2"), dateTime.Day.ToString("D2"), dateTime.Hour.ToString("D2"), dateTime.Minute.ToString("D2")), procedure.Name, tester, string.Empty, allResults[0].AmbientTempAve.ToString("F1") + " °C", allResults[0].AmbientPressAve.ToString("F0") + " mbar", allResults[0].AmbientHumiAve.ToString("F0") + " %", }; /// Determine max. left column width in characters float maxWdth = 0; foreach (var s in leftColumn) { float wdth = e.Graphics.MeasureString(s, font).Width; if (wdth > maxWdth) maxWdth = wdth; } /// Write aligned columns for (int i = 0; i < Math.Min(leftColumn.Length, rightColumn.Length); i++) { PrintAt(e, 100, HdrTop + SpacingOne * i, leftColumn[i]); PrintAt(e, 100 + (int)maxWdth + 20, HdrTop + SpacingOne * i, rightColumn[i]); } } ///---------------- /// More pages ? ///---------------- if (pageNr == 1) { /// Determine the number of pages once nrTabLinesOnNextPage = (topMargin + printHeight - TableTopNextPage - 70) / SpacingOne; nrTabLinesOnFirstPage = (topMargin + printHeight - TableTopFirstPage - 70) / SpacingOne; if (nrRows <= nrTabLinesOnFirstPage) { nrPages = 1; } else { nrPages = 1 + ((nrRows - nrTabLinesOnFirstPage) + nrTabLinesOnNextPage - 1) / nrTabLinesOnNextPage; } } int nrTabLinesOnThisPage = (pageNr == 1) ? nrTabLinesOnFirstPage : nrTabLinesOnNextPage; int rowFrom = nextTableRow; int rowTo; if (nrRows <= nextTableRow + nrTabLinesOnThisPage) { rowTo = nrRows - 1; e.HasMorePages = false; } else { rowTo = rowFrom + nrTabLinesOnThisPage - 1; nextTableRow = rowFrom + nrTabLinesOnThisPage; e.HasMorePages = true; } ///-------- /// Body ///-------- int[] columnPos = GetColumnPositions(e, dataToPrint, rowFrom, rowTo, leftMargin + Padding, 2 * Padding); int tableLeft = leftMargin; int tableRight = columnPos[nrColumns] - Padding; int currentTableTop = (pageNr == 1) ? TableTopFirstPage : TableTopNextPage; int yyy = currentTableTop; /// Horizontal line e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy)); yyy += 2; /// Line with test names (larger columns, names centered) for (int bigcol = 0; bigcol < testsPerMeter; bigcol++) { float width = e.Graphics.MeasureString(testNames[bigcol], font).Width; int bc = 2 + bigcol * resultItems.Count; int xxx = (columnPos[bc] + columnPos[bc + resultItems.Count]) / 2 - Padding - (int)(width / 2 + 0.5f); PrintAt(e, xxx, yyy, testNames[bigcol]); } yyy += SpacingOne; int tableTop2 = yyy; /// Indented horizontal line e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[2] - Padding, yyy), new Point(tableRight, yyy)); yyy += 2; /// Line with header texts PrintAt(e, columnPos[0], yyy - SpacingOne / 2, GetHeaderItem(0)); PrintAt(e, columnPos[1], yyy - SpacingOne / 2, GetHeaderItem(1)); for (int col = 2; col < nrColumns; col++) { PrintAt(e, columnPos[col], yyy, GetHeaderItem(col)); } yyy += SpacingOne; /// Horizontal line e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy)); yyy += 2; /// Table with results for (int row = rowFrom; row <= rowTo; row++) { for (int col = 0; col < nrColumns; col++) { PrintAt(e, columnPos[col], yyy, dataToPrint[row, col]); } yyy += SpacingOne; } /// Horizontal line e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy)); int tableBottom = yyy; /// Vertical lines for (int col = 0; col <= nrColumns; col++) { if (col < 2 || ((col-2) % resultItems.Count) == 0) { e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[col] - Padding, currentTableTop), new Point(columnPos[col] - Padding, tableBottom)); } else { e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[col] - Padding, tableTop2), new Point(columnPos[col] - Padding, tableBottom)); } } ///---------- /// Footer ///---------- PrintAt(e, leftMargin, topMargin + printHeight - SpacingOne, string.Format("{0} {1}/{2}", Strings.Page, pageNr++, nrPages)); } /// /// Returns header text for each column of the table. /// /// COlumn nymber (0-based) /// Header text string GetHeaderItem(int column) { switch (column) { case 0: return "Nr."; case 1: return "S/N"; default: return resultItems[(column - 2) % resultItems.Count].ClmnHeaderText; } } /// /// Determine column widths and return column left positions for a subset of table rows /// /// string[nrRows, nrColumns] /// First row to consider /// Last row to consider /// Left column positions and right side float[nrColumns + 1] int[] GetColumnPositions(System.Drawing.Printing.PrintPageEventArgs e, string[,] dataToPrint, int rowFrom, int rowTo, int leftMargin, int padding) { int nrColumns = dataToPrint.GetLength(1); int[] columnPos = new int[nrColumns + 1]; columnPos[0] = leftMargin; for (int column = 0; column < nrColumns; column++) { float columnWidth = e.Graphics.MeasureString(GetHeaderItem(column), font).Width; for (int row = rowFrom; row <= rowTo; row++) { float itemWidth = e.Graphics .MeasureString(dataToPrint[row, column] == null ? string.Empty : dataToPrint[row, column], font) .Width; if (itemWidth > columnWidth) columnWidth = itemWidth; } columnPos[column + 1] = columnPos[column] + (int)(columnWidth + 0.5f) + padding; } return columnPos; } void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, Point p, string text) { PrintAt(e, p.X, p.Y, text); } void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, int x, int y, string text) { RectangleF printArea = new RectangleF(x, y, 667, SpacingOne); e.Graphics.DrawString(text, this.font, Brushes.Black, printArea); } void PrintBoldAt(System.Drawing.Printing.PrintPageEventArgs e, Point p, string text) { PrintBoldAt(e, p.X, p.Y, text); } void PrintBoldAt(System.Drawing.Printing.PrintPageEventArgs e, int x, int y, string text) { RectangleF printArea = new RectangleF(x, y, 667, SpacingOne); e.Graphics.DrawString(text, this.boldFont, Brushes.Black, printArea); } private void InitializeComponent() { } } }