using System.ComponentModel;
using System.Drawing;
using System.Drawing.Printing;
using Storm.TextEditor.Parser.Objects;
using Storm.TextEditor.Parser.Objects.Collections;
namespace Storm.TextEditor.Editor.Printing
{
/// <summary>
/// Defines a reusable object that sends output to a printer, when printing from a SyntaxDocument.
/// </summary>
[ToolboxItem(true)]
public class CodePrintDocument
: PrintDocument
{
#region Fields
private Font fontNormal = null;
private Font fontBreak = null;
private int rowIndex = 0;
private SyntaxDocument document = null;
private RowCollection rowCollection = null;
#endregion
#region Properties
/// <summary>
/// Gets or sets the document that the CodePrintDocument should print.
/// </summary>
public SyntaxDocument Document
{
get { return document; }
set { document = value; }
}
#endregion
#region Methods
#region Protected
/// <summary>
/// Override OnBeginPaint to re-initialize fields of the CodePrintDocument when it is about to print.
/// </summary>
/// <param name="ev">PrintEventArgs.</param>
protected override void OnBeginPrint(PrintEventArgs ev)
{
fontNormal = new Font("Courier new", 8, FontStyle.Regular);
fontBreak = new Font("Courier New", 8, FontStyle.Bold);
rowIndex = 0;
base.OnBeginPrint(ev);
}
/// <summary>
/// Override OnPrintPage to execute logic for printing a SyntaxDocument.
/// </summary>
/// <param name="ev">PrintPageEventArgs.</param>
protected override void OnPrintPage(PrintPageEventArgs ev)
{
float maximumHeight = 0;
int currentIndex = 0;
float leftMargin = ev.MarginBounds.Left;
float rightMargin = ev.MarginBounds.Right;
float topMargin = ev.MarginBounds.Top;
float y = 0;
if (rowCollection == null)
{
Document.ParseAll();
Document.ParseAll(true);
rowCollection = new RowCollection();
foreach (Row row in this.Document)
{
bool rowBreak = false;
float x = leftMargin;
Row newRow = new Row();
rowCollection.Add(newRow);
foreach (Word word in row)
{
Font font = fontNormal;
if (word.Style != null)
{
FontStyle fontStyle = 0;
if (word.Style.Bold == true)
fontStyle |= FontStyle.Bold;
if (word.Style.Italic == true)
fontStyle |= FontStyle.Italic;
if (word.Style.Underline == true)
fontStyle |= FontStyle.Underline;
font = new Font("Courier new", 8, fontStyle);
}
SizeF wordSize = ev.Graphics.MeasureString(word.Text, font);
if (x + wordSize.Width > rightMargin)
{
Word breakWord = new Word();
char breakCharacter = (char)0xbf;
breakWord.Text = breakCharacter + "";
newRow.Add(breakWord);
rowBreak = true;
newRow = new Row();
rowCollection.Add(newRow);
x = leftMargin;
}
x += wordSize.Width;
newRow.Add(word);
}
if (rowBreak == true)
rowCollection.Add(new Row());
}
}
maximumHeight = ev.MarginBounds.Height / fontNormal.GetHeight(ev.Graphics);
while (currentIndex < maximumHeight && (rowIndex < rowCollection.Count))
{
float x = leftMargin;
y = topMargin + (currentIndex * fontNormal.GetHeight(ev.Graphics));
Row row = rowCollection[rowIndex];
foreach (Word word in row)
{
if (word.Text == ((char)0xbf) + "") // Word is a break word.
ev.Graphics.DrawString(word.Text, fontBreak, Brushes.Black, x, y, new StringFormat());
else
{
SizeF wordSize = ev.Graphics.MeasureString(word.Text, fontNormal);
if (word.Text != null && (".,:;".IndexOf(word.Text) >= 0))
{
wordSize.Width = 6;
x -= 4;
}
if (word.Text == "\t")
wordSize.Width = ev.Graphics.MeasureString("...", fontNormal).Width;
Color foreColor = Color.Black;
Font font = fontNormal;
if (word.Style != null)
{
foreColor = word.Style.ForeColor;
FontStyle fontStyle = 0;
if (word.Style.Bold == true)
fontStyle |= FontStyle.Bold;
if (word.Style.Italic == true)
fontStyle |= FontStyle.Italic;
if (word.Style.Underline == true)
fontStyle |= FontStyle.Underline;
font = new Font("Courier new", 8, fontStyle);
if (word.Style.Transparent == false)
{
Color backColor = word.Style.BackColor;
ev.Graphics.FillRectangle(new SolidBrush(backColor), x, y, wordSize.Width, fontNormal.GetHeight(ev.Graphics));
}
}
foreColor = Color.FromArgb(foreColor.R, foreColor.G, foreColor.B); // Refresh.
ev.Graphics.DrawString(word.Text, font, new SolidBrush(foreColor), x, y, new StringFormat());
x += wordSize.Width;
}
}
currentIndex++;
rowIndex++;
}
if (rowIndex < rowCollection.Count)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
base.OnPrintPage(ev);
}
#endregion
#endregion
/// <summary>
/// Initializes a new instance of CodePrintDocument.
/// </summary>
public CodePrintDocument()
: base()
{
}
/// <summary>
/// Initializes a new instance of CodePrintDocument.
/// </summary>
public CodePrintDocument(SyntaxDocument document)
: base()
{
this.Document = document;
}
}
}