2 * Copyright (C) 2013 FooProject
\r
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
\r
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
\r
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
\r
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/>.
\r
13 using System.Collections.Generic;
\r
15 namespace FooEditEngine
\r
25 /// キャレットとドキュメントの表示を担当します。レイアウト関連もこちらで行います
\r
27 sealed class EditView : ViewBase
\r
29 internal const float LineMarkerThickness = 2;
\r
30 Point _CaretLocation = new Point();
\r
31 TextPoint _CaretPostion = new TextPoint();
\r
33 bool _CaretBlink,_HideRuler = true;
\r
34 internal const int LineNumberLength = 6;
\r
39 public EditView(Document doc, IEditorRender r,int MarginLeftAndRight = 5)
\r
40 : this(doc,r,new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))
\r
47 /// <param name="doc">ドキュメント</param>
\r
48 /// <param name="r">レンダー</param>
\r
49 /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>
\r
50 public EditView(Document doc, IEditorRender r, Padding margin)
\r
51 : base(doc,r,margin)
\r
53 this.CaretBlinkTime = 500;
\r
54 this.CaretWidthOnInsertMode = 1;
\r
55 this.CalculateClipRect();
\r
56 this._CaretLocation.X = this.render.TextArea.X;
\r
57 this._CaretLocation.Y = this.render.TextArea.Y;
\r
58 this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;
\r
59 this.InsertPoint = null;
\r
60 this.HideLineMarker = true;
\r
61 this.IsFocused = false;
\r
62 this.Selections = new SelectCollection();
\r
68 internal SelectCollection Selections
\r
75 /// ラインマーカーを描くなら偽。そうでなければ真
\r
77 public bool HideLineMarker
\r
84 /// キャレットを描くなら偽。そうでなければ真
\r
86 public bool HideCaret
\r
93 /// 挿入モードなら真を返し、上書きモードなら偽を返す
\r
95 public bool InsertMode
\r
104 public int CaretBlinkTime
\r
113 public double CaretWidthOnInsertMode
\r
120 /// フォーカスがあるなら真をセットする
\r
122 public bool IsFocused
\r
129 /// キャレットを点滅させるなら真。そうでないなら偽
\r
131 /// <remarks>キャレット点滅タイマーもリセットされます</remarks>
\r
132 public bool CaretBlink
\r
134 get { return this._CaretBlink; }
\r
137 this._CaretBlink = value;
\r
139 this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);
\r
144 /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)
\r
146 public int LineCountOnScreenWithInVisible
\r
153 /// スクロール時に確保するマージン幅
\r
155 public double ScrollMarginWidth
\r
157 get { return this.PageBound.Width * 20 / 100; }
\r
161 /// ルーラーを表示しないなら真、そうでないなら偽
\r
163 public bool HideRuler
\r
165 get { return this._HideRuler; }
\r
168 this._HideRuler = value;
\r
169 this.LayoutLines.ClearLayoutCache();
\r
170 CalculateClipRect();
\r
171 CalculateLineCountOnScreen();
\r
176 /// 矩形選択モード中に文字列が挿入される位置を表す
\r
178 public SelectCollection InsertPoint
\r
187 public Point CaretLocation
\r
189 get { return this._CaretLocation; }
\r
193 /// レイアウト行のどこにキャレットがあるかを表す
\r
195 public TextPoint CaretPostion
\r
197 get { return this._CaretPostion; }
\r
203 /// <param name="x">x座標</param>
\r
204 /// <param name="y">y座標</param>
\r
205 /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>
\r
206 public bool HitTextArea(double x, double y)
\r
208 if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&
\r
209 y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)
\r
218 /// <param name="x">x座標</param>
\r
219 /// <param name="row">行</param>
\r
220 /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>
\r
221 public FoldingItem HitFoldingData(double x, int row)
\r
223 IEditorRender render = (IEditorRender)base.render;
\r
225 if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)
\r
227 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
228 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
229 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
230 if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))
\r
231 return foldingData;
\r
237 /// Rectで指定された範囲にドキュメントを描く
\r
239 /// <param name="updateRect">描写する範囲</param>
\r
240 /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>
\r
241 public override void Draw(Rectangle updateRect)
\r
243 if (this.LayoutLines.Count == 0)
\r
246 IEditorRender render = (IEditorRender)base.render;
\r
248 if ((updateRect.Height < this.PageBound.Height ||
\r
249 updateRect.Width < this.PageBound.Width) &&
\r
250 render.IsVaildCache())
\r
252 render.DrawCachedBitmap(updateRect);
\r
256 Rectangle background = this.PageBound;
\r
257 render.FillBackground(background);
\r
259 if (this.HideRuler == false)
\r
262 this.DrawLineMarker(this.CaretPostion.row);
\r
264 Point pos = this.render.TextArea.TopLeft;
\r
265 pos.X -= this.Src.X;
\r
266 double endposy = this.render.TextArea.Bottom;
\r
267 Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);
\r
268 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
\r
270 int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
271 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
272 ITextLayout layout = this.LayoutLines.GetLayout(i);
\r
274 if (pos.Y + layout.Height > endposy)
\r
277 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);
\r
279 if (foldingData != null)
\r
281 if ((foldingData.Parent == null || foldingData.Parent.Expand) && foldingData.IsFirstLine(this.LayoutLines, i))
\r
282 render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);
\r
283 if (foldingData.IsHidden(lineIndex))
\r
287 var selectRange = from s in this.Selections.Get(lineIndex, lineLength)
\r
288 let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)
\r
291 this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);
\r
293 if (this.DrawLineNumber)
\r
295 this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);
\r
298 pos.Y += this.LayoutLines.GetLayout(i).Height;
\r
301 if (this.InsertPoint != null)
\r
302 this.DrawInsertPoint();
\r
304 render.CacheContent();
\r
312 IEditorRender render = (IEditorRender)base.render;
\r
314 Point pos, from, to;
\r
315 Size emSize = render.emSize;
\r
316 Rectangle clipRect = this.render.TextArea;
\r
318 double markerHeight = emSize.Height / 2;
\r
319 if (this.render.RightToLeft)
\r
321 pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);
\r
322 for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)
\r
325 to = new Point(pos.X, pos.Y + emSize.Height);
\r
326 int mod = count % 10;
\r
329 string countStr = (count / 10).ToString();
\r
330 double counterWidth = emSize.Width * countStr.Length;
\r
331 this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));
\r
334 from.Y = from.Y + emSize.Height / 2;
\r
336 from.Y = from.Y + emSize.Height * 3 / 4;
\r
337 render.DrawLine(from, to);
\r
338 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
\r
339 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
\r
344 pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);
\r
345 for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)
\r
348 to = new Point(pos.X, pos.Y + emSize.Height);
\r
349 int mod = count % 10;
\r
351 this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));
\r
353 from.Y = from.Y + emSize.Height / 2;
\r
355 from.Y = from.Y + emSize.Height * 3 / 4;
\r
356 render.DrawLine(from, to);
\r
357 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
\r
358 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
\r
361 from = clipRect.TopLeft;
\r
362 from.Y -= LineMarkerThickness;
\r
363 to = clipRect.TopRight;
\r
364 to.Y -= LineMarkerThickness;
\r
365 render.DrawLine(from, to);
\r
368 void DrawInsertPoint()
\r
370 IEditorRender render = (IEditorRender)base.render;
\r
371 foreach (Selection sel in this.InsertPoint)
\r
373 if (sel.length == 0)
\r
375 TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
\r
376 Point left = this.GetPostionFromTextPoint(tp);
\r
377 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
\r
378 Rectangle InsertRect = new Rectangle(left.X,
\r
380 CaretWidthOnInsertMode,
\r
382 render.FillRectangle(InsertRect, FillRectType.InsertPoint);
\r
389 if (this.HideCaret || !this.IsFocused)
\r
392 long diff = DateTime.Now.Ticks - this.tickCount;
\r
393 long blinkTime = this.To100nsTime(this.CaretBlinkTime);
\r
395 if (this._CaretBlink && diff % blinkTime >= blinkTime / 2)
\r
398 Rectangle CaretRect = new Rectangle();
\r
400 IEditorRender render = (IEditorRender)base.render;
\r
402 int row = this.CaretPostion.row;
\r
403 double lineHeight = this.LayoutLines.GetLayout(row).Height;
\r
404 double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);
\r
406 if (this.InsertMode || charWidth == 0)
\r
408 CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);
\r
409 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);
\r
410 render.FillRectangle(CaretRect, FillRectType.InsertCaret);
\r
414 double height = lineHeight / 3;
\r
415 CaretRect.Size = new Size(charWidth, height);
\r
416 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);
\r
417 render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);
\r
421 long To100nsTime(int ms)
\r
426 public void DrawLineMarker(int row)
\r
428 if (this.HideLineMarker || !this.IsFocused)
\r
430 IEditorRender render = (IEditorRender)base.render;
\r
431 Point p = this.CaretLocation;
\r
432 double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;
\r
433 double width = this.render.TextArea.Width;
\r
434 render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);
\r
438 /// 指定した座標の一番近くにあるTextPointを取得する
\r
440 /// <param name="p">テキストエリアを左上とする相対位置</param>
\r
441 /// <returns>レイアウトラインを指し示すTextPoint</returns>
\r
442 public TextPoint GetTextPointFromPostion(Point p)
\r
444 if (p.Y < this.render.TextArea.TopLeft.Y ||
\r
445 p.Y > this.render.TextArea.BottomRight.Y)
\r
446 return TextPoint.Null;
\r
447 TextPoint tp = new TextPoint();
\r
449 if (this.LayoutLines.Count == 0)
\r
452 p.Y -= this.render.TextArea.Y;
\r
454 int lineHeadIndex, lineLength;
\r
456 tp.row = this.LayoutLines.Count - 1;
\r
457 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
\r
459 double height = this.LayoutLines.GetLayout(i).Height;
\r
461 lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
462 lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
464 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
466 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
469 if (y + height > p.Y)
\r
477 if (p.X < this.render.TextArea.X)
\r
480 tp.col = GetIndexFromColPostion(tp.row, p.X);
\r
482 lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
\r
483 if (tp.col > lineLength)
\r
484 tp.col = lineLength;
\r
490 /// 桁方向の座標に対応するインデックスを取得する
\r
492 /// <param name="row">対象となる行</param>
\r
493 /// <param name="x">テキストエリアからの相対位置</param>
\r
494 /// <returns></returns>
\r
495 public int GetIndexFromColPostion(int row, double x)
\r
497 x -= this.render.TextArea.X;
\r
498 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
499 if (lineLength == 0)
\r
501 int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
\r
506 /// インデックスに対応する桁方向の座標を得る
\r
508 /// <param name="row">対象となる行</param>
\r
509 /// <param name="index">インデックス</param>
\r
510 /// <returns>テキストエリアからの相対位置を返す</returns>
\r
511 public double GetColPostionFromIndex(int row, int index)
\r
513 double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
\r
514 return x - Src.X + this.render.TextArea.X;
\r
518 /// TextPointに対応する座標を得る
\r
520 /// <param name="tp">レイアウトライン上の位置</param>
\r
521 /// <returns>テキストエリアを左上とする相対位置</returns>
\r
522 public Point GetPostionFromTextPoint(TextPoint tp)
\r
524 Point p = new Point();
\r
525 for (int i = this.Src.Row; i < tp.row; i++)
\r
527 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
528 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
529 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
530 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
532 p.Y += this.LayoutLines.GetLayout(i).Height;
\r
534 p.X = this.GetColPostionFromIndex(tp.row, tp.col);
\r
535 p.Y += this.render.TextArea.Y;
\r
540 /// キャレットを指定した位置に移動させる
\r
542 /// <param name="row"></param>
\r
543 /// <param name="col"></param>
\r
544 /// <param name="autoExpand">折り畳みを展開するなら真</param>
\r
545 public void JumpCaret(int row, int col, bool autoExpand = true)
\r
549 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
550 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
551 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
552 if (foldingData != null && (!foldingData.IsFirstLine(this.LayoutLines, row) || foldingData.IsParentHidden()))
\r
554 this.LayoutLines.FoldingCollection.Expand(foldingData);
\r
558 this._CaretPostion.row = row;
\r
559 this._CaretPostion.col = col;
\r
563 /// index上の文字が表示されるようにSrcを調整する
\r
565 /// <param name="index">インデックス</param>
\r
566 /// <returns>調整されたら真。そうでなければ偽</returns>
\r
567 public bool AdjustSrc(int index)
\r
569 TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
\r
570 double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
\r
571 if (x < this.Src.X ||
\r
572 x > this.Src.X + this.PageBound.Width)
\r
574 this.TryScroll(x, this.Src.Row);
\r
577 if (startTextPoint.row < this.Src.Row ||
\r
578 startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
\r
580 this.TryScroll(this.Src.X, startTextPoint.row);
\r
587 /// キャレットがあるところまでスクロールする
\r
589 /// <return>再描写する必要があるなら真を返す</return>
\r
590 /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>
\r
591 public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)
\r
593 IEditorRender render = (IEditorRender)base.render;
\r
595 if (this.PageBound.Width == 0 || this.PageBound.Height == 0)
\r
597 this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);
\r
601 bool result = false;
\r
602 TextPoint tp = this.CaretPostion;
\r
603 double x = this.CaretLocation.X;
\r
604 double y = this.CaretLocation.Y;
\r
606 if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
\r
608 x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
\r
610 double left = this.Src.X;
\r
611 double right = this.Src.X + this.render.TextArea.Width;
\r
613 if (x >= left && x <= right) //xは表示領域にないにある
\r
617 else if (x > right) //xは表示領域の右側にある
\r
619 this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;
\r
620 if (this.render.RightToLeft && this._Src.X > 0)
\r
622 System.Diagnostics.Debug.Assert(x > 0);
\r
627 x = this.render.TextArea.Width - this.ScrollMarginWidth;
\r
631 else if (x < left) //xは表示領域の左側にある
\r
633 this._Src.X = x - this.ScrollMarginWidth;
\r
634 if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X)
\r
640 x = this.ScrollMarginWidth;
\r
644 x += this.render.TextArea.X;
\r
647 if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
\r
650 int lineCount = this.LineCountOnScreenWithInVisible;
\r
651 if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
\r
652 caretRow = tp.row - this.Src.Row;
\r
653 else if (tp.row >= this.Src.Row + lineCount)
\r
655 this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);
\r
656 caretRow = tp.row - this._Src.Row;
\r
658 CalculateLineCountOnScreen();
\r
660 else if (tp.row < this.Src.Row)
\r
662 this._Src.Row = tp.row;
\r
664 CalculateLineCountOnScreen();
\r
671 for (int i = 0; i < caretRow; i++)
\r
673 int currentRow = this.Src.Row + i;
\r
674 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
\r
675 int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
\r
677 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
679 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
682 y += this.LayoutLines.GetLayout(currentRow).Height;
\r
685 y += this.render.TextArea.Y;
\r
688 this.SetCaretPostion(x, y);
\r
691 this.OnSrcChanged(null);
\r
696 int GetSrcRow(int row,int count)
\r
698 if (this.LayoutLines.FoldingStrategy == null)
\r
699 return row - count;
\r
700 for (int i = row; i >= 0; i--)
\r
702 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
703 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
704 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
\r
705 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
715 /// レイアウト行をテキストポイントからインデックスに変換する
\r
717 /// <param name="tp">テキストポイント表す</param>
\r
718 /// <returns>インデックスを返す</returns>
\r
719 public int GetIndexFromLayoutLine(TextPoint tp)
\r
721 return this.LayoutLines.GetIndexFromTextPoint(tp);
\r
725 /// インデックスからレイアウト行を指し示すテキストポイントに変換する
\r
727 /// <param name="index">インデックスを表す</param>
\r
728 /// <returns>テキストポイント返す</returns>
\r
729 public TextPoint GetLayoutLineFromIndex(int index)
\r
731 return this.LayoutLines.GetTextPointFromIndex(index);
\r
735 /// 指定した座標までスクロールする
\r
737 /// <param name="x"></param>
\r
738 /// <param name="row"></param>
\r
740 /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます
\r
742 public void Scroll(double x, int row)
\r
748 int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;
\r
753 base.TryScroll(x, row);
\r
756 public int AdjustRow(int row, bool isMoveNext)
\r
758 if (this.LayoutLines.FoldingStrategy == null)
\r
760 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
761 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
762 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
\r
763 if (foldingData != null && !foldingData.Expand)
\r
765 if (foldingData.End == this.Document.Length)
\r
767 if (isMoveNext && lineHeadIndex > foldingData.Start)
\r
768 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;
\r
770 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
\r
775 protected override void CalculateClipRect()
\r
777 IEditorRender render = (IEditorRender)base.render;
\r
778 double x, y, width, height;
\r
780 if (this.DrawLineNumber)
\r
782 if (this.render.RightToLeft)
\r
783 x = this.Padding.Left;
\r
785 x = this.render.LineNemberWidth + render.FoldingWidth + this.Padding.Left;
\r
786 width = this.PageBound.Width - this.render.LineNemberWidth - this.Padding.Left - this.Padding.Right - render.FoldingWidth;
\r
790 if (this.render.RightToLeft)
\r
791 x = this.Padding.Left;
\r
793 x = this.Padding.Left + render.FoldingWidth;
\r
794 width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth;
\r
797 y = this.Padding.Top;
\r
798 height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;
\r
800 if (this.HideRuler == false)
\r
802 double rulerHeight = this.render.emSize.Height + LineMarkerThickness;
\r
804 height -= rulerHeight;
\r
813 this.render.TextArea = new Rectangle(x, y, width, height);
\r
815 this.LineBreakingMarginWidth = width * 5 / 100;
\r
818 public override void CalculateLineCountOnScreen()
\r
820 if (this.Document.Length == 0 || this.LayoutLines.Count == 0 || this.PageBound.Height == 0)
\r
824 int i = this.Src.Row;
\r
825 int visualCount = this.Src.Row;
\r
828 int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
\r
830 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
831 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
833 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
835 if (foldingData != null && foldingData.End < this.Document.Length - 1 && foldingData.IsHidden(lineHeadIndex))
\r
838 ITextLayout layout = this.LayoutLines.GetLayout(row);
\r
840 double width = layout.Width;
\r
842 if (width > this._LongestWidth)
\r
843 this._LongestWidth = width;
\r
845 double lineHeight = layout.Height;
\r
849 if (y >= this.render.TextArea.Height)
\r
853 this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);
\r
854 this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
\r
857 void SetCaretPostion(double x, double y)
\r
859 this._CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
\r
862 void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)
\r
864 this.CalculateLineCountOnScreen();
\r
874 double GetRealtiveX(AreaType type)
\r
876 IEditorRender render = (IEditorRender)base.render;
\r
879 case AreaType.FoldingArea:
\r
880 if (this.render.RightToLeft)
\r
881 return this.PageBound.TopRight.X - render.FoldingWidth;
\r
882 if (this.DrawLineNumber)
\r
883 return this.render.TextArea.X - this.render.LineNemberWidth - this.Padding.Left - render.FoldingWidth;
\r
885 return this.render.TextArea.X - render.FoldingWidth - this.Padding.Left;
\r
886 case AreaType.LineNumberArea:
\r
887 if (this.DrawLineNumber == false)
\r
888 throw new InvalidOperationException();
\r
889 if (this.render.RightToLeft)
\r
890 return this.PageBound.TopRight.X - render.FoldingWidth - this.render.LineNemberWidth;
\r
892 return this.render.TextArea.X - this.render.LineNemberWidth - this.Padding.Left;
\r
893 case AreaType.TextArea:
\r
894 return this.render.TextArea.X;
\r
896 throw new ArgumentOutOfRangeException();
\r