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;
31 Point _CaretLocation = new Point();
32 TextPoint _CaretPostion = new TextPoint();
34 bool _CaretBlink, _HideRuler = true;
35 internal const int LineNumberLength = 6;
36 const int UpdateAreaPaddingWidth = 2;
37 const int UpdateAreaWidth = 4;
38 const int UpdateAreaTotalWidth = UpdateAreaWidth + UpdateAreaPaddingWidth;
39 GripperView[] selectionGrippers = new GripperView[2];
44 public EditView(Document doc, IEditorRender r, int MarginLeftAndRight = 5)
45 : this(doc, r, new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))
52 /// <param name="doc">ドキュメント</param>
53 /// <param name="r">レンダー</param>
54 /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>
55 public EditView(Document doc, IEditorRender r, Padding margin)
56 : base(doc, r, margin)
58 this.CaretBlinkTime = 500;
59 this.CaretWidthOnInsertMode = 1;
60 this.CalculateClipRect();
61 this._CaretLocation.X = this.render.TextArea.X;
62 this._CaretLocation.Y = this.render.TextArea.Y;
63 this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;
64 this.InsertPoint = null;
65 this.HideLineMarker = true;
66 this.IsFocused = false;
67 this.Selections = new SelectCollection();
68 this.selectionGrippers[0] = new GripperView(this.render);
69 this.selectionGrippers[1] = new GripperView(this.render);
75 internal SelectCollection Selections
84 public IList<GripperView> SelectGrippers
88 return this.selectionGrippers;
93 /// ラインマーカーを描くなら偽。そうでなければ真
95 public bool HideLineMarker
102 /// キャレットを描くなら偽。そうでなければ真
104 public bool HideCaret
111 /// 挿入モードなら真を返し、上書きモードなら偽を返す
113 public bool InsertMode
122 public int CaretBlinkTime
131 public double CaretWidthOnInsertMode
138 /// フォーカスがあるなら真をセットする
140 public bool IsFocused
147 /// キャレットを点滅させるなら真。そうでないなら偽
149 /// <remarks>キャレット点滅タイマーもリセットされます</remarks>
150 public bool CaretBlink
152 get { return this._CaretBlink; }
155 this._CaretBlink = value;
157 this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);
162 /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)
164 public int LineCountOnScreenWithInVisible
173 public double ScrollMarginWidth
175 get { return this.PageBound.Width * 20 / 100; }
179 /// ルーラーを表示しないなら真、そうでないなら偽
181 public bool HideRuler
183 get { return this._HideRuler; }
186 this._HideRuler = value;
187 this.LayoutLines.ClearLayoutCache();
189 CalculateLineCountOnScreen();
194 /// 矩形選択モード中に文字列が挿入される位置を表す
196 public SelectCollection InsertPoint
205 public Point CaretLocation
207 get { return this._CaretLocation; }
211 /// レイアウト行のどこにキャレットがあるかを表す
213 public TextPoint CaretPostion
215 get { return this._CaretPostion; }
221 /// <param name="x">x座標</param>
222 /// <param name="y">y座標</param>
223 /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>
224 public bool HitTextArea(double x, double y)
226 if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&
227 y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)
236 /// <param name="x">x座標</param>
237 /// <param name="row">行</param>
238 /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>
239 public FoldingItem HitFoldingData(double x, int row)
241 IEditorRender render = (IEditorRender)base.render;
243 if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)
245 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
246 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
247 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
248 if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))
255 /// Rectで指定された範囲にドキュメントを描く
257 /// <param name="updateRect">描写する範囲</param>
258 /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>
259 public override void Draw(Rectangle updateRect)
261 if (this.LayoutLines.Count == 0)
264 IEditorRender render = (IEditorRender)base.render;
266 if ((updateRect.Height < this.PageBound.Height ||
267 updateRect.Width < this.PageBound.Width) &&
268 render.IsVaildCache())
270 render.DrawCachedBitmap(updateRect);
274 Rectangle background = this.PageBound;
275 render.FillBackground(background);
277 if (this.HideRuler == false)
280 this.DrawLineMarker(this.CaretPostion.row);
282 Point pos = this.render.TextArea.TopLeft;
284 double endposy = this.render.TextArea.Bottom;
285 Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);
286 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
288 int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);
289 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
290 ITextLayout layout = this.LayoutLines.GetLayout(i);
292 if (pos.Y + layout.Height > endposy)
295 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);
297 if (foldingData != null)
299 if ((!this.LayoutLines.FoldingCollection.IsHasParent(foldingData) ||
300 !this.LayoutLines.FoldingCollection.IsParentHidden(foldingData))
301 && foldingData.IsFirstLine(this.LayoutLines, i))
302 render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);
303 if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex))
307 var selectRange = from s in this.Selections.Get(lineIndex, lineLength)
308 let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)
311 this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);
313 if (this.DrawLineNumber)
315 this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize,StringColorType.LineNumber);
318 DrawUpdateArea(i, pos.Y);
320 pos.Y += this.LayoutLines.GetLayout(i).Height;
323 if (this.InsertPoint != null)
324 this.DrawInsertPoint();
326 render.CacheContent();
331 foreach (GripperView gripper in this.selectionGrippers)
335 void DrawUpdateArea(int row,double ypos)
337 IEditorRender render = (IEditorRender)base.render;
338 if(this.LayoutLines.GetDirtyFlag(row))
340 Point pos = new Point(this.PageBound.X + this.GetRealtiveX(AreaType.UpdateArea), ypos);
341 Rectangle rect = new Rectangle(pos.X, pos.Y, UpdateAreaWidth, this.LayoutLines.GetLayout(row).Height);
342 render.FillRectangle(rect, FillRectType.UpdateArea);
348 IEditorRender render = (IEditorRender)base.render;
351 Size emSize = render.emSize;
352 Rectangle clipRect = this.render.TextArea;
354 double markerHeight = emSize.Height / 2;
355 if (this.render.RightToLeft)
357 pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);
358 for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)
361 to = new Point(pos.X, pos.Y + emSize.Height);
362 int mod = count % 10;
365 string countStr = (count / 10).ToString();
366 double counterWidth = emSize.Width * countStr.Length;
367 this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));
370 from.Y = from.Y + emSize.Height / 2;
372 from.Y = from.Y + emSize.Height * 3 / 4;
373 render.DrawLine(from, to);
374 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
375 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
380 pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);
381 for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)
384 to = new Point(pos.X, pos.Y + emSize.Height);
385 int mod = count % 10;
387 this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));
389 from.Y = from.Y + emSize.Height / 2;
391 from.Y = from.Y + emSize.Height * 3 / 4;
392 render.DrawLine(from, to);
393 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
394 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
397 from = clipRect.TopLeft;
398 from.Y -= LineMarkerThickness;
399 to = clipRect.TopRight;
400 to.Y -= LineMarkerThickness;
401 render.DrawLine(from, to);
404 void DrawInsertPoint()
406 IEditorRender render = (IEditorRender)base.render;
407 foreach (Selection sel in this.InsertPoint)
411 TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
412 Point left = this.GetPostionFromTextPoint(tp);
413 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
414 Rectangle InsertRect = new Rectangle(left.X,
416 CaretWidthOnInsertMode,
418 render.FillRectangle(InsertRect, FillRectType.InsertPoint);
425 if (this.HideCaret || !this.IsFocused)
428 long diff = DateTime.Now.Ticks - this.tickCount;
429 long blinkTime = this.To100nsTime(this.CaretBlinkTime);
431 if (this._CaretBlink && diff % blinkTime >= blinkTime / 2)
434 Rectangle CaretRect = new Rectangle();
436 IEditorRender render = (IEditorRender)base.render;
438 int row = this.CaretPostion.row;
439 double lineHeight = this.LayoutLines.GetLayout(row).Height;
440 double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);
442 if (this.InsertMode || charWidth == 0)
444 CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);
445 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);
446 render.FillRectangle(CaretRect, FillRectType.InsertCaret);
450 double height = lineHeight / 3;
451 CaretRect.Size = new Size(charWidth, height);
452 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);
453 render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);
457 long To100nsTime(int ms)
462 public void DrawLineMarker(int row)
464 if (this.HideLineMarker || !this.IsFocused)
466 IEditorRender render = (IEditorRender)base.render;
467 Point p = this.CaretLocation;
468 double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;
469 double width = this.render.TextArea.Width;
470 render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);
474 /// 指定した座標の一番近くにあるTextPointを取得する
476 /// <param name="p">テキストエリアを左上とする相対位置</param>
477 /// <returns>レイアウトラインを指し示すTextPoint</returns>
478 public TextPoint GetTextPointFromPostion(Point p)
480 if (p.Y < this.render.TextArea.TopLeft.Y ||
481 p.Y > this.render.TextArea.BottomRight.Y)
482 return TextPoint.Null;
483 TextPoint tp = new TextPoint();
485 if (this.LayoutLines.Count == 0)
488 p.Y -= this.render.TextArea.Y;
490 int lineHeadIndex, lineLength;
492 tp.row = this.LayoutLines.Count - 1;
493 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
495 double height = this.LayoutLines.GetLayout(i).Height;
497 lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
498 lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
500 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
503 if (y + height > p.Y)
511 if (p.X < this.render.TextArea.X)
514 tp.col = GetIndexFromColPostion(tp.row, p.X);
516 lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
517 if (tp.col > lineLength)
524 /// 桁方向の座標に対応するインデックスを取得する
526 /// <param name="row">対象となる行</param>
527 /// <param name="x">テキストエリアからの相対位置</param>
528 /// <returns></returns>
529 public int GetIndexFromColPostion(int row, double x)
531 x -= this.render.TextArea.X;
532 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
535 int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
540 /// インデックスに対応する桁方向の座標を得る
542 /// <param name="row">対象となる行</param>
543 /// <param name="index">インデックス</param>
544 /// <returns>テキストエリアからの相対位置を返す</returns>
545 public double GetColPostionFromIndex(int row, int index)
547 double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
548 return x - Src.X + this.render.TextArea.X;
552 /// TextPointに対応する座標を得る
554 /// <param name="tp">レイアウトライン上の位置</param>
555 /// <returns>テキストエリアを左上とする相対位置</returns>
556 public Point GetPostionFromTextPoint(TextPoint tp)
558 Point p = new Point();
559 for (int i = this.Src.Row; i < tp.row; i++)
561 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
562 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
563 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
565 p.Y += this.LayoutLines.GetLayout(i).Height;
567 p.X = this.GetColPostionFromIndex(tp.row, tp.col);
568 p.Y += this.render.TextArea.Y;
572 public GripperView HitGripperFromPoint(Point p)
574 for(int i = 0; i < this.selectionGrippers.Length; i++)
576 if (this.selectionGrippers[i].IsHit(p))
578 System.Diagnostics.Debug.WriteLine("gripper hitted number:{0}", i);
579 return selectionGrippers[i];
585 public Rectangle GetRectFromIndex(int index,int width,int height)
587 TextPoint tp = this.LayoutLines.GetTextPointFromIndex(index);
588 return this.GetRectFromTextPoint(tp, width, height);
591 public Rectangle GetRectFromTextPoint(TextPoint tp, int width, int height)
593 double radius = width / 2;
594 Point point = this.GetPostionFromTextPoint(tp);
595 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
597 return new Rectangle(point.X - radius, point.Y + lineHeight, width, height);
601 /// キャレットを指定した位置に移動させる
603 /// <param name="row"></param>
604 /// <param name="col"></param>
605 /// <param name="autoExpand">折り畳みを展開するなら真</param>
606 public void JumpCaret(int row, int col, bool autoExpand = true)
610 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
611 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
612 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
613 if(foldingData != null)
615 if (this.LayoutLines.FoldingCollection.IsParentHidden(foldingData) || !foldingData.IsFirstLine(this.LayoutLines, row))
617 this.LayoutLines.FoldingCollection.Expand(foldingData);
622 this._CaretPostion.row = row;
623 this._CaretPostion.col = col;
627 /// index上の文字が表示されるようにSrcを調整する
629 /// <param name="index">インデックス</param>
630 /// <returns>調整されたら真。そうでなければ偽</returns>
631 public bool AdjustSrc(int index)
633 TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
634 double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
635 if (x < this.Src.X ||
636 x > this.Src.X + this.PageBound.Width)
638 this.TryScroll(x, this.Src.Row);
641 if (startTextPoint.row < this.Src.Row ||
642 startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
644 this.TryScroll(this.Src.X, startTextPoint.row);
651 /// キャレットがあるところまでスクロールする
653 /// <return>再描写する必要があるなら真を返す</return>
654 /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>
655 public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)
657 IEditorRender render = (IEditorRender)base.render;
659 if (this.PageBound.Width == 0 || this.PageBound.Height == 0)
661 this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);
666 TextPoint tp = this.CaretPostion;
667 double x = this.CaretLocation.X;
668 double y = this.CaretLocation.Y;
670 if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
672 x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
674 double left = this.Src.X;
675 double right = this.Src.X + this.render.TextArea.Width;
677 if (x >= left && x <= right) //xは表示領域にないにある
681 else if (x > right) //xは表示領域の右側にある
683 this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;
684 if (this.render.RightToLeft && this._Src.X > 0)
686 System.Diagnostics.Debug.Assert(x > 0);
691 x = this.render.TextArea.Width - this.ScrollMarginWidth;
695 else if (x < left) //xは表示領域の左側にある
697 this._Src.X = x - this.ScrollMarginWidth;
698 if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X)
704 x = this.ScrollMarginWidth;
708 x += this.render.TextArea.X;
711 if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
714 int lineCount = this.LineCountOnScreenWithInVisible;
715 if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
716 caretRow = tp.row - this.Src.Row;
717 else if (tp.row >= this.Src.Row + lineCount)
719 this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);
720 caretRow = tp.row - this._Src.Row;
722 CalculateLineCountOnScreen();
724 else if (tp.row < this.Src.Row)
726 this._Src.Row = tp.row;
728 CalculateLineCountOnScreen();
735 for (int i = 0; i < caretRow; i++)
737 int currentRow = this.Src.Row + i;
738 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
739 int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
741 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
744 y += this.LayoutLines.GetLayout(currentRow).Height;
747 y += this.render.TextArea.Y;
750 this.SetCaretPostion(x, y);
753 this.OnSrcChanged(null);
758 int GetSrcRow(int row,int count)
760 if (this.LayoutLines.FoldingStrategy == null)
762 for (int i = row; i >= 0; i--)
764 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
765 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
766 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
776 /// レイアウト行をテキストポイントからインデックスに変換する
778 /// <param name="tp">テキストポイント表す</param>
779 /// <returns>インデックスを返す</returns>
780 public int GetIndexFromLayoutLine(TextPoint tp)
782 return this.LayoutLines.GetIndexFromTextPoint(tp);
786 /// インデックスからレイアウト行を指し示すテキストポイントに変換する
788 /// <param name="index">インデックスを表す</param>
789 /// <returns>テキストポイント返す</returns>
790 public TextPoint GetLayoutLineFromIndex(int index)
792 return this.LayoutLines.GetTextPointFromIndex(index);
798 /// <param name="x"></param>
799 /// <param name="row"></param>
801 /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます
803 public void Scroll(double x, int row)
809 int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;
814 base.TryScroll(x, row);
820 /// <param name="row">行</param>
821 /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>
822 public void ScrollIntoView(int row, bool alignTop)
827 double y = this.render.TextArea.Height;
828 for (int i = row; i >= 0; i--)
830 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
831 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
832 double height = this.LayoutLines.GetLayout(i).Height;
837 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
843 public int AdjustRow(int row, bool isMoveNext)
845 if (this.LayoutLines.FoldingStrategy == null)
847 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
848 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
849 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
850 if (foldingData != null && !foldingData.Expand)
852 if (foldingData.End == this.Document.Length)
854 if (isMoveNext && lineHeadIndex > foldingData.Start)
855 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;
857 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
858 if(row > this.LayoutLines.Count - 1)
859 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
864 protected override void CalculateClipRect()
866 IEditorRender render = (IEditorRender)base.render;
867 double x, y, width, height;
869 if (this.DrawLineNumber)
871 if (this.render.RightToLeft)
872 x = this.Padding.Left;
874 x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + this.LineNumberMargin + render.FoldingWidth;
875 width = this.PageBound.Width - this.render.LineNemberWidth - this.LineNumberMargin - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
879 if (this.render.RightToLeft)
880 x = this.Padding.Left;
882 x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth;
883 width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
886 y = this.Padding.Top;
887 height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;
889 if (this.HideRuler == false)
891 double rulerHeight = this.render.emSize.Height + LineMarkerThickness;
893 height -= rulerHeight;
902 this.render.TextArea = new Rectangle(x, y, width, height);
904 this.LineBreakingMarginWidth = width * 5 / 100;
907 public override void CalculateLineCountOnScreen()
909 if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0)
913 int i = this.Src.Row;
914 int visualCount = this.Src.Row;
917 int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
919 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
920 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
922 if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && row < this.LayoutLines.Count - 1)
925 ITextLayout layout = this.LayoutLines.GetLayout(row);
927 double width = layout.Width;
929 if (width > this._LongestWidth)
930 this._LongestWidth = width;
932 double lineHeight = layout.Height;
936 if (y >= this.render.TextArea.Height)
940 this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);
941 this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
944 void SetCaretPostion(double x, double y)
946 this._CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
949 void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)
951 this.CalculateLineCountOnScreen();
962 double GetRealtiveX(AreaType type)
964 IEditorRender render = (IEditorRender)base.render;
967 case AreaType.UpdateArea:
968 if (this.render.RightToLeft)
969 return this.PageBound.TopRight.X - UpdateAreaTotalWidth;
970 if (this.DrawLineNumber)
971 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth - UpdateAreaTotalWidth;
973 return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth;
974 case AreaType.FoldingArea:
975 if (this.render.RightToLeft)
976 return this.PageBound.TopRight.X - render.FoldingWidth;
977 if (this.DrawLineNumber)
978 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth;
980 return this.render.TextArea.X - render.FoldingWidth;
981 case AreaType.LineNumberArea:
982 if (this.DrawLineNumber == false)
983 throw new InvalidOperationException();
984 if (this.render.RightToLeft)
985 return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth;
987 return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin;
988 case AreaType.TextArea:
989 return this.render.TextArea.X;
991 throw new ArgumentOutOfRangeException();