OSDN Git Service

読み込み時に行分割を行わず、レタリング時に行分割を行うようにした
authortest <test@yahoo.co.jp>
Sat, 12 Dec 2020 05:37:08 +0000 (14:37 +0900)
committertest <test@yahoo.co.jp>
Sat, 12 Dec 2020 05:37:08 +0000 (14:37 +0900)
17 files changed:
Core/Controller.cs
Core/Direct2D/D2DRenderCommon.cs
Core/Direct2D/MyTextLayout.cs
Core/Document.cs
Core/DummyRender.cs
Core/EditView.cs
Core/ITextRender.cs
Core/LineToIndex.cs
Core/PrintableView.cs
Core/TextPoint.cs
Core/TextServiceFramework/TextStoreHelper.cs
Core/ViewBase.cs
WPF/FooEditEngine/FooTextBox.cs
WPF/FooEditEngine/WPF/TextLayout.cs
WPF/FooEditEngine/WPF/WPFRender.cs
Windows/FooEditEngine/PrintableTextRender.cs
Windows/Test/Form1.cs

index fb5f39f..3907808 100644 (file)
@@ -406,6 +406,13 @@ namespace FooEditEngine
         }
 
         double noti;
+        /// <summary>
+        /// スクロールする
+        /// </summary>
+        /// <param name="dir">方向を指定する</param>
+        /// <param name="delta">ピクセル単位の値でスクロール量を指定する</param>
+        /// <param name="isSelected">選択状態にするなら真</param>
+        /// <param name="withCaret">同時にキャレットを移動させるなら真</param>
         public void ScrollByPixel(ScrollDirection dir,int delta, bool isSelected, bool withCaret)
         {
             if (this.Document.FireUpdateEvent == false)
@@ -413,7 +420,7 @@ namespace FooEditEngine
 
             if (dir == ScrollDirection.Left || dir == ScrollDirection.Right)
             {
-                this.Scroll(dir, delta, isSelected, withCaret);
+                this.View.TryScroll(delta, 0);
                 return;
             }
 
@@ -428,8 +435,18 @@ namespace FooEditEngine
 
                 noti = 0;
 
-                this.Scroll(dir, delta_row, isSelected, withCaret);
+                this.View.TryScroll(0, delta);
             }
+
+            if (withCaret)
+            {
+                //カーソルを適切な位置に移動させる必要がある
+                this.View.AdjustCaretAndSrc();
+                this.SelectWithMoveCaret(isSelected);
+            }
+
+            this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+            this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
         }
 
         /// <summary>
@@ -511,7 +528,10 @@ namespace FooEditEngine
                 if (alignWord)
                     this.AlignNearestWord(MoveFlow);
             }
-            this.View.AdjustCaretAndSrc(AdjustFlow.Col);
+            if(this.Document.LayoutLines.WrapWidth == LineToIndexTable.NONE_BREAK_LINE)
+               this.View.AdjustCaretAndSrc(AdjustFlow.Col);
+            else
+                this.View.AdjustCaretAndSrc(AdjustFlow.Both);
             this.SelectWithMoveCaret(isSelected);
         }
 
@@ -827,14 +847,6 @@ namespace FooEditEngine
         }
 
         /// <summary>
-        /// キャレット位置を既定の位置に戻す
-        /// </summary>
-        public void ResetCaretPostion()
-        {
-            this.JumpCaret(0);
-        }
-
-        /// <summary>
         /// 行単位で移動後のキャレット位置を取得する
         /// </summary>
         /// <param name="count">移動量</param>
@@ -851,12 +863,21 @@ namespace FooEditEngine
 
             row = this.View.AdjustRow(row, count > 0);
 
-            double colpos = this.View.GetColPostionFromIndex(current.row, current.col);
-            int col = this.View.GetIndexFromColPostion(row, colpos);
+            Point pos = this.View.LayoutLines.GetLayout(current.row).GetPostionFromIndex(current.col);
+            int col = this.View.LayoutLines.GetLayout(row).GetIndexFromPostion(pos.X, pos.Y);
 
             return new TextPoint(row, col);
         }
 
+
+        /// <summary>
+        /// キャレット位置を既定の位置に戻す
+        /// </summary>
+        public void ResetCaretPostion()
+        {
+            this.JumpCaret(0);
+        }
+
         /// <summary>
         /// 選択文字列のインデントを一つ増やす
         /// </summary>
index 0cb0117..c0c9ba9 100644 (file)
@@ -789,16 +789,27 @@ namespace FooEditEngine
             }
         }
 
-        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges)
+        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges,double WrapWidth)
         {
             float dpix,dpiy;
             this.GetDpi(out dpix,out dpiy);
 
+            double layoutWidth = this.TextArea.Width;
+            if (WrapWidth != LineToIndexTable.NONE_BREAK_LINE)
+            {
+                this.format.WordWrapping = DW.WordWrapping.Wrap;
+                layoutWidth = WrapWidth;
+            }
+            else
+            {
+                this.format.WordWrapping = DW.WordWrapping.NoWrap;
+            }
+
             bool hasNewLine = str.Length > 0 && str[str.Length - 1] == Document.NewLine;
             MyTextLayout newLayout = new MyTextLayout(D2DRenderShared.DWFactory,
                 str,
                 this.format,
-                this.TextArea.Width,
+                layoutWidth,
                 this.TextArea.Height,
                 dpiy,
                 hasNewLine && this._ShowLineBreak);
@@ -856,6 +867,8 @@ namespace FooEditEngine
                 }
             }
 
+            this.format.WordWrapping = DW.WordWrapping.NoWrap;
+
             return newLayout;
        }
 
index 0a1f90a..ad95683 100644 (file)
@@ -97,17 +97,7 @@ namespace FooEditEngine
         
         public int GetIndexFromColPostion(double x)
         {
-            SharpDX.Mathematics.Interop.RawBool isTrailing, isInsed;
-            DW.HitTestMetrics metrics;
-            metrics = this.layout.HitTestPoint((float)x, 0, out isTrailing, out isInsed);
-            int index;
-            if(isTrailing)
-                index = metrics.TextPosition + metrics.Length;
-            else
-                index = metrics.TextPosition;
-            if (this.ShowLineBreak && index == this.lineBreakIndex + 1) //改行マークの後ろにヒットしたら
-                index--;
-            return index;
+            return this.GetIndexFromPostion(x, 0);
         }
 
         public double GetWidthFromIndex(int index)
