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
35 const int UpdateAreaPaddingWidth = 2;
\r
36 const int UpdateAreaWidth = 4;
\r
37 const int UpdateAreaTotalWidth = UpdateAreaWidth + UpdateAreaPaddingWidth;
\r
42 public EditView(Document doc, IEditorRender r,int MarginLeftAndRight = 5)
\r
43 : this(doc,r,new Padding(MarginLeftAndRight, 0, MarginLeftAndRight, 0))
\r
50 /// <param name="doc">ドキュメント</param>
\r
51 /// <param name="r">レンダー</param>
\r
52 /// <param name="margin">マージン(1番目:左、2番目:上、3番目:右、4番目:下)</param>
\r
53 public EditView(Document doc, IEditorRender r, Padding margin)
\r
54 : base(doc,r,margin)
\r
56 this.CaretBlinkTime = 500;
\r
57 this.CaretWidthOnInsertMode = 1;
\r
58 this.CalculateClipRect();
\r
59 this._CaretLocation.X = this.render.TextArea.X;
\r
60 this._CaretLocation.Y = this.render.TextArea.Y;
\r
61 this.LayoutLines.FoldingCollection.StatusChanged += FoldingCollection_StatusChanged;
\r
62 this.InsertPoint = null;
\r
63 this.HideLineMarker = true;
\r
64 this.IsFocused = false;
\r
65 this.Selections = new SelectCollection();
\r
71 internal SelectCollection Selections
\r
78 /// ラインマーカーを描くなら偽。そうでなければ真
\r
80 public bool HideLineMarker
\r
87 /// キャレットを描くなら偽。そうでなければ真
\r
89 public bool HideCaret
\r
96 /// 挿入モードなら真を返し、上書きモードなら偽を返す
\r
98 public bool InsertMode
\r
107 public int CaretBlinkTime
\r
116 public double CaretWidthOnInsertMode
\r
123 /// フォーカスがあるなら真をセットする
\r
125 public bool IsFocused
\r
132 /// キャレットを点滅させるなら真。そうでないなら偽
\r
134 /// <remarks>キャレット点滅タイマーもリセットされます</remarks>
\r
135 public bool CaretBlink
\r
137 get { return this._CaretBlink; }
\r
140 this._CaretBlink = value;
\r
142 this.tickCount = DateTime.Now.Ticks + this.To100nsTime(this.CaretBlinkTime);
\r
147 /// 一ページの高さに収まる行数を返す(こちらは表示されていない行も含みます)
\r
149 public int LineCountOnScreenWithInVisible
\r
156 /// スクロール時に確保するマージン幅
\r
158 public double ScrollMarginWidth
\r
160 get { return this.PageBound.Width * 20 / 100; }
\r
164 /// ルーラーを表示しないなら真、そうでないなら偽
\r
166 public bool HideRuler
\r
168 get { return this._HideRuler; }
\r
171 this._HideRuler = value;
\r
172 this.LayoutLines.ClearLayoutCache();
\r
173 CalculateClipRect();
\r
174 CalculateLineCountOnScreen();
\r
179 /// 矩形選択モード中に文字列が挿入される位置を表す
\r
181 public SelectCollection InsertPoint
\r
190 public Point CaretLocation
\r
192 get { return this._CaretLocation; }
\r
196 /// レイアウト行のどこにキャレットがあるかを表す
\r
198 public TextPoint CaretPostion
\r
200 get { return this._CaretPostion; }
\r
206 /// <param name="x">x座標</param>
\r
207 /// <param name="y">y座標</param>
\r
208 /// <returns>テキストエリア内にあれば真。そうでなければ偽</returns>
\r
209 public bool HitTextArea(double x, double y)
\r
211 if (x >= this.render.TextArea.X && x <= this.render.TextArea.Right &&
\r
212 y >= this.render.TextArea.Y && y <= this.render.TextArea.Bottom)
\r
221 /// <param name="x">x座標</param>
\r
222 /// <param name="row">行</param>
\r
223 /// <returns>ヒットした場合はFoldingDataオブジェクトが返され、そうでない場合はnullが返る</returns>
\r
224 public FoldingItem HitFoldingData(double x, int row)
\r
226 IEditorRender render = (IEditorRender)base.render;
\r
228 if (x >= this.GetRealtiveX(AreaType.FoldingArea) && x <= this.GetRealtiveX(AreaType.FoldingArea) + render.FoldingWidth)
\r
230 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
231 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
232 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
233 if (foldingData != null && foldingData.IsFirstLine(this.LayoutLines,row))
\r
234 return foldingData;
\r
240 /// Rectで指定された範囲にドキュメントを描く
\r
242 /// <param name="updateRect">描写する範囲</param>
\r
243 /// <remarks>キャレットを点滅させる場合、定期的のこのメソッドを呼び出してください</remarks>
\r
244 public override void Draw(Rectangle updateRect)
\r
246 if (this.LayoutLines.Count == 0)
\r
249 IEditorRender render = (IEditorRender)base.render;
\r
251 if ((updateRect.Height < this.PageBound.Height ||
\r
252 updateRect.Width < this.PageBound.Width) &&
\r
253 render.IsVaildCache())
\r
255 render.DrawCachedBitmap(updateRect);
\r
259 Rectangle background = this.PageBound;
\r
260 render.FillBackground(background);
\r
262 if (this.HideRuler == false)
\r
265 this.DrawLineMarker(this.CaretPostion.row);
\r
267 Point pos = this.render.TextArea.TopLeft;
\r
268 pos.X -= this.Src.X;
\r
269 double endposy = this.render.TextArea.Bottom;
\r
270 Size lineNumberSize = new Size(this.render.LineNemberWidth,this.render.TextArea.Height);
\r
271 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
\r
273 int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
274 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
275 ITextLayout layout = this.LayoutLines.GetLayout(i);
\r
277 if (pos.Y + layout.Height > endposy)
\r
280 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength);
\r
282 if (foldingData != null)
\r
284 if ((foldingData.Parent == null || foldingData.Parent.Expand) && foldingData.IsFirstLine(this.LayoutLines, i))
\r
285 render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y);
\r
286 if (foldingData.IsHidden(lineIndex))
\r
290 var selectRange = from s in this.Selections.Get(lineIndex, lineLength)
\r
291 let n = Util.ConvertAbsIndexToRelIndex(s, lineIndex, lineLength)
\r
294 this.render.DrawOneLine(this.LayoutLines, i, pos.X, pos.Y, selectRange);
\r
296 if (this.DrawLineNumber)
\r
298 this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);
\r
301 DrawUpdateArea(i, pos.Y);
\r
303 pos.Y += this.LayoutLines.GetLayout(i).Height;
\r
306 if (this.InsertPoint != null)
\r
307 this.DrawInsertPoint();
\r
309 render.CacheContent();
\r
315 void DrawUpdateArea(int row,double ypos)
\r
317 IEditorRender render = (IEditorRender)base.render;
\r
318 if(this.LayoutLines.GetDirtyFlag(row))
\r
320 Point pos = new Point(this.PageBound.X + this.GetRealtiveX(AreaType.UpdateArea), ypos);
\r
321 Rectangle rect = new Rectangle(pos.X, pos.Y, UpdateAreaWidth, this.LayoutLines.GetLayout(row).Height);
\r
322 render.FillRectangle(rect, FillRectType.UpdateArea);
\r
328 IEditorRender render = (IEditorRender)base.render;
\r
330 Point pos, from, to;
\r
331 Size emSize = render.emSize;
\r
332 Rectangle clipRect = this.render.TextArea;
\r
334 double markerHeight = emSize.Height / 2;
\r
335 if (this.render.RightToLeft)
\r
337 pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness);
\r
338 for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++)
\r
341 to = new Point(pos.X, pos.Y + emSize.Height);
\r
342 int mod = count % 10;
\r
345 string countStr = (count / 10).ToString();
\r
346 double counterWidth = emSize.Width * countStr.Length;
\r
347 this.render.DrawString(countStr, pos.X - counterWidth, pos.Y, StringAlignment.Right, new Size(counterWidth, double.MaxValue));
\r
350 from.Y = from.Y + emSize.Height / 2;
\r
352 from.Y = from.Y + emSize.Height * 3 / 4;
\r
353 render.DrawLine(from, to);
\r
354 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
\r
355 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
\r
360 pos = new Point(clipRect.TopLeft.X, clipRect.TopLeft.Y - emSize.Height - LineMarkerThickness);
\r
361 for (; pos.X < clipRect.TopRight.X; pos.X += emSize.Width, count++)
\r
364 to = new Point(pos.X, pos.Y + emSize.Height);
\r
365 int mod = count % 10;
\r
367 this.render.DrawString((count / 10).ToString(), pos.X, pos.Y, StringAlignment.Left, new Size(double.MaxValue, double.MaxValue));
\r
369 from.Y = from.Y + emSize.Height / 2;
\r
371 from.Y = from.Y + emSize.Height * 3 / 4;
\r
372 render.DrawLine(from, to);
\r
373 if (this.CaretLocation.X >= pos.X && this.CaretLocation.X < pos.X + emSize.Width)
\r
374 render.FillRectangle(new Rectangle(pos.X, pos.Y + markerHeight, emSize.Width, markerHeight), FillRectType.OverwriteCaret);
\r
377 from = clipRect.TopLeft;
\r
378 from.Y -= LineMarkerThickness;
\r
379 to = clipRect.TopRight;
\r
380 to.Y -= LineMarkerThickness;
\r
381 render.DrawLine(from, to);
\r
384 void DrawInsertPoint()
\r
386 IEditorRender render = (IEditorRender)base.render;
\r
387 foreach (Selection sel in this.InsertPoint)
\r
389 if (sel.length == 0)
\r
391 TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
\r
392 Point left = this.GetPostionFromTextPoint(tp);
\r
393 double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
\r
394 Rectangle InsertRect = new Rectangle(left.X,
\r
396 CaretWidthOnInsertMode,
\r
398 render.FillRectangle(InsertRect, FillRectType.InsertPoint);
\r
405 if (this.HideCaret || !this.IsFocused)
\r
408 long diff = DateTime.Now.Ticks - this.tickCount;
\r
409 long blinkTime = this.To100nsTime(this.CaretBlinkTime);
\r
411 if (this._CaretBlink && diff % blinkTime >= blinkTime / 2)
\r
414 Rectangle CaretRect = new Rectangle();
\r
416 IEditorRender render = (IEditorRender)base.render;
\r
418 int row = this.CaretPostion.row;
\r
419 double lineHeight = this.LayoutLines.GetLayout(row).Height;
\r
420 double charWidth = this.LayoutLines.GetLayout(row).GetWidthFromIndex(this.CaretPostion.col);
\r
422 if (this.InsertMode || charWidth == 0)
\r
424 CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight);
\r
425 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y);
\r
426 render.FillRectangle(CaretRect, FillRectType.InsertCaret);
\r
430 double height = lineHeight / 3;
\r
431 CaretRect.Size = new Size(charWidth, height);
\r
432 CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height);
\r
433 render.FillRectangle(CaretRect, FillRectType.OverwriteCaret);
\r
437 long To100nsTime(int ms)
\r
442 public void DrawLineMarker(int row)
\r
444 if (this.HideLineMarker || !this.IsFocused)
\r
446 IEditorRender render = (IEditorRender)base.render;
\r
447 Point p = this.CaretLocation;
\r
448 double height = this.LayoutLines.GetLayout(this.CaretPostion.row).Height;
\r
449 double width = this.render.TextArea.Width;
\r
450 render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, this.CaretLocation.Y, width, height), FillRectType.LineMarker);
\r
454 /// 指定した座標の一番近くにあるTextPointを取得する
\r
456 /// <param name="p">テキストエリアを左上とする相対位置</param>
\r
457 /// <returns>レイアウトラインを指し示すTextPoint</returns>
\r
458 public TextPoint GetTextPointFromPostion(Point p)
\r
460 if (p.Y < this.render.TextArea.TopLeft.Y ||
\r
461 p.Y > this.render.TextArea.BottomRight.Y)
\r
462 return TextPoint.Null;
\r
463 TextPoint tp = new TextPoint();
\r
465 if (this.LayoutLines.Count == 0)
\r
468 p.Y -= this.render.TextArea.Y;
\r
470 int lineHeadIndex, lineLength;
\r
472 tp.row = this.LayoutLines.Count - 1;
\r
473 for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
\r
475 double height = this.LayoutLines.GetLayout(i).Height;
\r
477 lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
478 lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
480 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
482 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
485 if (y + height > p.Y)
\r
493 if (p.X < this.render.TextArea.X)
\r
496 tp.col = GetIndexFromColPostion(tp.row, p.X);
\r
498 lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
\r
499 if (tp.col > lineLength)
\r
500 tp.col = lineLength;
\r
506 /// 桁方向の座標に対応するインデックスを取得する
\r
508 /// <param name="row">対象となる行</param>
\r
509 /// <param name="x">テキストエリアからの相対位置</param>
\r
510 /// <returns></returns>
\r
511 public int GetIndexFromColPostion(int row, double x)
\r
513 x -= this.render.TextArea.X;
\r
514 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
515 if (lineLength == 0)
\r
517 int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
\r
522 /// インデックスに対応する桁方向の座標を得る
\r
524 /// <param name="row">対象となる行</param>
\r
525 /// <param name="index">インデックス</param>
\r
526 /// <returns>テキストエリアからの相対位置を返す</returns>
\r
527 public double GetColPostionFromIndex(int row, int index)
\r
529 double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
\r
530 return x - Src.X + this.render.TextArea.X;
\r
534 /// TextPointに対応する座標を得る
\r
536 /// <param name="tp">レイアウトライン上の位置</param>
\r
537 /// <returns>テキストエリアを左上とする相対位置</returns>
\r
538 public Point GetPostionFromTextPoint(TextPoint tp)
\r
540 Point p = new Point();
\r
541 for (int i = this.Src.Row; i < tp.row; i++)
\r
543 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
544 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
545 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
546 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
548 p.Y += this.LayoutLines.GetLayout(i).Height;
\r
550 p.X = this.GetColPostionFromIndex(tp.row, tp.col);
\r
551 p.Y += this.render.TextArea.Y;
\r
556 /// キャレットを指定した位置に移動させる
\r
558 /// <param name="row"></param>
\r
559 /// <param name="col"></param>
\r
560 /// <param name="autoExpand">折り畳みを展開するなら真</param>
\r
561 public void JumpCaret(int row, int col, bool autoExpand = true)
\r
565 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
566 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
567 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
568 if (foldingData != null && (!foldingData.IsFirstLine(this.LayoutLines, row) || foldingData.IsParentHidden()))
\r
570 this.LayoutLines.FoldingCollection.Expand(foldingData);
\r
574 this._CaretPostion.row = row;
\r
575 this._CaretPostion.col = col;
\r
579 /// index上の文字が表示されるようにSrcを調整する
\r
581 /// <param name="index">インデックス</param>
\r
582 /// <returns>調整されたら真。そうでなければ偽</returns>
\r
583 public bool AdjustSrc(int index)
\r
585 TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
\r
586 double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
\r
587 if (x < this.Src.X ||
\r
588 x > this.Src.X + this.PageBound.Width)
\r
590 this.TryScroll(x, this.Src.Row);
\r
593 if (startTextPoint.row < this.Src.Row ||
\r
594 startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
\r
596 this.TryScroll(this.Src.X, startTextPoint.row);
\r
603 /// キャレットがあるところまでスクロールする
\r
605 /// <return>再描写する必要があるなら真を返す</return>
\r
606 /// <remarks>Document.Update(type == UpdateType.Clear)イベント時に呼び出した場合、例外が発生します</remarks>
\r
607 public bool AdjustCaretAndSrc(AdjustFlow flow = AdjustFlow.Both)
\r
609 IEditorRender render = (IEditorRender)base.render;
\r
611 if (this.PageBound.Width == 0 || this.PageBound.Height == 0)
\r
613 this.SetCaretPostion(this.Padding.Left + render.FoldingWidth, 0);
\r
617 bool result = false;
\r
618 TextPoint tp = this.CaretPostion;
\r
619 double x = this.CaretLocation.X;
\r
620 double y = this.CaretLocation.Y;
\r
622 if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
\r
624 x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
\r
626 double left = this.Src.X;
\r
627 double right = this.Src.X + this.render.TextArea.Width;
\r
629 if (x >= left && x <= right) //xは表示領域にないにある
\r
633 else if (x > right) //xは表示領域の右側にある
\r
635 this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth;
\r
636 if (this.render.RightToLeft && this._Src.X > 0)
\r
638 System.Diagnostics.Debug.Assert(x > 0);
\r
643 x = this.render.TextArea.Width - this.ScrollMarginWidth;
\r
647 else if (x < left) //xは表示領域の左側にある
\r
649 this._Src.X = x - this.ScrollMarginWidth;
\r
650 if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X)
\r
656 x = this.ScrollMarginWidth;
\r
660 x += this.render.TextArea.X;
\r
663 if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
\r
666 int lineCount = this.LineCountOnScreenWithInVisible;
\r
667 if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
\r
668 caretRow = tp.row - this.Src.Row;
\r
669 else if (tp.row >= this.Src.Row + lineCount)
\r
671 this._Src.Row = this.GetSrcRow(tp.row, this.LineCountOnScreen);
\r
672 caretRow = tp.row - this._Src.Row;
\r
674 CalculateLineCountOnScreen();
\r
676 else if (tp.row < this.Src.Row)
\r
678 this._Src.Row = tp.row;
\r
680 CalculateLineCountOnScreen();
\r
687 for (int i = 0; i < caretRow; i++)
\r
689 int currentRow = this.Src.Row + i;
\r
690 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
\r
691 int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
\r
693 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
695 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
698 y += this.LayoutLines.GetLayout(currentRow).Height;
\r
701 y += this.render.TextArea.Y;
\r
704 this.SetCaretPostion(x, y);
\r
707 this.OnSrcChanged(null);
\r
712 int GetSrcRow(int row,int count)
\r
714 if (this.LayoutLines.FoldingStrategy == null)
\r
715 return row - count;
\r
716 for (int i = row; i >= 0; i--)
\r
718 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
\r
719 int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
\r
720 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
\r
721 if (foldingData != null && foldingData.IsHidden(lineHeadIndex))
\r
731 /// レイアウト行をテキストポイントからインデックスに変換する
\r
733 /// <param name="tp">テキストポイント表す</param>
\r
734 /// <returns>インデックスを返す</returns>
\r
735 public int GetIndexFromLayoutLine(TextPoint tp)
\r
737 return this.LayoutLines.GetIndexFromTextPoint(tp);
\r
741 /// インデックスからレイアウト行を指し示すテキストポイントに変換する
\r
743 /// <param name="index">インデックスを表す</param>
\r
744 /// <returns>テキストポイント返す</returns>
\r
745 public TextPoint GetLayoutLineFromIndex(int index)
\r
747 return this.LayoutLines.GetTextPointFromIndex(index);
\r
751 /// 指定した座標までスクロールする
\r
753 /// <param name="x"></param>
\r
754 /// <param name="row"></param>
\r
756 /// 範囲外の座標を指定した場合、範囲内に収まるように調整されます
\r
758 public void Scroll(double x, int row)
\r
764 int endRow = this.LayoutLines.Count - 1 - this.LineCountOnScreen;
\r
769 base.TryScroll(x, row);
\r
772 public int AdjustRow(int row, bool isMoveNext)
\r
774 if (this.LayoutLines.FoldingStrategy == null)
\r
776 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
777 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
778 FoldingItem foldingData = this.LayoutLines.FoldingCollection.GetFarestHiddenFoldingData(lineHeadIndex, lineLength);
\r
779 if (foldingData != null && !foldingData.Expand)
\r
781 if (foldingData.End == this.Document.Length)
\r
783 if (isMoveNext && lineHeadIndex > foldingData.Start)
\r
784 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.End) + 1;
\r
786 row = this.LayoutLines.GetLineNumberFromIndex(foldingData.Start);
\r
791 protected override void CalculateClipRect()
\r
793 IEditorRender render = (IEditorRender)base.render;
\r
794 double x, y, width, height;
\r
796 if (this.DrawLineNumber)
\r
798 if (this.render.RightToLeft)
\r
799 x = this.Padding.Left;
\r
801 x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + render.FoldingWidth;
\r
802 width = this.PageBound.Width - this.render.LineNemberWidth - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
\r
806 if (this.render.RightToLeft)
\r
807 x = this.Padding.Left;
\r
809 x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth;
\r
810 width = this.PageBound.Width - this.Padding.Left - this.Padding.Right - render.FoldingWidth - UpdateAreaTotalWidth;
\r
813 y = this.Padding.Top;
\r
814 height = this.PageBound.Height - this.Padding.Top - this.Padding.Bottom;
\r
816 if (this.HideRuler == false)
\r
818 double rulerHeight = this.render.emSize.Height + LineMarkerThickness;
\r
820 height -= rulerHeight;
\r
829 this.render.TextArea = new Rectangle(x, y, width, height);
\r
831 this.LineBreakingMarginWidth = width * 5 / 100;
\r
834 public override void CalculateLineCountOnScreen()
\r
836 if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0)
\r
840 int i = this.Src.Row;
\r
841 int visualCount = this.Src.Row;
\r
844 int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
\r
846 int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row);
\r
847 int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
\r
849 FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineHeadIndex, lineLength);
\r
851 if (foldingData != null && foldingData.End < this.Document.Length - 1 && foldingData.IsHidden(lineHeadIndex))
\r
854 ITextLayout layout = this.LayoutLines.GetLayout(row);
\r
856 double width = layout.Width;
\r
858 if (width > this._LongestWidth)
\r
859 this._LongestWidth = width;
\r
861 double lineHeight = layout.Height;
\r
865 if (y >= this.render.TextArea.Height)
\r
869 this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0);
\r
870 this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
\r
873 void SetCaretPostion(double x, double y)
\r
875 this._CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
\r
878 void FoldingCollection_StatusChanged(object sender, FoldingItemStatusChangedEventArgs e)
\r
880 this.CalculateLineCountOnScreen();
\r
891 double GetRealtiveX(AreaType type)
\r
893 IEditorRender render = (IEditorRender)base.render;
\r
896 case AreaType.UpdateArea:
\r
897 if (this.render.RightToLeft)
\r
898 return this.PageBound.TopRight.X - UpdateAreaTotalWidth;
\r
899 if (this.DrawLineNumber)
\r
900 return this.render.TextArea.X - this.render.LineNemberWidth - render.FoldingWidth - UpdateAreaTotalWidth;
\r
902 return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth;
\r
903 case AreaType.FoldingArea:
\r
904 if (this.render.RightToLeft)
\r
905 return this.PageBound.TopRight.X - render.FoldingWidth;
\r
906 if (this.DrawLineNumber)
\r
907 return this.render.TextArea.X - this.render.LineNemberWidth - render.FoldingWidth;
\r
909 return this.render.TextArea.X - render.FoldingWidth;
\r
910 case AreaType.LineNumberArea:
\r
911 if (this.DrawLineNumber == false)
\r
912 throw new InvalidOperationException();
\r
913 if (this.render.RightToLeft)
\r
914 return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth;
\r
916 return this.render.TextArea.X - this.render.LineNemberWidth;
\r
917 case AreaType.TextArea:
\r
918 return this.render.TextArea.X;
\r
920 throw new ArgumentOutOfRangeException();
\r