OSDN Git Service

8c41b12fe95bd00dc2ec57674b72cfea79a31adf
[fooeditengine/FooEditEngine.git] / Core / PrintableView.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
13 namespace FooEditEngine
14 {
15     sealed class PrintableView : ViewBase
16     {
17         public PrintableView(Document doc, IPrintableTextRender r, Padding margin)
18             : base (doc,r,margin)
19         {
20         }
21
22         public string Header
23         {
24             get;
25             set;
26         }
27
28         public string Footer
29         {
30             get;
31             set;
32         }
33
34         public override void Draw(Rectangle updateRect)
35         {
36             if (this.LayoutLines.Count == 0)
37                 return;
38
39             if (this.Hilighter != null)
40                 this.Hilighter.Reset();
41
42             Point pos = this.render.TextArea.TopLeft;
43             pos.X -= Src.X;
44
45             int endRow = Math.Min(this.LayoutLines.Count - 1, Src.Row + this.LineCountOnScreen - 1);
46
47             Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);
48
49             IPrintableTextRender render = (IPrintableTextRender)this.render;
50
51             //ヘッダーを印刷する
52             if (this.Header != null && this.Header != string.Empty)
53             {
54                 this.render.DrawString(this.Header, pos.X, pos.Y, StringAlignment.Center,
55                     new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea),render.FooterHeight));
56
57                 pos.Y += (int)render.HeaderHeight;
58             }
59
60             //レイアウト行を印刷する
61             for (int i = Src.Row; i <= endRow; i++)
62             {
63                 double lineHeight = this.LayoutLines.GetLayout(i).Height;
64
65                 this.render.DrawOneLine(this.LayoutLines,i, pos.X + this.render.TextArea.X, pos.Y, null);
66
67                 if (this.Document.DrawLineNumber)
68                     this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);
69
70                 pos.Y += lineHeight;
71             }
72
73             //フッターを印刷する
74             if (this.Footer != null && this.Footer != string.Empty)
75             {
76                 pos.Y = render.TextArea.Bottom;
77                 this.render.DrawString(this.Footer, pos.X, pos.Y, StringAlignment.Center,
78                     new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea), render.FooterHeight));
79             }
80         }
81
82         public bool TryPageDown()
83         {
84             return base.TryScroll(this.Src.X, this.Src.Row + this.LineCountOnScreen);
85         }
86
87         protected override void CalculateClipRect()
88         {
89             double x, y, width, height;
90
91             if (this.Document.DrawLineNumber)
92             {
93                 if (this.render.RightToLeft)
94                     x = this.Padding.Left;
95                 else
96                     x = this.render.LineNemberWidth + this.render.emSize.Width + this.Padding.Left + this.LineNumberMargin;
97                 width = this.PageBound.Width - this.render.LineNemberWidth - this.render.emSize.Width - this.Padding.Right - this.Padding.Left - this.LineNumberMargin;
98             }
99             else
100             {
101                 x = this.Padding.Left;
102                 width = this.PageBound.Width  - this.Padding.Right - this.Padding.Left;
103             }
104
105             y = this.Padding.Top;
106             height = this.PageBound.Height - this.Padding.Bottom - this.Padding.Top;
107
108             if (width < 0)
109                 width = 0;
110
111             if (height < 0)
112                 height = 0;
113
114             IPrintableTextRender render = (IPrintableTextRender)this.render;
115
116             if (this.Footer != null && this.Footer != string.Empty)
117                 height -= render.FooterHeight;
118             if (this.Header != null && this.Header != string.Empty)
119                 height -= render.HeaderHeight;
120
121             this.render.TextArea = new Rectangle(x, y, width, height);
122         }
123
124         public override void CalculateLineCountOnScreen()
125         {
126             if (this.LayoutLines.Count == 0)
127                 return;
128
129             double y = 0;
130             int i = this.Src.Row;
131             for (; true; i++)
132             {
133                 int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
134
135                 ITextLayout layout = this.LayoutLines.GetLayout(row);
136
137                 double lineHeight = layout.Height;
138
139                 y += lineHeight;
140
141                 if (y >= this.render.TextArea.Height)
142                     break;
143             }
144             this.LineCountOnScreen = Math.Max(i - this.Src.Row - 1, 0); //ループを抜けると+1されている
145         }
146
147         enum AreaType
148         {
149             LineNumberArea,
150             TextArea
151         }
152
153         double GetRealtiveX(AreaType type)
154         {
155             switch (type)
156             {
157                 case AreaType.LineNumberArea:
158                     if (this.Document.DrawLineNumber == false)
159                         throw new InvalidOperationException();
160                     if (this.render.RightToLeft)
161                         return this.PageBound.TopRight.X - this.render.LineNemberWidth;
162                     else
163                         return this.render.TextArea.X - this.render.LineNemberWidth - this.render.emSize.Width - this.LineNumberMargin;
164                 case AreaType.TextArea:
165                     return this.render.TextArea.X;
166             }
167             throw new ArgumentOutOfRangeException();
168         }
169     }
170 }