/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.IO; using Config.Entities; using TBF.Resources; namespace TBF.BenchControl.ResultsPrinters.Basic { public class BasicPrintDocument : PrintDocument { const string FontFamilyName = "Arial"; //"Times New Roman"; const int SpacingOne = 18; const int SpacingOneAndHalf = (3 * SpacingOne) / 2; readonly int topMargin; readonly int bottomMargin; readonly int leftMargin; readonly int TitleX; readonly int TitleY; /// Depends on the size of the header readonly int HdrTop; /// = TitleY + 60 readonly int BodyTop; /// = HdrTop + 160 /// Size of the printed area without margins, after taking into account 'pageOrientation' int printHeight; int printWidth; /// /// Property variable for the Font the user wishes to use /// Font font; Font boldFont; Font titleFont; /// /// Data to print /// Results.Entities.Batch batch; /// /// Items to print /// readonly IList rsltItems; /// /// Layout and status /// int nrWMsOnFirstPage; int nrWMsOnNextPage; int nextWMNr; /// nr. of watermeter 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 /// /// Text to be printed public BasicPrintDocument(Results.Entities.Batch batch, PageOrientation pageOrientation, int topMargin, int bottomMargin, int leftMargin) { this.batch = batch; DefaultPageSettings.Landscape = (pageOrientation == PageOrientation.Landscape); this.topMargin = topMargin; this.bottomMargin = bottomMargin; this.leftMargin = leftMargin; TitleX = leftMargin; TitleY = topMargin; /// Depends on the size of the header HdrTop = TitleY + 60; BodyTop = HdrTop + 160; if (batch.WaterMeters[0].Compound()) { rsltItems = Results.ItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Printer_CombinedWM); } else { rsltItems = Results.ItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Printer_SingleWM); } /// Set print area size and margins (in dots using 100 dpi) if (DefaultPageSettings.Landscape) { printHeight = base.DefaultPageSettings.PaperSize.Width - topMargin - bottomMargin; printWidth = base.DefaultPageSettings.PaperSize.Height - leftMargin - leftMargin; } else { printHeight = base.DefaultPageSettings.PaperSize.Height - topMargin - bottomMargin; printWidth = base.DefaultPageSettings.PaperSize.Width - leftMargin - leftMargin; } int testsCount = 0; foreach (var mtr in batch.WaterMeters[0].MeterTestRslts) { if (mtr.Publish() == Config.Entities.Publish.Always) testsCount++; } if (batch.WaterMeters[0].Compound()) testsCount /= 3; int wmSectionHeight = (testsCount + 4) * SpacingOne; nrWMsOnFirstPage = (printHeight - BodyTop + TitleY - 2 * SpacingOne) / wmSectionHeight; nrWMsOnNextPage = (printHeight - 2 * SpacingOne) / wmSectionHeight; nrWMsOnNextPage = Math.Max(nrWMsOnNextPage, 1); /// Prevent division by zero if there are too many WM tests nrPages = 1 + (batch.WaterMeters.Count - nrWMsOnFirstPage + nrWMsOnNextPage - 1) / nrWMsOnNextPage; pageNr = 1; nextWMNr = 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); if (File.Exists("C:\\TBF\\header.png")) { Image img = Image.FromFile("C:\\TBF\\header.png"); e.Graphics.DrawImage(new Bitmap(img), new Rectangle(0, 0, 827, 1169)); } /// Use the StringFormat class for the text layout of our document StringFormat format = new StringFormat(StringFormatFlags.LineLimit); if (pageNr == 1) { ///---------- /// Header ///---------- RectangleF printArea = new RectangleF(TitleX, TitleY, printWidth, 40); e.Graphics.DrawString(batch.ProtocolTitle, titleFont, Brushes.Black, printArea); string[] leftColumn = new string[] { "Batch number: ", "Date and time: ", "Procedure: ", Strings.User + ": ", "Ambient temperature: ", "Ambient pressure: ", "Ambient humidity: ", }; string[] rightColumn = new string[] { batch.BatchNr.ToString(), //batch.EndTime.ToShortDateString() + " " + batch.EndTime.ToShortTimeString(), string.Format("{0:yyyy.MM.dd HH:mm}", batch.EndTime), batch.ProcedureName, Users.GlobalData.CurrentUser.UserName, batch.AmbientTempAve().ToString("F1") + " °C", Config.Units.ConvertTo(Config.Unit.mbar, batch.AmbientPressAve()).ToString("F0") + " mbar", batch.AmbientHumiAve().ToString("F0") + " %", }; /// Determine max. left column width in characters int maxLen = 0; foreach (var s in leftColumn) if (s.Length > maxLen) maxLen = s.Length; /// Write aligned columns for (int i = 0; i < Math.Min(leftColumn.Length, rightColumn.Length); i++) { PrintAt(e, leftMargin, HdrTop + SpacingOne * i, leftColumn[i]); PrintAt(e, 300, HdrTop + SpacingOne * i, rightColumn[i]); } } ///-------- /// Body ///-------- /// This variable represents the top coordinate of the area where WM results are printed /// and it is updated (increased by) the value returned by PrintXyzWM() - the section size. int nextWmTop = (pageNr == 1) ? BodyTop : TitleY; int nrWMsOnPage = (pageNr == 1) ? nrWMsOnFirstPage : nrWMsOnNextPage; for (int wmNr = nextWMNr; wmNr < Math.Min(nextWMNr + nrWMsOnPage, batch.WaterMeters.Count); wmNr++) /// wmNr is 0-based { int wmPosition = true ? batch.WaterMeters[wmNr].WMPosition : (wmNr + 1); nextWmTop += PrintWM(e, batch.WaterMeters[wmNr], wmPosition, nextWmTop); } nextWMNr += nrWMsOnPage; e.HasMorePages = (nextWMNr < batch.WaterMeters.Count); ///---------- /// Footer ///---------- string footerText = string.Format("str. {1}/{2}", Strings.Page, pageNr++, nrPages); int footerWidth = (int)e.Graphics.MeasureString(footerText, font).Width; PrintAt(e, leftMargin + (printWidth - footerWidth) / 2, topMargin + printHeight - SpacingOne, footerText); } /// /// Print one water meter results /// /// Water meter /// Number of the water meter printed /// Top coordinate of watermeter data /// The height of the printed section int PrintWM(System.Drawing.Printing.PrintPageEventArgs e, Results.Entities.WaterMeter wm, int printedWMNr, int top) { /// Determin column widths float[] columnPos = new float[rsltItems.Count + 1]; columnPos[0] = (float)leftMargin; for (int i = 0; i < rsltItems.Count; i++) { float columnWidth = e.Graphics.MeasureString(rsltItems[i].ClmnHeaderText, font).Width; foreach (var mtr in wm.MeterTestRslts) { string itemText; if (!wm.Compound()) { itemText = rsltItems[i].Print(mtr); } else if (mtr.CompoundMeterId == (byte)CompoundMeterId.Compound) { Results.Entities.MeterTestRslt mainMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundMain); Results.Entities.MeterTestRslt auxMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundAux); itemText = rsltItems[i].PrintCombined(mainMtr, auxMtr, mtr); } else { continue; } /// Strip color information string[] texts = itemText.Split(new char[] { '|' }); if (texts.Length == 2) { itemText = texts[0]; } float width = e.Graphics.MeasureString(itemText, font).Width; if (width > columnWidth) columnWidth = width; } columnPos[i + 1] = columnPos[i] + columnWidth + 20.0f; } int tableLeftX = (int)columnPos[0]; int tableRightX = (int)columnPos[rsltItems.Count] - 20; string wmText = string.Format("Water meter {0}", printedWMNr); PrintAt(e, leftMargin, top, wmText); if (!string.IsNullOrEmpty(wm.SerialNr)) { PrintAt(e, leftMargin + (int)e.Graphics.MeasureString(wmText, font).Width, top, string.Format(" s/n = {0}", wm.SerialNr)); } /// Horizontal line int horY = top + 25; e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeftX, horY), new Point(tableRightX, horY)); for (int i = 0; i < rsltItems.Count; i++) { PrintAt(e, (int)columnPos[i], top + 27, rsltItems[i].ClmnHeaderText); } /// Horizontal line horY = top + 27 + SpacingOne; e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeftX, horY), new Point(tableRightX, horY)); int testsCount = 0; foreach (var mtr in wm.MeterTestRslts) { if (mtr.Publish() == Config.Entities.Publish.Always) { testsCount++; for (int i = 0; i < rsltItems.Count; i++) { string itemText; if (!wm.Compound()) { /// Single water meter itemText = rsltItems[i].Print(mtr); } else if (mtr.CompoundMeterId == (byte)CompoundMeterId.Compound) { Results.Entities.MeterTestRslt mainMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundMain); Results.Entities.MeterTestRslt auxMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundMain); itemText = rsltItems[i].PrintCombined(mainMtr, auxMtr, mtr); } else { continue; } /// Strip color information string[] texts = itemText.Split(new char[] { '|' }); if (texts.Length == 2) { itemText = texts[0]; Color color = texts[1].Equals("Green") ? Color.Green : (texts[1].Equals("Red") ? Color.Red : Color.White); /// TODO: How to print colors? } PrintAt(e, (int)columnPos[i], top + 30 + SpacingOne * testsCount, itemText); } } } /// Horizontal line horY = top + 30 + SpacingOne * (testsCount + 1); e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeftX, horY), new Point(tableRightX, horY)); return (testsCount + 4) * SpacingOne; } 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); } } }