@@ -123,10 +113,31 @@ namespace FooEditEngine
 
         public double GetColPostionFromIndex(int index)
         {
+            Point p = this.GetPostionFromIndex(index);
+            return p.X;
+        }
+
+        public int GetIndexFromPostion(double x, double y)
+        {
+            SharpDX.Mathematics.Interop.RawBool isTrailing, isInsed;
+            DW.HitTestMetrics metrics;
+            metrics = this.layout.HitTestPoint((float)x, (float)y, out isTrailing, out isInsed);
+            int index;
+            if (isTrailing)
+                index = metrics.TextPosition + metrics.Length;
+            else
+                index = metrics.TextPosition;
+            if (this.ShowLineBreak && index == this.lineBreakIndex + 1) //改行マークの後ろにヒットしたら
+                index--;
+            return index;
+        }
+
+        public Point GetPostionFromIndex(int index)
+        {
             float x, y;
             DW.HitTestMetrics metrics;
             metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
-            return x;
+            return new Point(x,y);
         }
 
         public int AlignIndexToNearestCluster(int index, AlignDirection flow)
@@ -158,7 +169,7 @@ namespace FooEditEngine
             {
                 if (!double.IsNaN(this._height))
                     return this._height;
-                this._height = Util.RoundUp(layout.Metrics.Height);
+                this._height = Util.RoundUp(this.layout.Metrics.Height);
                 return this._height;
             }
         }
index 6e3993e..5395d20 100644 (file)
@@ -915,7 +915,9 @@ namespace FooEditEngine
                 start--;
 
             if (find_sep_func(str[start]))
+            {
                 start++;
+            }
 
             int end = index;
             while (end < this.Length && !find_sep_func(str[end]))
index 9d78d72..e786e5b 100644 (file)
@@ -135,7 +135,7 @@ namespace FooEditEngine
             throw new NotImplementedException();
         }
 
-        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges)
+        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges, double wrapwidth)
         {
             return new DummyTextLayout();
         }
@@ -228,5 +228,15 @@ namespace FooEditEngine
         {
             this.Disposed = true;
         }
+
+        public Point GetPostionFromIndex(int index)
+        {
+            return new Point();
+        }
+
+        public int GetIndexFromPostion(double x, double y)
+        {
+            return 0;
+        }
     }
 }
index 6a266f0..70990b9 100644 (file)
@@ -253,8 +253,8 @@ namespace FooEditEngine
                 this.DrawLineMarker(this.Document.CaretPostion.row);
 
                 Point pos = this.render.TextArea.TopLeft;
-                //画面上では(X,Y)が開始位置になるが、開始する行が決まっているのでオフセットを求め
-                pos.Y -= this.Src.GetOffsetY(this.render.emSize.Height);
+                //画面上では行をずらして表示す
+                pos.Y += this.Src.OffsetY;
 
                 double endposy = this.render.TextArea.Bottom;
                 Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);
@@ -297,7 +297,7 @@ namespace FooEditEngine
                 //リセットしないと行が正しく描けない
                 pos = this.render.TextArea.TopLeft;
                 pos.X -= this.Src.X;
-                pos.Y -= this.Src.GetOffsetY(this.render.emSize.Height);
+                pos.Y += this.Src.OffsetY;
 
                 this.render.BeginClipRect(this.render.TextArea);
 
@@ -321,7 +321,6 @@ namespace FooEditEngine
                     this.render.DrawOneLine(this.Document, this.LayoutLines, i, pos.X, pos.Y);
 
                     pos.Y += layout.Height;
-                    //pos.Y += this.render.emSize.Height;
                 }
 
                 this.render.EndClipRect();
@@ -418,7 +417,7 @@ namespace FooEditEngine
                 {
                     TextPoint tp = this.GetLayoutLineFromIndex(sel.start);
                     Point left = this.GetPostionFromTextPoint(tp);
-                    double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
+                    double lineHeight = render.emSize.Height;
                     Rectangle InsertRect = new Rectangle(left.X,
                         left.Y,
                         CaretWidthOnInsertMode,
@@ -445,7 +444,7 @@ namespace FooEditEngine
 
             int row = this.Document.CaretPostion.row;
             ITextLayout layout = this.LayoutLines.GetLayout(row);
-            double lineHeight = layout.Height;
+            double lineHeight = render.emSize.Height;
             double charWidth = layout.GetWidthFromIndex(this.Document.CaretPostion.col);
 
             if (this.InsertMode || charWidth == 0)
@@ -522,49 +521,31 @@ namespace FooEditEngine
             //表示領域から探索を始めるのでパディングの分だけ引く
             p.Y -= this.render.TextArea.Y;
 
-            int lineHeadIndex, lineLength;
-
-            if(p.Y >= 0)
+            //p.Y に最も近い行を調べる
+            var t = this.GetNearstRowAndOffsetY(this.Src.Row, p.Y);
+            double relX = 0, relY;
+            if (t == null)
             {
-                double y = 0;
-                tp.row = this.LayoutLines.Count - 1;
-                for (int i = this.Src.Row; i < this.LayoutLines.Count; i++)
+                if(p.Y > 0)
                 {
-                    double height = this.LayoutLines.GetLayout(i).Height;
-
-                    lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
-                    lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
-
-                    if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
-                        continue;
-
-                    if (y + height > p.Y)
-                    {
-                        tp.row = i;
-                        break;
-                    }
-                    y += height;
+                    tp.row = this.LayoutLines.Count - 1;
+                    relY = this.LayoutLines.GetLayout(tp.row).Height - this.render.emSize.Height;
                 }
-            }else{
-                double y = 0;
-                tp.row = 0;
-                for (int i = this.Src.Row; i >= 0; i--)
+                else if(p.Y == 0)
                 {
-                    double height = this.LayoutLines.GetLayout(i).Height;
-
-                    lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
-                    lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
-
-                    if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
-                        continue;
-
-                    if (y - height < p.Y)
-                    {
-                        tp.row = i;
-                        break;
-                    }
-                    y -= height;
+                    tp.row = this.Src.Row;
+                    relY = 0;
                 }
+                else
+                {
+                    tp.row = 0;
+                    relY = 0;
+                }
+            }
+            else
+            {
+                tp.row = t.Item1;
+                relY = t.Item2;    //相対位置がマイナスなので反転させる
             }
 
             if (searchRange == TextPointSearchRange.TextAreaOnly)
@@ -573,9 +554,10 @@ namespace FooEditEngine
                     return tp;
             }
 
-            tp.col = GetIndexFromColPostion(tp.row, p.X);
+            relX = p.X - this.render.TextArea.X;
+            tp.col = this.LayoutLines.GetLayout(tp.row).GetIndexFromPostion(relX,relY);
 
-            lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
+            int lineLength = this.LayoutLines.GetLengthFromLineNumber(tp.row);
             if (tp.col > lineLength)
                 tp.col = lineLength;
 
@@ -583,34 +565,6 @@ namespace FooEditEngine
         }
 
         /// <summary>
