373 lines
12 KiB
C#
373 lines
12 KiB
C#
///
|
|
/// Copyright (c) 2017 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.Output.Printers.Enhanced
|
|
{
|
|
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;
|
|
|
|
/// <summary>
|
|
/// Property variable for the Font the user wishes to use
|
|
/// </summary>
|
|
Font font;
|
|
Font boldFont;
|
|
Font titleFont;
|
|
|
|
///
|
|
/// Data to print
|
|
///
|
|
Results.Entities.Batch batch;
|
|
|
|
///
|
|
/// Items to print
|
|
///
|
|
readonly IList<Results.ItemSpec> 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
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="textToPrint">Text to be printed</param>
|
|
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.Count > 0 && 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;
|
|
if (batch.WaterMeters.Count > 0)
|
|
{
|
|
foreach (var mtr in batch.WaterMeters[0].MeterTestRslts)
|
|
{
|
|
if (mtr.Publish() == Config.Entities.Publish.Always) testsCount++;
|
|
}
|
|
}
|
|
|
|
if (batch.WaterMeters.Count > 0 && 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the default onbeginPrint method of the PrintDocument Object
|
|
/// </summary>
|
|
/// <param name=e></param>
|
|
/// <remarks></remarks>
|
|
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); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the default OnPrintPage method of the PrintDocument.
|
|
/// </summary>
|
|
/// <param name=e></param>
|
|
/// <remarks>This provides the print logic for our document</remarks>
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Print one water meter results
|
|
/// </summary>
|
|
/// <param name="wm">Water meter</param>
|
|
/// <param name="printedWMNr">Number of the water meter printed</param>
|
|
/// <param name="top">Top coordinate of watermeter data</param>
|
|
/// <returns>The height of the printed section</returns>
|
|
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);
|
|
}
|
|
}
|
|
}
|