]> O.S.I.I.S - jp/crow.git/commitdiff
Crow.Text namespace, new TextBox using TextChange structure
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 28 Jan 2021 08:38:30 +0000 (09:38 +0100)
committerj-p <jp_bruyere@hotmail.com>
Sat, 6 Feb 2021 19:28:02 +0000 (20:28 +0100)
18 files changed:
Crow/Crow.csproj
Crow/src/EventArgs/TextChangeEventArgs.cs
Crow/src/ExtensionsMethods.cs
Crow/src/IML/Instantiator.cs
Crow/src/Interface.cs
Crow/src/Text/CharLocation.cs [new file with mode: 0644]
Crow/src/Text/Text.cs [new file with mode: 0644]
Crow/src/Text/TextChange.cs [new file with mode: 0644]
Crow/src/Text/TextLine.cs [new file with mode: 0644]
Crow/src/Text/TextLineCollection.cs [new file with mode: 0644]
Crow/src/Text/TextSpan.cs [new file with mode: 0644]
Crow/src/Widgets/Label.cs
Crow/src/Widgets/OldLabel.cs
Crow/src/Widgets/OldTextBox.cs
Crow/src/Widgets/TextBox.cs
Crow/src/Widgets/Widget.cs
Samples/PerfTests/Program.cs
Samples/PerfTests/Properties/launchSettings.json

index ce2bd530180a78abf2124313316fb8b8592a1206..a3c9e80590e6d99add03de64cc2084c1280e7622 100644 (file)
@@ -23,7 +23,7 @@
                <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
                <GenerateDocumentationFile>true</GenerateDocumentationFile>
                <NoWarn>$(NoWarn);1591;1587;1570;1572;1573;1574</NoWarn>
-               <DefineConstants>DESIGN_MODE;MEASURE_TIME</DefineConstants>             
+               <DefineConstants>_DESIGN_MODE;_MEASURE_TIME</DefineConstants>           
                <EnableDefaultItems>false</EnableDefaultItems>
                <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
                <AppConfig>App.config</AppConfig>
index 33ca405cc9943ff2b4fe7ec1d7c91a06e5d68009..a51ce29f6c5ae3c4a7cca31157d97cbbe3e67cb1 100644 (file)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+using Crow.Text;
 using System;
 
 namespace Crow
 {
        public class TextChangeEventArgs: EventArgs
        {
-               public String Text;
+               public TextChange Change;
 
-               public TextChangeEventArgs (string _newValue) : base()
+               public TextChangeEventArgs (TextChange _newValue) : base()
                {
-                       Text = _newValue;
+                       Change = _newValue;
                }
        }
 }
index a40b25fc5d0a42e862203c166f7d7c0cef344e74..4961ea907feafcd31d8a2f7e2d9d7a31831880b9 100644 (file)
@@ -2,6 +2,7 @@
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
+using Crow.Text;
 using System;
 using System.IO;
 using System.Linq;
@@ -196,24 +197,24 @@ namespace Crow
 
                internal static bool IsAnyLineBreakCharacter (this char c) 
                        => c == '\n' || c == '\r' || c == '\u0085' || c == '\u2028' || c == '\u2029';