-        /// 桁方向の座標に対応するインデックスを取得する
-        /// </summary>
-        /// <param name="row">対象となる行</param>
-        /// <param name="x">テキストエリアからの相対位置</param>
-        /// <returns></returns>
-        public int GetIndexFromColPostion(int row, double x)
-        {
-            x -= this.render.TextArea.X;
-            int lineLength = this.LayoutLines.GetLengthFromLineNumber(row);
-            if (lineLength == 0)
-                return 0;
-            int index = this.LayoutLines.GetLayout(row).GetIndexFromColPostion(this.Src.X + x);
-            return index;
-        }
-
-        /// <summary>
-        /// インデックスに対応する桁方向の座標を得る
-        /// </summary>
-        /// <param name="row">対象となる行</param>
-        /// <param name="index">インデックス</param>
-        /// <returns>テキストエリアからの相対位置を返す</returns>
-        public double GetColPostionFromIndex(int row, int index)
-        {
-            double x = this.LayoutLines.GetLayout(row).GetColPostionFromIndex(index);
-            return x - Src.X + this.render.TextArea.X;
-        }
-
-        /// <summary>
         /// TextPointに対応する座標を得る
         /// </summary>
         /// <param name="tp">レイアウトライン上の位置</param>
@@ -626,8 +580,9 @@ namespace FooEditEngine
                     continue;
                 p.Y += this.LayoutLines.GetLayout(i).Height;
             }
-            p.X = this.GetColPostionFromIndex(tp.row, tp.col);
-            p.Y += this.render.TextArea.Y;
+            Point relP = this.LayoutLines.GetLayout(tp.row).GetPostionFromIndex(tp.col);
+            p.X += relP.X - Src.X + this.render.TextArea.X;
+            p.Y += this.render.TextArea.Y + relP.Y;
             return p;
         }
 
@@ -652,8 +607,8 @@ namespace FooEditEngine
                 return Rectangle.Empty;
             double radius = width / 2;
             Point point = this.GetPostionFromTextPoint(tp);
-            double lineHeight = this.LayoutLines.GetLayout(tp.row).Height;
-            double srcOffsetY = this.Src.GetOffsetY(this.render.emSize.Height); //画面上ではずれているので引く必要がある
+            double lineHeight = this.render.emSize.Height;
+            double srcOffsetY = this.Src.OffsetY; //画面上ではずれているので引く必要がある
 
             Rectangle rect =  new Rectangle(point.X - radius, point.Y + lineHeight - srcOffsetY, width, height);
 
@@ -698,17 +653,17 @@ namespace FooEditEngine
         public bool AdjustSrc(int index)
         {
             TextPoint startTextPoint = this.GetLayoutLineFromIndex(index);
-            double x = this.LayoutLines.GetLayout(startTextPoint.row).GetColPostionFromIndex(startTextPoint.col);
-            if (x < this.Src.X ||
-                x > this.Src.X + this.PageBound.Width)
+            Point relP = this.LayoutLines.GetLayout(startTextPoint.row).GetPostionFromIndex(startTextPoint.col);
+            if (relP.X < this.Src.X ||
+                relP.X > this.Src.X + this.PageBound.Width)
             {
-                this.TryScroll(x, this.Src.Row);
+                this.TryScroll(relP.X, this.Src.Row);
                 return true;
             }
             if (startTextPoint.row < this.Src.Row ||
                 startTextPoint.row > this.Src.Row + this.LineCountOnScreenWithInVisible)
             {
-                this.TryScroll(this.Src.X, startTextPoint.row);
+                this.TryScroll(this.Src.X, startTextPoint.row, relP.Y);
                 return true;
             }
             return false;
@@ -733,10 +688,11 @@ namespace FooEditEngine
             TextPoint tp = this.Document.CaretPostion;
             double x = this.CaretLocation.X;
             double y = this.CaretLocation.Y;
+            Point relPoint = this.LayoutLines.GetLayout(tp.row).GetPostionFromIndex(tp.col);
 
             if (flow == AdjustFlow.Col || flow == AdjustFlow.Both)
             {
-                x = this.LayoutLines.GetLayout(tp.row).GetColPostionFromIndex(tp.col);
+                x = relPoint.X;
 
                 double left = this.Src.X;
                 double right = this.Src.X + this.render.TextArea.Width;
@@ -747,11 +703,11 @@ namespace FooEditEngine
                 }
                 else if (x > right) //xは表示領域の右側にある
                 {
-                    this.Document.Src = new SrcPoint(x - this.render.TextArea.Width + this.ScrollMarginWidth,this.Document.Src.Row,this.Document.Src.Y);
+                    this.Document.Src = new SrcPoint(x - this.render.TextArea.Width + this.ScrollMarginWidth,this.Document.Src.Row,this.Document.Src.OffsetY);
                     if (this.Document.RightToLeft && this.Document.Src.X > 0)
                     {
                         System.Diagnostics.Debug.Assert(x > 0);
-                        this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Document.Src.Y);
+                        this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Document.Src.OffsetY);
                     }
                     else
                     {
@@ -761,10 +717,10 @@ namespace FooEditEngine
                 }
                 else if (x < left)    //xは表示領域の左側にある
                 {
-                    this.Document.Src = new SrcPoint(x - this.ScrollMarginWidth, this.Document.Src.Row, this.Document.Src.Y);
+                    this.Document.Src = new SrcPoint(x - this.ScrollMarginWidth, this.Document.Src.Row, this.Document.Src.OffsetY);
                     if (!this.Document.RightToLeft && this.Document.Src.X < this.render.TextArea.X)
                     {
-                        this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Document.Src.Y);
+                        this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Document.Src.OffsetY);
                     }
                     else
                     {
@@ -777,45 +733,46 @@ namespace FooEditEngine
 
             if (flow == AdjustFlow.Row || flow == AdjustFlow.Both)
             {
-                int caretRow = 0;
-                int lineCount = this.LineCountOnScreenWithInVisible;
-                if (tp.row >= this.Src.Row && tp.row < this.Src.Row + lineCount)
+                //計算量を減らすため
+                if (tp.row < this.Src.Row)
+                    this.Document.Src = new SrcPoint(this.Src.X, tp.row, -relPoint.Y);
+
+                //キャレットのY座標を求める
+                double lineHeight = this.render.emSize.Height;
+                double caret_y = this.Src.OffsetY;  //src.rowからキャレット位置
+                double alignedHeight = (int)(this.render.TextArea.Height / this.render.emSize.Height) * this.render.emSize.Height;
+                for (int i = this.Src.Row; i < tp.row; i++)
                 {
-                    caretRow = tp.row - this.Src.Row;
-                    y = -this.Src.GetOffsetY(this.render.emSize.Height);    //画面上ではずれているので引く必要がある
+                    int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+                    int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+
+                    if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+                        continue;
+                    caret_y += this.LayoutLines.GetLayout(i).Height;
                 }
-                else if (tp.row >= this.Src.Row + lineCount)
+                caret_y += relPoint.Y;
+
+                if (caret_y < 0)
                 {
-                    int srcRow = this.GetSrcRow(tp.row, this.LineCountOnScreen);
-                    this.Document.Src = new SrcPoint(this.Document.Src.X, srcRow, srcRow * this.render.emSize.Height);
-                    caretRow = tp.row - this.Document.Src.Row;
+                    this.Document.Src = new SrcPoint(this.Src.X, tp.row, -relPoint.Y);
                     y = 0;
-                    result = true;
-                    CalculateLineCountOnScreen();
                 }
-                else if (tp.row < this.Src.Row)
+                else if (caret_y >= 0 && caret_y < alignedHeight)
                 {
-                    this.Document.Src = new SrcPoint(this.Document.Src.X, tp.row, tp.row * this.render.emSize.Height);
-                    y = 0;
-                    result = true;
-                    CalculateLineCountOnScreen();
+                    y = caret_y;
                 }
-
-                if (caretRow > 0)
+                else if(caret_y >= alignedHeight)
                 {
-                    for (int i = 0; i < caretRow; i++)
-                    {
-                        int currentRow = this.Src.Row + i;
-                        int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(currentRow);
-                        int lineLength = this.LayoutLines.GetLengthFromLineNumber(currentRow);
-
-                        if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
-                            continue;
-
-                        y += this.LayoutLines.GetLayout(currentRow).Height;
-                    }
+                    double caretYFromTextArea = Math.Min(caret_y - alignedHeight, alignedHeight - lineHeight);
+                    var newsrc = this.GetNearstRowAndOffsetY(tp.row, -caretYFromTextArea);
+                    if(newsrc == null)
+                        this.Document.Src = new SrcPoint(this.Src.X, tp.row, 0);
+                    else
+                        this.Document.Src = new SrcPoint(this.Src.X, newsrc.Item1, -newsrc.Item2);
+                    y = caretYFromTextArea;
                 }
                 y += this.render.TextArea.Y;
+                result = true;
             }
 
             this.SetCaretPostion(x, y);
@@ -828,23 +785,6 @@ namespace FooEditEngine
             return result;
         }
 
