435 lines
18 KiB
C#
435 lines
18 KiB
C#
///
|
|
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Printing;
|
|
using Common;
|
|
|
|
namespace Results.Output
|
|
{
|
|
public enum TableLines
|
|
{
|
|
None,
|
|
FirstAndLast,
|
|
FirstSecondAndLast,
|
|
All,
|
|
}
|
|
|
|
public class TableStyle
|
|
{
|
|
public float MarginX;
|
|
public float MarginY;
|
|
public Font Font;
|
|
public Font HeaderFont;
|
|
public int TopHeadersCount;
|
|
public int LeftHeadersCount;
|
|
public float LineWidth;
|
|
public TableLines HorizLines;
|
|
public TableLines VertLines;
|
|
public float[] ColumnWidths; /// null = automatic
|
|
}
|
|
|
|
public class Table
|
|
{
|
|
public readonly int ColumnsCount;
|
|
public readonly string AutoTestParam;
|
|
public int RowsCount { get { return Rows.Count; } }
|
|
|
|
public readonly IList<string[]> Rows;
|
|
public readonly IList<Alignment[]> HorizAlignments;
|
|
public readonly IList<VertAlignment[]> VertAlignments;
|
|
public TableStyle Style;
|
|
|
|
|
|
public Table(int columnsCount, string autoTestParam = null)
|
|
{
|
|
this.ColumnsCount = columnsCount;
|
|
this.AutoTestParam = autoTestParam;
|
|
|
|
Rows = new List<string[]>();
|
|
HorizAlignments = new List<Alignment[]>();
|
|
VertAlignments = new List<VertAlignment[]>();
|
|
Style = new TableStyle();
|
|
}
|
|
|
|
|
|
public void AddRow(string[] texts, Alignment[] horizAlignment, VertAlignment[] vertAlignemnt)
|
|
{
|
|
Rows.Add(texts);
|
|
HorizAlignments.Add(horizAlignment);
|
|
VertAlignments.Add(vertAlignemnt);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Returns true when table has either rows or columns count == 0
|
|
/// </summary>
|
|
/// <returns>true when empty</returns>
|
|
public bool IsEmpty()
|
|
{
|
|
return (Rows == null || RowsCount == 0 || Rows[0] == null || Rows[0].Length == 0);
|
|
}
|
|
|
|
|
|
public SizeF Measure(System.Drawing.Printing.PrintPageEventArgs e)
|
|
{
|
|
SizeF retVal = new SizeF(0, 0);
|
|
|
|
if (IsEmpty()) return retVal; /// Empty table => zero Size
|
|
|
|
float[] columnWidth = new float[ColumnsCount];
|
|
float[] rowHeight = new float[RowsCount];
|
|
|
|
///
|
|
/// Measure table column widths and header height
|
|
///
|
|
for (int colIx = 0; colIx < ColumnsCount; colIx++)
|
|
{
|
|
for (int rowIx = 0; rowIx < RowsCount; rowIx++)
|
|
{
|
|
if (Rows[rowIx] == null)
|
|
{
|
|
/// Separator row -> do nothing
|
|
}
|
|
else
|
|
{
|
|
bool isHeader = (colIx < Style.LeftHeadersCount) || (rowIx < Style.TopHeadersCount);
|
|
SizeF size = Common.Printers.PrintersCommon.Measure(e, Rows[rowIx][colIx], isHeader ? Style.HeaderFont : Style.Font);
|
|
if (size.Width > columnWidth[colIx]) columnWidth[colIx] = size.Width;
|
|
if (size.Height > rowHeight[rowIx]) rowHeight[rowIx] = size.Height;
|
|
}
|
|
}
|
|
|
|
bool hasLineToTheLeft = (Style.VertLines == TableLines.All)
|
|
|| ((Style.VertLines == TableLines.FirstAndLast) && (colIx == 0))
|
|
|| ((Style.VertLines == TableLines.FirstSecondAndLast) && (colIx <= 1));
|
|
|
|
retVal.Width += columnWidth[colIx] + (hasLineToTheLeft ? (Style.LineWidth + Style.MarginX) : 0) + Style.MarginX;
|
|
}
|
|
for (int rowIx = 0; rowIx < RowsCount; rowIx++)
|
|
{
|
|
if (Rows[rowIx] == null)
|
|
{
|
|
/// Separator row -> do nothing
|
|
}
|
|
else
|
|
{
|
|
bool hasLineAbove = (Style.HorizLines == TableLines.All)
|
|
|| ((Style.HorizLines == TableLines.FirstAndLast) && (rowIx == 0))
|
|
|| ((Style.HorizLines == TableLines.FirstSecondAndLast) && (rowIx <= 1))
|
|
|| ((rowIx >= 1) && (Rows[rowIx - 1] == null));
|
|
|
|
retVal.Height += rowHeight[rowIx] + (hasLineAbove ? (Style.LineWidth + Style.MarginY) : 0) + Style.MarginY;
|
|
}
|
|
}
|
|
|
|
if (Style.VertLines == TableLines.None) retVal.Width -= Style.MarginX;
|
|
if (Style.HorizLines == TableLines.None) retVal.Height -= Style.MarginY;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
public float Draw(System.Drawing.Printing.PrintPageEventArgs e, float left, float top)
|
|
{
|
|
if (IsEmpty()) return top; /// Empty table
|
|
|
|
int tblColumnsCount = Rows[0].Length;
|
|
|
|
float[] columnWidth = new float[tblColumnsCount];
|
|
float[] columnPos = new float[tblColumnsCount];
|
|
float[] vertLinePos = new float[tblColumnsCount + 1];
|
|
|
|
float[] rowHeight = new float[RowsCount];
|
|
float[] rowPos = new float[RowsCount];
|
|
float[] horizLinePos = new float[RowsCount + 1];
|
|
|
|
///
|
|
/// Measure table column widths and header height
|
|
///
|
|
vertLinePos[0] = left;
|
|
horizLinePos[0] = top;
|
|
for (int colIx = 0; colIx < tblColumnsCount; colIx++)
|
|
{
|
|
for (int rowIx = 0; rowIx < RowsCount; rowIx++)
|
|
{
|
|
if (Rows[rowIx] != null)
|
|
{
|
|
/// In not a separator line
|
|
bool isHeader = (colIx < Style.LeftHeadersCount) || (rowIx < Style.TopHeadersCount);
|
|
SizeF size = Common.Printers.PrintersCommon.Measure(e, Rows[rowIx][colIx], isHeader ? Style.HeaderFont : Style.Font);
|
|
if ((Style.ColumnWidths != null) && (Style.ColumnWidths.Length > colIx))
|
|
{
|
|
size.Width = Style.ColumnWidths[colIx]; /// Override measurement if column width is defined
|
|
}
|
|
if (size.Width > columnWidth[colIx]) columnWidth[colIx] = size.Width;
|
|
if (size.Height > rowHeight[rowIx]) rowHeight[rowIx] = size.Height;
|
|
}
|
|
else
|
|
{
|
|
/// Separator line -> do nothing
|
|
rowHeight[rowIx] = 0;
|
|
}
|
|
}
|
|
|
|
bool hasLineToTheLeft = (Style.VertLines == TableLines.All)
|
|
|| ((Style.VertLines == TableLines.FirstAndLast) && (colIx == 0))
|
|
|| ((Style.VertLines == TableLines.FirstSecondAndLast) && (colIx <= 1));
|
|
|
|
columnPos[colIx] = vertLinePos[colIx] + (hasLineToTheLeft ? (Style.LineWidth + Style.MarginX) : 0);
|
|
vertLinePos[colIx + 1] = columnPos[colIx] + columnWidth[colIx] + Style.MarginX;
|
|
}
|
|
for (int rowIx = 0; rowIx < RowsCount; rowIx++)
|
|
{
|
|
if (Rows[rowIx] != null)
|
|
{
|
|
/// In not a separator line
|
|
bool hasLineAbove = (Style.HorizLines == TableLines.All)
|
|
|| ((Style.HorizLines == TableLines.FirstAndLast) && (rowIx == 0))
|
|
|| ((Style.HorizLines == TableLines.FirstSecondAndLast) && (rowIx <= 1))
|
|
|| ((rowIx >= 1) && (Rows[rowIx - 1] == null));
|
|
|
|
rowPos[rowIx] = horizLinePos[rowIx] + (hasLineAbove ? Style.MarginY : 0);
|
|
horizLinePos[rowIx + 1] = rowPos[rowIx] + rowHeight[rowIx] + Style.LineWidth + Style.MarginY;
|
|
}
|
|
else if (rowIx > 0)
|
|
{
|
|
/// Separator line
|
|
rowPos[rowIx] = rowPos[rowIx - 1];
|
|
horizLinePos[rowIx + 1] = horizLinePos[rowIx];
|
|
}
|
|
}
|
|
|
|
/// Horizontal lines
|
|
float tableLeftX = left;
|
|
float tableRightX = vertLinePos[tblColumnsCount] + Style.LineWidth;
|
|
if (Style.HorizLines != TableLines.None)
|
|
{
|
|
for (int rowIx = 0; rowIx <= RowsCount; rowIx++)
|
|
{
|
|
if (Style.HorizLines == TableLines.All || rowIx == 0
|
|
|| rowIx == RowsCount
|
|
|| (Style.HorizLines == TableLines.FirstSecondAndLast && rowIx == 1)
|
|
|| ((rowIx >= 1) && (Rows[rowIx - 1] == null)))
|
|
{
|
|
e.Graphics.DrawLine(new Pen(Color.Black, Style.LineWidth), new PointF(tableLeftX, horizLinePos[rowIx] + Style.LineWidth / 2), new PointF(tableRightX, horizLinePos[rowIx] + Style.LineWidth / 2));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Vertical lines
|
|
float tableTopY = top;
|
|
float tableBottomY = horizLinePos[RowsCount] + Style.LineWidth;
|
|
if (Style.VertLines != TableLines.None)
|
|
{
|
|
for (int colIx = 0; colIx <= tblColumnsCount; colIx++)
|
|
{
|
|
if (Style.VertLines == TableLines.All || colIx == 0 || colIx == ColumnsCount || (Style.VertLines == TableLines.FirstSecondAndLast && colIx == 1))
|
|
{
|
|
e.Graphics.DrawLine(new Pen(Color.Black, Style.LineWidth), new PointF(vertLinePos[colIx] + Style.LineWidth / 2, tableTopY), new PointF(vertLinePos[colIx] + Style.LineWidth / 2, tableBottomY));
|
|
}
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Draw table body
|
|
///
|
|
for (int rowIndex = 0; rowIndex < RowsCount; rowIndex++)
|
|
{
|
|
string[] oneTableRow = Rows[rowIndex];
|
|
if (oneTableRow != null)
|
|
{
|
|
Alignment[] horizAlignment = HorizAlignments[(RowsCount > rowIndex) ? rowIndex : 0];
|
|
VertAlignment[] vertAlignment = VertAlignments[(RowsCount > rowIndex) ? rowIndex : 0];
|
|
for (int colIndex = 0; colIndex < tblColumnsCount; colIndex++)
|
|
{
|
|
bool isHeader = (colIndex < Style.LeftHeadersCount) || (rowIndex < Style.TopHeadersCount);
|
|
Common.Printers.PrintersCommon.PrintAt(e, oneTableRow[colIndex],
|
|
isHeader ? Style.HeaderFont : Style.Font,
|
|
columnPos[colIndex],
|
|
rowPos[rowIndex],
|
|
columnWidth[colIndex],
|
|
rowHeight[rowIndex],
|
|
horizAlignment[colIndex],
|
|
vertAlignment[colIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return tableBottomY;
|
|
}
|
|
|
|
|
|
public static Table Create_TestsAreRows(Results.Entities.WaterMeter wm, IList<WMeterRsltItemSpec> items, TableStyle style, string autoTestParam = null)
|
|
{
|
|
/// Top row contains column captions
|
|
|
|
Table table = new Table(items.Count);
|
|
table.Style = style;
|
|
|
|
string[] tableHeader = new string[table.ColumnsCount];
|
|
Alignment[] horizAlignment = new Alignment[table.ColumnsCount];
|
|
VertAlignment[] vertAlignment = new VertAlignment[table.ColumnsCount];
|
|
for (int i = 0; i < table.ColumnsCount; i++)
|
|
{
|
|
tableHeader[i] = items[i].Caption;
|
|
horizAlignment[i] = Alignment.Center;
|
|
vertAlignment[i] = VertAlignment.Middle;
|
|
}
|
|
table.AddRow(tableHeader, horizAlignment, vertAlignment);
|
|
|
|
WMeterRsltItemSpec.TableRowNr = 1;
|
|
foreach (var mtr in string.IsNullOrEmpty(autoTestParam) ? wm.RegularMeterTestRslts() : wm.AutoMeterTestRslts(autoTestParam))
|
|
{
|
|
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Publish.Always)
|
|
{
|
|
string[] oneTableRow = new string[table.ColumnsCount];
|
|
horizAlignment = new Alignment[table.ColumnsCount];
|
|
vertAlignment = new VertAlignment[table.ColumnsCount];
|
|
|
|
for (int i = 0; i < table.ColumnsCount; i++)
|
|
{
|
|
WMeterRsltItemSpec.TableColumnNr = i + 1;
|
|
oneTableRow[i] = items[i].Print(wm, mtr.Name()).Split(new char[] { '|' })[0];
|
|
horizAlignment[i] = items[i].Alignment;
|
|
vertAlignment[i] = VertAlignment.Middle;
|
|
}
|
|
|
|
table.AddRow(oneTableRow, horizAlignment, vertAlignment);
|
|
|
|
WMeterRsltItemSpec.TableRowNr++;
|
|
}
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
|
|
public static Table Create_TestsAreColumns(Results.Entities.WaterMeter wm, IList<WMeterRsltItemSpec> items, TableStyle style, string autoTestParam = null)
|
|
{
|
|
/// Left column contains row captions
|
|
|
|
///
|
|
/// Calculate columns count
|
|
///
|
|
int columnsCount = 1; /// Left column contains item caption
|
|
foreach (var mtr in string.IsNullOrEmpty(autoTestParam) ? wm.RegularMeterTestRslts() : wm.AutoMeterTestRslts(autoTestParam))
|
|
{
|
|
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Publish.Always)
|
|
{
|
|
columnsCount++; /// One additional column for each test to be published
|
|
}
|
|
}
|
|
|
|
Table table = new Table(columnsCount);
|
|
table.Style = style;
|
|
|
|
///
|
|
/// Table content
|
|
///
|
|
WMeterRsltItemSpec.TableRowNr = 1;
|
|
for (int i = 0; i < items.Count; i++)
|
|
{
|
|
string[] oneTableRow = new string[columnsCount];
|
|
Alignment[] horizAlignment = new Alignment[columnsCount];
|
|
VertAlignment[] vertAlignment = new VertAlignment[columnsCount];
|
|
|
|
oneTableRow[0] = items[i].Caption;
|
|
horizAlignment[0] = Alignment.Center;
|
|
vertAlignment[0] = VertAlignment.Middle;
|
|
|
|
WMeterRsltItemSpec.TableColumnNr = 1;
|
|
foreach (var mtr in string.IsNullOrEmpty(autoTestParam) ? wm.RegularMeterTestRslts() : wm.AutoMeterTestRslts(autoTestParam))
|
|
{
|
|
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Publish.Always)
|
|
{
|
|
/// Strip color information
|
|
oneTableRow[WMeterRsltItemSpec.TableColumnNr] =
|
|
items[i].Print(wm, mtr.Name()).Split(new char[] { '|' })[0];
|
|
horizAlignment[WMeterRsltItemSpec.TableColumnNr] = items[i].Alignment;
|
|
vertAlignment[WMeterRsltItemSpec.TableColumnNr] = VertAlignment.Middle;
|
|
|
|
WMeterRsltItemSpec.TableColumnNr++;
|
|
}
|
|
}
|
|
|
|
table.AddRow(oneTableRow, horizAlignment, vertAlignment);
|
|
|
|
WMeterRsltItemSpec.TableRowNr++;
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
|
|
public static Table Create_TestsAreColumnsPL(Results.Entities.WaterMeter wm, IList<WMeterRsltItemSpec> items, TableStyle style, string autoTestParam = null)
|
|
{
|
|
/// Left column contains row captions
|
|
|
|
///
|
|
/// Calculate columns count
|
|
///
|
|
int columnsCount = 2; /// Left two columns contain item caption and units
|
|
foreach (var mtr in string.IsNullOrEmpty(autoTestParam) ? wm.RegularMeterTestRslts() : wm.AutoMeterTestRslts(autoTestParam))
|
|
{
|
|
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Publish.Always)
|
|
{
|
|
columnsCount++; /// One additional column for each test to be published
|
|
}
|
|
}
|
|
|
|
Table table = new Table(columnsCount);
|
|
table.Style = style;
|
|
|
|
///
|
|
/// Table content
|
|
///
|
|
WMeterRsltItemSpec.TableRowNr = 1;
|
|
for (int i = 0; i < items.Count; i++)
|
|
{
|
|
if (items[i].Uid == (int)ItemID.Separator)
|
|
{
|
|
table.AddRow(null, null, null); /// 'separator' row
|
|
}
|
|
else
|
|
{
|
|
string[] oneTableRow = new string[columnsCount];
|
|
Alignment[] horizAlignment = new Alignment[columnsCount];
|
|
VertAlignment[] vertAlignment = new VertAlignment[columnsCount];
|
|
|
|
oneTableRow[0] = items[i].Caption;
|
|
horizAlignment[0] = Alignment.Center;
|
|
vertAlignment[0] = VertAlignment.Middle;
|
|
|
|
oneTableRow[1] = (i == 0) ? "Jednostka" : items[i].Units.ToDescription();
|
|
horizAlignment[1] = Alignment.Center;
|
|
vertAlignment[1] = VertAlignment.Middle;
|
|
|
|
WMeterRsltItemSpec.TableColumnNr = 1;
|
|
foreach (var mtr in string.IsNullOrEmpty(autoTestParam) ? wm.RegularMeterTestRslts() : wm.AutoMeterTestRslts(autoTestParam))
|
|
{
|
|
if (mtr != null && mtr.IsPilotRslt() && mtr.Publish() == Publish.Always)
|
|
{
|
|
int colIx = WMeterRsltItemSpec.TableColumnNr + 1;
|
|
|
|
/// Strip color information
|
|
oneTableRow[colIx] = items[i].Print(wm, mtr.Name()).Split(new char[] { '|' })[0];
|
|
horizAlignment[colIx] = items[i].Alignment;
|
|
vertAlignment[colIx] = VertAlignment.Middle;
|
|
|
|
WMeterRsltItemSpec.TableColumnNr++;
|
|
}
|
|
}
|
|
|
|
table.AddRow(oneTableRow, horizAlignment, vertAlignment);
|
|
}
|
|
WMeterRsltItemSpec.TableRowNr++;
|
|
}
|
|
|
|
return table;
|
|
}
|
|
}
|
|
}
|