-               internal static ReadOnlySpan<char> GetLine (this string str, LineSpan ls) {
+               internal static ReadOnlySpan<char> GetLine (this string str, TextLine ls) {
                        if (ls.Start >= str.Length)
                                return "".AsSpan ();
                        return str.AsSpan ().Slice (ls.Start, ls.Length);                               
                }
-               internal static ReadOnlySpan<char> GetLine (this string str, LineSpan ls, int offset) {
+               internal static ReadOnlySpan<char> GetLine (this string str, TextLine ls, int offset) {
                        int start = ls.Start + offset;
                        if (start >= str.Length)
                                return "".AsSpan ();
                        return str.AsSpan ().Slice (start, ls.Length);
                                
                }
-               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, LineSpan ls) {
+               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, TextLine ls) {
                        if (ls.Start >= str.Length)
                                return "".AsSpan ();
                        return str.AsSpan ().Slice (ls.Start, ls.LengthIncludingLineBreak);
                }
-               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, LineSpan ls, int offset) {
+               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, TextLine ls, int offset) {
                        int start = ls.Start + offset;
                        if (start >= str.Length)
                                return "".AsSpan ();
index 12a8bef23c409992456d4c113f97e0107d269095..3a249a1ed0aea8bb5291cd13d6c7b124b2a8a498 100644 (file)
@@ -231,11 +231,7 @@ namespace Crow.IML {
                        ctx.curLine += li.LineNumber - 1;
                        #endif
 
-                       string tmpXml = reader.ReadOuterXml ();
-
-
-                       XmlTextReader r = reader as XmlTextReader;
-                       
+                       string tmpXml = reader.ReadOuterXml ();                 
 
                        if (ctx.nodesStack.Peek().HasTemplate)
                                emitTemplateLoad (ctx, tmpXml);
index 11417dec8e0832766add3e6e24ffe907633b46b1..1c55ad3823dd73f86ff67b8a34d812349be03ed9 100644 (file)
@@ -209,7 +209,7 @@ namespace Crow
 
                #endregion
 
-               public string WindowTitle {
+               public string WindowTitle {                     
                        set => Glfw3.SetWindowTitle (hWin, value);
                }
 
@@ -219,7 +219,6 @@ namespace Crow
                }
                public virtual void InterfaceThread ()
                {
-
                        while (!Glfw3.WindowShouldClose (hWin)) {
                                Update ();
                                Thread.Sleep (UPDATE_INTERVAL);
@@ -767,9 +766,9 @@ namespace Crow
 
                                DiscardQueue = new Queue<LayoutingQueueItem> (LayoutingQueue.Count);
                                //Debug.WriteLine ("======= Layouting queue start =======");
-                               LayoutingQueueItem lqi;
+                                                               
                                while (LayoutingQueue.Count > 0) {
-                                       lqi = LayoutingQueue.Dequeue ();
+                                       LayoutingQueueItem lqi = LayoutingQueue.Dequeue ();
                                        lqi.ProcessLayouting ();
                                }
                                LayoutingQueue = DiscardQueue;
diff --git a/Crow/src/Text/CharLocation.cs b/Crow/src/Text/CharLocation.cs
new file mode 100644 (file)
index 0000000..8a8b978
--- /dev/null
@@ -0,0 +1,35 @@
+using System;
+using System.Diagnostics;
+
+namespace Crow.Text
+{
+    [DebuggerDisplay ("{Line}, {Column}, {VisualCharXPosition}")]
+       public struct CharLocation : IEquatable<CharLocation>
+       {
+               public readonly int Line;
+               public int Column;
+               public double VisualCharXPosition;
+               public CharLocation (int line, int column, double visualX = -1) {
+                       Line = line;
+                       Column = column;
+                       VisualCharXPosition = visualX;
+               }
+               public bool HasVisualX => Column >= 0 && VisualCharXPosition >= 0;
+               
+               public static bool operator == (CharLocation a, CharLocation b)
+                       => a.Equals (b);
+               public static bool operator != (CharLocation a, CharLocation b)
+                       => !a.Equals (b);
+               public bool Equals (CharLocation other) {
+                       return Column < 0 ?
+                               Line == other.Line && VisualCharXPosition == other.VisualCharXPosition :
+                               Line == other.Line && Column == other.Column;
+               }
+               public override bool Equals (object obj) => obj is CharLocation loc ? Equals (loc) : false;
+               public override int GetHashCode () {
+                       return Column < 0 ?
+                               HashCode.Combine (Line, VisualCharXPosition) :
+                               HashCode.Combine (Line, Column);
+               }
+       }
+}
diff --git a/Crow/src/Text/Text.cs b/Crow/src/Text/Text.cs
new file mode 100644 (file)
index 0000000..4ebb6e5
--- /dev/null
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Crow.Text
+{
+    public class Text
+    {
+        char[] buffer;
+               int length;
+        TextLine[] lines;
+
+               public Text (string text, int capacity = -1) {
+                       if (string.IsNullOrEmpty (text)) {
+                               buffer = new char[capacity > 0 ? capacity : 0];
+                               length = 0;
+                       } else {
+                               if (capacity >= text.Length) {
+                                       buffer = new char[capacity];
+                                       text.AsSpan ().CopyTo (buffer.AsSpan ());
+                               } else
+                                       buffer = text.ToCharArray ();
+
+                               length = text.Length;
+                               updateLines ();
+                       }
+        }
+               public Text (int capacity) {
+                       buffer = new char[capacity];
+                       length = 0;
+        }
+
+               void updateLines () {
+                       if (length == 0) {
+                               lines = new TextLine[] { new TextLine (0, 0, 0) };
+                               return;
+                       }
+
+                       List<TextLine> _lines = new List<TextLine> ();
+                       int start = 0, i = 0;
+                       while (i < length) {
+                               char c = buffer[i];
+                               if (c == '\r') {
+                                       if (++i < length) {
+                                               if (buffer[i] == '\n')
+                                                       _lines.Add (new TextLine (start, i - 1, ++i));
+                                               else
+                                                       _lines.Add (new TextLine (start, i - 1, i));
+                                       } else
+                                               _lines.Add (new TextLine (start, i - 1, i));
+                                       start = i;
+                               } else if (c == '\n') {
+                                       if (++i < length) {
+                                               if (buffer[i] == '\r')
+                                                       _lines.Add (new TextLine (start, i - 1, ++i));
+                                               else
+                                                       _lines.Add (new TextLine (start, i - 1, i));
+                                       } else
+                                               _lines.Add (new TextLine (start, i - 1, i));
+                                       start = i;
+
+                               } else if (c == '\u0085' || c == '\u2028' || c == '\u2029')
+                                       _lines.Add (new TextLine (start, i - 1, i));
+                               else
+                                       i++;
+                       }
+
+                       if (start < i)
+                               _lines.Add (new TextLine (start, length, length));
+                       else
+                               _lines.Add (new TextLine (length, length, length));
+
+                       lines = _lines.ToArray ();
+               }
+
+               public void Append (ReadOnlySpan<char> str) {
+                       
+                       if (length + str.Length > buffer.Length) {
+                               char[] newbuff = new char[length + str.Length];
+                               Span<char> tmp = newbuff.AsSpan ();
+                               buffer.AsSpan ().CopyTo (tmp);
+                               str.CopyTo (tmp.Slice (length));
+                               buffer = newbuff;                               
+            } else {
+                               str.CopyTo (buffer.AsSpan ().Slice (length));
+                       }
+                       length = length + str.Length;
+               }
+               public void Insert (ReadOnlySpan<char> str, int start) {
+                       if (length + str.Length > buffer.Length) {
+                               char[] newbuff = new char[length + str.Length];
+                               Span<char> tmp = newbuff.AsSpan ();
+                               buffer.AsSpan ().Slice (0, start).CopyTo (tmp);
+                               tmp = tmp.Slice (start);
+                               str.CopyTo (tmp);
+                               tmp = tmp.Slice (str.Length);
+                               buffer.AsSpan ().Slice (start, length - start).CopyTo (tmp);                            
+                               buffer = newbuff;
+                       } else {
+                               buffer.AsSpan ().Slice (start, length - start).CopyTo (buffer.AsSpan ().Slice (start + str.Length));
+                               str.CopyTo (buffer.AsSpan ().Slice (start, str.Length));
+                       }
+                       length = length + str.Length;
+               }
+               public void Remove (int start, int length) {
+                       Span<char> tmp = buffer.AsSpan ();
+                       int end = Math.Min (this.length, start + length);
+                       if (end < this.length)
+                               tmp.Slice (end, this.length - end).CopyTo (tmp.Slice (start, this.length - end));
+                       this.length = start + (this.length - end);
+        }
+
+               public void Update (TextChange change) {
+
+        }
+
+               public override string ToString () => new string (buffer, 0, length);
+    }
+}
diff --git a/Crow/src/Text/TextChange.cs b/Crow/src/Text/TextChange.cs
new file mode 100644 (file)
index 0000000..636c732
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Crow.Text
+{
+    public struct TextChange
+    {
+        public readonly int Start;
+        public readonly int Length;
+        public readonly string ChangedText;
+
+        public int End => Start + Length;
+        public TextChange (int position, int length, string changedText) {
+            Start = position;
+            Length = length;
+            ChangedText = changedText;
+        }
+    }
+}
diff --git a/Crow/src/Text/TextLine.cs b/Crow/src/Text/TextLine.cs
new file mode 100644 (file)
index 0000000..5319074
--- /dev/null
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace Crow.Text
+{
+       [DebuggerDisplay ("{Start}, {Length}, {LengthInPixel}")]
+       public struct TextLine : IComparable<TextLine>
+       {
+               public int Start;
+               public int Length;
+               public int LengthIncludingLineBreak;
+               public int LengthInPixel;
+               public int End => Start + Length;
+               public int EndIncludingLineBreak => Start + LengthIncludingLineBreak;
+               public int LineBreakLength => LengthIncludingLineBreak - Length;
+               public bool HasLineBreak => LineBreakLength > 0;
+               public TextLine (int start, int end, int endIncludingLineBreak) {
+                       Start = start;
+                       Length = end - start;
+                       LengthIncludingLineBreak = endIncludingLineBreak - start;
+                       LengthInPixel = -1;
+               }
+               public TextLine (int start) {
+                       Start = start;
+                       Length = 0;
+                       LengthIncludingLineBreak = 0;
+                       LengthInPixel = -1;
+               }
+               public TextLine WithStartOffset (int start) => new TextLine (Start + start, End, EndIncludingLineBreak);
+
+               public int CompareTo (TextLine other) => Start - other.Start;
+        /*public ReadOnlySpan<char> GetSubString (string str) {                        
+    if (Start >= str.Length)
+        return "".AsSpan();
+    return str.Length - Start < Length ?
+        str.AsSpan().Slice (Start, Length) :
+        str.AsSpan().Slice (Start);
+}
+public ReadOnlySpan<char> GetSubStringIncludingLineBreak (string str) {
+    if (Start >= str.Length)
+        return "".AsSpan ();
+    return (str.Length - Start < LengthIncludingLineBreak) ?
+        str.AsSpan ().Slice (Start, LengthIncludingLineBreak) :
+        str.AsSpan ().Slice (Start);
+}*/
+    }
+}
diff --git a/Crow/src/Text/TextLineCollection.cs b/Crow/src/Text/TextLineCollection.cs
new file mode 100644 (file)
index 0000000..a505409
--- /dev/null
@@ -0,0 +1,110 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Crow.Text
+{
+    public class LineCollection : IList<TextLine>
+    {
+        TextLine[] lines;
+        int length;
+
+        #region CTOR
+        public LineCollection (int capacity) {
+            lines = new TextLine[capacity];
+            length = 0;
+        }
+        public LineCollection (TextLine[] _lines, int capacity = -1) {
+            if (capacity >= _lines.Length) {
+                lines = new TextLine[capacity];
+                _lines.AsSpan ().CopyTo (lines);
+            } else
+                lines =_lines;
+            
+            length = _lines.Length;
+        }
+        #endregion
+
+        public int GetAbsolutePosition (CharLocation loc) => lines[loc.Line].Start + loc.Column;
+        public CharLocation GetLocation (int absolutePosition) {
+            TextLine tl = new TextLine (absolutePosition);
+            int result = lines.AsSpan (0, length).BinarySearch (tl);            
+            if (result < 0) {
+                result = ~result;
+                return result == 0 ?
+                    new CharLocation (0, absolutePosition) :
+                    new CharLocation (result - 1, absolutePosition - lines[result - 1].Start);
+            }
+            return new CharLocation (result, absolutePosition - lines[result].Start);
+        }
+        public void UpdateLineLengthInPixel (int index, int lengthInPixel) {
+            lines[index].LengthInPixel = lengthInPixel;
+        }
+        public int Count => length;
+        public bool IsReadOnly => false;
+
+        public TextLine this[int index] { get => lines[index]; set => lines[index] = value; }
+
+        public void Add (TextLine item) {
+            if (lines.Length < length + 1) {
+                TextLine[] tmp = new TextLine[length + 4];
+                lines.AsSpan ().CopyTo (tmp);
+                lines = tmp;
+            }
+            lines[length] = item;
+            length++;
+        }
+
+        public void Clear () {
+            length = 0;
+        }
+
+        public bool Contains (TextLine item) => Array.IndexOf<TextLine> (lines, item) >= 0;
+
+        public void CopyTo (TextLine[] array, int arrayIndex) {
+            lines.AsSpan (0, length).CopyTo (array.AsSpan (arrayIndex));
+        }
+
+        public bool Remove (TextLine item) {
+            int idx = Array.IndexOf<TextLine> (lines, item);
+            if (idx < 0)
+                return false;
+            if (idx + 1 < length)
+                lines.AsSpan (idx + 1, length - idx - 1).CopyTo (lines.AsSpan (idx));
+            length--;
+            return true;
+        }
+        public IEnumerator<TextLine> GetEnumerator () => new LineEnumerator (this);
+        IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
+
+        public int IndexOf (TextLine item) {
+            throw new NotImplementedException ();
+        }
+
+        public void Insert (int index, TextLine item) {
+            throw new NotImplementedException ();
+        }
+
+        public void RemoveAt (int index) {
+            throw new NotImplementedException ();
+        }
+
+        public class LineEnumerator : IEnumerator<TextLine>
+        {
+            TextLine[] lines;
+            int length, position = -1;
+            public LineEnumerator (LineCollection coll) {
+                lines = coll.lines;
+                length = coll.length;
+            }
+            public TextLine Current => lines[position];
+            object IEnumerator.Current => Current;
+            public void Dispose () { }
+            public bool MoveNext () => ++position < length;            
+            public void Reset () {
+                position = -1;
+            }
+        }
+    }
+}
diff --git a/Crow/src/Text/TextSpan.cs b/Crow/src/Text/TextSpan.cs
new file mode 100644 (file)
index 0000000..486d8e2
--- /dev/null
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Crow.Text
+{
+       public struct TextSpan
+       {
+               public readonly int Start;
+               public readonly int End;
+               public TextSpan (int start, int end) {
+                       Start = start;
+                       End = end;
+               }
+
+               public bool IsEmpty => Start == End;
+               public int Length => End - Start;
+       }
+}
index 486f58dce6ecda2cdf5fd26c9b227ed44f219f1d..fc261cb5a59900e2a7e08df60102aea372b7719d 100644 (file)
@@ -12,162 +12,9 @@ using System.Text;
 using System.Diagnostics;
 using Glfw;
 using System.Collections;
+using Crow.Text;
 
 namespace Crow {
-       internal struct TextSpan
-    {
-               public readonly int Start;
-               public readonly int End;
-               public TextSpan (int start, int end) {
-                       Start = start;
-                       End = end;
-        }
-       }
-
-    [DebuggerDisplay ("{Line}, {Column}, {VisualCharXPosition}")]
-    internal struct CharLocation : IEquatable<CharLocation>
-    {
-               public readonly int Line;
-               public int Column;
-               public double VisualCharXPosition;
-               public CharLocation (int line, int column, double visualX = -1) {
-                       Line = line;
-                       Column = column;
-                       VisualCharXPosition = visualX;
-        }
-               public bool HasVisualX => Column >= 0 && VisualCharXPosition >= 0;
-
-               public static bool operator ==(CharLocation a, CharLocation b)
-                       => a.Equals (b);
-               public static bool operator != (CharLocation a, CharLocation b)
-                       => !a.Equals (b);
-               public bool Equals (CharLocation other) {
-                       return Column < 0 ?
-                               Line == other.Line && VisualCharXPosition == other.VisualCharXPosition :
-                               Line == other.Line && Column == other.Column;
-               }
-        public override bool Equals (object obj) => obj is CharLocation loc ? Equals(loc) : false;
-        public override int GetHashCode () {
-            return Column < 0 ?
-                               HashCode.Combine (Line, VisualCharXPosition) :
-                               HashCode.Combine (Line, Column);
-               }
-    }
-    internal class LineCollection : ICollection<LineSpan>
-    {
-               LineSpan[] lines;
-
-        public int Count => throw new NotImplementedException ();
-
-        public bool IsReadOnly => throw new NotImplementedException ();
-
-        public void Add (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public void Clear () {
-            throw new NotImplementedException ();
-        }
-
-        public bool Contains (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public void CopyTo (LineSpan[] array, int arrayIndex) {
-            throw new NotImplementedException ();
-        }
-
-        public IEnumerator<LineSpan> GetEnumerator () {
-            throw new NotImplementedException ();
-        }
-
-        public bool Remove (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator () {
-            throw new NotImplementedException ();
-        }
-
-        /*public LineSpan this[int index] {
-                       get => lines[index];
-                       set => lines[index] = value;
-               }
-        public int Count => lines.Length;
-        public bool IsReadOnly => false;
-
-        public void Add (LineSpan item) {
-            
-        }
-
-        public void Clear () {
-            throw new NotImplementedException ();
-        }
-
-        public bool Contains (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public void CopyTo (LineSpan[] array, int arrayIndex) {
-            throw new NotImplementedException ();
-        }
-
-        public IEnumerator<LineSpan> GetEnumerator () {
-            throw new NotImplementedException ();
-        }
-
-        public int IndexOf (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public void Insert (int index, LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public bool Remove (LineSpan item) {
-            throw new NotImplementedException ();
-        }
-
-        public void RemoveAt (int index) {
-            throw new NotImplementedException ();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator () {
-            throw new NotImplementedException ();
-        }*/
-    }
-    internal struct LineSpan
-    {
-               public int Start;
-               public int Length;
-               public int LengthIncludingLineBreak;
-               public int LengthInPixel;
-               public int End => Start + Length;
-               public int EndIncludingLineBreak => Start + LengthIncludingLineBreak;
-               public int LineBreakLength => LengthIncludingLineBreak - Length;
-               public bool HasLineBreak => LineBreakLength > 0;
-               public LineSpan (int start, int end, int endIncludingLineBreak) {
-                       Start = start;
-                       Length = end - start;
-                       LengthIncludingLineBreak = endIncludingLineBreak - start;
-                       LengthInPixel = -1;
-        }
-               public LineSpan WithStartOffset (int start) => new LineSpan (Start + start, End, EndIncludingLineBreak);
-               /*public ReadOnlySpan<char> GetSubString (string str) {                 
-                       if (Start >= str.Length)
-                               return "".AsSpan();
-                       return str.Length - Start < Length ?
-                               str.AsSpan().Slice (Start, Length) :
-                               str.AsSpan().Slice (Start);
-               }
-               public ReadOnlySpan<char> GetSubStringIncludingLineBreak (string str) {
-                       if (Start >= str.Length)
-                               return "".AsSpan ();
-                       return (str.Length - Start < LengthIncludingLineBreak) ?
-                               str.AsSpan ().Slice (Start, LengthIncludingLineBreak) :
-                               str.AsSpan ().Slice (Start);
-               }*/
-       }
        /// <summary>
        /// Simple label widget possibly multiline but without tabulation handling.
        /// </summary>
@@ -184,15 +31,13 @@ namespace Crow {
                public event EventHandler<TextChangeEventArgs> TextChanged;
 
                public virtual void OnTextChanged(Object sender, TextChangeEventArgs e)
-               {
-                       textMeasureIsUpToDate = false;
-                       NotifyValueChanged ("Text", Text);
+               {                       
                        TextChanged.Raise (this, e);
                }
         //TODO:change protected to private
 
                #region private and protected fields
-               string _text;
+               protected string _text;
         TextAlignment _textAlignment;
                bool horizontalStretch;
                bool verticalStretch;
@@ -204,9 +49,9 @@ namespace Crow {
                //Point mouseLocalPos = -1;//mouse coord in widget space, filled only when clicked
 
                
-               CharLocation? hoverLoc = null;
-               CharLocation? currentLoc = null;
-               CharLocation? selectionStart = null;    //selection start (row,column)
+               protected CharLocation? hoverLoc = null;
+               protected CharLocation? currentLoc = null;
+               protected CharLocation? selectionStart = null;  //selection start (row,column)
 
                protected FontExtents fe;
                protected TextExtents te;
@@ -239,18 +84,6 @@ namespace Crow {
                                RegisterForRedraw ();
                        }
                }
-               void resetLocationXs () {
-                       if (currentLoc.HasValue) {
-                               CharLocation cl = currentLoc.Value;
-                               cl.VisualCharXPosition = -1;
-                               currentLoc = cl;
-                       }
-                       if (selectionStart.HasValue) {
-                               CharLocation cl = selectionStart.Value;
-                               cl.VisualCharXPosition = -1;
-                               selectionStart = cl;
-                       }
-               }
                /// <summary>
                /// If measure is not 'Fit', align text inside the bounds of this label.
                /// </summary>
@@ -281,18 +114,21 @@ namespace Crow {
                                if (_text.AsSpan ().SequenceEqual (value.AsSpan ()))
                     return;
 
+                               int oldTextLength = string.IsNullOrEmpty (_text) ? 0 : _text.Length;
                 _text = value;
 
                                getLines ();
 
-                               OnTextChanged (this, new TextChangeEventArgs (Text));
+                               textMeasureIsUpToDate = false;
+                               NotifyValueChanged ("Text", Text);
+                               OnTextChanged (this, new TextChangeEventArgs (new TextChange (0, oldTextLength, _text)));
                                RegisterForGraphicUpdate ();
             }
         }
 
                /// <summary>
                /// If 'true', linebreaks will be interpreted. If 'false', linebreaks are threated as unprintable
-               /// unicode characters.
+               /// unicode characters. Default value is 'False'.
                /// </summary>
                [DefaultValue(false)]
                public bool Multiline
@@ -467,7 +303,7 @@ namespace Crow {
                        targetColumn = -1;
                        CharLocation loc = currentLoc.Value;
                        if (loc.Column == lines[loc.Line].Length) {
-                               if (loc.Line == lines.Length - 1)
+                               if (loc.Line == lines.Count - 1)
                                        return false;
                                currentLoc = new CharLocation (loc.Line + 1, 0);
                        } else
@@ -495,7 +331,7 @@ namespace Crow {
                }
                public bool MoveDown () {
                        CharLocation loc = currentLoc.Value;
-                       if (loc.Line == lines.Length - 1)
+                       if (loc.Line == lines.Count - 1)
                                return false;
 
                        if (loc.Column > lines[loc.Line + 1].Length) {
@@ -511,22 +347,8 @@ namespace Crow {
 
                        return true;
                }
+
                /*
-               /// <summary>
-               /// Moves cursor one char to the right.
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public bool MoveRight(){
-                       int tmp = _currentCol + 1;
-                       if (tmp > lines [_currentLine].Length){
-                               if (CurrentLine == lines.Length - 1)
-                                       return false;
-                               CurrentLine++;
-                               CurrentColumn = 0;
-                       } else
-                               CurrentColumn = tmp;
-                       return true;
-               }
                public void GotoWordStart(){
                        CurrentColumn--;
                        //skip white spaces
@@ -624,54 +446,96 @@ namespace Crow {
                */
                bool textMeasureIsUpToDate = false;
                Size cachedTextSize = default(Size);
-               LineSpan[] lines;
-               void getLines () {
+               protected LineCollection lines;         
+               protected void getLines () {
                        if (string.IsNullOrEmpty (_text)) {
-                               lines = new LineSpan[] { new LineSpan (0, 0, 0) };
+                               lines = new LineCollection(new TextLine[] { new TextLine (0, 0, 0) });
                                return;
                        }
                        if (!_multiline) {
-                               lines = new LineSpan[] { new LineSpan (0, _text.Length, _text.Length) };
+                               lines = new LineCollection (new TextLine[] { new TextLine (0, _text.Length, _text.Length) });
                                return;
                        }
 
-                       List<LineSpan> _lines = new List<LineSpan> ();                  
+                       List<TextLine> _lines = new List<TextLine> ();                  
                        int start = 0, i = 0;
                        while (i < _text.Length) {
                                char c = _text[i];
                                if (c == '\r') {
                                        if (++i < _text.Length) {
                                                if (_text[i] == '\n')
-                                                       _lines.Add (new LineSpan (start, i - 1, ++i));
+                                                       _lines.Add (new TextLine (start, i - 1, ++i));
                                                else
-                                                       _lines.Add (new LineSpan (start, i - 1, i));
+                                                       _lines.Add (new TextLine (start, i - 1, i));
                                        } else
-                                               _lines.Add (new LineSpan (start, i - 1, i));
+                                               _lines.Add (new TextLine (start, i - 1, i));
                                        start = i;
                                } else if (c == '\n') {
                                        if (++i < _text.Length) {
                                                if (_text[i] == '\r')
-                                                       _lines.Add (new LineSpan (start, i - 1, ++i));
+                                                       _lines.Add (new TextLine (start, i - 1, ++i));
                                                else
-                                                       _lines.Add (new LineSpan (start, i - 1, i));
+                                                       _lines.Add (new TextLine (start, i - 1, i));
                                        } else
-                                               _lines.Add (new LineSpan (start, i - 1, i));
+                                               _lines.Add (new TextLine (start, i - 1, i));
                                        start = i;
 
                                } else if (c == '\u0085' || c == '\u2028' || c == '\u2029')
-                                       _lines.Add (new LineSpan (start, i - 1, i));
+                                       _lines.Add (new TextLine (start, i - 1, i));
                                else
                                        i++;
                        }
 
                        if (start < i)
-                               _lines.Add (new LineSpan (start, _text.Length, _text.Length));
+                               _lines.Add (new TextLine (start, _text.Length, _text.Length));
                        else
-                               _lines.Add (new LineSpan (_text.Length, _text.Length, _text.Length));
+                               _lines.Add (new TextLine (_text.Length, _text.Length, _text.Length));
 
-                       lines = _lines.ToArray ();
+                       lines = new LineCollection (_lines.ToArray ());
+               }
+               void resetLocationXs () {
+                       if (currentLoc.HasValue) {
+                               CharLocation cl = currentLoc.Value;
+                               cl.VisualCharXPosition = -1;
+                               currentLoc = cl;
+                       }
+                       if (selectionStart.HasValue) {
+                               CharLocation cl = selectionStart.Value;
+                               cl.VisualCharXPosition = -1;
+                               selectionStart = cl;
+                       }
+               }
+               double getX (int clientWidth, TextLine ls) {
+                       switch (TextAlignment) {
+                       case TextAlignment.Right:
+                               return clientWidth - ls.LengthInPixel;
+                       case TextAlignment.Center:
+                               return clientWidth / 2 - ls.LengthInPixel / 2;
+                       }
+                       return 0;
                }
 
+               protected TextSpan Selection {
+                       get {                           
+                               CharLocation selStart = currentLoc.Value, selEnd = currentLoc.Value;
+                               if (selectionStart.HasValue) {
+                                       if (currentLoc.Value.Line < selectionStart.Value.Line) {
+                                               selStart = currentLoc.Value;
+                                               selEnd = selectionStart.Value;
+                                       } else if (currentLoc.Value.Line > selectionStart.Value.Line) {
+                                               selStart = selectionStart.Value;
+                                               selEnd = currentLoc.Value;
+                                       } else if (currentLoc.Value.Column < selectionStart.Value.Column) {
+                                               selStart = currentLoc.Value;
+                                               selEnd = selectionStart.Value;
+                                       } else {
+                                               selStart = selectionStart.Value;
+                                               selEnd = currentLoc.Value;
+                                       }
+                               }
+                               return new TextSpan (lines.GetAbsolutePosition (selStart), lines.GetAbsolutePosition (selEnd));
+                       }
+        }
 
                #region GraphicObject overrides
                public override int measureRawSize(LayoutingType lt)
@@ -691,17 +555,17 @@ namespace Crow {
                                        fe = gr.FontExtents;
                                        te = new TextExtents ();
 
-                                       cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Length));
+                                       cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Count));
 
                                        TextExtents tmp = default;
                                        int longestLine = 0;
-                                       for (int i = 0; i < lines.Length; i++) {                                                        
+                                       for (int i = 0; i < lines.Count; i++) {                                                 
                                                if (lines[i].LengthInPixel < 0) {
                                                        if (lines[i].Length == 0)
-                                                               lines[i].LengthInPixel = 0;// (int)Math.Ceiling (fe.MaxXAdvance);
+                                                               lines.UpdateLineLengthInPixel (i, 0);// (int)Math.Ceiling (fe.MaxXAdvance);
                                                        else {
                                                                gr.TextExtents (_text.GetLine (lines[i]), Interface.TAB_SIZE, out tmp);
-                                                               lines[i].LengthInPixel = (int)Math.Ceiling (tmp.XAdvance);
+                                                               lines.UpdateLineLengthInPixel (i, (int)Math.Ceiling (tmp.XAdvance));
                                                        }
                                                }
                                                if (lines[i].LengthInPixel > lines[longestLine].LengthInPixel)
@@ -714,15 +578,6 @@ namespace Crow {
                        return Margin * 2 + (lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width);
                }
 
-               double getX (int clientWidth, ref LineSpan ls) {
-                       switch (TextAlignment) {
-                       case TextAlignment.Right:
-                               return clientWidth - ls.LengthInPixel;                          
-                       case TextAlignment.Center:
-                               return clientWidth / 2 - ls.LengthInPixel / 2;
-                       }
-                       return 0;
-               }
                protected override void onDraw (Context gr)
                {
                        base.onDraw (gr);
@@ -783,7 +638,7 @@ namespace Crow {
                        TextExtents extents;
                        Span<byte> bytes = stackalloc byte[128];                        
 
-                       for (int i = 0; i < lines.Length; i++) {
+                       for (int i = 0; i < lines.Count; i++) {
                                int encodedBytes = -1;
                                if (lines[i].Length > 0) {
 
@@ -796,12 +651,12 @@ namespace Crow {
 
                                        if (lines[i].LengthInPixel < 0) {
                                                gr.TextExtents (bytes.Slice (0, encodedBytes), out extents);
-                                               lines[i].LengthInPixel = (int)extents.XAdvance;
+                                               lines.UpdateLineLengthInPixel (i, (int)extents.XAdvance);
                                        }
                                }
 
                                Rectangle lineRect = new Rectangle (
-                                       Width.IsFit && !Multiline ? cb.X : (int)getX (cb.Width, ref lines[i]) + cb.X,
+                                       Width.IsFit && !Multiline ? cb.X : (int)getX (cb.Width, lines[i]) + cb.X,
                                        cb.Y + i * lineHeight,
                                        lines[i].LengthInPixel,
                                        lineHeight);
@@ -860,7 +715,7 @@ namespace Crow {
                        base.onFocused (sender, e);
                        if (currentLoc == null) {
                                selectionStart = new CharLocation (0, 0);                               
-                               currentLoc = new CharLocation (lines.Length - 1, lines[lines.Length - 1].Length);
+                               currentLoc = new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
                        }
                        RegisterForRedraw ();
                }
@@ -875,7 +730,7 @@ namespace Crow {
 
                        Point mouseLocalPos = e.Position - ScreenCoordinates (Slot).TopLeft - ClientRectangle.TopLeft;
                        int hoverLine = _multiline ?
-                               (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))), lines.Length - 1) : 0;
+                               (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))), lines.Count - 1) : 0;
                        hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X);
 
                        if (HasFocus && IFace.IsDown (Glfw.MouseButton.Left)) {
@@ -946,7 +801,7 @@ namespace Crow {
                                break;
                        case Key.End:
                                checkShift ();
-                               int l = IFace.Ctrl ? lines.Length - 1 : currentLoc.Value.Line;
+                               int l = IFace.Ctrl ? lines.Count - 1 : currentLoc.Value.Line;
                                currentLoc = new CharLocation (l, lines[l].Length);
                                RegisterForRedraw ();
                                break;
@@ -1008,9 +863,9 @@ namespace Crow {
                        CharLocation loc = location.Value;
                        if (loc.HasVisualX)
                                return;
-                       LineSpan ls = lines[loc.Line];
-                       ReadOnlySpan<char> curLine = _text.GetLine (lines[loc.Line]);
-                       double cPos = Width.IsFit && !Multiline ? 0 : getX (clientWidth, ref ls);
+                       TextLine ls = lines[loc.Line];
+                       ReadOnlySpan<char> curLine = _text.GetLine (ls);
+                       double cPos = Width.IsFit && !Multiline ? 0 : getX (clientWidth, ls);
                        
                        if (loc.Column >= 0) {
                                loc.VisualCharXPosition = gr.TextExtents (curLine.Slice (0, loc.Column), Interface.TAB_SIZE).XAdvance + cPos;
index 080bc5a0912193855bdd4068221fa18613c19ea7..ed87d712238ca0a390e21ddf38f86f6a673db1f6 100644 (file)
@@ -128,7 +128,7 @@ namespace Crow {
 
                                lines = getLines;
 
-                               OnTextChanged (this, new TextChangeEventArgs (Text));
+                               OnTextChanged (this, new TextChangeEventArgs (default));
                                RegisterForGraphicUpdate ();
             }
         }
@@ -380,7 +380,7 @@ namespace Crow {
                                        lines [CurrentLine] += lines [CurrentLine + 1];
                                        lines.RemoveAt (CurrentLine + 1);
 
-                                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                                       OnTextChanged (this, new TextChangeEventArgs (default));
                                        return;
                                }
                                CurrentColumn--;
@@ -403,7 +403,7 @@ namespace Crow {
                                SelBegin = -1;
                                SelRelease = -1;
                        }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       OnTextChanged (this, new TextChangeEventArgs (default));
                }
                /// <summary>
                /// Insert new string at caret position, should be sure no line break is inside.
@@ -426,7 +426,7 @@ namespace Crow {
                                lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str);
                                CurrentColumn += str.Length;
                        }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       OnTextChanged (this, new TextChangeEventArgs (default));
                }
                /// <summary>
                /// Insert a line break.
@@ -437,7 +437,7 @@ namespace Crow {
                        lines [CurrentLine] = lines [CurrentLine].Substring (0, CurrentColumn);
                        CurrentLine++;
                        CurrentColumn = 0;
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       OnTextChanged (this, new TextChangeEventArgs (default));
                }
                bool textMeasureIsUpToDate = false;
                Size cachedTextSize = default(Size);
index 8c0fce1fbe4977446d81ae6832dfc67bdbdbde11..f209746f3415cb870442100c2b620a7c074625d1 100644 (file)
@@ -59,7 +59,7 @@ namespace Crow
                                if (Multiline)
                                        InsertLineBreak ();
                                else
-                                       OnTextChanged(this,new TextChangeEventArgs(Text));
+                                       OnTextChanged(this,new TextChangeEventArgs(default));
                                break;
                        case Key.Escape:
                                Text = "";
index f33f89d02c98b820b66a40ee6b2393a21c82a5fe..3564ee499e186a4c9830f4dab7c4929b21874c4d 100644 (file)
@@ -3,7 +3,9 @@
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using Crow.Cairo;
+using Crow.Text;
 using Glfw;
+using System;
 
 namespace Crow
 {
@@ -19,131 +21,49 @@ namespace Crow
                public override void onKeyDown (object sender, KeyEventArgs e)
                {
                        Key key = e.Key;
-
+                       TextSpan selection = Selection;
                        switch (key)
                        {
-                       /*case Key.Backspace:
-                               if (CurrentPosition == 0)
-                                       return;
-                               DeleteChar();
-                               break;
-                       case Key.Delete:
-                               if (selectionIsEmpty) {
-                                       if (!MoveRight ())
+                       case Key.Backspace:
+                               if (selection.Length == 0) {
+                                        if (selection.Start == 0)
                                                return;
-                               }else if (IFace.Shift)
-                                       IFace.Clipboard = SelectedText;
-                               DeleteChar ();
-                               break;
-                       case Key.KeypadEnter:
-                       case Key.Enter:
-                               if (!selectionIsEmpty)
-                                       DeleteChar ();
-                               if (Multiline)
-                                       InsertLineBreak ();
-                               else
-                                       OnTextChanged(this,new TextChangeEventArgs(Text));
+                                       update (new TextChange (selection.Start - 1, 1, ""));
+                               } else                                  
+                                       update (new TextChange (selection.Start, selection.Length, ""));
                                break;
-                       case Key.Escape:
-                               Text = "";
-                               CurrentColumn = 0;
-                               SelRelease = -1;
-                               break;
-                       case Key.Home:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = new Point (CurrentColumn, CurrentLine);
-                                       if (IFace.Ctrl)
-                                               CurrentLine = 0;
-                                       CurrentColumn = 0;
-                                       SelRelease = new Point (CurrentColumn, CurrentLine);
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       CurrentLine = 0;
-                               CurrentColumn = 0;
-                               break;
-                       case Key.End:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       if (IFace.Ctrl)
-                                               CurrentLine = int.MaxValue;
-                                       CurrentColumn = int.MaxValue;
-                                       SelRelease = CurrentPosition;
-                                       break;
+                       case Key.Delete:
+                               if (selection.Length == 0) {
+                                       if (selection.Start == Text.Length)
+                                               return;                                 
+                                       update (new TextChange (selection.Start, 1, ""));
+                               } else {
+                                       if (IFace.Shift)
+                                               IFace.Clipboard = Text.AsSpan(selection.Start, selection.End).ToString();
+                                       update (new TextChange (selection.Start, selection.Length, ""));
                                }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       CurrentLine = int.MaxValue;
-                               CurrentColumn = int.MaxValue;
                                break;
                        case Key.Insert:
                                if (IFace.Shift)
-                                       this.Insert (IFace.Clipboard);
-                               else if (IFace.Ctrl && !selectionIsEmpty)
-                                       IFace.Clipboard = this.SelectedText;
-                               break;
-                       case Key.Left:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = new Point(CurrentColumn, CurrentLine);
-                                       if (IFace.Ctrl)
-                                               GotoWordStart ();
-                                       else if (!MoveLeft ())
-                                               return;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       GotoWordStart ();
-                               else
-                                       MoveLeft();
+                                       update (new TextChange (selection.Start, selection.Length, IFace.Clipboard));
+                               else if (IFace.Ctrl && !selection.IsEmpty)
+                                       IFace.Clipboard = Text.AsSpan (selection.Start, selection.End).ToString ();
                                break;
-                       case Key.Right:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       if (IFace.Ctrl)
-                                               GotoWordEnd ();
-                                       else if (!MoveRight ())
-                                               return;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       GotoWordEnd ();
+                       case Key.KeypadEnter:
+                       case Key.Enter:                         
+                               if (Multiline)
+                                       update (new TextChange (selection.Start, selection.Length, "\n"));
                                else
-                                       MoveRight ();
-                               break;
-                       case Key.Up:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine--;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               CurrentLine--;
+                                       OnTextChanged(this,new TextChangeEventArgs(default));
                                break;
-                       case Key.Down:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine++;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               CurrentLine++;                          
+                       case Key.Escape:
+                               selectionStart = null;
+                               currentLoc = lines.GetLocation (selection.Start);
+                               RegisterForRedraw ();
+                               break;                  
+                       case Key.Tab:                           
+                               update (new TextChange (selection.Start, selection.Length, "\t"));
                                break;
-                       case Key.Tab:
-                               this.Insert ("\t");
-                               break;*/
                        default:
                                base.onKeyDown (sender, e);
                                break;
@@ -154,6 +74,9 @@ namespace Crow
                {
                        base.onKeyPress (sender, e);
 
+                       TextSpan selection = Selection;
+                       update (new TextChange (selection.Start, selection.Length, e.KeyChar.ToString ()));
+                       
                        /*Insert (e.KeyChar.ToString());
 
                        SelRelease = -1;
@@ -162,5 +85,17 @@ namespace Crow
                        RegisterForGraphicUpdate();*/
                }
         #endregion
+
+               void update(TextChange change) {
+                       Span<char> tmp = stackalloc char[Text.Length + (change.ChangedText.Length - change.Length)];
+                       ReadOnlySpan<char> src = Text.AsSpan ();                        
+                       src.Slice (0, change.Start).CopyTo (tmp);
+                       change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
+                       src.Slice (change.End).CopyTo (tmp.Slice (change.Start + change.ChangedText.Length));
+                       Text = tmp.ToString ();
+                       
+                       selectionStart = null;
+                       currentLoc = lines.GetLocation (change.Start + change.ChangedText.Length);
+               }
        } 
 }
index e76c807fcc1c72c16b1cc15b5dfeaebddc0f6b15..8a844ed06ac478979192ec8ea0b36488f1b4abba 100644 (file)
@@ -1212,7 +1212,7 @@ namespace Crow
                {
                        if (pi.GetSetMethod () == null)
                                return;
-                       XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof (XmlIgnoreAttribute));
+                       XmlIgnoreAttribute xia = pi.GetCustomAttribute <XmlIgnoreAttribute>();
                        if (xia != null)
                                return;
 
index dcc412ed4d3b0012282a290ba2550f2690246bb9..d6ada8b490d7474297b03560557066e195df150a 100644 (file)
@@ -32,7 +32,7 @@ namespace PerfTests
                        System.Runtime.Loader.AssemblyLoadContext.Default.ResolvingUnmanagedDll+=resolveUnmanaged;
                }
 #endif         
-               readonly int count = 1, updateCycles = 0;                       
+               readonly int count = 10, updateCycles = 0;                      
                readonly bool screenOutput = false;
                readonly string inDirectory = null;//directory to test
                readonly string outFilePath;
@@ -68,7 +68,7 @@ namespace PerfTests
                        Console.WriteLine ("-i,--input:\n\tInput directory to search recursively for '.crow' file to test. If ommitted, builtin unit tests are performs");
                        Console.WriteLine ("-w,--width:\n\toutput surface width, not displayed on screen.");
                        Console.WriteLine ("-h,--height:\n\toutput surface height, not displayed on screen.");
-                       Console.WriteLine ("-c,--count:\n\trepeat each test 'c' times.");
+                       Console.WriteLine ("-c,--count:\n\trepeat each test 'c' times. (default = 10, minimum = 5");
 
                        Console.WriteLine ("-b,--begin:\n\tStarting stage for measures, may be the stage name or stage index");
             foreach (Stage s in Enum.GetValues(typeof(Stage))) {
@@ -76,7 +76,7 @@ namespace PerfTests
                        }
                        Console.WriteLine ("-e,--end:\n\tEnding stage for measures, may be the stage name or stage index");
                        Console.WriteLine ("-r,--reset:\n\tenable clear iterators after each test file.");
-                       Console.WriteLine ("-u,--update:\n\tmeasure 'n' update cycle with DateTime.Now string notified.");
+                       Console.WriteLine ("-u,--update:\n\tmeasure 'n' update cycle with elapsed ticks string notified. (default = 0)");
                        Console.WriteLine ("-s,--screen:\n\tenable output to screen.");
                        Console.WriteLine ("--help:\n\tthis help message.");
                }
@@ -100,7 +100,7 @@ namespace PerfTests
                                                break;
                                        case "-c":
                                        case "--count":
-                                               count = int.Parse (args[i++]);
+                                               count = Math.Max(5, int.Parse (args[i++]));
                                                break;
                                        case "-w":
                                        case "--width":
@@ -511,10 +511,13 @@ namespace PerfTests
 
                public static void Main (string [] args)
                {
-            try {
+                       
+                       try {
                                using (TestInterface iface = new TestInterface (args)) {
-                                       iface.PerformUnitTests ();
-                                       iface.PerformTests ();
+                                       if (string.IsNullOrEmpty(iface.inDirectory))
+                                               iface.PerformUnitTests ();
+                                       else
+                                               iface.PerformTests ();
                                }
                        } catch (Exception) {
             }
index 49325a0c24826660b2c2c47a2a3b9e5dcc1c745f..0d2830a2b74dc9cceea7061df0d2d40df29693d3 100644 (file)
@@ -2,7 +2,7 @@
   "profiles": {
     "PerfTests": {
       "commandName": "Project",
-      "commandLineArgs": "-c 20 -i Interfaces/PerfLabels"
+      "commandLineArgs": "-c 10 -b 0 -e 1 "
     }
   }
 }
\ No newline at end of file