-        int GetSrcRow(int row,int count)
-        {
-            if (this.LayoutLines.FoldingStrategy == null)
-                return row - count;
-            for (int i = row; i >= 0; i--)
-            {
-                int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
-                int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
-                if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
-                    continue;
-                if (count <= 0)
-                    return i;
-                count--;
-            }
-            return 0;
-        }
-
         /// <summary>
         /// レイアウト行をテキストポイントからインデックスに変換する
         /// </summary>
@@ -1014,6 +954,24 @@ namespace FooEditEngine
             this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0);
         }
 
+        public override void CalculateWhloeViewPort()
+        {
+            double width = 0, height = 0;
+            for(int i = 0; i < this.LayoutLines.Count; i++)
+            {
+                int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+                int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+
+                if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && i < this.LayoutLines.Count - 1)
+                    continue;
+
+                ITextLayout layout = this.LayoutLines.GetLayout(i);
+                if (width > this._LongestWidth)
+                    this._LongestWidth = width;
+                height += layout.Height;
+            }
+        }
+
         void SetCaretPostion(double x, double y)
         {
             this.CaretLocation = new Point(x + this.PageBound.X, y + this.PageBound.Y);
index 0271ecb..12d3a4d 100644 (file)
@@ -604,7 +604,8 @@ namespace FooEditEngine
         /// <param name="syntaxCollection">ハイライト関連の情報を保持しているコレクション</param>
         /// <param name="MarkerRanges">マーカーを保持しているコレクション。マーカーの開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示しないこと)</param>
         /// <param name="Selections">選択領域を保持しているコレクション。マーカーの開始位置は行の先頭を0とする相対位置としてください(位置が-1の場合表示しないこと)</param>
-        ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> Selections);
+        /// <param name="WrapWidth">折り返しの幅</param>
+        ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> Selections,double WrapWidth);
 
         /// <summary>
         /// グリッパーを描く
index ef32a08..1a44990 100644 (file)
@@ -76,6 +76,23 @@ namespace FooEditEngine
         double GetColPostionFromIndex(int index);
 
         /// <summary>
+        /// 座標に対応するインデックスを取得する
+        /// </summary>
+        /// <param name="x">桁方向の座標</param>
+        /// <param name="y">行方向の座標</param>
+        /// <returns>インデックス</returns>
+        /// <remarks>行番号の幅は考慮されてないのでView以外のクラスは呼び出さないでください</remarks>
+        int GetIndexFromPostion(double x, double y);
+
+        /// <summary>
+        /// インデックスに対応する座標を得る
+        /// </summary>
+        /// <param name="index">インデックス</param>
+        /// <returns>行方向と桁方向の相対座標</returns>
+        /// <remarks>行頭にEOFが含まれている場合、0が返ります</remarks>
+        Point GetPostionFromIndex(int index);
+
+        /// <summary>
         /// 適切な位置にインデックスを調整する
         /// </summary>
         /// <param name="index">インデックス</param>
@@ -232,6 +249,7 @@ namespace FooEditEngine
             this.Document.Markers.Updated += Markers_Updated;
             this._generators[FOLDING_INDEX] = new FoldingGenerator();
             this._generators[SYNTAX_HIGLITHER_INDEX] = new SyntaxHilightGenerator();
