/*
* Copyright (C) 2013 FooProject
* * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see .
*/
using System;
using Windows.Graphics.Display;
using Windows.Graphics.Printing;
using System.Runtime.InteropServices;
using Windows.UI;
using FooEditEngine.Metro;
namespace FooEditEngine
{
///
/// イベントデータ
///
public sealed class ParseCommandEventArgs
{
///
/// 印刷中のページ番号
///
public int PageNumber;
///
/// ページ範囲内で許容されている最大の番号
///
public int MaxPageNumber;
///
/// 処理前の文字列
///
public string Original;
///
/// コンストラクター
///
/// 印刷中のページ番号
/// 印刷すべき最大のページ番号
/// 処理前の文字列
public ParseCommandEventArgs(int nowPage, int maxPage, string org)
{
this.PageNumber = nowPage;
this.MaxPageNumber = maxPage;
this.Original = org;
}
}
///
/// コマンド処理用デリゲート
///
/// 送信元のクラス
/// イベントデータ
/// 処理後の文字列
public delegate string ParseCommandHandler(object sender, ParseCommandEventArgs e);
sealed class PrintableViewFactory
{
Windows.UI.Color foreground, comment, keyword1, keyword2, literal, url;
string fontName;
double fontSize;
LineBreakMethod lineBreakMethod;
int lineBreakCharCount, tabCount;
Document document;
bool urlMark;
IHilighter hilighter;
float displayDpi;
Padding padding;
public PrintableViewFactory(FooTextBox textbox,Padding padding)
{
this.foreground = textbox.Foreground;
this.comment = textbox.Comment;
this.keyword1 = textbox.Keyword1;
this.keyword2 = textbox.Keyword2;
this.literal = textbox.Literal;
this.url = textbox.URL;
this.fontName = textbox.FontFamily.Source;
this.fontSize = textbox.FontSize;
this.tabCount = textbox.TabChars;
this.document = textbox.Document;
this.lineBreakMethod = textbox.LineBreakMethod;
this.lineBreakCharCount = textbox.LineBreakCharCount;
this.drawLineNumber = textbox.DrawLineNumber;
this.urlMark = textbox.MarkURL;
this.hilighter = textbox.Hilighter;
this.displayDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
this.padding = padding;
this.EnableHilight = true;
}
public D2DPrintRender CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget)
{
D2DPrintRender render;
Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
render = new D2DPrintRender(this.fontName, this.fontSize, size, Math.Min(pagedesc.DpiX, pagedesc.DpiY), docPackageTarget);
render.Foreground = D2DRenderBase.ToColor4(this.foreground);
render.Comment = D2DRenderBase.ToColor4(this.comment);
render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1);
render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2);
render.Literal = D2DRenderBase.ToColor4(this.literal);
render.Url = D2DRenderBase.ToColor4(this.url);
return render;
}
public D2DPrintPreviewRender CreateRender(PrintPageDescription pagedesc)
{
D2DPrintPreviewRender render;
Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
render = new D2DPrintPreviewRender(this.fontName, this.fontSize, size, this.displayDpi);
render.Foreground = D2DRenderBase.ToColor4(this.foreground);
render.Comment = D2DRenderBase.ToColor4(this.comment);
render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1);
render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2);
render.Literal = D2DRenderBase.ToColor4(this.literal);
render.Url = D2DRenderBase.ToColor4(this.url);
return render;
}
public PrintableView CreateView(PrintPageDescription pagedesc, IPrintableTextRender render, string header, string footer)
{
Document documentSnap = new Document(this.document);
documentSnap.LayoutLines.Render = render;
PrintableView view = new PrintableView(documentSnap, render,padding);
view.Header = header;
view.Footer = footer;
view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
view.Hilighter = this.EnableHilight ? this.hilighter : null;
documentSnap.DrawLineNumber = this.drawLineNumber;
view.PerfomLayouts();
return view;
}
public bool drawLineNumber
{
get;
set;
}
public bool EnableHilight
{
get;
set;
}
}
sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource,IPrintPreviewSource
{
IPrintPreviewDxgiPackageTarget dxgiPreviewTarget;
bool paginateCalled = false;
Size imageRect;
PrintableViewFactory factory;
D2DPrintPreviewRender previewRender;
PrintableView previewView;
int maxPreviePageCount;
public ParseCommandHandler ParseHF;
public string Header = string.Empty;
public string Fotter = string.Empty;
public DocumentSource(FooTextBox textbox,Padding padding)
{
this.factory = new PrintableViewFactory(textbox, padding);
}
internal enum SyntaxHilightApplibility
{
Apply,
NoApply,
}
[DisplayPrintOptionResourceID("SyntaxHilight")]
internal SyntaxHilightApplibility EnableHilight
{
get
{
return this.factory.EnableHilight ? SyntaxHilightApplibility.Apply : SyntaxHilightApplibility.NoApply;
}
set
{
this.factory.EnableHilight = value == SyntaxHilightApplibility.Apply;
}
}
internal enum LineNumberVisiblity
{
Visible,
Hidden
}
[DisplayPrintOptionResourceID("ShowLineNumber")]
internal LineNumberVisiblity ShowLineNumber
{
get
{
return this.factory.drawLineNumber ? LineNumberVisiblity.Visible : LineNumberVisiblity.Hidden;
}
set
{
this.factory.drawLineNumber = value == LineNumberVisiblity.Visible;
}
}
public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget, out IPrintPreviewPageCollection docPageCollection)
{
Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI);
IntPtr target;
docPackageTarget.GetPackageTarget(guid, guid, out target);
this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target);
docPageCollection = (IPrintPreviewPageCollection)this;
}
public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget)
{
PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;
PrintPageDescription pagedesc = options.GetPageDescription(1);
D2DPrintRender render = this.factory.CreateRender(pagedesc, docPackageTarget);
PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter);
bool result = false;
int currentPage = 0;
while (!result)
{
if(!string.IsNullOrEmpty(this.Header))
view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Header));
if (!string.IsNullOrEmpty(this.Fotter))
view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Fotter));
render.DrawContent(view);
result = view.TryPageDown();
currentPage++;
}
render.Dispose();
view.Dispose();
}
public void Paginate(uint currentJobPage, object printTaskOptions)
{
PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;
PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage);
this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
this.previewRender = this.factory.CreateRender(pagedesc);
this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter);
int maxPage = 1;
while (!this.previewView.TryPageDown())
maxPage++;
this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage);
this.dxgiPreviewTarget.InvalidatePreview();
this.maxPreviePageCount = maxPage;
this.paginateCalled = true;
}
public void InvalidatePreview()
{
this.dxgiPreviewTarget.InvalidatePreview();
}
public void MakePage(uint desiredJobPage, float width, float height)
{
if (width <= 0 || height <= 0)
throw new COMException("", 0x70057/*E_INVALIDARG*/);
if (!this.paginateCalled)
return;
if (desiredJobPage == 0xFFFFFFFF)
desiredJobPage = 1;
this.previewView.TryScroll(0, 0); //元に戻さないとページ番号が変わった時に正しく動作しない
for (int i = 1; i < desiredJobPage; i++)
this.previewView.TryPageDown();
if (!string.IsNullOrEmpty(this.Header))
this.previewView.Header = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Header));
if (!string.IsNullOrEmpty(this.Fotter))
this.previewView.Footer = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Fotter));
this.previewRender.Resize(width, height);
this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る
this.previewRender.DrawContent(this.previewView, this.dxgiPreviewTarget, desiredJobPage);
}
public void Dispose()
{
if (this.previewView != null)
this.previewView.Dispose();
if (this.previewRender != null)
this.previewRender.Dispose();
}
}
}