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/>.
13 using System.Collections.Generic;
15 namespace FooEditEngine
25 /// キャレットとドキュメントの表示を担当します。レイアウト関連もこちらで行います
27 sealed class EditView : ViewBase
30 internal const float LineMarkerThickness = 2;
32 bool _CaretBlink, _HideRuler = true;
33 internal const int LineNumberLength = 6;
34 const int UpdateAreaPaddingWidth = 2;
35 const int UpdateAreaWidth = 4;
36 const int UpdateAreaTotalWidth = UpdateAreaWidth + UpdateAreaPaddingWidth;
41 public EditView(Document doc, IEditorRender r, int MarginLeftAndRight = 5)
42 : this(doc, r, new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))
49 /// <param name="doc">ドキュメント</param>
50 /// <param name="r">レンダー</param>
51 /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>
52 public EditView(Document doc, IEditorRender r, Padding margin)
53 : base(doc, r, margin)
55 this.CaretBlinkTime = 500;
56 this.CaretWidthOnInsertMode = 1;
57 this.CalculateClipRect();
58 this.CaretLocation = new Point(this.render.TextArea.X, this.render.TextArea.Y);
59 this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;
60 this.IsFocused = false;
61 this.SelectGrippers = new GripperRectangle(new GripperView(this.render), new GripperView(this.render));
62 this.Document.HideRulerChanged += (s, e) => {
64 CalculateLineCountOnScreen();
71 internal SelectCollection Selections
73 get { return this.Document.Selections; }
74 set { this.Document.Selections = value; }
80 public GripperRectangle SelectGrippers
87 /// ラインマーカーを描くなら偽。そうでなければ真
89 public bool HideLineMarker
91 get { return this.Document.HideLineMarker; }
92 set { this.Document.HideLineMarker = value; }
96 /// キャレットを描くなら偽。そうでなければ真
100 get { return this.Document.HideCaret; }
101 set { this.Document.HideCaret = value; }
105 /// 挿入モードなら真を返し、上書きモードなら偽を返す
107 public bool InsertMode
109 get { return this.Document.InsertMode; }
110 set { this.Document.InsertMode = value; }
116 public int CaretBlinkTime
125 public double CaretWidthOnInsertMode
132 /// フォーカスがあるなら真をセットする
134 public bool IsFocused
141 /// キャレットを点滅させるなら真。そうでないなら偽
143 /// <remarks>キャレット点滅タイマーもリセットされます</remarks>
144 public bool CaretBlink
146 get { return this._CaretBlink; }
149 this._CaretBlink = value;
151 this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);
156 /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)
158 public int LineCountOnScreenWithInVisible
167 public double ScrollMarginWidth
169 get { return this.PageBound.Width * 20 / 100; }
173 /// ルーラーを表示しないなら真、そうでないなら偽
175 public bool HideRuler
177 get { return this.Document.HideRuler; }
180 this.Document.HideRuler = value;
187 public Point CaretLocation
194 /// レイアウト行のどこにキャレットがあるかを表す
196 public TextPoint CaretPostion
198 get { return this.Document.CaretPostion; }
199 private set { this.Document.CaretPostion = value; }
205 /// <param name="x">x座標</param>
206 /// <param name="y">y座標</param>
207 /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>
208 public bool HitTextArea(double x, double y)
210 if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&
211 y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)
220 /// <param name="x">x座標</param>
221 /// <param name="row">行</param>
222 /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>
223 public FoldingItem HitFoldingData(double x, int row)
225 IEditorRender render = (IEditorRender)base.render;
227 if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)
229 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
230 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
231 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
232 if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))
239 /// Rectで指定された範囲にドキュメントを描く
241 /// <param name="updateRect">描写する範囲</param>
242 /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>
243 public override void Draw(Rectangle updateRect)
245 if (this.LayoutLines.Count == 0)
248 IEditorRender render = (IEditorRender)base.render;
250 if ((updateRect.Height < this.PageBound.Height ||
251 updateRect.Width < this.PageBound.Width) &&
252 render.IsVaildCache())
254 render.DrawCachedBitmap(updateRect);
258 Rectangle background = this.PageBound;
259 render.FillBackground(background);
261 if (this.HideRuler == false)
264 this.DrawLineMarker(this.CaretPostion.row);
266 Point pos = this.render.TextArea.TopLeft;
268 double endposy = this.render.TextArea.Bottom;
269 Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);
270 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
272 int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);
273 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
274 ITextLayout layout = this.LayoutLines.GetLayout(i);
276 if (pos.Y + layout.Height > endposy)
279 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);
281 if (foldingData != null)
283 if ((!this.LayoutLines.FoldingCollection.IsHasParent(foldingData) ||
284 !this.LayoutLines.FoldingCollection.IsParentHidden(foldingData))
285 && foldingData.IsFirstLine(this.LayoutLines, i))
286 render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);
287 if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex))
291 var selectRange = from s in this.Selections.Get(lineIndex, lineLength)
292 let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)
295 this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);
297 if (this.DrawLineNumber)
299 this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize,StringColorType.LineNumber);
302 DrawUpdateArea(i, pos.Y);
304 pos.Y += this.LayoutLines.GetLayout(i).Height;
307 this.DrawInsertPoint();
309 render.CacheContent();
314 this.SelectGrippers.BottomLeft.Draw();
315 this.SelectGrippers.BottomRight.Draw();
318 void DrawUpdateArea(int row,double ypos)
320 IEditorRender render = (IEditorRender)base.render;
321 if(this.LayoutLines.GetDirtyFlag(row))
323 Point pos = new Point(this.PageBound.X + this.GetRealtiveX(AreaType.UpdateArea), ypos);
324 Rectangle rect = new Rectangle(pos.X, pos.Y, UpdateAreaWidth, this.LayoutLines.GetLayout(row).Height);
325 render.FillRectangle(rect, FillRectType.UpdateArea);
331 IEditorRender render = (IEditorRender)base.render;
334 Size emSize = render.emSize;
335 Rectangle clipRect = this.render.TextArea;
337 double markerHeight = emSize.Height / 2;
338 if (this.Document.RightToLeft)
340 pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);
341 for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)
344 to = new Point(pos.X, pos.Y + emSize.Height);
345 int mod = count % 10;
348 string countStr = (count / 10).ToString();
349 double counterWidth = emSize.Width * countStr.Length;
350 this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));
353 from.Y = from.Y + emSize.Height / 2;
355 from.Y = from.Y + emSize.Height * 3 / 4;
356 render.DrawLine(from, to);
357 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
358 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
363 pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);
364 for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)
367 to = new Point(pos.X, pos.Y + emSize.Height);
368 int mod = count % 10;
370 this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));
372 from.Y = from.Y + emSize.Height / 2;
374 from.Y = from.Y + emSize.Height * 3 / 4;
375 render.DrawLine(from, to);
376 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
377 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
380 from = clipRect.TopLeft;
381 from.Y -= LineMarkerThickness;
382 to = clipRect.TopRight;
383 to.Y -= LineMarkerThickness;
384 render.DrawLine(from, to);
387 void DrawInsertPoint()
389 //一つしかない場合は行選択の可能性がある
390 if (this.Selections.Count <= 1)
392 IEditorRender render = (IEditorRender)base.render;
393 foreach (Selection sel in this.Selections)
397 TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
398 Point left = this.GetPostionFromTextPoint(tp);
399 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
400 Rectangle InsertRect = new Rectangle(left.X,
402 CaretWidthOnInsertMode,
404 render.FillRectangle(InsertRect, FillRectType.InsertPoint);
411 if (this.HideCaret || !this.IsFocused)
414 long diff = DateTime.Now.Ticks - this.tickCount;
415 long blinkTime = this.To100nsTime(this.CaretBlinkTime);
417 if (this.CaretBlink && diff % blinkTime >= blinkTime / 2)
420 Rectangle CaretRect = new Rectangle();
422 IEditorRender render = (IEditorRender)base.render;
424 int row = this.CaretPostion.row;
425 double lineHeight = this.LayoutLines.GetLayout(row).Height;
426 double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);
428 if (this.InsertMode || charWidth == 0)
430 CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);
431 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);
432 render.FillRectangle(CaretRect, FillRectType.InsertCaret);
436 double height = lineHeight / 3;
437 CaretRect.Size = new Size(charWidth, height);
438 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);
439 render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);
443 long To100nsTime(int ms)
448 public void DrawLineMarker(int row)
450 if (this.HideLineMarker || !this.IsFocused)
452 IEditorRender render = (IEditorRender)base.render;
453 Point p = this.CaretLocation;
454 double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;
455 double width = this.render.TextArea.Width;
456 render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);
460 /// 指定した座標の一番近くにあるTextPointを取得する
462 /// <param name="p">テキストエリアを左上とする相対位置</param>
463 /// <returns>レイアウトラインを指し示すTextPoint</returns>
464 public TextPoint GetTextPointFromPostion(Point p)
466 if (p.Y < this.render.TextArea.TopLeft.Y ||
467 p.Y > this.render.TextArea.BottomRight.Y)
468 return TextPoint.Null;
469 TextPoint tp = new TextPoint();
471 if (this.LayoutLines.Count == 0)
474 p.Y -= this.render.TextArea.Y;
476 int lineHeadIndex, lineLength;
478 tp.row = this.LayoutLines.Count - 1;
479 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
481 double height = this.LayoutLines.GetLayout(i).Height;
483 lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
484 lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
486 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
489 if (y + height > p.Y)
497 if (p.X < this.render.TextArea.X)
500 tp.col = GetIndexFromColPostion(tp.row, p.X);
502 lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
503 if (tp.col > lineLength)
510 /// 桁方向の座標に対応するインデックスを取得する
512 /// <param name="row">対象となる行</param>
513 /// <param name="x">テキストエリアからの相対位置</param>
514 /// <returns></returns>
515 public int GetIndexFromColPostion(int row, double x)
517 x -= this.render.TextArea.X;
518 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
521 int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
526 /// インデックスに対応する桁方向の座標を得る
528 /// <param name="row">対象となる行</param>
529 /// <param name="index">インデックス</param>
530 /// <returns>テキストエリアからの相対位置を返す</returns>
531 public double GetColPostionFromIndex(int row, int index)
533 double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
534 return x - Src.X + this.render.TextArea.X;
538 /// TextPointに対応する座標を得る
540 /// <param name="tp">レイアウトライン上の位置</param>
541 /// <returns>テキストエリアを左上とする相対位置</returns>
542 public Point GetPostionFromTextPoint(TextPoint tp)
544 Point p = new Point();
545 for (int i = this.Src.Row; i < tp.row; i++)
547 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
548 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
549 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
551 p.Y += this.LayoutLines.GetLayout(i).Height;
553 p.X = this.GetColPostionFromIndex(tp.row, tp.col);
554 p.Y += this.render.TextArea.Y;
558 public GripperView HitGripperFromPoint(Point p)
560 if (this.SelectGrippers.BottomLeft.IsHit(p))
561 return this.SelectGrippers.BottomLeft;
562 if (this.SelectGrippers.BottomRight.IsHit(p))
563 return this.SelectGrippers.BottomRight;
567 public Rectangle GetRectFromIndex(int index,int width,int height)
569 TextPoint tp = this.LayoutLines.GetTextPointFromIndex(index);
570 return this.GetRectFromTextPoint(tp, width, height);
573 public Rectangle GetRectFromTextPoint(TextPoint tp, int width, int height)
575 double radius = width / 2;
576 Point point = this.GetPostionFromTextPoint(tp);
577 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
579 return new Rectangle(point.X - radius, point.Y + lineHeight, width, height);
583 /// キャレットを指定した位置に移動させる
585 /// <param name="row"></param>
586 /// <param name="col"></param>
587 /// <param name="autoExpand">折り畳みを展開するなら真</param>
588 public void JumpCaret(int row, int col, bool autoExpand = true)
592 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
593 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
594 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
595 if(foldingData != null)
597 if (this.LayoutLines.FoldingCollection.IsParentHidden(foldingData) || !foldingData.IsFirstLine(this.LayoutLines, row))
599 this.LayoutLines.FoldingCollection.Expand(foldingData);
604 this.CaretPostion = new TextPoint(row, col);
608 /// index上の文字が表示されるようにSrcを調整する
610 /// <param name="index">インデックス</param>
611 /// <returns>調整されたら真。そうでなければ偽</returns>
612 public bool AdjustSrc(int index)
614 TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
615 double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
616 if (x < this.Src.X ||
617 x > this.Src.X + this.PageBound.Width)
619 this.TryScroll(x, this.Src.Row);
622 if (startTextPoint.row < this.Src.Row ||
623 startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
625 this.TryScroll(this.Src.X, startTextPoint.row);
632 /// キャレットがあるところまでスクロールする
634 /// <return>再描写する必要があるなら真を返す</return>
635 /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>
636 public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)
638 IEditorRender render = (IEditorRender)base.render;
640 if (this.PageBound.Width == 0 || this.PageBound.Height == 0)
642 this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);
647 TextPoint tp = this.CaretPostion;
648 double x = this.CaretLocation.X;
649 double y = this.CaretLocation.Y;
651 if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
653 x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
655 double left = this.Src.X;
656 double right = this.Src.X + this.render.TextArea.Width;
658 if (x >= left && x <= right) //xは表示領域にないにある
662 else if (x > right) //xは表示領域の右側にある
664 this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;
665 if (this.Document.RightToLeft && this._Src.X > 0)
667 System.Diagnostics.Debug.Assert(x > 0);
672 x = this.render.TextArea.Width - this.ScrollMarginWidth;
676 else if (x < left) //xは表示領域の左側にある
678 this._Src.X = x - this.ScrollMarginWidth;
679 if (!this.Document.RightToLeft && this._Src.X < this.render.TextArea.X)
685 x = this.ScrollMarginWidth;
689 x += this.render.TextArea.X;
692 if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
695 int lineCount = this.LineCountOnScreenWithInVisible;
696 if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
697 caretRow = tp.row - this.Src.Row;
698 else if (tp.row >= this.Src.Row + lineCount)
700 this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);
701 caretRow = tp.row - this._Src.Row;
703 CalculateLineCountOnScreen();
705 else if (tp.row < this.Src.Row)
707 this._Src.Row = tp.row;
709 CalculateLineCountOnScreen();
716 for (int i = 0; i < caretRow; i++)
718 int currentRow = this.Src.Row + i;
719 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
720 int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
722 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
725 y += this.LayoutLines.GetLayout(currentRow).Height;
728 y += this.render.TextArea.Y;
731 this.SetCaretPostion(x, y);
734 this.OnSrcChanged(null);
739 int GetSrcRow(int row,int count)
741 if (this.LayoutLines.FoldingStrategy == null)
743 for (int i = row; i >= 0; i--)
745 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
746 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
747 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
757 /// レイアウト行をテキストポイントからインデックスに変換する
759 /// <param name="tp">テキストポイント表す</param>
760 /// <returns>インデックスを返す</returns>
761 public int GetIndexFromLayoutLine(TextPoint tp)
763 return this.LayoutLines.GetIndexFromTextPoint(tp);
767 /// インデックスからレイアウト行を指し示すテキストポイントに変換する
769 /// <param name="index">インデックスを表す</param>
770 /// <returns>テキストポイント返す</returns>
771 public TextPoint GetLayoutLineFromIndex(int index)
773 return this.LayoutLines.GetTextPointFromIndex(index);
779 /// <param name="x"></param>
780 /// <param name="row"></param>
782 /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます
784 public void Scroll(double x, int row)
790 int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;
795 base.TryScroll(x, row);
801 /// <param name="row">行</param>
802 /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>
803 public void ScrollIntoView(int row, bool alignTop)
808 double y = this.render.TextArea.Height;
809 for (int i = row; i >= 0; i--)
811 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
812 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
813 double height = this.LayoutLines.GetLayout(i).Height;
818 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
824 public int AdjustRow(int row, bool isMoveNext)
826 if (this.LayoutLines.FoldingStrategy == null)
828 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
829 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
830 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
831 if (foldingData != null && !foldingData.Expand)
833 if (foldingData.End == this.Document.Length)
835 if (isMoveNext && lineHeadIndex > foldingData.Start)
836 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;
838 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
839 if(row > this.LayoutLines.Count - 1)
840 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
845 protected override void CalculateClipRect()
847 IEditorRender render = (IEditorRender)base.render;
848 double x, y, width, height;
850 if (this.DrawLineNumber)
852 if (this.Document.RightToLeft)
853 x = this.Padding.Left;
855 x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + this.LineNumberMargin + render.FoldingWidth;
856 width = this.PageBound.Width - this.render.LineNemberWidth - this.LineNumberMargin - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
860 if (this.Document.RightToLeft)
861 x = this.Padding.Left;
863 x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth;
864 width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
867 y = this.Padding.Top;
868 height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;
870 if (this.HideRuler == false)
872 double rulerHeight = this.render.emSize.Height + LineMarkerThickness;
874 height -= rulerHeight;
883 this.render.TextArea = new Rectangle(x, y, width, height);
885 this.LineBreakingMarginWidth = width * 5 / 100;
888 public override void CalculateLineCountOnScreen()
890 if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0)
894 int i = this.Src.Row;
895 int visualCount = this.Src.Row;
898 int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
900 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
901 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
903 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && row < this.LayoutLines.Count - 1)
906 ITextLayout layout = this.LayoutLines.GetLayout(row);
908 double width = layout.Width;
910 if (width > this._LongestWidth)
911 this._LongestWidth = width;
913 double lineHeight = layout.Height;
917 if (y >= this.render.TextArea.Height)
921 this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);
922 this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
925 void SetCaretPostion(double x, double y)
927 this.CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
930 void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)
932 this.CalculateLineCountOnScreen();
943 double GetRealtiveX(AreaType type)
945 IEditorRender render = (IEditorRender)base.render;
948 case AreaType.UpdateArea:
949 if (this.Document.RightToLeft)
950 return this.PageBound.TopRight.X - UpdateAreaTotalWidth;
951 if (this.DrawLineNumber)
952 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth - UpdateAreaTotalWidth;
954 return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth;
955 case AreaType.FoldingArea:
956 if (this.Document.RightToLeft)
957 return this.PageBound.TopRight.X - render.FoldingWidth;
958 if (this.DrawLineNumber)
959 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth;
961 return this.render.TextArea.X - render.FoldingWidth;
962 case AreaType.LineNumberArea:
963 if (this.DrawLineNumber == false)
964 throw new InvalidOperationException();
965 if (this.Document.RightToLeft)
966 return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth;
968 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin;
969 case AreaType.TextArea:
970 return this.render.TextArea.X;
972 throw new ArgumentOutOfRangeException();