+            this.WrapWidth = NONE_BREAK_LINE;
 #if DEBUG && !NETFX_CORE
             if (!Debugger.IsAttached)
             {
@@ -319,6 +337,20 @@ namespace FooEditEngine
         }
 
         /// <summary>
+        /// ピクセル単位で折り返すかどうか
+        /// </summary>
+        public double WrapWidth
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// 行を折り返さないことを表す
+        /// </summary>
+        public const double NONE_BREAK_LINE = -1;
+
+        /// <summary>
         /// 保持しているレイアウトキャッシュをクリアーする
         /// </summary>
         public void ClearLayoutCache()
@@ -651,7 +683,7 @@ namespace FooEditEngine
             LineToIndexTableData lineData = this.Lines[row];
             if (lineData.Length == 0)
             {
-                layout = this.render.CreateLaytout("", null, null, null);
+                layout = this.render.CreateLaytout("", null, null, null,this.WrapWidth);
             }
             else
             {
@@ -674,7 +706,7 @@ namespace FooEditEngine
                                   let n = Util.ConvertAbsIndexToRelIndex(s, lineHeadIndex, lineData.Length)
                                   select n;
 
-                layout = this.render.CreateLaytout(content, lineData.Syntax, markerRange, selectRange);
+                layout = this.render.CreateLaytout(content, lineData.Syntax, markerRange, selectRange,this.WrapWidth);
             }
 
             return layout;
index 6604270..5d808cc 100644 (file)
@@ -40,11 +40,8 @@ namespace FooEditEngine
                 this.Hilighter.Reset();
 
             Point pos = this.render.TextArea.TopLeft;
-            pos.X -= Src.X;
-
-            int endRow = Math.Min(this.LayoutLines.Count - 1, Src.Row + this.LineCountOnScreen - 1);
-
-            Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);
+            pos.X = Src.X;
+            pos.Y = 0;
 
             IPrintableTextRender render = (IPrintableTextRender)this.render;
 
@@ -52,24 +49,32 @@ namespace FooEditEngine
             if (this.Header != null && this.Header != string.Empty)
             {
                 this.render.DrawString(this.Header, pos.X, pos.Y, StringAlignment.Center,
-                    new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea),render.FooterHeight));
-
+                    new Size(render.TextArea.Width - this.GetRealtiveX(AreaType.TextArea), render.FooterHeight));
                 pos.Y += (int)render.HeaderHeight;
             }
 
             //レイアウト行を印刷する
-            for (int i = Src.Row; i <= endRow; i++)
+            Rectangle contentArea = new Rectangle(pos.X, pos.Y, this.PageBound.Width, this.render.TextArea.Height);
+            this.render.BeginClipRect(contentArea);
+
+            Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height);
+            for (int i = Src.Row; pos.Y <= this.render.TextArea.Bottom; i++)
             {
-                double lineHeight = this.LayoutLines.GetLayout(i).Height;
+                if (i >= this.LayoutLines.Count)
+                    break;
 
-                this.render.DrawOneLine(this.Document, this.LayoutLines,i, pos.X + this.render.TextArea.X, pos.Y);
+                double layoutHeight = this.LayoutLines.GetLayout(i).Height;
 
+                this.render.DrawOneLine(this.Document, this.LayoutLines, i, pos.X + this.render.TextArea.X, pos.Y + this.Src.OffsetY);
                 if (this.Document.DrawLineNumber)
-                    this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize);
+                    this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y + this.Src.OffsetY, StringAlignment.Right, lineNumberSize);
+
+                pos.Y += layoutHeight;
 
-                pos.Y += lineHeight;
             }
 
+            this.render.EndClipRect();
+
             //フッターを印刷する
             if (this.Footer != null && this.Footer != string.Empty)
             {
@@ -83,7 +88,8 @@ namespace FooEditEngine
 
         public bool TryPageDown()
         {
-            return base.TryScroll(this.Src.X, this.Src.Row + this.LineCountOnScreen);
+            double alignedPage = (int)(this.render.TextArea.Height / this.render.emSize.Height) * this.render.emSize.Height;
+            return base.TryScroll(this.Src.X, alignedPage);
         }
 
         protected override void CalculateClipRect()
@@ -125,25 +131,6 @@ namespace FooEditEngine
 
         public override void CalculateLineCountOnScreen()
         {
-            if (this.LayoutLines.Count == 0)
-                return;
-
-            double y = 0;
-            int i = this.Src.Row;
-            for (; true; i++)
-            {
-                int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1;
-
-                ITextLayout layout = this.LayoutLines.GetLayout(row);
-
-                double lineHeight = layout.Height;
-
-                y += lineHeight;
-
-                if (y >= this.render.TextArea.Height)
-                    break;
-            }
-            this.LineCountOnScreen = Math.Max(i - this.Src.Row - 1, 0); //ループを抜けると+1されている
         }
 
         enum AreaType
index 7e32fbe..deed4c1 100644 (file)
@@ -16,18 +16,14 @@ namespace FooEditEngine
     {
         public double X;
         public int Row;
-        public double Y;
-        public double GetOffsetY(double line_height)
-        {
-            return this.Row * line_height - this.Y;
-        }
+        public double OffsetY;
         public SrcPoint(double x, int row, double y)
         {
             if (row < 0)
                 throw new ArgumentOutOfRangeException("マイナスを値を指定することはできません");
             this.X = x;
             this.Row = row;
-            this.Y = y;
+            this.OffsetY = y;
         }
     }
 
index 21541dc..f6508f2 100644 (file)
@@ -63,7 +63,7 @@ namespace FooEditEngine
             endTextPoint = view.GetLayoutLineFromIndex(endIndex);
             endPos = view.GetPostionFromTextPoint(endTextPoint);
             //アンダーラインを描くことがあるので少しずらす
-            endPos.Y += view.LayoutLines.GetLayout(endTextPoint.row).Height + 5;
+            endPos.Y += view.render.emSize.Height + 5;
         }
 
         public static void GetSelection(Controller controller, SelectCollection selectons, out TextRange sel)
index 0107448..14e116c 100644 (file)
@@ -79,7 +79,7 @@ namespace FooEditEngine
 
         Document _Document;
         protected Rectangle _Rect;
