OSDN Git Service

ウィンドウの幅が変わったら折り返しの幅も再計算するようにした
[fooeditengine/FooEditEngine.git] / WPF / FooEditEngine / FooPrintText.cs
1 /*
2  * Copyright (C) 2013 FooProject
3  * * 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
4  * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
5
6  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
10  */
11 using System;
12 using System.Threading.Tasks;
13 using System.Printing;
14 using System.Windows;
15 using System.Windows.Xps;
16 using Shapes = System.Windows.Shapes;
17 using System.Collections.Generic;
18 using System.Windows.Controls;
19 using System.Windows.Documents;
20 using System.Windows.Documents.Serialization;
21 using System.Windows.Media;
22
23 namespace FooEditEngine.WPF
24 {
25     /// <summary>
26     /// イベントデータ
27     /// </summary>
28     public sealed class ParseCommandEventArgs
29     {
30         /// <summary>
31         /// 印刷中のページ番号
32         /// </summary>
33         public int PageNumber;
34         /// <summary>
35         /// ページ範囲内で許容されている最大の番号
36         /// </summary>
37         public int MaxPageNumber;
38         /// <summary>
39         /// 処理前の文字列
40         /// </summary>
41         public string Original;
42         /// <summary>
43         /// コンストラクター
44         /// </summary>
45         /// <param name="nowPage">印刷中のページ番号</param>
46         /// <param name="maxPage">印刷すべき最大のページ番号</param>
47         /// <param name="org">処理前の文字列</param>
48         public ParseCommandEventArgs(int nowPage,int maxPage,string org)
49         {
50             this.PageNumber = nowPage;
51             this.MaxPageNumber = maxPage;
52             this.Original = org;
53         }
54     }
55
56     /// <summary>
57     /// コマンド処理用デリゲート
58     /// </summary>
59     /// <param name="sender">送信元のクラス</param>
60     /// <param name="e">イベントデータ</param>
61     /// <returns>処理後の文字列</returns>
62     public delegate string ParseCommandHandler(object sender,ParseCommandEventArgs e);
63
64     /// <summary>
65     /// 印刷用のクラス
66     /// </summary>
67     public class FooPrintText
68     {
69         /// <summary>
70         /// コンストラクター
71         /// </summary>
72         public FooPrintText()
73         {
74             this.ParseHF = new ParseCommandHandler((s, e) => { return e.Original; });
75         }
76
77         /// <summary>
78         /// 印刷する最小のページ番号
79         /// </summary>
80         public int StartPage
81         {
82             get;
83             set;
84         }
85
86         /// <summary>
87         /// 印刷する最大のページ番号
88         /// </summary>
89         public int EndPage
90         {
91             get;
92             set;
93         }
94
95         /// <summary>
96         /// 印刷する領域の大きさ
97         /// </summary>
98         public System.Windows.Rect PageRect
99         {
100             get;
101             set;
102         }
103
104         /// <summary>
105         /// 対象となるドキュメント
106         /// </summary>
107         public Document Document
108         {
109             get;
110             set;
111         }
112
113         /// <summary>
114         /// レタリング時のフロー方向を示す
115         /// </summary>
116         public FlowDirection FlowDirection
117         {
118             get;
119             set;
120         }
121
122         /// <summary>
123         /// 行番号を表示するかどうか
124         /// </summary>
125         public bool DrawLineNumber
126         {
127             get;
128             set;
129         }
130
131         /// <summary>
132         /// ハイパーリンクに下線を引くなら真
133         /// </summary>
134         public bool MarkURL
135         {
136             get;
137             set;
138         }
139
140         /// <summary>
141         /// デフォルトの文字ブラシ
142         /// </summary>
143         public System.Windows.Media.Color Foreground
144         {
145             get;
146             set;
147         }
148
149         /// <summary>
150         /// URLを表すブラシ
151         /// </summary>
152         public System.Windows.Media.Color URL
153         {
154             get;
155             set;
156         }
157
158         /// <summary>
159         /// キーワード1を表すブラシ
160         /// </summary>
161         public System.Windows.Media.Color Keyword1
162         {
163             get;
164             set;
165         }
166
167         /// <summary>
168         /// キーワード2を表すブラシ
169         /// </summary>
170         public System.Windows.Media.Color Keyword2
171         {
172             get;
173             set;
174         }
175
176         /// <summary>
177         /// コメントを表すブラシ
178         /// </summary>
179         public System.Windows.Media.Color Comment
180         {
181             get;
182             set;
183         }
184
185         /// <summary>
186         /// 文字リテラルを表すブラシ
187         /// </summary>
188         public System.Windows.Media.Color Litral
189         {
190             get;
191             set;
192         }
193
194         /// <summary>
195         /// 印刷に使用するフォント
196         /// </summary>
197         public FontFamily Font
198         {
199             get;
200             set;
201         }
202
203         /// <summary>
204         /// フォントサイズ
205         /// </summary>
206         public double FontSize
207         {
208             get;
209             set;
210         }
211
212         /// <summary>
213         /// 折り返しの方法を指定する
214         /// </summary>
215         public LineBreakMethod LineBreakMethod
216         {
217             get;
218             set;
219         }
220
221         /// <summary>
222         /// 折り返した時の文字数を指定する
223         /// </summary>
224         public int LineBreakCharCount
225         {
226             get;
227             set;
228         }
229
230         /// <summary>
231         /// ヘッダー
232         /// </summary>
233         public string Header
234         {
235             get;
236             set;
237         }
238
239         /// <summary>
240         /// フッター
241         /// </summary>
242         public string Footer
243         {
244             get;
245             set;
246         }
247
248         /// <summary>
249         /// シンタックスハイライター
250         /// </summary>
251         public IHilighter Hilighter
252         {
253             get;
254             set;
255         }
256
257         /// <summary>
258         /// 余白
259         /// </summary>
260         public Padding Padding
261         {
262             get;
263             set;
264         }
265
266         /// <summary>
267         /// ヘッダーやフッターを処理する
268         /// </summary>
269         public ParseCommandHandler ParseHF;
270
271         /// <summary>
272         /// 印刷する
273         /// </summary>
274         /// <param name="pd">プリントダイアログ</param>
275         public void Print(PrintDialog pd)
276         {
277             if (this.Font == null || this.Document == null)
278                 throw new InvalidOperationException();
279
280             WPFRender render = new WPFRender(this.Font, this.FontSize);
281             render.Foreground = this.Foreground;
282             render.Comment = this.Comment;
283             render.Keyword1 = this.Keyword1;
284             render.Keyword2 = this.Keyword2;
285             render.Literal = this.Litral;
286             render.Url = this.URL;
287             render.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft;
288             render.Printing = true;
289             Document documentSnap = new Document(this.Document);
290             documentSnap.LayoutLines.Render = render;
291             PrintableView view = new PrintableView(documentSnap, render,this.Padding);
292             view.Header = this.Header;
293             view.Footer = this.Footer;
294             view.PageBound = this.PageRect;
295             view.Hilighter = this.Hilighter;
296             documentSnap.LineBreak = this.LineBreakMethod;
297             documentSnap.LineBreakCharCount = this.LineBreakCharCount;
298             documentSnap.DrawLineNumber = this.DrawLineNumber;
299             documentSnap.UrlMark = this.MarkURL;
300             documentSnap.PerformLayout(false);
301
302             try
303             {
304                 FixedDocument fd = new FixedDocument();
305                 fd.DocumentPaginator.PageSize = this.PageRect.Size;
306                 
307                 int currentPage = 0;
308
309                 bool result = false;
310
311                 while (!result)
312                 {
313                     if (this.EndPage != -1 && currentPage > this.EndPage)
314                         break;
315
316                     if (this.StartPage == -1 || currentPage >= this.StartPage)
317                     {
318                         PageContent pc = new PageContent();
319                         
320                         FixedPage fp = new FixedPage();
321                         fp.Width = this.PageRect.Width;
322                         fp.Height = this.PageRect.Height;
323
324                         pc.Child = fp;
325
326                         view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.EndPage, this.Header));
327                         view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.EndPage, this.Footer));
328
329                         DrawingVisual dv = new DrawingVisual();
330
331                         using (DrawingContext dc = dv.RenderOpen())
332                         {
333                             render.SetDrawingContext(dc);
334                             view.Draw(view.PageBound);
335                         }
336
337                         VisualHost host = new VisualHost();
338                         host.AddVisual(dv);
339
340                         fp.Children.Add(host);
341
342                         fd.Pages.Add(pc);
343                     }
344                     result = view.TryPageDown();
345                     currentPage++;
346                 }
347
348                 pd.PrintDocument(fd.DocumentPaginator,"");
349             }
350             catch (PrintingCanceledException)
351             {
352             }
353             finally
354             {
355                 view.Dispose();
356             }
357         }
358     }
359
360     class VisualHost : FrameworkElement
361     {
362         private List<Visual> fVisuals;
363
364         public VisualHost()
365         {
366             fVisuals = new List<Visual>();
367         }
368
369         protected override Visual GetVisualChild(int index)
370         {
371             return fVisuals[index];
372         }
373
374         protected override int VisualChildrenCount
375         {
376             get { return fVisuals.Count; }
377         }
378
379         public void AddVisual(Visual visual)
380         {
381             fVisuals.Add(visual);
382             base.AddVisualChild(visual);
383         }
384
385         public void RemoveVisual(Visual visual)
386         {
387             fVisuals.Remove(visual);
388             base.RemoveVisualChild(visual);
389         }
390     }
391 }