226 lines
9.6 KiB
C#
226 lines
9.6 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Drawing;
|
|||
|
|
using System.Drawing.Printing;
|
|||
|
|
using Config.Entities;
|
|||
|
|
|
|||
|
|
namespace Results.Output.Printers
|
|||
|
|
{
|
|||
|
|
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 class PrintersCommon : PrintDocument
|
|||
|
|
{
|
|||
|
|
protected SizeF MeasureTable(System.Drawing.Printing.PrintPageEventArgs e, IList<string[]> rows, TableStyle tableStyle)
|
|||
|
|
{
|
|||
|
|
SizeF retVal = new SizeF(0, 0);
|
|||
|
|
|
|||
|
|
if (rows == null || rows.Count == 0) return retVal;
|
|||
|
|
|
|||
|
|
int tblColumnsCount = rows[0].Length;
|
|||
|
|
|
|||
|
|
float[] columnWidth = new float[tblColumnsCount];
|
|||
|
|
float[] rowHeight = new float[rows.Count];
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Measure table column widths and header height
|
|||
|
|
///
|
|||
|
|
for (int colIx = 0; colIx < tblColumnsCount; colIx++)
|
|||
|
|
{
|
|||
|
|
for (int rowIx = 0; rowIx < rows.Count; rowIx++)
|
|||
|
|
{
|
|||
|
|
bool isHeader = (colIx < tableStyle.LeftHeadersCount) || (rowIx < tableStyle.TopHeadersCount);
|
|||
|
|
SizeF size = Measure(e, rows[rowIx][colIx], isHeader ? tableStyle.HeaderFont : tableStyle.Font);
|
|||
|
|
if (size.Width > columnWidth[colIx]) columnWidth[colIx] = size.Width;
|
|||
|
|
if (size.Height > rowHeight[rowIx]) rowHeight[rowIx] = size.Height;
|
|||
|
|
}
|
|||
|
|
retVal.Width += columnWidth[colIx] + 2 * tableStyle.MarginX;
|
|||
|
|
}
|
|||
|
|
for (int rowIx = 0; rowIx < rows.Count; rowIx++)
|
|||
|
|
{
|
|||
|
|
retVal.Height += rowHeight[rowIx] + 2 * tableStyle.MarginY;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return retVal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
protected float DrawTable(System.Drawing.Printing.PrintPageEventArgs e, float left, float top, IList<string[]> rows,
|
|||
|
|
IList<Alignment[]> horizAlignments, IList<VertAlignment[]> vertAlignments, TableStyle tableStyle)
|
|||
|
|
{
|
|||
|
|
if (rows == null || rows.Count == 0) return top;
|
|||
|
|
|
|||
|
|
int tblColumnsCount = rows[0].Length;
|
|||
|
|
float[] columnWidth = new float[tblColumnsCount];
|
|||
|
|
float[] columnPos = new float[tblColumnsCount + 1];
|
|||
|
|
float[] rowHeight = new float[rows.Count];
|
|||
|
|
float[] rowPos = new float[rows.Count + 1];
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Measure table column widths and header height
|
|||
|
|
///
|
|||
|
|
columnPos[0] = left;
|
|||
|
|
rowPos[0] = top;
|
|||
|
|
for (int colIx = 0; colIx < tblColumnsCount; colIx++)
|
|||
|
|
{
|
|||
|
|
for (int rowIx = 0; rowIx < rows.Count; rowIx++)
|
|||
|
|
{
|
|||
|
|
bool isHeader = (colIx < tableStyle.LeftHeadersCount) || (rowIx < tableStyle.TopHeadersCount);
|
|||
|
|
SizeF size = Measure(e, rows[rowIx][colIx], isHeader ? tableStyle.HeaderFont : tableStyle.Font);
|
|||
|
|
if (size.Width > columnWidth[colIx]) columnWidth[colIx] = size.Width;
|
|||
|
|
if (size.Height > rowHeight[rowIx]) rowHeight[rowIx] = size.Height;
|
|||
|
|
}
|
|||
|
|
columnPos[colIx + 1] = columnPos[colIx] + columnWidth[colIx] + 2 * tableStyle.MarginX + tableStyle.LineWidth;
|
|||
|
|
}
|
|||
|
|
for (int rowIx = 0; rowIx < rows.Count; rowIx++)
|
|||
|
|
{
|
|||
|
|
rowPos[rowIx + 1] = rowPos[rowIx] + rowHeight[rowIx] + 2 * tableStyle.MarginY + tableStyle.LineWidth;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Horizontal lines
|
|||
|
|
float tableLeftX = left;
|
|||
|
|
float tableRightX = columnPos[tblColumnsCount] + tableStyle.LineWidth;
|
|||
|
|
if (tableStyle.HorizLines != TableLines.None)
|
|||
|
|
{
|
|||
|
|
for (int rowIx = 0; rowIx <= rows.Count; rowIx++)
|
|||
|
|
{
|
|||
|
|
if (tableStyle.HorizLines == TableLines.All || rowIx == 0 || rowIx == rows.Count || (tableStyle.HorizLines == TableLines.FirstSecondAndLast && rowIx == 1))
|
|||
|
|
{
|
|||
|
|
e.Graphics.DrawLine(new Pen(Color.Black, tableStyle.LineWidth), new PointF(tableLeftX, rowPos[rowIx] + tableStyle.LineWidth / 2), new PointF(tableRightX, rowPos[rowIx] + tableStyle.LineWidth / 2));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Vertical lines
|
|||
|
|
float tableTopY = top;
|
|||
|
|
float tableBottomY = rowPos[rows.Count] + tableStyle.LineWidth;
|
|||
|
|
if (tableStyle.VertLines != TableLines.None)
|
|||
|
|
{
|
|||
|
|
for (int colIx = 0; colIx <= tblColumnsCount; colIx++)
|
|||
|
|
{
|
|||
|
|
if (tableStyle.VertLines == TableLines.All || colIx == 0 || colIx == rows.Count || (tableStyle.VertLines == TableLines.FirstSecondAndLast && colIx == 1))
|
|||
|
|
{
|
|||
|
|
e.Graphics.DrawLine(new Pen(Color.Black, tableStyle.LineWidth), new PointF(columnPos[colIx] + tableStyle.LineWidth / 2, tableTopY), new PointF(columnPos[colIx] + tableStyle.LineWidth / 2, tableBottomY));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Draw table body
|
|||
|
|
///
|
|||
|
|
for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
|
|||
|
|
{
|
|||
|
|
string[] oneTableRow = rows[rowIndex];
|
|||
|
|
Alignment[] horizAlignment = horizAlignments[(horizAlignments.Count > rowIndex) ? rowIndex : 0];
|
|||
|
|
VertAlignment[] vertAlignment = vertAlignments[(vertAlignments.Count > rowIndex) ? rowIndex : 0];
|
|||
|
|
for (int colIndex = 0; colIndex < tblColumnsCount; colIndex++)
|
|||
|
|
{
|
|||
|
|
bool isHeader = (colIndex < tableStyle.LeftHeadersCount) || (rowIndex < tableStyle.TopHeadersCount);
|
|||
|
|
PrintAt(e, oneTableRow[colIndex],
|
|||
|
|
isHeader ? tableStyle.HeaderFont : tableStyle.Font,
|
|||
|
|
columnPos[colIndex] + tableStyle.MarginX + tableStyle.LineWidth,
|
|||
|
|
rowPos[rowIndex] + tableStyle.MarginY,
|
|||
|
|
columnWidth[colIndex],
|
|||
|
|
rowHeight[rowIndex],
|
|||
|
|
horizAlignment[colIndex],
|
|||
|
|
vertAlignment[colIndex]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return tableBottomY;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
static Font lastFont = null;
|
|||
|
|
static float lastSpacing = 0;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Measure the size of a paragraph of text, lines are separated by '~'.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="e">PrintPageEventArgs</param>
|
|||
|
|
/// <param name="text">Text, lines are separated by '~'</param>
|
|||
|
|
/// <param name="font">Font</param>
|
|||
|
|
/// <returns>Size of the paragraph of text</returns>
|
|||
|
|
protected SizeF Measure(System.Drawing.Printing.PrintPageEventArgs e, string text, Font font)
|
|||
|
|
{
|
|||
|
|
if (font != lastFont)
|
|||
|
|
{
|
|||
|
|
lastFont = font;
|
|||
|
|
lastSpacing = e.Graphics.MeasureString("Abcgq", font).Height;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string[] lines = text.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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Print a paragraph of text, lines are separated by '~'.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="e">PrintPageEventArgs</param>
|
|||
|
|
/// <param name="text">Text, lines are separated by '~'</param>
|
|||
|
|
/// <param name="font">Font</param>
|
|||
|
|
/// <param name="x">Position x</param>
|
|||
|
|
/// <param name="y">Position y</param>
|
|||
|
|
/// <param name="width">Width (required when alignment=Alignment.Center or alignment=Aligmenr.Right</param>
|
|||
|
|
/// <param name="height">Height, 0 = no vertical centering</param>
|
|||
|
|
/// <param name="horizAlignment">Horizontal alignment</param>
|
|||
|
|
/// <param name="vertAlignment">Vertical alignment</param>
|
|||
|
|
protected void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, string text, Font font,
|
|||
|
|
float x, float y, float width, float height, Alignment horizAlignment, VertAlignment vertAlignment)
|
|||
|
|
{
|
|||
|
|
SizeF size = Measure(e, text, font);
|
|||
|
|
|
|||
|
|
string[] lines = text.Split(new char[] { '~' });
|
|||
|
|
|
|||
|
|
if (height <= size.Height) vertAlignment = VertAlignment.Top;
|
|||
|
|
float y0;
|
|||
|
|
switch (vertAlignment)
|
|||
|
|
{
|
|||
|
|
default:
|
|||
|
|
case VertAlignment.Top: y0 = y; break;
|
|||
|
|
case VertAlignment.Middle: y0 = y + (height - size.Height) / 2; break;
|
|||
|
|
case VertAlignment.Bottom: y0 = y + (height - size.Height); break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (var line in lines)
|
|||
|
|
{
|
|||
|
|
float x0;
|
|||
|
|
switch (horizAlignment)
|
|||
|
|
{
|
|||
|
|
default:
|
|||
|
|
case Alignment.Left: x0 = x; break;
|
|||
|
|
case Alignment.Center: x0 = x + (width - e.Graphics.MeasureString(line, font).Width) / 2; break;
|
|||
|
|
case Alignment.Right: x0 = x + width - e.Graphics.MeasureString(line, font).Width; break;
|
|||
|
|
}
|
|||
|
|
e.Graphics.DrawString(line, font, Brushes.Black, new PointF(x0, y0));
|
|||
|
|
y0 += 0.8f * lastSpacing;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|