-        protected double _LongestWidth;
+        protected double _LongestWidth,_LongestHeight;
         Padding _Padding;
 
         public ViewBase(Document doc, ITextRender r,Padding padding)
@@ -125,6 +125,7 @@ namespace FooEditEngine
 
         private void _Document_PerformLayouted(object sender, EventArgs e)
         {
+            CalculateWhloeViewPort();
             CalculateLineCountOnScreen();
             if(this.PerformLayouted != null)
                 this.PerformLayouted(this, e);
@@ -146,6 +147,7 @@ namespace FooEditEngine
                 this.render.ShowTab = this.Document.ShowTab;
             if (this.render.ShowLineBreak != this.Document.ShowLineBreak)
                 this.render.ShowLineBreak = this.Document.ShowLineBreak;
+            CalculateWhloeViewPort();
             CalculateClipRect();
             CalculateLineCountOnScreen();
             this._LayoutLines.ClearLayoutCache();
@@ -153,10 +155,14 @@ namespace FooEditEngine
 
         private void Document_LineBreakChanged(object sender, EventArgs e)
         {
-            if (this.Document.LineBreak != LineBreakMethod.None)
-                this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByPixelbase);
+            if (this.Document.LineBreak == LineBreakMethod.PageBound)
+                this._LayoutLines.WrapWidth = this.render.TextArea.Width - LineBreakingMarginWidth;  //余白を残さないと欠ける
+            else if (this.Document.LineBreak == LineBreakMethod.CharUnit)
+                this._LayoutLines.WrapWidth = this.render.emSize.Width * this.Document.LineBreakCharCount;
             else
-                this._LayoutLines.SpilitString = new SpilitStringEventHandler(LayoutLines_SpilitStringByChar);
+                this._LayoutLines.WrapWidth = LineToIndexTable.NONE_BREAK_LINE;
+
+            this._LayoutLines.ClearLayoutCache();
         }
 
         protected LineToIndexTable _LayoutLines
@@ -191,7 +197,7 @@ namespace FooEditEngine
             get;
             protected set;
         }
-
+        
         /// <summary>
         /// 折り返し時の右マージン
         /// </summary>
@@ -217,6 +223,11 @@ namespace FooEditEngine
             get { return this._LongestWidth; }
         }
 
+        public double LongestHeight
+        {
+            get { return this._LongestHeight; }
+        }
+
         public double LineNumberMargin
         {
             get
@@ -296,17 +307,101 @@ namespace FooEditEngine
             return;
         }
 
-        public virtual bool TryScroll(double x, int row)
+        /// <summary>
+        /// スクロールを試行する
+        /// </summary>
+        /// <param name="x">X座標</param>
+        /// <param name="row">行</param>
+        /// <param name="rel_y">各行の左上を0とするY座標</param>
+        /// <returns>成功すれば偽、そうでなければ真</returns>
+        public virtual bool TryScroll(double x, int row,double rel_y = 0)
         {
             if (row < 0)
                 return true;
             if (row > this.LayoutLines.Count - 1)
                 return true;
-            this.Document.Src = new SrcPoint(x, row, row * this.render.emSize.Height);
+            double abs_y = 0;
+            for (int i = 0; i < row; i++)
+                abs_y += this.LayoutLines.GetLayout(i).Height;
+            this.Document.Src = new SrcPoint(x, row, rel_y);
             this.SrcChanged(this,null);
             return false;
         }
 
+        /// <summary>
+        /// スクロールを試行する
+        /// </summary>
+        /// <param name="offset_x">X方向の移動量</param>
+        /// <param name="offset_y">Y方向の移動量</param>
+        /// <returns>成功すれば偽、そうでなければ真</returns>
+        public virtual bool TryScroll(double offset_x,double offset_y)
+        {
+            double x = this.Document.Src.X - offset_x;
+            if (x < 0)
+                return true;
+            var t = GetNearstRowAndOffsetY(this.Document.Src.Row, -this.Document.Src.OffsetY + offset_y);
+            if (t == null)
+                return true;
+            this.Document.Src = new SrcPoint(x, t.Item1, -t.Item2);
+            return false;
+        }
+
+        /// <summary>
+        /// srcRowを起点としてrect_heightが収まる行とオフセットYを求めます
+        /// </summary>
+        /// <param name="srcRow">起点となる行</param>
+        /// <param name="rect_hight">Y方向のバウンディングボックス</param>
+        /// <returns>失敗した場合、NULL。成功した場合、行とオフセットY</returns>
+        public Tuple<int,double> GetNearstRowAndOffsetY(int srcRow, double rect_hight)
+        {
+            if (rect_hight > 0)
+            {
+                for (int i = srcRow; i < this.Document.LayoutLines.Count; i++)
+                {
+                    ITextLayout layout = this.Document.LayoutLines.GetLayout(i);
+
+                    int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+                    int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+                    double layoutHeight = layout.Height;
+
+                    if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+                        continue;
+
+                    if (rect_hight == 0)
+                        return new Tuple<int, double>(i, 0);
+
+                    if (rect_hight - layoutHeight < 0)
+                        return new Tuple<int, double>(i, rect_hight);
+
+                    rect_hight -= layoutHeight;
+                }
+            }
+            else if(rect_hight < 0)
+            {
+                for (int i = srcRow - 1; i >= 0; i--)
+                {
+                    ITextLayout layout = this.Document.LayoutLines.GetLayout(i);
+
+                    int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i);
+                    int lineLength = this.LayoutLines.GetLengthFromLineNumber(i);
+                    double layoutHeight = layout.Height;
+
+                    if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex))
+                        continue;
+
+                    if(rect_hight == 0)
+                        return new Tuple<int, double>(i, 0);
+
+                    if (rect_hight + layoutHeight >= 0)
+                        return new Tuple<int, double>(i, layoutHeight + rect_hight);
+
+                    rect_hight += layoutHeight;
+                }
+                return new Tuple<int, double>(0, 0);
+            }
+            return null;
+        }
+
         public void Dispose()
         {
             this.Dispose(true);
@@ -317,6 +412,10 @@ namespace FooEditEngine
         {
         }
 
+        public virtual void CalculateWhloeViewPort()
+        {
+        }
+
         protected virtual void Dispose(bool disposing)
         {
             if (disposing)
@@ -357,7 +456,7 @@ namespace FooEditEngine
 
         void render_ChangedRightToLeft(object sender, EventArgs e)
         {
-            this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Src.Y);
+            this.Document.Src = new SrcPoint(0, this.Document.Src.Row, this.Src.OffsetY);
         }
 
         void render_ChangedRenderResource(object sender, ChangedRenderRsourceEventArgs e)
@@ -367,6 +466,7 @@ namespace FooEditEngine
             {
                 this.CalculateClipRect();
                 this.CalculateLineCountOnScreen();
+                this.CalculateWhloeViewPort();
             }
         }
 
