Printers.Zapiska, OnePerMeter, etc. changes: flow coordinates, content separated from layout, etc.
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
///
|
||||
/// 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 Results.Resources;
|
||||
|
||||
namespace Results.Output.Printers.OnePerMeter
|
||||
{
|
||||
public class OnePerMeterPrintDocument : PrintDocument
|
||||
{
|
||||
const float GapBetweenTableColumns = 10;
|
||||
const float GapBetweenCommonColumns = 10;
|
||||
|
||||
/// Size of the printed area without margins, after taking into account 'pageOrientation'
|
||||
readonly int printHeight;
|
||||
readonly int printWidth;
|
||||
|
||||
readonly int topMargin;
|
||||
readonly int bottomMargin;
|
||||
readonly int leftMargin;
|
||||
readonly int TitleX;
|
||||
readonly int TitleY; /// Depends on the size of the header
|
||||
|
||||
readonly int spacingOne;
|
||||
readonly int spacingOne4Header;
|
||||
|
||||
float commonTop; /// = TitleY + 60
|
||||
float bodyTop; /// = HdrTop + 160
|
||||
///
|
||||
float titleHeight;
|
||||
float commonHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Property variable for the Font the user wishes to use
|
||||
/// </summary>
|
||||
Font font;
|
||||
Font headerFont;
|
||||
Font titleFont;
|
||||
|
||||
///
|
||||
/// Data to print
|
||||
///
|
||||
Results.Entities.Batch batch;
|
||||
OnePerMeterPrinterCfg cfg;
|
||||
Results.Entities.WaterMeter wm;
|
||||
|
||||
///
|
||||
/// Items to print
|
||||
///
|
||||
string header;
|
||||
IList<WMeterRsltItemSpec> commonItems;
|
||||
IList<WMeterRsltItemSpec> testItems;
|
||||
IList<WMeterRsltItemSpec> testItems2;
|
||||
string footer;
|
||||
|
||||
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 OnePerMeterPrintDocument(Results.Entities.Batch batch, OnePerMeterPrinterCfg cfg, Results.Entities.WaterMeter wm)
|
||||
{
|
||||
this.batch = batch;
|
||||
this.cfg = cfg;
|
||||
this.wm = wm;
|
||||
|
||||
topMargin = cfg.TopMargin;
|
||||
bottomMargin = cfg.BottomMargin;
|
||||
leftMargin = cfg.LeftMargin;
|
||||
|
||||
header = string.IsNullOrEmpty(cfg.Header) ? string.Empty : cfg.Header.Replace("~", Environment.NewLine);
|
||||
commonItems = Results.WMeterRsltItemSpec.FromStrArray(cfg.CommonItems);
|
||||
testItems = Results.WMeterRsltItemSpec.FromStrArray(cfg.TestItems); /// TestID info will be overwritten later on
|
||||
testItems2 = Results.WMeterRsltItemSpec.FromStrArray(cfg.TestItems2); /// TestID info will be overwritten later on
|
||||
footer = string.IsNullOrEmpty(cfg.Footer) ? string.Empty : cfg.Footer.Replace("~", Environment.NewLine);
|
||||
|
||||
/// Initialize fonts
|
||||
titleFont = new Font((cfg.TitFntFml != null ? cfg.TitFntFml : "Arial"), (cfg.TitFntSz > 0 ? cfg.TitFntSz : 10), (FontStyle)cfg.TitFntSty);
|
||||
headerFont = new Font((cfg.HdrFntFml != null ? cfg.HdrFntFml : "Arial"), (cfg.HdrFntSz > 0 ? cfg.HdrFntSz : 10), (FontStyle)cfg.HdrFntSty);
|
||||
font = new Font((cfg.BodyFntFml != null ? cfg.BodyFntFml : "Arial"), (cfg.BodyFntSz > 0 ? cfg.BodyFntSz : 10), (FontStyle)cfg.BodyFntSty);
|
||||
|
||||
/// Set print area size and margins (in dots using 100 dpi)
|
||||
DefaultPageSettings.Landscape = (cfg.PageOrientation == PageOrientation.Landscape);
|
||||
///
|
||||
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;
|
||||
}
|
||||
|
||||
spacingOne = System.Windows.Forms.TextRenderer.MeasureText("Abcgq", font).Height;
|
||||
spacingOne4Header = System.Windows.Forms.TextRenderer.MeasureText("Abcgq", headerFont).Height;
|
||||
|
||||
/// Prepare document outline
|
||||
TitleX = cfg.LeftMargin;
|
||||
TitleY = cfg.TopMargin;
|
||||
|
||||
pageNr = 1;
|
||||
nrPages = (testItems2.Count != 0) ? 2 : 1;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <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 (pageNr == 1)
|
||||
{
|
||||
titleHeight = System.Windows.Forms.TextRenderer.MeasureText(header, titleFont).Height;
|
||||
commonTop = TitleY + titleHeight + spacingOne4Header;
|
||||
|
||||
commonHeight = commonItems.Count * spacingOne;
|
||||
bodyTop = commonTop + commonHeight + spacingOne4Header;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
///
|
||||
/// Title
|
||||
///
|
||||
RectangleF printArea = new RectangleF(TitleX, TitleY, printWidth, titleHeight);
|
||||
e.Graphics.DrawString(header, titleFont, Brushes.Black, printArea);
|
||||
|
||||
///
|
||||
/// Common items
|
||||
///
|
||||
string[] leftColumn = new string[commonItems.Count];
|
||||
string[] rightColumn = new string[commonItems.Count];
|
||||
|
||||
int cnt = 0;
|
||||
foreach (var v in commonItems)
|
||||
{
|
||||
leftColumn[cnt] = v.Caption;
|
||||
rightColumn[cnt] = (batch.WaterMeters.Count > 0) ? v.Print(batch.WaterMeters[0]) : string.Empty;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/// Determine left column width
|
||||
float maxWidth = 0;
|
||||
foreach (var str in leftColumn)
|
||||
{
|
||||
float width = e.Graphics.MeasureString(str, font).Width;
|
||||
if (width > maxWidth) maxWidth = width;
|
||||
}
|
||||
|
||||
/// Write aligned columns
|
||||
for (int i = 0; i < Math.Min(leftColumn.Length, rightColumn.Length); i++)
|
||||
{
|
||||
PrintAt(e, leftMargin, commonTop + spacingOne * i, maxWidth, leftColumn[i], font, Alignment.Left);
|
||||
PrintAt(e, leftMargin + maxWidth + GapBetweenCommonColumns, commonTop + spacingOne * i, 0, rightColumn[i], font, Alignment.Left);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Body
|
||||
///
|
||||
if (pageNr == 1)
|
||||
{
|
||||
string[] tableHeader;
|
||||
IList<string[]> tableRows;
|
||||
Alignment[] itemAlignment;
|
||||
|
||||
///
|
||||
/// Prepare table content: tableHeader + tableRows + itemAlignment
|
||||
///
|
||||
if (cfg.TestsAreRows)
|
||||
{
|
||||
GetContentTestsAreRows(wm, testItems, out tableHeader, out tableRows, out itemAlignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetContentTestsAreColumns(wm, testItems, out tableHeader, out tableRows, out itemAlignment);
|
||||
}
|
||||
|
||||
DrawTable(e, (float)leftMargin, bodyTop, tableHeader, tableRows, itemAlignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] tableHeader;
|
||||
IList<string[]> tableRows;
|
||||
Alignment[] itemAlignment;
|
||||
|
||||
///
|
||||
/// Prepare table content: tableHeader + tableRows + itemAlignment
|
||||
///
|
||||
if (cfg.TestsAreRows2)
|
||||
{
|
||||
GetContentTestsAreRows(wm, testItems2, out tableHeader, out tableRows, out itemAlignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetContentTestsAreColumns(wm, testItems2, out tableHeader, out tableRows, out itemAlignment);
|
||||
}
|
||||
|
||||
DrawTable(e, (float)leftMargin, (float)topMargin, tableHeader, tableRows, itemAlignment);
|
||||
}
|
||||
|
||||
if (pageNr == nrPages)
|
||||
{
|
||||
///
|
||||
/// Footer on the last page
|
||||
///
|
||||
float footerWidth = e.Graphics.MeasureString(footer, font).Width;
|
||||
PrintAt(e, leftMargin, topMargin + printHeight - 2 * spacingOne, 0, footer, font, Alignment.Left);
|
||||
}
|
||||
|
||||
///
|
||||
/// Page number on each page
|
||||
///
|
||||
string pageNrText = string.Format("{0} {1}/{2}", Strings.Page, pageNr, nrPages);
|
||||
float pageNrWidth = e.Graphics.MeasureString(pageNrText, font).Width;
|
||||
PrintAt(e, leftMargin + (printWidth - pageNrWidth) / 2, topMargin + printHeight - spacingOne, 0, pageNrText, font, Alignment.Left);
|
||||
|
||||
e.HasMorePages = !(pageNr == nrPages);
|
||||
|
||||
pageNr++;
|
||||
}
|
||||
|
||||
|
||||
void GetContentTestsAreRows(Results.Entities.WaterMeter wm, IList<WMeterRsltItemSpec> items, out string[] tableHeader, out IList<string[]> tableRows, out Alignment[] itemAlignment)
|
||||
{
|
||||
int tableColumnsCount = items.Count;
|
||||
|
||||
tableRows = new List<string[]>();
|
||||
tableHeader = new string[tableColumnsCount];
|
||||
itemAlignment = new Alignment[tableColumnsCount];
|
||||
|
||||
for (int i = 0; i < tableColumnsCount; i++)
|
||||
{
|
||||
tableHeader[i] = items[i].Caption;
|
||||
itemAlignment[i] = items[i].Alignment;
|
||||
}
|
||||
|
||||
WMeterRsltItemSpec.TableRowNr = 0;
|
||||
foreach (var mtr in wm.MeterTestRslts)
|
||||
{
|
||||
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Config.Entities.Publish.Always)
|
||||
{
|
||||
string[] oneTableRow = new string[tableColumnsCount];
|
||||
WMeterRsltItemSpec.TableRowNr++;
|
||||
|
||||
for (int i = 0; i < tableColumnsCount; i++)
|
||||
{
|
||||
WMeterRsltItemSpec.TableColumnNr = i + 1;
|
||||
oneTableRow[i] = items[i].Print(wm, mtr.Name()).Split(new char[] { '|' })[0];
|
||||
}
|
||||
|
||||
tableRows.Add(oneTableRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GetContentTestsAreColumns(Results.Entities.WaterMeter wm, IList<WMeterRsltItemSpec> items, out string[] tableHeader, out IList<string[]> tableRows, out Alignment[] itemAlignment)
|
||||
{
|
||||
int tableColumnsCount = 1;
|
||||
foreach (var mtr in wm.MeterTestRslts)
|
||||
{
|
||||
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Config.Entities.Publish.Always)
|
||||
{
|
||||
tableColumnsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
tableRows = new List<string[]>();
|
||||
tableHeader = new string[tableColumnsCount];
|
||||
itemAlignment = new Alignment[tableColumnsCount];
|
||||
|
||||
tableHeader[0] = string.Empty;
|
||||
itemAlignment[0] = Alignment.Left;
|
||||
int columnsCount = 1;
|
||||
foreach (var mtr in wm.MeterTestRslts)
|
||||
{
|
||||
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Config.Entities.Publish.Always)
|
||||
{
|
||||
tableHeader[columnsCount] = mtr.Name();
|
||||
itemAlignment[columnsCount] = Alignment.Left;
|
||||
columnsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
WMeterRsltItemSpec.TableRowNr = 0;
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
string[] oneTableRow = new string[tableColumnsCount];
|
||||
WMeterRsltItemSpec.TableRowNr++;
|
||||
|
||||
oneTableRow[0] = items[i].Caption;
|
||||
|
||||
WMeterRsltItemSpec.TableColumnNr = 1;
|
||||
foreach (var mtr in wm.MeterTestRslts)
|
||||
{
|
||||
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Config.Entities.Publish.Always)
|
||||
{
|
||||
/// Strip color information
|
||||
oneTableRow[WMeterRsltItemSpec.TableColumnNr] =
|
||||
items[i].Print(wm, mtr.Name()).Split(new char[] { '|' })[0];
|
||||
WMeterRsltItemSpec.TableColumnNr++;
|
||||
}
|
||||
}
|
||||
|
||||
tableRows.Add(oneTableRow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float DrawTable(System.Drawing.Printing.PrintPageEventArgs e, float left, float top, string[] header, IList<string[]> rows, Alignment[] alignment)
|
||||
{
|
||||
int tblColumnsCount = header.Length;
|
||||
|
||||
float[] columnWidth = new float[tblColumnsCount];
|
||||
float[] columnPos = new float[tblColumnsCount + 1];
|
||||
columnPos[0] = left;
|
||||
|
||||
///
|
||||
/// Measure table column widths and header height
|
||||
///
|
||||
float headerHeight = 0;
|
||||
for (int i = 0; i < tblColumnsCount; i++)
|
||||
{
|
||||
SizeF size = e.Graphics.MeasureString(header[i], headerFont);
|
||||
columnWidth[i] = (int)(size.Width + 0.99f);
|
||||
if (size.Height > headerHeight) headerHeight = (int)(size.Height + 0.99f);
|
||||
|
||||
foreach (var tableRow in rows)
|
||||
{
|
||||
int width = (int)(e.Graphics.MeasureString(tableRow[i], font).Width + 0.99f);
|
||||
if (width > columnWidth[i]) columnWidth[i] = width;
|
||||
}
|
||||
columnPos[i + 1] = columnPos[i] + columnWidth[i] + GapBetweenTableColumns;
|
||||
}
|
||||
|
||||
float tableLeftX = columnPos[0];
|
||||
float tableRightX = columnPos[tblColumnsCount] - GapBetweenTableColumns;
|
||||
|
||||
/// Horizontal line
|
||||
float horY = top + 1.5f * spacingOne4Header;
|
||||
e.Graphics.DrawLine(new Pen(Color.Black, 2), new PointF(tableLeftX, horY), new PointF(tableRightX, horY));
|
||||
|
||||
///
|
||||
/// Draw table header
|
||||
///
|
||||
for (int i = 0; i < tblColumnsCount; i++)
|
||||
{
|
||||
PrintAt(e, columnPos[i],
|
||||
top + 1.7f * spacingOne4Header,
|
||||
columnWidth[i],
|
||||
header[i],
|
||||
headerFont,
|
||||
Alignment.Center);
|
||||
}
|
||||
/// Horizontal line
|
||||
horY = top + 2.1f * spacingOne4Header + headerHeight;
|
||||
e.Graphics.DrawLine(new Pen(Color.Black, 2), new PointF(tableLeftX, horY), new PointF(tableRightX, horY));
|
||||
|
||||
///
|
||||
/// Draw table body
|
||||
///
|
||||
int rowsCount = 0;
|
||||
foreach (var oneTableRow in rows)
|
||||
{
|
||||
for (int i = 0; i < tblColumnsCount; i++)
|
||||
{
|
||||
PrintAt(e, columnPos[i],
|
||||
horY + 0.2f * spacingOne4Header + spacingOne * rowsCount,
|
||||
columnWidth[i],
|
||||
oneTableRow[i],
|
||||
font,
|
||||
alignment[i]);
|
||||
}
|
||||
rowsCount++;
|
||||
}
|
||||
|
||||
/// Horizontal line
|
||||
horY = horY + spacingOne * rowsCount + (3 * spacingOne4Header / 10);
|
||||
e.Graphics.DrawLine(new Pen(Color.Black, 2), new PointF(tableLeftX, horY), new PointF(tableRightX, horY));
|
||||
|
||||
return horY - top + spacingOne;
|
||||
}
|
||||
|
||||
|
||||
static Font lastFont = null;
|
||||
static float lastSpacing = 0;
|
||||
|
||||
SizeF Measure(System.Drawing.Printing.PrintPageEventArgs e, string paragraph, Font font)
|
||||
{
|
||||
if (font != lastFont)
|
||||
{
|
||||
lastFont = font;
|
||||
lastSpacing = e.Graphics.MeasureString("Abcgq", font).Height;
|
||||
}
|
||||
|
||||
string[] lines = paragraph.Split(new char[] { '~' });
|
||||
float width = 0;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
float lineWid = e.Graphics.MeasureString(line, font).Width;
|
||||
if (lineWid > width) width = lineWid;
|
||||
}
|
||||
|
||||
return new SizeF(width, 0.8f * lines.Length * lastSpacing + 0.2f);
|
||||
}
|
||||
|
||||
|
||||
void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, float x, float y, float width, string paragraph, Font font, Alignment alignment)
|
||||
{
|
||||
SizeF size = Measure(e, paragraph, font);
|
||||
|
||||
string[] lines = paragraph.Split(new char[] { '~' });
|
||||
foreach (var line in lines)
|
||||
{
|
||||
float xx;
|
||||
switch (alignment)
|
||||
{
|
||||
default:
|
||||
case Alignment.Left: xx = x; break;
|
||||
case Alignment.Center: xx = x + (width - e.Graphics.MeasureString(line, font).Width) / 2; break;
|
||||
case Alignment.Right: xx = x + width - e.Graphics.MeasureString(line, font).Width; break;
|
||||
}
|
||||
e.Graphics.DrawString(line, font, Brushes.Black, new PointF(xx, y));
|
||||
y += 0.8f * lastSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
|
||||
namespace Results.Output.Printers.OnePerMeter
|
||||
{
|
||||
public class OnePerMeterPrinterCfg
|
||||
{
|
||||
public Config.Entities.PageOrientation PageOrientation;
|
||||
public int TopMargin;
|
||||
public int BottomMargin;
|
||||
public int LeftMargin;
|
||||
public string TitFntFml;
|
||||
public int TitFntSz;
|
||||
public int TitFntSty;
|
||||
public string HdrFntFml;
|
||||
public int HdrFntSz;
|
||||
public int HdrFntSty;
|
||||
public string BodyFntFml;
|
||||
public int BodyFntSz;
|
||||
public int BodyFntSty;
|
||||
public bool GoodOnly;
|
||||
public bool SupressPrinting; /// Bypass printing when true
|
||||
public System.Globalization.CultureInfo CultureInfo;
|
||||
public string Header; /// =Title
|
||||
public string[] CommonItems;
|
||||
public string[] TestItems;
|
||||
public string[] TestItems2;
|
||||
public string Footer;
|
||||
public bool TestsAreRows;
|
||||
public bool TestsAreRows2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user