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.
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.
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/>.
12 using System.Collections.Generic;
15 using System.Text.RegularExpressions;
16 using System.Threading.Tasks;
18 namespace FooEditEngine
21 /// LineBreakMethod列挙体
23 public enum LineBreakMethod
63 /// <param name="left">左</param>
64 /// <param name="top">上</param>
65 /// <param name="right">右</param>
66 /// <param name="bottom">下</param>
67 public Padding(int left, int top, int right, int bottom)
76 abstract class ViewBase : IDisposable
78 const int SpiltCharCount = 1024;
80 protected Document Document;
81 protected Point2 _Src = new Point2();
82 protected Rectangle _Rect;
83 protected double _LongestWidth;
86 public ViewBase(Document doc, ITextRender r,Padding padding)
88 this._Padding = padding;
90 this.Document.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);
91 this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);
93 this.render.ChangedRenderResource += new ChangedRenderResourceEventHandler(render_ChangedRenderResource);
94 this.render.ChangedRightToLeft += render_ChangedRightToLeft;
95 this.SrcChanged += new EventHandler((s, e) => { });
96 this.PerformLayouted += new EventHandler((s, e) => { });
97 this.PageBoundChanged += new EventHandler((s, e) => { });
98 this.Document.LineBreakChanged += (s, e) =>
100 if (this.Document.LineBreak != LineBreakMethod.None)
101 this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByPixelbase);
103 this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);
105 this.Document.TabStopsChanged += (s, e) =>
107 this.render.TabWidthChar = this.Document.TabStops;
109 this.Document.DrawLineNumberChanged += (s, e) =>
113 this.Document.RightToLeftChanged += (s, e) =>
115 this.render.RightToLeft = this.Document.RightToLeft;
117 this.Document.ShowFullSpaceChanged += (s, e) =>
119 this.render.ShowFullSpace = this.Document.ShowFullSpace;
120 this._LayoutLines.ClearLayoutCache();
122 this.Document.ShowHalfSpaceChanged += (s, e) =>
124 this.render.ShowHalfSpace = this.Document.ShowHalfSpace;
125 this._LayoutLines.ClearLayoutCache();
127 this.Document.ShowTabChanged += (s, e) =>
129 this.render.ShowTab = this.Document.ShowTab;
130 this._LayoutLines.ClearLayoutCache();
132 this.Document.ShowLineBreakChanged += (s, e) =>
134 this.render.ShowLineBreak = this.Document.ShowLineBreak;
135 this._LayoutLines.ClearLayoutCache();
139 protected LineToIndexTable _LayoutLines
143 return this.Document.LayoutLines;
147 public event EventHandler SrcChanged;
149 public event EventHandler PerformLayouted;
151 public event EventHandler PageBoundChanged;
156 public ITextRender render
165 public int LineCountOnScreen
174 public double LineBreakingMarginWidth
183 public LineToIndexTable LayoutLines
185 get { return this._LayoutLines; }
191 public double LongestWidth
193 get { return this._LongestWidth; }
196 public double LineNumberMargin
200 return this.render.emSize.Width;
207 /// <remarks>差し替えた場合、再構築する必要があります</remarks>
208 public IHilighter Hilighter
210 get { return this._LayoutLines.Hilighter; }
211 set { this._LayoutLines.Hilighter = value; }
215 /// すべてのレイアウト行を破棄し、再度レイアウトをやり直す
217 public virtual void PerfomLayouts()
219 this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Clear, -1, -1, -1));
220 this.Document.FireUpdate(new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, this.Document.Length));
221 CalculateLineCountOnScreen();
222 this.PerformLayouted(this, null);
228 public Padding Padding
231 return this._Padding;
234 this._Padding = value;
236 CalculateLineCountOnScreen();
237 if (this.Document.RightToLeft)
238 this._LayoutLines.ClearLayoutCache();
239 this.PageBoundChanged(this, null);
246 public Rectangle PageBound
248 get { return this._Rect; }
251 if (value.Width < 0 || value.Height < 0)
252 throw new ArgumentOutOfRangeException("");
255 CalculateLineCountOnScreen();
256 if (this.Document.RightToLeft)
257 this._LayoutLines.ClearLayoutCache();
258 this.PageBoundChanged(this, null);
263 /// Draw()の対象となる領域の左上を表す
267 get { return this._Src; }
268 set { this._Src = value; }
271 public virtual void Draw(Rectangle updateRect)
275 public virtual bool TryScroll(double x, int row)
279 if (row > this.LayoutLines.Count - 1)
283 CalculateLineCountOnScreen();
284 this.SrcChanged(this,null);
288 public void Dispose()
291 GC.SuppressFinalize(this);
294 public virtual void CalculateLineCountOnScreen()
298 protected virtual void Dispose(bool disposing)
302 this.Document.UpdateCalledAlways -= new DocumentUpdateEventHandler(this.doc_Update); //これをしないと複数のビューを作成した時に妙なエラーが発生する
304 this._LayoutLines.Clear();
307 protected virtual void CalculateClipRect()
312 protected virtual void OnSrcChanged(EventArgs e)
314 EventHandler handler = this.SrcChanged;
316 this.SrcChanged(this, e);
319 protected virtual void OnPerformLayoutedChanged(EventArgs e)
321 EventHandler handler = this.PerformLayouted;
323 this.PerformLayouted(this, e);
326 protected virtual void OnPageBoundChanged(EventArgs e)
328 EventHandler handler = this.PageBoundChanged;
330 this.PageBoundChanged(this, e);
333 void render_ChangedRightToLeft(object sender, EventArgs e)
336 this._LayoutLines.ClearLayoutCache();
337 this.CalculateClipRect();
340 void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)
342 this._LayoutLines.ClearLayoutCache();
343 if (e.type == ResourceType.Font)
345 this.CalculateClipRect();
346 this.CalculateLineCountOnScreen();
350 void doc_Update(object sender, DocumentUpdateEventArgs e)
354 case UpdateType.Clear:
355 this._LongestWidth = 0;
360 IList<LineToIndexTableData> LayoutLines_SpilitStringByPixelbase(object sender, SpilitStringEventArgs e)
363 if (this.Document.LineBreak == LineBreakMethod.PageBound)
364 WrapWidth = this.render.TextArea.Width - LineBreakingMarginWidth; //余白を残さないと欠ける
366 WrapWidth = this.render.emSize.Width * this.Document.LineBreakCharCount;
368 if (WrapWidth < 0 && this.Document.LineBreak != LineBreakMethod.None)
369 throw new InvalidOperationException();
371 int startIndex = e.index;
372 int endIndex = e.index + e.length - 1;
374 LineToIndexTable layoutLineCollection = (LineToIndexTable)sender;
376 return this.render.BreakLine(e.buffer,layoutLineCollection, startIndex, endIndex, WrapWidth);
379 IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)
381 return this.Document.CreateLineList(e.index, e.length, Document.MaximumLineLength);