@@ -380,25 +480,6 @@ namespace FooEditEngine
             }
         }
 
-        IList<LineToIndexTableData> LayoutLines_SpilitStringByPixelbase(object sender, SpilitStringEventArgs e)
-        {
-            double WrapWidth;
-            if (this.Document.LineBreak == LineBreakMethod.PageBound)
-                WrapWidth = this.render.TextArea.Width - LineBreakingMarginWidth;  //余白を残さないと欠ける
-            else
-                WrapWidth = this.render.emSize.Width * this.Document.LineBreakCharCount;
-
-            if (WrapWidth < 0 && this.Document.LineBreak != LineBreakMethod.None)
-                throw new InvalidOperationException();
-
-            int startIndex = e.index;
-            int endIndex = e.index + e.length - 1;
-
-            LineToIndexTable layoutLineCollection = (LineToIndexTable)sender;
-
-            return this.render.BreakLine(e.buffer,layoutLineCollection, startIndex, endIndex, WrapWidth);
-        }
-
         IList<LineToIndexTableData> LayoutLines_SpilitStringByChar(object sender, SpilitStringEventArgs e)
         {
             return this.Document.CreateLineList(e.index, e.length, Document.MaximumLineLength);
index 88ad07a..4b63ed3 100644 (file)
@@ -191,9 +191,9 @@ namespace FooEditEngine.WPF
             this.verticalScrollBar = this.GetTemplateChild("PART_VerticalScrollBar") as ScrollBar;
             if (this.verticalScrollBar != null)
             {
-                this.verticalScrollBar.SmallChange = 1;
-                this.verticalScrollBar.LargeChange = 10;
-                this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
+                this.verticalScrollBar.SmallChange = this.View.render.emSize.Height;
+                this.verticalScrollBar.LargeChange = this.View.render.emSize.Height * 10;
+                this.verticalScrollBar.Maximum = this.View.LongestHeight;
                 this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll);
             }
         }
@@ -397,6 +397,7 @@ namespace FooEditEngine.WPF
                 TextStoreHelper.NotifyTextChanged(this.textStore, 0, 0, this.Document.Length);
                 if (this.verticalScrollBar != null)
                     this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
+                this.View.CalculateWhloeViewPort();
                 this.View.CalculateLineCountOnScreen();
                 this.IsEnabled = true;
                 this.Refresh(this.View.PageBound);
@@ -1163,18 +1164,18 @@ namespace FooEditEngine.WPF
                 toX = this.horizontalScrollBar.Value;
             else
                 toX = -this.horizontalScrollBar.Value;
-            this._Controller.Scroll(toX, this.View.Src.Row, false, false);
+            this.Controller.ScrollByPixel(ScrollDirection.Left, (int)toX, false, false);
             this.Refresh();
         }
 
+        double oldScrollValueY = 0;
         void verticalScrollBar_Scroll(object sender, ScrollEventArgs e)
         {
             if (this.verticalScrollBar == null)
                 return;
-            int newRow = (int)this.verticalScrollBar.Value;
-            if (newRow >= this.View.LayoutLines.Count)
-                return;
-            this._Controller.Scroll(this.View.Src.X,newRow, false, false);
+            double delta =  e.NewValue - oldScrollValueY;
+            oldScrollValueY = e.NewValue;
+            this.Controller.ScrollByPixel(ScrollDirection.Up, (int)delta, false, false);
             this.Refresh();
         }
 
@@ -1184,7 +1185,7 @@ namespace FooEditEngine.WPF
                 return;
             EditView view = this.View;
             if (view.Src.Row > this.verticalScrollBar.Maximum)
-                this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;
+                this.verticalScrollBar.Maximum += this.View.render.emSize.Height * 100 + 1;
             double absoulteX = Math.Abs(view.Src.X);
             if(absoulteX > this.horizontalScrollBar.Maximum)
                 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;
@@ -1306,7 +1307,7 @@ namespace FooEditEngine.WPF
             this._Document.AutoComplete.GetPostion = (tp, edoc) =>
             {
                 var p = this.View.GetPostionFromTextPoint(tp);
-                int height = (int)doc.LayoutLines.GetLayout(edoc.CaretPostion.row).Height;
+                int height = (int)this.Render.emSize.Height;
                 p.Y += height;
                 return PointToScreen(this.TranslatePoint(p.Scale(Util.GetScale()), this));
             };
index a0e6c24..d7ed60a 100644 (file)
@@ -102,7 +102,12 @@ namespace FooEditEngine.WPF
                 }
             }
 
-            this.lines[0].Draw(dc, new System.Windows.Point(x, y), InvertAxes.None);
+            double posY = y;
+            foreach(var line in this.lines)
+            {
+                line.Draw(dc, new System.Windows.Point(x, posY), InvertAxes.None);
+                posY += line.Height;
+            }
         }
 
         public void Dispose()
@@ -145,14 +150,32 @@ namespace FooEditEngine.WPF
             }
         }
 
+        double _actualWidth = 0;
         public double Width
         {
-            get { return this.Lines[0].Width; }
+            get
+            {
+                if (_actualWidth != 0)
+                    return _actualWidth;
+                foreach (var line in this.Lines)
+                {
+                    if(line.Width > _actualWidth)
+                        _actualWidth = line.Width;
+                }
+                return _actualWidth;
+            }
         }
 
+        double _height = 0;
         public double Height
         {
-            get { return this.Lines[0].Height; }
+            get {
+                if (_height != 0)
+                    return _height;
+                foreach (var line in this.Lines)
+                    _height += line.Height;
+                return _height;
+            }
         }
 
         public int GetIndexFromColPostion(double x)
@@ -172,6 +195,16 @@ namespace FooEditEngine.WPF
             return this.Lines[0].GetDistanceFromCharacterHit(new CharacterHit(index, 0));
         }
 
+        public int GetIndexFromPostion(double x, double y)
+        {
+            return 0;
+        }
+
+        public Point GetPostionFromIndex(int index)
+        {
+            throw new NotImplementedException();
+        }
+
         public int AlignIndexToNearestCluster(int index, AlignDirection flow)
         {
             CharacterHit hit = this.Lines[0].GetNextCaretCharacterHit(new CharacterHit(index, 0));
index 330e162..f0deeaf 100644 (file)
@@ -489,10 +489,12 @@ namespace FooEditEngine.WPF
 
         public void BeginClipRect(Rectangle rect)
         {
+            this.Context.PushClip(new RectangleGeometry(rect));
         }
 
         public void EndClipRect()
         {
+            this.Context.Pop();
         }
 
         public List<LineToIndexTableData> BreakLine(Document doc, LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double wrapwidth)
@@ -534,10 +536,19 @@ namespace FooEditEngine.WPF
             return output;
         }
 
-        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges)
+        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> SelectRanges, double wrapwidth)
         {
-            TextLayout layout = new TextLayout(str,this.FontFamily,this.FontSize,Brushes[this.Foreground],this.TextArea.Width);
-            layout.TextWarpping = TextWrapping.NoWrap;
+            TextLayout layout;
+            if(wrapwidth == LineToIndexTable.NONE_BREAK_LINE)
+            {
+                layout = new TextLayout(str, this.FontFamily, this.FontSize, Brushes[this.Foreground], this.TextArea.Width);
+                layout.TextWarpping = TextWrapping.NoWrap;
+            }
+            else
+            {
+                layout = new TextLayout(str, this.FontFamily, this.FontSize, Brushes[this.Foreground], wrapwidth);
+                layout.TextWarpping = TextWrapping.Wrap;
+            }
             layout.FlowDirection = this.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
 
             if (syntaxCollection != null)
index 69706ae..72281c1 100644 (file)
@@ -6,14 +6,38 @@ namespace FooEditEngine.Windows
 {
     class PrintableTextLayout : ITextLayout
     {
-        public PrintableTextLayout(Font font)
+        List<String> lines = new List<string>();
+        Font font;
+        StringFormat sf;
+        public PrintableTextLayout(Font font, Graphics g, StringFormat sf, double maxwidth,String str)
         {
             this.Disposed = false;
+            this.sf = sf;
+            this.font = font;
             this.Height = font.Height;
+
+            if (maxwidth == LineToIndexTable.NONE_BREAK_LINE)
+            {
+                lines.Add(str);
+                return;
+            }
+
+            int fitlen, index = 0;
+            do
+            {
+                int linesFilled;
+                SizeF metrics = g.MeasureString(str.Substring(index), font, new SizeF((float)maxwidth, font.Height + 1), sf, out fitlen, out linesFilled);
+                if (metrics.Width > Width)
+                    this.Width = metrics.Width;
+                this.Height += metrics.Height;
+                lines.Add(str.Substring(index, fitlen));
+                index += fitlen;
+            } while (index < str.Length);
         }
         public double Width
         {
-            get { return 0; }
+            get;
+            private set;
         }
 
         public double Height
@@ -57,6 +81,27 @@ namespace FooEditEngine.Windows
         {
             this.Disposed = true;
         }
+
+        public int GetIndexFromPostion(double x, double y)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Point GetPostionFromIndex(int index)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void Draw(Graphics g,double x, double y,System.Drawing.Color fore)
+        {
+            double posy = y;
+            foreach(string line in this.lines)
+            {
+                g.DrawString(line, this.font, new SolidBrush(fore), new PointF((float)x, (float)posy), this.sf);
+                var size = g.MeasureString(line,this.font);
+                posy += size.Height;
+            }
+        }
     }
     class PrintableTextRender : IPrintableTextRender
     {
@@ -89,7 +134,7 @@ namespace FooEditEngine.Windows
 
         public ITextLayout CreateLaytout(string str)
         {
-            return new PrintableTextLayout(this.font);
+            return new PrintableTextLayout(this.font,this.g,this.sf,(float)LineToIndexTable.NONE_BREAK_LINE ,str);
         }
 
         public float HeaderHeight { get { return this.font.Height; } }
@@ -139,7 +184,8 @@ namespace FooEditEngine.Windows
         {
             get
             {
-                return new Size(0, 0);
+                SizeF metrics = g.MeasureString("0", this.font, Int16.MaxValue, this.sf);
+                return new Size(metrics.Width, metrics.Height);
             }
         }
 
@@ -185,16 +231,19 @@ namespace FooEditEngine.Windows
         }
 
         public void DrawOneLine(Document doc,LineToIndexTable lti, int row, double x, double y)
-        {           
-            g.DrawString(lti[row], this.font, new SolidBrush(this.Foreground), new RectangleF((float)x, (float)y, (float)this.TextArea.Width, (float)this.TextArea.Height), this.sf);
+        {
+            PrintableTextLayout layout = (PrintableTextLayout)lti.GetLayout(row);
+            layout.Draw(g, x, y, this.Foreground);
         }
 
         public void BeginClipRect(Rectangle rect)
         {
+            g.Clip = new Region(rect);
         }
 
         public void EndClipRect()
         {
+            g.Clip = new Region();
         }
 
         public void FillRectangle(Rectangle rect, FillRectType type)
@@ -205,11 +254,6 @@ namespace FooEditEngine.Windows
         {
         }
 
-        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> Selections)
-        {
-            return new PrintableTextLayout(this.font);
-        }
-
         public List<LineToIndexTableData> BreakLine(Document doc, LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double maxwidth)
         {
             List<LineToIndexTableData> output = new List<LineToIndexTableData>();
@@ -253,6 +297,11 @@ namespace FooEditEngine.Windows
             throw new NotImplementedException();
         }
 
+        public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges, IEnumerable<Selection> Selections, double WrapWidth)
+        {
+            return new PrintableTextLayout(this.font, this.g, this.sf, WrapWidth, str);
+        }
+
         public System.Drawing.Color Foreground
         {
             get;
index ebab1c3..81cd310 100644 (file)
@@ -20,6 +20,8 @@ namespace Test.Windows
             this.fooTextBox1.ShowTab = true;
             this.fooTextBox1.ShowFullSpace = true;
             this.fooTextBox1.ShowLineBreak = true;
+            this.fooTextBox1.LineBreakMethod = LineBreakMethod.CharUnit;
+            this.fooTextBox1.LineBreakCharCount = 10;
             var collection = new CompleteCollection<ICompleteItem>();
             collection.Add(new CompleteWord("int"));
             collection.Add(new CompleteWord("float"));