]> O.S.I.I.S - jp/crow.git/commitdiff
source tree organization
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 9 May 2020 13:07:52 +0000 (15:07 +0200)
committerj-p <jp_bruyere@hotmail.com>
Sat, 9 May 2020 22:50:02 +0000 (00:50 +0200)
45 files changed:
Crow/Crow.csproj
Crow/src/2d/Measure.cs [new file with mode: 0644]
Crow/src/2d/Point.cs [new file with mode: 0644]
Crow/src/2d/PointD.cs [new file with mode: 0644]
Crow/src/2d/Rectangle.cs [new file with mode: 0644]
Crow/src/2d/RectangleD.cs [new file with mode: 0644]
Crow/src/2d/Size.cs [new file with mode: 0644]
Crow/src/2d/SizeD.cs [new file with mode: 0644]
Crow/src/DragDropEventArgs.cs [deleted file]
Crow/src/EventArgs/DragDropEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/LayoutingEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/ListChangedEventArg.cs [new file with mode: 0644]
Crow/src/EventArgs/MouseCursorChangedEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/ScrollingEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/SelectionChangeEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/TextChangeEventArgs.cs [new file with mode: 0644]
Crow/src/EventArgs/ValueChangeEventArgs.cs [new file with mode: 0644]
Crow/src/Fill/Gradient.cs [new file with mode: 0644]
Crow/src/Gradient.cs [deleted file]
Crow/src/IListChanged.cs [deleted file]
Crow/src/IML/IMLAttributes.cs [new file with mode: 0644]
Crow/src/IML/Instantiator.cs [new file with mode: 0644]
Crow/src/IMLAttributes.cs [deleted file]
Crow/src/IObservableList.cs [new file with mode: 0644]
Crow/src/IValueChange.cs [new file with mode: 0644]
Crow/src/Instantiator.cs [deleted file]
Crow/src/LayoutingEventArgs.cs [deleted file]
Crow/src/Measure.cs [deleted file]
Crow/src/MouseCursorChangedEventArgs.cs [deleted file]
Crow/src/Point.cs [deleted file]
Crow/src/PointD.cs [deleted file]
Crow/src/Rectangle.cs [deleted file]
Crow/src/RectangleD.cs [deleted file]
Crow/src/ReflexionExtensions.cs
Crow/src/ScrollingEventArgs.cs [deleted file]
Crow/src/SelectionChangeEventArgs.cs [deleted file]
Crow/src/Size.cs [deleted file]
Crow/src/SizeD.cs [deleted file]
Crow/src/Style.cs [deleted file]
Crow/src/StyleReader.cs [deleted file]
Crow/src/TextChangeEventArgs.cs [deleted file]
Crow/src/ValueChangeEventArgs.cs [deleted file]
Crow/src/Widgets/IValueChange.cs [deleted file]
Crow/src/styling/Style.cs [new file with mode: 0644]
Crow/src/styling/StyleReader.cs [new file with mode: 0644]

index 5f29d798603d33b591df3ffe843e98e0de9f0746..0094690cadc670d383ee425dd62adf025ed26b35 100644 (file)
@@ -4,13 +4,14 @@
                <TargetFramework>netstandard2.0</TargetFramework>
                
                <AssemblyVersion>$(CrowVersion)</AssemblyVersion>
-               <ReleaseVersion>0.8.0</ReleaseVersion>
+               <ReleaseVersion>$(CrowVersion)</ReleaseVersion>
+               <PackageVersion>$(CrowPackageVersion)</PackageVersion>
+               
                <Title>C# Rapid Open Widget Toolkit</Title>
                <Description>C.R.O.W. is a widget toolkit and rendering engine developed in C# with templates, styles, compositing, and bindings.</Description>
                <License>MIT</License>
                <Authors>Jean-Philippe Bruyère</Authors>
                <RepositoryUrl>https://github.com/jpbruyere/Crow</RepositoryUrl>
-               <PackageVersion>$(CrowPackageVersion)</PackageVersion>
                <PackageTags>GUI Widget toolkit Interface C# .Net Mono</PackageTags>
                <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
                <PackageProjectUrl>https://github.com/jpbruyere/Crow/wiki</PackageProjectUrl>
@@ -38,7 +39,7 @@
                <PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.6.0" />
                <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.6.0" />
                <!--<PackageReference Include="glfw-sharp" Version="0.2.0" />-->
-               <PackageReference Include="glfw-sharp" Version="0.2.2" />
+               <PackageReference Include="glfw-sharp" Version="0.2.4" />
        </ItemGroup>
        <PropertyGroup Condition=" '$(CrowStbSharp)' == 'true'">
                <DefineConstants>$(DefineConstants);STB_SHARP</DefineConstants>
diff --git a/Crow/src/2d/Measure.cs b/Crow/src/2d/Measure.cs
new file mode 100644 (file)
index 0000000..c77d66b
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+       /// <summary>
+       /// Measurement unit
+       /// </summary>
+       public enum Unit {Undefined, Pixel, Percent, Inherit }
+       /// <summary>
+       /// Measure class allow proportional sizes as well as stretched and fit on content.
+       /// </summary>
+       public struct Measure
+       {
+               /// <summary>
+               /// Integer value of the measure
+               /// </summary>
+               public int Value;
+               /// <summary>
+               /// Measurement unit
+               /// </summary>
+               public Unit Units;
+
+               /// <summary>
+               /// Fit on content, this special measure is defined as a fixed integer set to -1 pixel
+               /// </summary>
+               public static Measure Fit = new Measure(-1,Unit.Percent);
+               /// <summary>
+               /// Stretched into parent client area. This special measure is defined as a proportional cote
+               /// set to 100 Percents
+               /// </summary>
+               public static Measure Stretched = new Measure(100, Unit.Percent);
+               public static Measure Inherit = new Measure (0, Unit.Inherit);
+               #region CTOR
+               public Measure (int _value, Unit _units = Unit.Pixel)
+               {
+                       Value = _value;
+                       Units = _units;
+               }
+               #endregion
+
+               /// <summary>
+               /// True is size is fixed in pixels, this means not proportional, stretched nor fit.
+               /// </summary>
+               public bool IsFixed { get { return Units == Unit.Pixel; }}
+               public bool IsFit { get { return Value == -1 && Units == Unit.Percent; }}
+               public bool IsRelativeToParent { get { return Value >= 0 && Units == Unit.Percent; }}
+               #region Operators
+               public static implicit operator int(Measure m){
+                       return m.Value;
+               }
+               public static implicit operator Measure(int i){
+                       return new Measure(i);
+               }
+               public static implicit operator string(Measure m){
+                       return m.ToString();
+               }
+               public static implicit operator Measure(string s){
+                       return Measure.Parse(s);
+               }
+
+               public static bool operator ==(Measure m1, Measure m2){
+                       return m1.Value == m2.Value && m1.Units == m2.Units;
+               }
+               public static bool operator !=(Measure m1, Measure m2){
+                       return !(m1.Value == m2.Value && m1.Units == m2.Units);
+               }
+               #endregion
+
+               #region Object overrides
+               public override int GetHashCode ()
+               {
+                       return Value.GetHashCode ();
+               }
+               public override bool Equals (object obj)
+               {
+                       return (obj == null || obj.GetType() != typeof(Measure)) ?
+                               false :
+                               this == (Measure)obj;
+               }
+               public override string ToString ()
+               {
+                       return Units == Unit.Inherit ? "Inherit" :
+                               Value == -1 ? "Fit" :
+                               Units == Unit.Percent ? Value == 100 ? "Stretched" :
+                               Value.ToString () + "%" : Value.ToString ();
+               }
+               #endregion
+
+               public static Measure Parse(string s){
+                       if (string.IsNullOrEmpty (s))
+                               return default(Measure);
+
+                       string st = s.Trim ();
+                       int tmp = 0;
+
+                       if (string.Equals ("Inherit", st, StringComparison.Ordinal))
+                               return Measure.Inherit;
+                       else if (string.Equals ("Fit", st, StringComparison.Ordinal))
+                               return Measure.Fit;
+                       else if (string.Equals ("Stretched", s, StringComparison.Ordinal))
+                               return Measure.Stretched;                       
+                       else {
+                               if (st.EndsWith ("%", StringComparison.Ordinal)) {
+                                       if (int.TryParse (s.Substring(0, st.Length - 1), out tmp))
+                                               return new Measure (tmp, Unit.Percent);
+                               }else if (int.TryParse (s, out tmp))
+                                       return new Measure (tmp);
+                       }
+
+                       throw new Exception ("Error parsing Measure.");
+               }
+
+       }
+}
diff --git a/Crow/src/2d/Point.cs b/Crow/src/2d/Point.cs
new file mode 100644 (file)
index 0000000..02f12e2
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Crow
+{
+    public struct Point
+    {
+               public int X;
+               public int Y;
+
+               public Point (int x, int y)
+               {
+                       X = x;
+                       Y = y;
+               }
+
+               public int Length => (int)Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
+               public double LengthD => Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
+               public Point Normalized {
+                       get {
+                               int l = Length;
+                               return new Point (X / l, Y / l);
+                       }
+               }
+               public static implicit operator PointD (Point p) => new PointD (p.X, p.Y);
+               public static implicit operator Point (int i) => new Point (i, i);
+
+               public static Point operator + (Point p1, Point p2) => new Point (p1.X + p2.X, p1.Y + p2.Y);
+               public static Point operator + (Point p, int i) => new Point (p.X + i, p.Y + i);
+               public static Point operator - (Point p1, Point p2) => new Point (p1.X - p2.X, p1.Y - p2.Y);
+               public static Point operator - (Point p, int i) => new Point (p.X - i, p.Y - i);
+               public static Point operator * (Point p1, Point p2) => new Point (p1.X * p2.X, p1.Y * p2.Y);
+               public static Point operator * (Point p, int d) => new Point (p.X * d, p.Y * d);
+               public static Point operator / (Point p1, Point p2) => new Point (p1.X / p2.X, p1.Y / p2.Y);
+               public static Point operator / (Point p, int d) => new Point (p.X / d, p.Y / d);
+
+               public static bool operator == (Point s1, Point s2) => s1.X == s2.X && s1.Y == s2.Y;
+               public static bool operator == (Point s, int i) => s.X == i && s.Y == i;
+               public static bool operator != (Point s1, Point s2) => !(s1.X == s2.X && s1.Y == s2.Y);
+               public static bool operator != (Point s, int i) => !(s.X == i && s.Y == i);
+               public static bool operator > (Point p1, Point p2) => p1.X > p2.X && p1.Y > p2.Y;
+               public static bool operator > (Point s, int i) => s.X > i && s.Y > i;
+               public static bool operator < (Point p1, Point p2) => p1.X < p2.X && p1.Y < p2.Y;
+               public static bool operator < (Point s, int i) => s.X < i && s.Y < i;
+               public static bool operator >= (Point p1, Point p2) => p1.X >= p2.X && p1.Y >= p2.Y;
+               public static bool operator >= (Point s, int i) => s.X >= i && s.Y >= i;
+               public static bool operator <= (Point p1, Point p2) => p1.X <= p2.X && p1.Y <= p2.Y;
+               public static bool operator <= (Point s, int i) => s.X <= i && s.Y <= i;
+
+               public override string ToString () => string.Format ("{0},{1}", X, Y);
+               public override bool Equals (object obj) => obj is Point ? this == (Point)obj :
+                       obj is Point && (Point)this == (Point)obj;
+               public static Point Parse (string s)
+               {
+                       if (string.IsNullOrEmpty (s))
+                               return default (Point);
+                       string [] d = s.Trim ().Split (',');
+                       if (d.Length == 2)
+                               return new Point (int.Parse (d [0]), int.Parse (d [1]));
+                       else if (d.Length == 1) {
+                               int tmp = int.Parse (d [0]);
+                               return new Point (tmp, tmp);
+                       }
+                       throw new Exception ("Crow.PointD Parsing Error: " + s);
+               }
+
+               public override int GetHashCode ()
+               {
+#pragma warning disable RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »
+                       unchecked {
+                               var hashCode = 1861411795;
+                               hashCode = hashCode * -1521134295 + X.GetHashCode ();
+
+                               hashCode = hashCode * -1521134295 + Y.GetHashCode ();
+                               return hashCode;
+                       }
+#pragma warning restore RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »    }
+               }
+       }
+}
diff --git a/Crow/src/2d/PointD.cs b/Crow/src/2d/PointD.cs
new file mode 100644 (file)
index 0000000..d70e5b8
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow {
+       public struct PointD {
+               public double X;
+               public double Y;
+               public PointD (double x, double y)
+               {
+                       X = x;
+                       Y = y;
+               }
+
+               public double Length => Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
+               public PointD Normalized {
+                       get {
+                               double l = Length;
+                               return new PointD (X / l, Y / l);
+                       }
+               }
+               public static implicit operator Point (PointD p) => new Point ((int)Math.Round (p.X), (int)Math.Round (p.Y));
+               public static implicit operator PointD (double i) => new PointD (i, i);
+
+               public static PointD operator + (PointD p1, PointD p2) => new PointD (p1.X + p2.X, p1.Y + p2.Y);
+               public static PointD operator + (PointD p, double i) => new PointD (p.X + i, p.Y + i);
+               public static PointD operator - (PointD p1, PointD p2) => new PointD (p1.X - p2.X, p1.Y - p2.Y);
+               public static PointD operator - (PointD p, double i) => new PointD (p.X - i, p.Y - i);
+               public static PointD operator * (PointD p1, PointD p2) => new PointD (p1.X * p2.X, p1.Y * p2.Y);
+               public static PointD operator * (PointD p, double d) => new PointD (p.X * d, p.Y * d);
+               public static PointD operator / (PointD p1, PointD p2) => new PointD (p1.X / p2.X, p1.Y / p2.Y);
+               public static PointD operator / (PointD p, double d) => new PointD (p.X / d, p.Y / d);
+
+               public static bool operator == (PointD s1, PointD s2) => s1.X == s2.X && s1.Y == s2.Y;
+               public static bool operator == (PointD s, double i) => s.X == i && s.Y == i;
+               public static bool operator != (PointD s1, PointD s2) => !(s1.X == s2.X && s1.Y == s2.Y);
+               public static bool operator != (PointD s, double i) => !(s.X == i && s.Y == i);
+               public static bool operator > (PointD p1, PointD p2) => p1.X > p2.X && p1.Y > p2.Y;
+               public static bool operator > (PointD s, double i) => s.X > i && s.Y > i;
+               public static bool operator < (PointD p1, PointD p2) => p1.X < p2.X && p1.Y < p2.Y;
+               public static bool operator < (PointD s, double i) => s.X < i && s.Y < i;
+               public static bool operator >= (PointD p1, PointD p2) => p1.X >= p2.X && p1.Y >= p2.Y;
+               public static bool operator >= (PointD s, double i) => s.X >= i && s.Y >= i;
+               public static bool operator <= (PointD p1, PointD p2) => p1.X <= p2.X && p1.Y <= p2.Y;
+               public static bool operator <= (PointD s, double i) => s.X <= i && s.Y <= i;
+
+               public override string ToString () => string.Format ("{0},{1}", X, Y);
+               public override bool Equals (object obj) => obj is PointD ? this == (PointD)obj :
+                       obj is Point && (Point)this == (Point)obj;
+               public static PointD Parse (string s)
+               {
+                       if (string.IsNullOrEmpty (s))
+                               return default (PointD);
+                       string [] d = s.Trim ().Split (',');
+                       if (d.Length == 2)
+                               return new PointD (double.Parse (d [0]), double.Parse (d [1]));
+                       else if (d.Length == 1) {
+                               double tmp = double.Parse (d [0]);
+                               return new PointD (tmp, tmp);
+                       }
+                       throw new Exception ("Crow.PointD Parsing Error: " + s);
+               }
+
+               public override int GetHashCode ()
+               {
+#pragma warning disable RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »
+                       unchecked {
+                               var hashCode = 1861411795;
+                               hashCode = hashCode * -1521134295 + X.GetHashCode ();
+
+                               hashCode = hashCode * -1521134295 + Y.GetHashCode ();
+                               return hashCode;
+                       }
+#pragma warning restore RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »    }
+               }
+       }
+}
\ No newline at end of file
diff --git a/Crow/src/2d/Rectangle.cs b/Crow/src/2d/Rectangle.cs
new file mode 100644 (file)
index 0000000..a0e5ccf
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Runtime.InteropServices;
+
+namespace Crow {
+       [StructLayout(LayoutKind.Sequential)]
+       public struct Rectangle
+    {
+               public static readonly Rectangle Zero = new Rectangle (0, 0, 0, 0);
+
+               public int X, Y, Width, Height;
+
+               #region ctor
+               public Rectangle(Point p, Size s): this (p.X, p.Y, s.Width, s.Height) { }
+               public Rectangle(Size s) : this (0, 0, s.Width, s.Height) { }
+        public Rectangle(int x, int y, int width, int height) {
+                       X = x;
+                       Y = y;
+                       Width = width;
+                       Height = height;
+        }
+               #endregion
+
+               #region PROPERTIES
+               [XmlIgnore]public int Left{
+                       get => X;
+            set { X = value; }
+        }
+               [XmlIgnore]public int Top{
+            get => Y;
+            set { Y = value; }
+        }
+               [XmlIgnore] public int Right => X + Width;
+               [XmlIgnore]public int Bottom => Y + Height;
+               [XmlIgnore]public Size Size{
+                       get => new Size (Width, Height);
+            set {
+                Width = value.Width;
+                Height = value.Height;
+            }
+        }
+               [XmlIgnore]
+               public SizeD SizeD => new SizeD (Width, Height); 
+               [XmlIgnore]public Point Position{
+                       get => new Point (X, Y);
+                       set {
+                               X = value.X;
+                               Y = value.Y;
+                       }
+               }
+               [XmlIgnore]public Point TopLeft{
+                       get => new Point (X, Y);
+                       set {
+                X = value.X;
+                Y = value.Y;
+            }
+        }
+               [XmlIgnore] public Point TopRight => new Point (Right, Y);
+               [XmlIgnore] public Point BottomLeft => new Point (X, Bottom);
+               [XmlIgnore] public Point BottomRight => new Point (Right, Bottom);        
+               [XmlIgnore] public Point Center => new Point (Left + Width / 2, Top + Height / 2);
+               [XmlIgnore] public Point CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0);
+
+               #endregion
+
+               #region FUNCTIONS
+               public void Inflate(int xDelta, int yDelta)
+        {
+            this.X -= xDelta;
+            this.Width += 2 * xDelta;
+            this.Y -= yDelta;
+            this.Height += 2 * yDelta;
+        }
+               public void Inflate(int delta)
+               {
+                       Inflate (delta, delta);
+               }
+               public Rectangle Inflated (int delta) => Inflated (delta, delta);
+               public Rectangle Inflated (int deltaX, int deltaY) {
+                       Rectangle r = this;
+                       r.Inflate (deltaX, deltaY);
+                       return r;
+               }
+               public bool ContainsOrIsEqual (Point p) => (p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height);
+               public bool ContainsOrIsEqual (Rectangle r) => r.TopLeft >= this.TopLeft && r.BottomRight <= this.BottomRight;
+        public bool Intersect(Rectangle r)
+        {
+            int maxLeft = Math.Max(this.Left, r.Left);
+            int minRight = Math.Min(this.Right, r.Right);
+            int maxTop = Math.Max(this.Top, r.Top);
+            int minBottom = Math.Min(this.Bottom, r.Bottom);
+
+                       return (maxLeft < minRight) && (maxTop < minBottom);
+        }
+        public Rectangle Intersection(Rectangle r)
+        {
+            Rectangle result = new Rectangle();
+            
+            if (r.Left >= Left)
+                result.Left = r.Left;
+            else
+                result.TopLeft = TopLeft;
+
+            if (r.Right >= Right)
+                result.Width = Right - result.Left;
+            else
+                result.Width = r.Right - result.Left;
+
+            if (r.Top >= Top)
+                result.Top = r.Top;
+            else
+                result.Top = Top;
+
+            if (r.Bottom >= Bottom)
+                result.Height = Bottom - result.Top;
+            else
+                result.Height = r.Bottom - result.Top;
+
+            return result;
+        }
+               #endregion
+
+        #region operators
+        public static Rectangle operator +(Rectangle r1, Rectangle r2)
+        {
+            int x = Math.Min(r1.X, r2.X);
+            int y = Math.Min(r1.Y, r2.Y);
+            int x2 = Math.Max(r1.Right, r2.Right);
+            int y2 = Math.Max(r1.Bottom, r2.Bottom);
+            return new Rectangle(x, y, x2 - x, y2 - y);
+        }
+               public static Rectangle operator + (Rectangle r, Point p) => new Rectangle (r.X + p.X, r.Y + p.Y, r.Width, r.Height);
+               public static Rectangle operator - (Rectangle r, Point p) => new Rectangle (r.X - p.X, r.Y - p.Y, r.Width, r.Height);
+               public static bool operator == (Rectangle r1, Rectangle r2) => r1.TopLeft == r2.TopLeft && r1.Size == r2.Size;
+               public static bool operator != (Rectangle r1, Rectangle r2) => !(r1.TopLeft == r2.TopLeft && r1.Size == r2.Size);
+
+               public static implicit operator Rectangle (RectangleD r) => new Rectangle ((int)Math.Round(r.X), (int)Math.Round (r.Y),
+                       (int)Math.Round (r.Width), (int)Math.Round (r.Height));
+               #endregion
+
+               public override string ToString () => $"{X},{Y},{Width},{Height}";        
+        public static Rectangle Parse(string s)
+        {
+            string[] d = s.Split(new char[] { ',' });
+            return new Rectangle(
+                int.Parse(d[0]),
+                int.Parse(d[1]),
+                int.Parse(d[2]),
+                int.Parse(d[3]));
+        }
+               public override int GetHashCode ()
+               {
+                       unchecked // Overflow is fine, just wrap
+                       {
+                               int hash = 17;
+                               // Suitable nullity checks etc, of course :)
+                               hash = hash * 23 + X.GetHashCode();
+                               hash = hash * 23 + Y.GetHashCode();
+                               hash = hash * 23 + Width.GetHashCode();
+                               hash = hash * 23 + Height.GetHashCode();
+                               return hash;
+                       }
+               }
+               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (Rectangle)) ?
+                               false : this == (Rectangle)obj;
+    }
+}
diff --git a/Crow/src/2d/RectangleD.cs b/Crow/src/2d/RectangleD.cs
new file mode 100644 (file)
index 0000000..817b3ad
--- /dev/null
@@ -0,0 +1,166 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Runtime.InteropServices;
+
+namespace Crow {
+       [StructLayout(LayoutKind.Sequential)]
+       public struct RectangleD
+    {
+               public static readonly RectangleD Zero = new RectangleD (0, 0, 0, 0);
+
+               public double X, Y, Width, Height;
+
+               #region ctor
+               public RectangleD(PointD p, Size s): this (p.X, p.Y, s.Width, s.Height) { }
+               public RectangleD(SizeD s) : this (0, 0, s.Width, s.Height) { }
+        public RectangleD(double x, double y, double width, double height) {
+                       X = x;
+                       Y = y;
+                       Width = width;
+                       Height = height;
+        }
+               #endregion
+
+               #region PROPERTIES
+               [XmlIgnore]public double Left{
+                       get => X;
+            set { X = value; }
+        }
+               [XmlIgnore]public double Top{
+            get => Y;
+            set { Y = value; }
+        }
+               [XmlIgnore] public double Right => X + Width;
+               [XmlIgnore]public double Bottom => Y + Height;
+               [XmlIgnore]public SizeD Size{
+                       get => new SizeD (Width, Height);
+            set {
+                Width = value.Width;
+                Height = value.Height;
+            }
+        }
+               [XmlIgnore]public PointD Position{
+                       get => new PointD (X, Y);
+                       set {
+                               X = value.X;
+                               Y = value.Y;
+                       }
+               }
+               [XmlIgnore]public PointD TopLeft{
+                       get => new PointD (X, Y);
+                       set {
+                X = value.X;
+                Y = value.Y;
+            }
+        }
+               [XmlIgnore] public PointD TopRight => new PointD (Right, Y);
+               [XmlIgnore] public PointD BottomLeft => new PointD (X, Bottom);
+               [XmlIgnore] public PointD BottomRight => new PointD (Right, Bottom);        
+               [XmlIgnore] public PointD Center => new PointD (Left + Width / 2, Top + Height / 2);
+               [XmlIgnore] public PointD CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0);
+
+               #endregion
+
+               #region FUNCTIONS
+               public void Inflate(double xDelta, double yDelta)
+        {
+            this.X -= xDelta;
+            this.Width += 2 * xDelta;
+            this.Y -= yDelta;
+            this.Height += 2 * yDelta;
+        }
+               public void Inflate(double delta)
+               {
+                       Inflate (delta, delta);
+               }
+               public RectangleD Inflated (double delta) => Inflated (delta, delta);
+               public RectangleD Inflated (double deltaX, double deltaY) {
+                       RectangleD r = this;
+                       r.Inflate (deltaX, deltaY);
+                       return r;
+               }
+               public bool ContainsOrIsEqual (PointD p) => (p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height);
+               public bool ContainsOrIsEqual (RectangleD r) => r.TopLeft >= this.TopLeft && r.BottomRight <= this.BottomRight;
+        public bool Intersect(RectangleD r)
+        {
+            double maxLeft = Math.Max(this.Left, r.Left);
+            double minRight = Math.Min(this.Right, r.Right);
+            double maxTop = Math.Max(this.Top, r.Top);
+            double minBottom = Math.Min(this.Bottom, r.Bottom);
+
+                       return (maxLeft < minRight) && (maxTop < minBottom);
+        }
+        public RectangleD Intersection(RectangleD r)
+        {
+            RectangleD result = new RectangleD();
+            
+            if (r.Left >= Left)
+                result.Left = r.Left;
+            else
+                result.TopLeft = TopLeft;
+
+            if (r.Right >= Right)
+                result.Width = Right - result.Left;
+            else
+                result.Width = r.Right - result.Left;
+
+            if (r.Top >= Top)
+                result.Top = r.Top;
+            else
+                result.Top = Top;
+
+            if (r.Bottom >= Bottom)
+                result.Height = Bottom - result.Top;
+            else
+                result.Height = r.Bottom - result.Top;
+
+            return result;
+        }
+               #endregion
+
+        #region operators
+        public static RectangleD operator +(RectangleD r1, RectangleD r2)
+        {
+            double x = Math.Min(r1.X, r2.X);
+            double y = Math.Min(r1.Y, r2.Y);
+            double x2 = Math.Max(r1.Right, r2.Right);
+            double y2 = Math.Max(r1.Bottom, r2.Bottom);
+            return new RectangleD(x, y, x2 - x, y2 - y);
+        }
+               public static RectangleD operator + (RectangleD r, PointD p) => new RectangleD (r.X + p.X, r.Y + p.Y, r.Width, r.Height);
+               public static RectangleD operator - (RectangleD r, PointD p) => new RectangleD (r.X - p.X, r.Y - p.Y, r.Width, r.Height);
+               public static bool operator == (RectangleD r1, RectangleD r2) => r1.TopLeft == r2.TopLeft && r1.Size == r2.Size;
+               public static bool operator != (RectangleD r1, RectangleD r2) => !(r1.TopLeft == r2.TopLeft && r1.Size == r2.Size);
+
+               public static implicit operator RectangleD(Rectangle r) => new RectangleD(r.X,r.Y,r.Width,r.Height);
+        #endregion        
+
+               public override string ToString () => $"{X},{Y},{Width},{Height}";        
+        public static RectangleD Parse(string s)
+        {
+            string[] d = s.Split(new char[] { ',' });
+            return new RectangleD(
+                double.Parse(d[0]),
+                double.Parse(d[1]),
+                double.Parse(d[2]),
+                double.Parse(d[3]));
+        }
+               public override int GetHashCode ()
+               {
+                       unchecked // Overflow is fine, just wrap
+                       {
+                               int hash = 17;
+                               // Suitable nullity checks etc, of course :)
+                               hash = hash * 23 + X.GetHashCode();
+                               hash = hash * 23 + Y.GetHashCode();
+                               hash = hash * 23 + Width.GetHashCode();
+                               hash = hash * 23 + Height.GetHashCode();
+                               return hash;
+                       }
+               }
+               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (RectangleD)) ?
+                               false : this == (RectangleD)obj;
+    }
+}
diff --git a/Crow/src/2d/Size.cs b/Crow/src/2d/Size.cs
new file mode 100644 (file)
index 0000000..77347f0
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+namespace Crow
+{
+    public struct Size
+    {
+               public static Size Zero => new Size (0, 0);
+
+               public int Width, Height;
+
+               #region CTOR
+               public Size (int width, int height)
+               {
+                       Width = width;
+                       Height = height;
+               }
+               public Size (int size)
+               {
+                       Width = size;
+                       Height = size;
+               }
+               #endregion
+
+               #region operators
+               public static implicit operator Rectangle(Size s)=> new Rectangle (s);
+        public static implicit operator Size(int i)=> new Size(i, i);
+               public static implicit operator string(Size s)=> s.ToString ();
+               public static implicit operator Size(string s)=> string.IsNullOrEmpty (s) ? Zero : Parse (s);
+
+               public static bool operator == (Size s1, Size s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
+               public static bool operator != (Size s1, Size s2) => (s1.Width != s2.Width || s1.Height != s2.Height);
+               public static bool operator > (Size s1, Size s2) => (s1.Width > s2.Width && s1.Height > s2.Height);
+               public static bool operator >= (Size s1, Size s2) => (s1.Width >= s2.Width && s1.Height >= s2.Height);
+               public static bool operator < (Size s1, Size s2) => (s1.Width < s2.Width) ? s1.Height <= s2.Height :
+                                                                                                                               (s1.Width == s2.Width && s1.Height < s2.Height);
+               public static bool operator < (Size s, int i) => s.Width < i && s.Height < i;
+               public static bool operator <= (Size s, int i) => s.Width <= i && s.Height <= i;
+               public static bool operator > (Size s, int i) => s.Width > i && s.Height > i;
+               public static bool operator >= (Size s, int i) => s.Width >= i && s.Height >= i;
+               public static bool operator <= (Size s1, Size s2) => (s1.Width <= s2.Width && s1.Height <= s2.Height);
+               public static bool operator == (Size s, int i) => (s.Width == i && s.Height == i);
+               public static bool operator != (Size s, int i) => (s.Width != i || s.Height != i);
+               public static Size operator + (Size s1, Size s2) => new Size (s1.Width + s2.Width, s1.Height + s2.Height);
+               public static Size operator + (Size s, int i) => new Size (s.Width + i, s.Height + i);
+               public static Size operator * (Size s, int i) => new Size (s.Width * i, s.Height * i);
+               public static Size operator / (Size s, int i) => new Size (s.Width / i, s.Height / i);
+               #endregion
+
+               public override int GetHashCode ()
+               {
+                       unchecked // Overflow is fine, just wrap
+                       {
+                               int hash = 17;
+                               // Suitable nullity checks etc, of course :)
+                               hash = hash * 23 + Width.GetHashCode();
+                               hash = hash * 23 + Height.GetHashCode();
+                               return hash;
+                       }
+               }
+               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (Size)) ? false : this == (Size)obj;
+               public override string ToString () => $"{Width},{Height}";
+               public static Size Parse(string s)
+               {
+                       string[] d = s.Split(new char[] { ',' });
+                       return d.Length == 1 ? new Size(int.Parse(d[0])) : new Size(
+                               int.Parse(d[0]),
+                               int.Parse(d[1]));
+               }
+       }
+}
diff --git a/Crow/src/2d/SizeD.cs b/Crow/src/2d/SizeD.cs
new file mode 100644 (file)
index 0000000..2dbdb02
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+namespace Crow
+{
+       public struct SizeD {
+               public static SizeD Zero => new SizeD (0, 0);
+
+               public double Width, Height;
+
+               #region CTOR
+               public SizeD (double width, double height)
+               {
+                       Width = width;
+                       Height = height;
+               }
+               public SizeD (double size)
+               {
+                       Width = size;
+                       Height = size;
+               }
+               #endregion
+
+               #region operators
+               public static implicit operator RectangleD (SizeD s) => new RectangleD (s);
+               public static implicit operator SizeD (double i) => new SizeD (i, i);
+               public static implicit operator string (SizeD s) => s.ToString ();
+               public static implicit operator SizeD (string s) => string.IsNullOrEmpty (s) ? Zero : Parse (s);
+
+               public static bool operator == (SizeD s1, SizeD s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
+               public static bool operator != (SizeD s1, SizeD s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
+               public static bool operator > (SizeD s1, SizeD s2) => (s1.Width > s2.Width && s1.Height > s2.Height);
+               public static bool operator >= (SizeD s1, SizeD s2) => (s1.Width >= s2.Width && s1.Height >= s2.Height);
+               public static bool operator < (SizeD s1, SizeD s2) => (s1.Width < s2.Width) ? s1.Height <= s2.Height :
+                                                                                                                               (s1.Width == s2.Width && s1.Height < s2.Height);
+               public static bool operator < (SizeD s, double i) => s.Width < i && s.Height < i;
+               public static bool operator <= (SizeD s, double i) => s.Width <= i && s.Height <= i;
+               public static bool operator > (SizeD s, double i) => s.Width > i && s.Height > i;
+               public static bool operator >= (SizeD s, double i) => s.Width >= i && s.Height >= i;
+               public static bool operator <= (SizeD s1, SizeD s2) => (s1.Width <= s2.Width && s1.Height <= s2.Height);
+               public static bool operator == (SizeD s, double i) => (s.Width == i && s.Height == i);
+               public static bool operator != (SizeD s, double i) => (s.Width == i && s.Height == i);
+               public static SizeD operator + (SizeD s1, SizeD s2) => new SizeD (s1.Width + s2.Width, s1.Height + s2.Height);
+               public static SizeD operator + (SizeD s, double i) => new SizeD (s.Width + i, s.Height + i);
+               public static SizeD operator * (SizeD s, double i) => new SizeD (s.Width * i, s.Height * i);
+               public static SizeD operator / (SizeD s, double i) => new SizeD (s.Width / i, s.Height / i);
+               #endregion
+
+               public override int GetHashCode ()
+               {
+                       unchecked // Overflow is fine, just wrap
+                       {
+                               int hash = 17;
+                               // Suitable nullity checks etc, of course :)
+                               hash = hash * 23 + Width.GetHashCode ();
+                               hash = hash * 23 + Height.GetHashCode ();
+                               return hash;
+                       }
+               }
+               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (SizeD)) ? false : this == (SizeD)obj;
+               public override string ToString () => $"{Width},{Height}";
+               public static SizeD Parse (string s)
+               {
+                       string [] d = s.Split (new char [] { ',' });
+                       return d.Length == 1 ? new SizeD (double.Parse (d [0])) : new SizeD (
+                               double.Parse (d [0]),
+                               double.Parse (d [1]));
+               }
+       }
+}
diff --git a/Crow/src/DragDropEventArgs.cs b/Crow/src/DragDropEventArgs.cs
deleted file mode 100644 (file)
index b79c366..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// LayoutingEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class DragDropEventArgs: EventArgs
-       {
-               /// <summary>
-               /// Source of the drag and drop operation
-               /// </summary>
-               public Widget DragSource;
-               /// <summary>
-               /// Target of the drag and drop operation
-               /// </summary>
-               public Widget DropTarget;
-
-               //public DragDropEventArgs (GraphicObject source, GraphicObject target = null) : base()
-               public DragDropEventArgs (Widget source = null, Widget target = null) : base()
-               {
-                       DragSource = source;
-                       DropTarget = target;
-               }
-
-               public override string ToString ()
-               {
-                       return string.Format ("{0} => {1}", DragSource,DropTarget);
-               }
-       }
-}
-
diff --git a/Crow/src/EventArgs/DragDropEventArgs.cs b/Crow/src/EventArgs/DragDropEventArgs.cs
new file mode 100644 (file)
index 0000000..b79c366
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// LayoutingEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class DragDropEventArgs: EventArgs
+       {
+               /// <summary>
+               /// Source of the drag and drop operation
+               /// </summary>
+               public Widget DragSource;
+               /// <summary>
+               /// Target of the drag and drop operation
+               /// </summary>
+               public Widget DropTarget;
+
+               //public DragDropEventArgs (GraphicObject source, GraphicObject target = null) : base()
+               public DragDropEventArgs (Widget source = null, Widget target = null) : base()
+               {
+                       DragSource = source;
+                       DropTarget = target;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("{0} => {1}", DragSource,DropTarget);
+               }
+       }
+}
+
diff --git a/Crow/src/EventArgs/LayoutingEventArgs.cs b/Crow/src/EventArgs/LayoutingEventArgs.cs
new file mode 100644 (file)
index 0000000..9254aec
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// LayoutingEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class LayoutingEventArgs: EventArgs
+       {
+               public LayoutingType  LayoutType;
+
+               public LayoutingEventArgs (LayoutingType  _layoutType) : base()
+               {
+                       LayoutType = _layoutType;
+               }
+       }
+}
+
diff --git a/Crow/src/EventArgs/ListChangedEventArg.cs b/Crow/src/EventArgs/ListChangedEventArg.cs
new file mode 100644 (file)
index 0000000..3fc509e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (c) 2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+namespace Crow
+{
+       public class ListChangedEventArg : EventArgs
+       {
+               public int Index;
+               public object Element;
+               public ListChangedEventArg (int index, object element)
+               {
+                       Index = index;
+                       Element = element;
+               }
+       }
+}
diff --git a/Crow/src/EventArgs/MouseCursorChangedEventArgs.cs b/Crow/src/EventArgs/MouseCursorChangedEventArgs.cs
new file mode 100644 (file)
index 0000000..5e58b86
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// MouseCursorChangedEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class MouseCursorChangedEventArgs : EventArgs
+       {
+               public MouseCursor NewCursor;
+               public MouseCursorChangedEventArgs (MouseCursor newCursor) : base()
+               {
+                       NewCursor = newCursor;
+               }
+       }
+}
diff --git a/Crow/src/EventArgs/ScrollingEventArgs.cs b/Crow/src/EventArgs/ScrollingEventArgs.cs
new file mode 100644 (file)
index 0000000..3ff4206
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// ScrollingEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class ScrollingEventArgs: EventArgs
+       {
+               public Orientation  Direction;
+
+               public ScrollingEventArgs (Orientation  _direction) : base()
+               {
+                       Direction = _direction;
+               }
+       }
+}
+
diff --git a/Crow/src/EventArgs/SelectionChangeEventArgs.cs b/Crow/src/EventArgs/SelectionChangeEventArgs.cs
new file mode 100644 (file)
index 0000000..988a697
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// SelectionChangeEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class SelectionChangeEventArgs: EventArgs
+       {               
+               public object NewValue;
+
+
+               public SelectionChangeEventArgs (object _newValue) : base()
+               {
+                       NewValue = _newValue;
+               }
+       }
+}
+
diff --git a/Crow/src/EventArgs/TextChangeEventArgs.cs b/Crow/src/EventArgs/TextChangeEventArgs.cs
new file mode 100644 (file)
index 0000000..33ca405
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// TextChangeEventArgs.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Crow
+{
+       public class TextChangeEventArgs: EventArgs
+       {
+               public String Text;
+
+               public TextChangeEventArgs (string _newValue) : base()
+               {
+                       Text = _newValue;
+               }
+       }
+}
+
diff --git a/Crow/src/EventArgs/ValueChangeEventArgs.cs b/Crow/src/EventArgs/ValueChangeEventArgs.cs
new file mode 100644 (file)
index 0000000..854e2cd
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+       /// <summary>
+       /// Arguments for the ValueChange event used for Binding
+       /// </summary>
+       public class ValueChangeEventArgs: EventArgs
+       {
+               /// <summary>The name of the member whose value has changed</summary>
+               public string MemberName;
+               /// <summary>New value for that member</summary>
+               public object NewValue;
+
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:Crow.ValueChangeEventArgs"/> class.
+               /// </summary>
+               /// <param name="_memberName">Member name.</param>
+               /// <param name="_newValue">New value.</param>
+               public ValueChangeEventArgs (string _memberName, object _newValue) : base()
+               {
+                       MemberName = _memberName;
+                       NewValue = _newValue;
+               }
+       }
+}
+
diff --git a/Crow/src/Fill/Gradient.cs b/Crow/src/Fill/Gradient.cs
new file mode 100644 (file)
index 0000000..0e81484
--- /dev/null
@@ -0,0 +1,140 @@
+//
+// Gradient.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using Crow.Cairo;
+
+namespace Crow
+{
+       public class Gradient : Fill
+       {
+               public enum Type
+               {
+                       Vertical,
+                       Horizontal,
+                       Oblic,
+                       Radial
+               }
+               public class ColorStop
+               {
+                       public double Offset;
+                       public Color Color;
+
+                       public ColorStop(double offset, Color color){ 
+                               Offset = offset;
+                               Color = color;
+                       }
+                       public static object Parse(string s)
+                       {
+                               if (string.IsNullOrEmpty (s))
+                                       return null;
+                               
+                               string[] parts = s.Trim ().Split (':');
+
+                               if (parts.Length > 2)
+                                       throw new Exception ("too many parameters in color stop: " + s);
+                               
+                               if (parts.Length == 2)
+                                       return new ColorStop (double.Parse (parts [0]), (Color)parts [1]);
+
+                               return new ColorStop (-1, (Color)parts [0]);
+                       }
+               }
+               public Gradient.Type GradientType = Type.Vertical;
+//             public double x0;
+//             public double y0;
+//             public double x1;
+//             public double y1;
+//             public double Radius1;
+//             public double Radius2;
+               public List<ColorStop> Stops = new List<ColorStop>();
+               public Gradient(Gradient.Type _type)
+               {
+                       GradientType = _type;
+               }
+
+               #region implemented abstract members of Fill
+
+               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
+               {
+                       Cairo.Gradient grad = null;
+                       switch (GradientType) {
+                       case Type.Vertical:
+                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Left, bounds.Bottom);
+                               break;
+                       case Type.Horizontal:
+                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Top);
+                               break;
+                       case Type.Oblic:
+                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
+                               break;
+                       case Type.Radial:
+                               throw new NotImplementedException ();
+                       }
+
+                       foreach (ColorStop cs in Stops) {
+                               if (cs == null)
+                                       continue;
+                               grad.AddColorStop (cs.Offset, cs.Color);
+                       }
+                       
+                       ctx.SetSource (grad);
+                       grad.Dispose ();
+               }
+               #endregion
+
+               public static new object Parse(string s)
+               {
+                       if (string.IsNullOrEmpty (s))
+                               return Color.White;
+
+                       Crow.Gradient tmp;
+
+                       string[] stops = s.Trim ().Split ('|');
+
+                       switch (stops[0].Trim()) {
+                       case "vgradient":
+                               tmp = new Gradient (Type.Vertical);
+                               break;
+                       case "hgradient":
+                               tmp = new Gradient (Type.Horizontal);
+                               break;
+                       case "ogradient":
+                               tmp = new Gradient (Type.Oblic);
+                               break;
+                       default:
+                               throw new Exception ("Unknown gradient type: " + stops [0]);
+                       }
+
+                       for (int i = 1; i < stops.Length; i++)
+                               tmp.Stops.Add((ColorStop)ColorStop.Parse(stops[i]));
+
+                       return tmp;
+               }
+       }
+}
+
diff --git a/Crow/src/Gradient.cs b/Crow/src/Gradient.cs
deleted file mode 100644 (file)
index 0e81484..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// Gradient.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using Crow.Cairo;
-
-namespace Crow
-{
-       public class Gradient : Fill
-       {
-               public enum Type
-               {
-                       Vertical,
-                       Horizontal,
-                       Oblic,
-                       Radial
-               }
-               public class ColorStop
-               {
-                       public double Offset;
-                       public Color Color;
-
-                       public ColorStop(double offset, Color color){ 
-                               Offset = offset;
-                               Color = color;
-                       }
-                       public static object Parse(string s)
-                       {
-                               if (string.IsNullOrEmpty (s))
-                                       return null;
-                               
-                               string[] parts = s.Trim ().Split (':');
-
-                               if (parts.Length > 2)
-                                       throw new Exception ("too many parameters in color stop: " + s);
-                               
-                               if (parts.Length == 2)
-                                       return new ColorStop (double.Parse (parts [0]), (Color)parts [1]);
-
-                               return new ColorStop (-1, (Color)parts [0]);
-                       }
-               }
-               public Gradient.Type GradientType = Type.Vertical;
-//             public double x0;
-//             public double y0;
-//             public double x1;
-//             public double y1;
-//             public double Radius1;
-//             public double Radius2;
-               public List<ColorStop> Stops = new List<ColorStop>();
-               public Gradient(Gradient.Type _type)
-               {
-                       GradientType = _type;
-               }
-
-               #region implemented abstract members of Fill
-
-               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
-               {
-                       Cairo.Gradient grad = null;
-                       switch (GradientType) {
-                       case Type.Vertical:
-                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Left, bounds.Bottom);
-                               break;
-                       case Type.Horizontal:
-                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Top);
-                               break;
-                       case Type.Oblic:
-                               grad = new Cairo.LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
-                               break;
-                       case Type.Radial:
-                               throw new NotImplementedException ();
-                       }
-
-                       foreach (ColorStop cs in Stops) {
-                               if (cs == null)
-                                       continue;
-                               grad.AddColorStop (cs.Offset, cs.Color);
-                       }
-                       
-                       ctx.SetSource (grad);
-                       grad.Dispose ();
-               }
-               #endregion
-
-               public static new object Parse(string s)
-               {
-                       if (string.IsNullOrEmpty (s))
-                               return Color.White;
-
-                       Crow.Gradient tmp;
-
-                       string[] stops = s.Trim ().Split ('|');
-
-                       switch (stops[0].Trim()) {
-                       case "vgradient":
-                               tmp = new Gradient (Type.Vertical);
-                               break;
-                       case "hgradient":
-                               tmp = new Gradient (Type.Horizontal);
-                               break;
-                       case "ogradient":
-                               tmp = new Gradient (Type.Oblic);
-                               break;
-                       default:
-                               throw new Exception ("Unknown gradient type: " + stops [0]);
-                       }
-
-                       for (int i = 1; i < stops.Length; i++)
-                               tmp.Stops.Add((ColorStop)ColorStop.Parse(stops[i]));
-
-                       return tmp;
-               }
-       }
-}
-
diff --git a/Crow/src/IListChanged.cs b/Crow/src/IListChanged.cs
deleted file mode 100644 (file)
index fd6e60a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// IListChanged.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-
-namespace Crow
-{
-       public class ListChangedEventArg : EventArgs {
-               public int Index;
-               public object Element;
-               public ListChangedEventArg (int index, object element) {
-                       Index = index;
-                       Element = element;
-               }
-       }
-       public interface IObservableList {
-               event EventHandler<ListChangedEventArg> ListAdd;
-               event EventHandler<ListChangedEventArg> ListRemove;
-               event EventHandler<ListChangedEventArg> ListEdit;
-
-               void Insert ();
-               void Remove ();
-               void RaiseEdit ();
-       }
-}
-
diff --git a/Crow/src/IML/IMLAttributes.cs b/Crow/src/IML/IMLAttributes.cs
new file mode 100644 (file)
index 0000000..929fd4f
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// IMLAttributes.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Crow
+{
+       public class DesignIgnore : Attribute
+       {               
+       }
+
+       public class DesignCategory : Attribute
+       {
+               public string Name { get; set; }
+
+               public DesignCategory (string name)
+               {
+                       Name = name;
+               }
+       }
+}
+
diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs
new file mode 100644 (file)
index 0000000..760b5b1
--- /dev/null
@@ -0,0 +1,1465 @@
+// Copyright (c) 2013-2019  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Xml;
+
+namespace Crow.IML {
+       public class InstantiatorException : Exception {
+               public string Path;
+               public InstantiatorException (string path, Exception innerException)
+                       : base ("ITor error:" + path, innerException){
+                       Path = path;
+               }
+       }
+       public delegate object InstanciatorInvoker(Interface iface);
+
+       /// <summary>
+       /// Reflexion being very slow, the settings of the starting values for widgets are set by a dynamic method.
+       /// This method is created on the first instacing and is recalled for further widget instancing.
+       /// 
+       /// It includes:
+       ///     - XML values setting
+       ///     - Default values (appearing as attribute in C#)  loading
+       ///     - Styling
+       /// 
+       /// Instantiators are shared amongs interfaces. Their are stored with their path as key, and inlined template
+       /// and itemtemplate are stored with a generated uuid
+       /// </summary>
+       public class Instantiator
+       {
+               #region Dynamic Method ID generation
+               static long curId = 0;
+               internal static long NewId {
+                       get { return curId++; }
+               }
+               #endregion
+
+               internal static Dictionary<string, Type> knownGOTypes = new Dictionary<string, Type> ();
+
+               public Type RootType;
+               InstanciatorInvoker loader;
+               protected Interface iface;
+
+               internal string sourcePath;
+
+               #if DESIGN_MODE
+               public static int NextInstantiatorID = 0;
+               public int currentInstantiatorID = 0;
+               int currentDesignID = 0;
+               internal string NextDesignID { get { return string.Format ("{0}_{1}",currentInstantiatorID, currentDesignID++); }}
+               #endif
+
+               #region CTOR
+               /// <summary>
+               /// Initializes a new instance of the Instantiator class.
+               /// </summary>
+               public Instantiator (Interface _iface, string path) : this (_iface, _iface.GetStreamFromPath(path), path) {
+                       
+               }
+               /// <summary>
+               /// Initializes a new instance of the Instantiator class.
+               /// </summary>
+               public Instantiator (Interface _iface, Stream stream, string srcPath = null)
+               {
+                       #if DESIGN_MODE
+                       currentInstantiatorID = NextInstantiatorID++;
+                       #endif
+                       iface = _iface;
+                       sourcePath = srcPath;
+                       #if DEBUG_LOAD
+                       Stopwatch loadingTime = Stopwatch.StartNew ();
+                       #endif
+                       try {
+                               using (XmlReader itr = XmlReader.Create (stream)) {
+                                       parseIML (itr);
+                               }
+                       } catch (Exception ex) {
+                               throw new InstantiatorException(sourcePath, ex);
+                       } finally {
+                               stream?.Dispose ();
+#if DEBUG_LOAD
+                               loadingTime.Stop ();
+                               using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
+                                       sw.WriteLine ($"ITOR;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
+                               }
+#endif
+                       }
+               }
+               /// <summary>
+               /// Initializes a new instance of the Instantiator class with an already openned xml reader
+               /// positionned on the start tag inside the itemTemplate
+               /// </summary>
+               public Instantiator (Interface _iface, XmlReader itr){
+                       #if DESIGN_MODE
+                       currentInstantiatorID = NextInstantiatorID++;
+                       #endif
+                       iface = _iface;
+                       parseIML (itr);
+               }
+               //TODO:check if still used
+               public Instantiator (Interface _iface, Type _root, InstanciatorInvoker _loader)
+               {
+                       #if DESIGN_MODE
+                       currentInstantiatorID = NextInstantiatorID++;
+                       #endif
+                       iface = _iface;
+                       RootType = _root;
+                       loader = _loader;
+               }
+               /// <summary>
+               /// Create a new instantiator from IML fragment provided directely as a string
+               /// </summary>
+               /// <returns>A new instantiator</returns>
+               /// <param name="fragment">IML string</param>
+               public static Instantiator CreateFromImlFragment (Interface _iface, string fragment)
+               {
+                       using (Stream s = new MemoryStream (Encoding.UTF8.GetBytes (fragment))) {
+                               return new Instantiator (_iface, s);
+                       }
+               }
+               #endregion
+
+               /// <summary>
+               /// Creates a new instance of the GraphicObject compiled in the instantiator
+               /// </summary>
+               /// <returns>The new graphic object instance</returns>
+               public Widget CreateInstance(){
+#if DEBUG_LOAD
+                       Stopwatch loadingTime = Stopwatch.StartNew ();
+                       GraphicObject o = loader (iface) as GraphicObject;
+                       loadingTime.Stop ();
+                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
+                               sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
+                       }
+                       return o;
+#else
+                       return loader (iface) as Widget;
+#endif
+               }
+               /// <summary>
+               /// Creates a new instance of T compiled in the instantiator
+               /// and bind it the an interface
+               /// </summary>
+               /// <returns>The new T instance</returns>
+               public T CreateInstance<T>(){
+#if DEBUG_LOAD
+                       Stopwatch loadingTime = Stopwatch.StartNew ();
+                       T i = (T)loader (iface);
+                       loadingTime.Stop ();
+                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
+                               sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
+                       }
+                       return i;
+#else
+                       return (T)loader (iface);
+#endif
+               }
+               List<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
+               List<Delegate> cachedDelegates = new List<Delegate>();
+               /// <summary>
+               /// store indices of template delegate to be handled by root parentChanged event
+               /// </summary>
+               List<int> templateCachedDelegateIndices = new List<int>();
+               /// <summary>
+               /// Store template bindings in the instantiator
+               /// </summary>
+               Delegate templateBinding;
+
+#if DESIGN_MODE
+               public List<DynamicMethod> DsValueChangedDynMeths =>dsValueChangedDynMeths;
+               public List<Delegate> CachedDelegates => cachedDelegates;
+               /// <summary>
+               /// store indices of template delegate to be handled by root parentChanged event
+               /// </summary>
+               public List<int> TemplateCachedDelegateIndices => templateCachedDelegateIndices;
+               /// <summary>
+               /// Store template bindings in the instantiator
+               /// </summary>
+               public Delegate TemplateBinding => templateBinding;
+
+#endif
+               #region IML parsing
+               /// <summary>
+               /// Parses IML and build a dynamic method that will be used to instantiate one or multiple occurences of the IML file or fragment
+               /// </summary>
+               void parseIML (XmlReader reader) {
+                       IMLContext ctx = new IMLContext (findRootType (reader));
+
+                       ctx.PushNode (ctx.RootType);
+                       emitLoader (reader, ctx);
+                       ctx.PopNode ();
+
+                       foreach (int idx in templateCachedDelegateIndices)
+                               ctx.emitCachedDelegateHandlerAddition(idx, CompilerServices.eiLogicalParentChanged);
+
+                       ctx.ResolveNamedTargets ();
+
+                       emitBindingDelegates (ctx);
+
+            ctx.il.Emit (OpCodes.Ldloc_0);//load root obj to return
+                       ctx.il.Emit(OpCodes.Ret);
+
+                       reader.Read ();//close tag
+                       RootType = ctx.RootType;
+                       loader = (InstanciatorInvoker)ctx.dm.CreateDelegate (typeof (InstanciatorInvoker), this);
+               }
+               /// <summary>
+               /// read first node to set GraphicObject class for loading
+               /// and let reader position on that node
+               /// </summary>
+               Type findRootType (XmlReader reader)
+               {
+                       string root = "Object";
+                       while (reader.NodeType != XmlNodeType.Element)
+                               reader.Read ();
+                       root = reader.Name;
+                       Type t = tryGetGOType (root);
+                       if (t == null)
+                               throw new Exception ("IML parsing error: undefined root type (" + root + ")");
+                       return t;
+               }
+               /// <summary>
+               /// main parsing entry point
+               /// </summary>
+               void emitLoader (XmlReader reader, IMLContext ctx)
+               {
+                       int curLine = ctx.curLine;
+
+                       #if DESIGN_MODE
+                       IXmlLineInfo li = (IXmlLineInfo)reader;
+                       ctx.curLine += li.LineNumber - 1;
+                       #endif
+
+                       string tmpXml = reader.ReadOuterXml ();
+
+                       if (ctx.nodesStack.Peek().HasTemplate)
+                               emitTemplateLoad (ctx, tmpXml);
+
+                       emitGOLoad (ctx, tmpXml);
+
+                       ctx.curLine = curLine;
+               }
+               /// <summary>
+               /// Parses the item template tag.
+               /// </summary>
+               /// <returns>the string triplet dataType, itemTmpID read as attribute of this tag</returns>
+               /// <param name="reader">current xml text reader</param>
+               /// <param name="itemTemplatePath">file containing the templates if its a dedicated one</param>
+               string[] parseItemTemplateTag (IMLContext ctx, XmlReader reader, string itemTemplatePath = "") {
+                       string dataType = "default", datas = "", path = "", dataTest = "TypeOf";
+                       while (reader.MoveToNextAttribute ()) {
+                               if (reader.Name == "DataType")
+                                       dataType = reader.Value;
+                               else if (reader.Name == "Data")
+                                       datas = reader.Value;
+                               else if (reader.Name == "Path")
+                                       path = reader.Value;
+                               else if (reader.Name == "DataTest")
+                                       dataTest = reader.Value;
+                       }
+                       reader.MoveToElement ();
+
+                       string itemTmpID = itemTemplatePath;
+
+                       if (string.IsNullOrEmpty (path)) {
+                               itemTmpID += Guid.NewGuid ().ToString ();
+                               iface.ItemTemplates [itemTmpID] =
+                                       new ItemTemplate (iface, new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataTest, dataType, datas);
+
+                       } else {
+                               if (!reader.IsEmptyElement)
+                                       throw new Exception ("ItemTemplate with Path attribute set may not include sub nodes");
+                               itemTmpID += path+dataType+datas;
+                               if (!iface.ItemTemplates.ContainsKey (itemTmpID))
+                                       iface.ItemTemplates [itemTmpID] =
+                                               new ItemTemplate (iface, path, ctx.CurrentNodeType, dataTest, dataType, datas);
+                       }
+                       return new string [] { dataType, itemTmpID, datas, dataTest };
+               }
+               /// <summary>
+               /// process template and item template definition prior to
+               /// other attributes or childs processing
+               /// </summary>
+               /// <param name="ctx">Loading Context</param>
+               /// <param name="tmpXml">xml fragment</param>
+               void emitTemplateLoad (IMLContext ctx, string tmpXml) {
+                       //if its a template, first read template elements
+                       using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
+                               List<string[]> itemTemplateIds = new List<string[]> ();
+                               bool inlineTemplate = false;
+
+                               reader.Read ();
+                               string templatePath = reader.GetAttribute ("Template");
+                               string itemTemplatePath = reader.GetAttribute ("ItemTemplate");
+
+                               int depth = reader.Depth + 1;
+                               while (reader.Read ()) {
+                                       if (!reader.IsStartElement () || reader.Depth > depth)
+                                               continue;
+                                       if (reader.Name == "Template") {
+                                               inlineTemplate = true;
+                                               #if DESIGN_MODE
+                                               ctx.il.Emit (OpCodes.Ldloc_0);
+                                               ctx.il.Emit (OpCodes.Ldc_I4_1);
+                                               ctx.il.Emit (OpCodes.Stfld, typeof(TemplatedControl).GetField("design_inlineTemplate"));
+                                               #endif
+                                               reader.Read ();
+                                               readChildren (reader, ctx, -1);
+                                       } else if (reader.Name == "ItemTemplate")
+                                               itemTemplateIds.Add (parseItemTemplateTag (ctx, reader));                                       
+                               }
+
+                               if (!inlineTemplate) {//load from path or default template
+
+                                       if (!string.IsNullOrEmpty (templatePath)) {
+                                               ctx.il.Emit (OpCodes.Ldloc_0);//Load  current templatedControl ref
+                                               //      ctx.il.Emit (OpCodes.Ldnull);//default template loading
+                                               //} else {
+                                               ctx.il.Emit (OpCodes.Ldarg_1);//load currentInterface
+                                               ctx.il.Emit (OpCodes.Ldstr, templatePath); //Load template path string
+                                               //get declaring type for search fallback assembly
+                                               ctx.il.Emit (OpCodes.Ldloc_0);
+                                               ctx.il.Emit (OpCodes.Call, CompilerServices.miGetType);
+                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miIFaceCreateTemplateInst);
+                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadTmp);//load template
+                                       }
+                               }
+                               if (itemTemplateIds.Count == 0) {
+                                       //try to load ItemTemplate(s) from ItemTemplate attribute of TemplatedGroup
+                                       if (!string.IsNullOrEmpty (itemTemplatePath)) {
+                                               //check if it is already loaded in cache as a single itemTemplate instantiator
+                                               if (iface.ItemTemplates.ContainsKey (itemTemplatePath)) {
+                                                       itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
+                                               } else {
+                                                       using (Stream stream = iface.GetTemplateStreamFromPath (itemTemplatePath, ctx.CurrentNodeType)) {
+                                                               //itemtemplate files may have multiple root nodes
+                                                               XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
+                                                               using (XmlReader itr = XmlReader.Create (stream, itrSettings)) {                                                                        
+                                                                       while (itr.Read ()) {
+                                                                               if (!itr.IsStartElement ())
+                                                                                       continue;
+                                                                               if (itr.NodeType == XmlNodeType.Element) {
+                                                                                       if (itr.Name != "ItemTemplate") {
+                                                                                               //the file contains a single template to use as default
+                                                                                               iface.ItemTemplates [itemTemplatePath] =
+                                                                                                       new ItemTemplate (iface, itr);
+                                                                                               itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "", "TypeOf" });
+                                                                                               break;//we should be at the end of the file
+                                                                                       }
+                                                                                       itemTemplateIds.Add (parseItemTemplateTag (ctx, itr, itemTemplatePath));
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (!ctx.nodesStack.Peek ().IsTemplatedGroup)
+                                       return;
+                               //add the default item template if no default is defined
+                               if (!itemTemplateIds.Any(ids=>ids[0] == "default"))
+                                       itemTemplateIds.Add (new string [] { "default", "#Crow.DefaultItem.template", "", "TypeOf"});
+                               //get item templates 
+                               foreach (string [] iTempId in itemTemplateIds) {
+                                       ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
+                                       ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);//load ItemTemplates dic field
+
+                                       //prepare argument to add itemTemplate to templated group dic of ItemTemplates
+                                       ctx.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key
+                                       //load itemTemplate
+                                       ctx.il.Emit (OpCodes.Ldarg_1);//load currentInterface
+                                       ctx.il.Emit (OpCodes.Ldstr, iTempId [1]);//load path
+                                       //second arg is Type, to find assembly where to search if not in entry
+                                       ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
+                                       ctx.il.Emit (OpCodes.Call, CompilerServices.miGetType);
+                                       ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITemp);
+                                       ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miAddITemp);
+
+                                       if (!string.IsNullOrEmpty (iTempId [2])) {
+                                               //expand delegate creation
+                                               ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
+                                               ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);
+                                               ctx.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key
+                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITempFromDic);
+                                               ctx.il.Emit (OpCodes.Ldloc_0);//load root of treeView
+                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miCreateExpDel);
+                                       }
+                               }
+                       }
+               }
+
+               #if DESIGN_MODE
+               void emitSetDesignAttribute (IMLContext ctx, string name, string value){
+                       //store member value in iml
+                       ctx.il.Emit (OpCodes.Ldloc_0);
+                       ctx.il.Emit (OpCodes.Ldfld, typeof(Widget).GetField("design_iml_values"));
+                       ctx.il.Emit (OpCodes.Ldstr, name);
+                       if (string.IsNullOrEmpty (value))
+                               ctx.il.Emit (OpCodes.Ldnull);
+                       else
+                               ctx.il.Emit (OpCodes.Ldstr, value);
+                       ctx.il.Emit (OpCodes.Call, CompilerServices.miDicStrStrAdd);
+               }
+               #endif
+
+               /// <summary>
+               /// process styling, attributes and children loading.
+               /// </summary>
+               /// <param name="ctx">parsing context</param>
+               /// <param name="tmpXml">xml fragment</param>
+               void emitGOLoad (IMLContext ctx, string tmpXml) {
+                       using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
+                               reader.Read ();
+
+#if DESIGN_MODE
+                               IXmlLineInfo li = (IXmlLineInfo)reader;
+                               ctx.il.Emit (OpCodes.Ldloc_0);
+                               ctx.il.Emit (OpCodes.Ldstr, this.NextDesignID);
+                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_id"));
+                               ctx.il.Emit (OpCodes.Ldloc_0);
+                               ctx.il.Emit (OpCodes.Ldc_I4, ctx.curLine + li.LineNumber);
+                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_line"));
+                               ctx.il.Emit (OpCodes.Ldloc_0);
+                               ctx.il.Emit (OpCodes.Ldc_I4, li.LinePosition);
+                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_column"));
+                               if (!string.IsNullOrEmpty (sourcePath)) {
+                                       ctx.il.Emit (OpCodes.Ldloc_0);
+                                       ctx.il.Emit (OpCodes.Ldstr, sourcePath);
+                                       ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_imlPath"));
+                               }
+#endif
+                               #region Styling and default values loading
+                               //first check for Style attribute then trigger default value loading
+                               if (reader.HasAttributes) {
+                                       string style = reader.GetAttribute ("Style");
+                                       if (!string.IsNullOrEmpty (style)) {
+                                               CompilerServices.EmitSetValue (ctx.il, CompilerServices.piStyle, style);
+#if DESIGN_MODE
+                                               emitSetDesignAttribute (ctx, "Style", style);
+#endif
+                                       }
+                                       //check for dataSourceType, if set, datasource bindings will use direct setter/getter
+                                       //instead of reflexion
+                                       string dataSourceType = reader.GetAttribute ("DataSourceType");
+                                       if (string.IsNullOrEmpty (dataSourceType)) {
+                                               //if not set but dataSource is not null, reset dsType to null
+                                               string ds = reader.GetAttribute ("DataSource");
+                                               if (!string.IsNullOrEmpty (ds)) 
+                                                       ctx.SetDataSourceTypeForCurrentNode (null);
+                                       } else
+                                               ctx.SetDataSourceTypeForCurrentNode(CompilerServices.getTypeFromName (dataSourceType));
+                               }
+                               ctx.il.Emit (OpCodes.Ldloc_0);
+                ctx.il.Emit (OpCodes.Call, CompilerServices.miLoadDefaultVals);
+#endregion
+
+
+                               #region Attributes reading
+                               if (reader.HasAttributes) {
+
+                                       while (reader.MoveToNextAttribute ()) {
+                                               if (reader.Name == "Style" || reader.Name == "DataSourceType" || reader.Name == "Template")
+                                                       continue;
+
+                                               #if DESIGN_MODE
+                                               emitSetDesignAttribute (ctx, reader.Name, reader.Value);
+                                               #endif
+
+                                               MemberInfo mi = ctx.CurrentNodeType.GetMember (reader.Name).FirstOrDefault ();
+                                               if (mi == null)
+                                                       throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNodeType.Name);
+
+                                               if (mi.MemberType == MemberTypes.Event) {
+                                                       foreach (string exp in reader.Value.Split (';')) {
+                                                               string trimed = exp.Trim();
+                                                               if (trimed.StartsWith ("{", StringComparison.Ordinal))
+                                                                       compileAndStoreDynHandler (ctx, mi as EventInfo, trimed.Substring (1, trimed.Length - 2));
+                                                               else
+                                                                       emitHandlerBinding (ctx, mi as EventInfo, trimed);
+                                                       }
+
+                                                       continue;
+                                               }
+                                               PropertyInfo pi = mi as PropertyInfo;
+                                               if (pi == null)
+                                                       throw new Exception ("Member '" + reader.Name + "' is not a property in " + ctx.CurrentNodeType.Name);
+
+                                               if (pi.Name == "Name")
+                                                       ctx.StoreCurrentName (reader.Value);
+
+                                               if (reader.Value.StartsWith ("{", StringComparison.Ordinal))
+                                                       readPropertyBinding (ctx, reader.Name, reader.Value.Substring (1, reader.Value.Length - 2));
+                                               else
+                                                       CompilerServices.EmitSetValue (ctx.il, pi, reader.Value);
+
+                                       }
+                                       reader.MoveToElement ();
+                               }
+                               #endregion
+
+                               readChildren (reader, ctx);
+
+                               ctx.nodesStack.ResetCurrentNodeIndex ();
+                       }
+               }
+               /// <summary>
+               /// Parse child node an generate corresponding msil
+               /// </summary>
+               void readChildren (XmlReader reader, IMLContext ctx, int startingIdx = 0)
+               {
+                       bool endTagReached = false;
+                       int nodeIdx = startingIdx;
+                       while (reader.Read ()) {
+                               switch (reader.NodeType) {
+                               case XmlNodeType.EndElement:
+                                       endTagReached = true;
+                                       break;
+                               case XmlNodeType.Element:
+                                       //skip Templates
+                                       if (reader.Name == "Template" ||
+                                           reader.Name == "ItemTemplate") {
+                                               reader.Skip ();
+                                               continue;
+                                       }
+
+                                       //push 2x current instance on stack for parenting and reseting loc0 to parent
+                                       //loc_0 will be used for child
+                                       ctx.il.Emit (OpCodes.Ldloc_0);
+                                       ctx.il.Emit (OpCodes.Ldloc_0);
+
+                                       Type t = tryGetGOType (reader.Name);
+                                       if (t == null)
+                                               throw new Exception (reader.Name + " type not found");
+                                       ConstructorInfo ci = t.GetConstructor (
+                                                                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,  
+                                               null, Type.EmptyTypes, null);
+                                       if (ci == null)
+                                               throw new Exception ("No default parameterless constructor found in " + t.Name);                                        
+                                       ctx.il.Emit (OpCodes.Newobj, ci);
+                                       ctx.il.Emit (OpCodes.Stloc_0);//child is now loc_0
+                                       CompilerServices.emitSetCurInterface (ctx.il);
+
+                                       ctx.nodesStack.Push (new Node (t, nodeIdx));
+                                       emitLoader (reader, ctx);
+                                       ctx.nodesStack.Pop ();
+
+                                       ctx.il.Emit (OpCodes.Ldloc_0);//load child on stack for parenting
+                                       ctx.il.Emit (OpCodes.Callvirt, ctx.nodesStack.Peek().GetAddMethod(nodeIdx));
+                                       ctx.il.Emit (OpCodes.Stloc_0); //reset local to current go
+
+                                       nodeIdx++;
+
+                                       break;
+                               }
+                               if (endTagReached)
+                                       break;
+                       }
+               }
+               #endregion
+               /// <summary>
+               /// Reads binding expression found as attribute value in iml
+               /// </summary>
+               /// <param name="ctx">IML Context</param>
+               /// <param name="sourceMember">IML Attribute name</param>
+               /// <param name="expression">Binding Expression with accollades trimed</param>
+               void readPropertyBinding (IMLContext ctx, string sourceMember, string expression)
+               {
+                       NodeAddress sourceNA = ctx.CurrentNodeAddress;
+                       BindingDefinition bindingDef = sourceNA.GetBindingDef (sourceMember, expression);
+
+#if DEBUG_BINDING
+                       Debug.WriteLine("Property Binding: " + bindingDef.ToString());
+#endif
+
+                       if (bindingDef.IsDataSourceBinding) {//bind on data source
+                               if (ctx.CurrentNodeHasDataSourceType)
+                                       emitDataSourceBindings (ctx, bindingDef, ctx.CurrentDataSourceType);
+                               else
+                                       emitDataSourceBindings (ctx, bindingDef);
+                       } else
+                               ctx.StorePropertyBinding (bindingDef);
+               }
+
+               #region Emit Helper
+               void dataSourceChangedEmitHelper(object dscSource, object dataSource, int dynMethIdx){
+                       if (dataSource is IValueChange)
+                               (dataSource as IValueChange).ValueChanged +=
+                                       (EventHandler<ValueChangeEventArgs>)dsValueChangedDynMeths [dynMethIdx].CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>), dscSource);
+               }
+               /// <summary> Emits remove old data source event handler.</summary>
+               void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){
+                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Ldarg_2);//load old parent
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
+                       il.Emit (OpCodes.Brfalse, cancel);//old parent is null
+
+                       //remove handler
+                       if (DSSide){//event is defined in the dataSource instance
+                               il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
+                       }else//the event is in the source
+                               il.Emit (OpCodes.Ldarg_1);//1st arg load old datasource
+                       il.Emit (OpCodes.Ldstr, eventName);//2nd arg event name
+                       il.Emit (OpCodes.Ldstr, delegateName);//3d arg: delegate name
+                       il.Emit (OpCodes.Call, CompilerServices.miRemEvtHdlByName);
+                       il.MarkLabel(cancel);
+               }
+               #endregion
+
+               #region Event Bindings
+               /// <summary>
+               /// Compile events expression in IML attributes, and store the result in the instanciator
+               /// Those handlers will be bound when instatiing
+               /// </summary>
+               void compileAndStoreDynHandler (IMLContext ctx, EventInfo sourceEvent, string expression)
+               {
+                       //store event handler dynamic method in instanciator
+                       int dmIdx = cachedDelegates.Count;
+                       cachedDelegates.Add (CompilerServices.compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress));
+                       ctx.emitCachedDelegateHandlerAddition(dmIdx, sourceEvent);
+               }
+               /// <summary> Emits handler method bindings </summary>
+               void emitHandlerBinding (IMLContext ctx, EventInfo sourceEvent, string expression){
+                       NodeAddress currentNode = ctx.CurrentNodeAddress;
+                       BindingDefinition bindingDef = currentNode.GetBindingDef (sourceEvent.Name, expression);
+
+                       #if DEBUG_BINDING
+                       Debug.WriteLine("Event Binding: " + bindingDef.ToString());
+                       #endif
+
+                       if (bindingDef.IsTemplateBinding | bindingDef.IsDataSourceBinding) {
+                               //we need to bind datasource method to source event
+                               DynamicMethod dm = new DynamicMethod ("dyn_dsORtmpChangedForHandler" + NewId,
+                                                          typeof(void),
+                                                          CompilerServices.argsBoundDSChange, true);
+
+                               ILGenerator il = dm.GetILGenerator (256);
+                               System.Reflection.Emit.Label cancel = il.DefineLabel ();
+
+                               il.DeclareLocal (typeof(MethodInfo));//used to cancel binding if method doesn't exist
+
+                               il.Emit (OpCodes.Nop);
+
+                               emitRemoveOldDataSourceHandler (il, sourceEvent.Name, bindingDef.TargetMember, false);
+
+
+                               //fetch method in datasource and test if it exist
+                               il.Emit (OpCodes.Ldarg_2);//load new datasource
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Brfalse, cancel);//cancel if new datasource is null
+                               il.Emit (OpCodes.Ldarg_2);//load new datasource
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load handler method name
+                               il.Emit (OpCodes.Call, CompilerServices.miGetMethInfoWithRefx);
+                               il.Emit (OpCodes.Stloc_0);//save MethodInfo                                          
+                il.Emit (OpCodes.Ldloc_0);//push mi for test if null
+                il.Emit (OpCodes.Brfalse, cancel);//cancel if null
+
+                il.Emit (OpCodes.Ldarg_1);//load datasource change source where the event is as 1st arg of handler.add
+                if (bindingDef.IsTemplateBinding)//fetch source instance with address
+                    CompilerServices.emitGetInstance (il, bindingDef.SourceNA);
+
+                //load handlerType of sourceEvent to create delegate (1st arg)
+                il.Emit (OpCodes.Ldtoken, sourceEvent.EventHandlerType);
+                il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                il.Emit (OpCodes.Ldarg_2);//load new datasource where the method is defined
+                il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                il.Emit (OpCodes.Ldloc_0);//load methodInfo (3rd arg)
+
+                il.Emit (OpCodes.Call, CompilerServices.miCreateBoundDel);
+                il.Emit (OpCodes.Callvirt, sourceEvent.AddMethod);//call add event
+                                          
+                System.Reflection.Emit.Label finish = il.DefineLabel ();
+                il.Emit (OpCodes.Br, finish);
+                il.MarkLabel (cancel);
+                               #if DEBUG_BINDING
+                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' NOT FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
+                               #endif
+                               il.MarkLabel (finish);
+                               #if DEBUG_BINDING
+                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
+                               #endif
+                                              
+                               il.Emit (OpCodes.Ret);
+
+                               //store dschange delegate in instatiator instance for access while instancing graphic object
+                               int delDSIndex = cachedDelegates.Count;
+                               cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+
+                               if (bindingDef.IsDataSourceBinding)
+                                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+                               else //template handler binding, will be added to root parentChanged
+                                       templateCachedDelegateIndices.Add (delDSIndex);
+                       } else {//normal in tree handler binding, store until tree is complete (end of parse)
+                               ctx.UnresolvedTargets.Add (new EventBinding (
+                                       bindingDef.SourceNA, sourceEvent,
+                                       bindingDef.TargetNA, bindingDef.TargetMember, bindingDef.TargetName));
+                       }
+               }
+               #endregion
+
+               #region Property Bindings
+               /// <summary>
+               /// Create and store in the instanciator the ValueChanged delegates
+               /// those delegates uses grtree functions to set destination value so they don't
+               /// need to be bound to destination instance as in the ancient system.
+               /// </summary>
+               void emitBindingDelegates(IMLContext ctx){
+                       foreach (KeyValuePair<NodeAddress,Dictionary<string, List<MemberAddress>>> bindings in ctx.Bindings ) {
+                               if (bindings.Key.Count == 0)//template binding
+                                       emitTemplateBindings (ctx, bindings.Value);
+                               else
+                                       emitPropertyBindings (ctx,  bindings.Key, bindings.Value);
+                       }
+               }
+               void emitPropertyBindings(IMLContext ctx, NodeAddress origine, Dictionary<string, List<MemberAddress>> bindings){
+                       Type origineNodeType = origine.NodeType;
+
+                       //value changed dyn method
+                       DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId,
+                               typeof (void), CompilerServices.argsValueChange, true);
+                       ILGenerator il = dm.GetILGenerator (256);
+
+                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                       il.DeclareLocal (typeof(object));
+
+                       il.Emit (OpCodes.Nop);
+
+                       int i = 0;
+                       foreach (KeyValuePair<string, List<MemberAddress>> bindingCase in bindings ) {
+
+                               System.Reflection.Emit.Label nextTest = il.DefineLabel ();
+
+                               #region member name test
+                               //load source member name
+                               il.Emit (OpCodes.Ldarg_1);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                               il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test
+                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                               il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case
+                               #endregion
+
+                               #region destination member affectations
+                               PropertyInfo piOrig = origineNodeType.GetProperty (bindingCase.Key);
+                               Type origineType = null;
+                               if (piOrig != null)
+                                       origineType = piOrig.PropertyType;
+                               foreach (MemberAddress ma in bindingCase.Value) {
+                                       //first we have to load destination instance onto the stack, it is access
+                                       //with graphic tree functions deducted from nodes topology
+                                       il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
+
+                                       NodeAddress destination = ma.Address;
+
+                                       if (destination.Count == 0){//template reverse binding
+                                               //fetch destination instance (which is the template root)
+                                               for (int j = 0; j < origine.Count ; j++)
+                                                       il.Emit(OpCodes.Callvirt, CompilerServices.miGetLogicalParent);
+                                       }else
+                                               CompilerServices.emitGetInstance (il, origine, destination);
+
+                                       if (origineType != null && destination.Count > 0){//else, prop less binding or reverse template bind, no init requiered
+                                               //for initialisation dynmeth, push destination instance loc_0 is root node in ctx
+                                               ctx.il.Emit(OpCodes.Ldloc_0);
+                                               CompilerServices.emitGetInstance (ctx.il, destination);
+
+                                               //init dynmeth: load actual value from origine
+                                               ctx.il.Emit (OpCodes.Ldloc_0);
+                                               CompilerServices.emitGetInstance (ctx.il, origine);
+                                               ctx.il.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
+                                       }
+                                       //load new value
+                                       il.Emit (OpCodes.Ldarg_1);
+                                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                                       if (origineType == null)//property less binding, no init
+                                               CompilerServices.emitConvert (il, ma.Property.PropertyType);
+                                       else if (destination.Count > 0) {
+                                               if (origineType.IsValueType)
+                                                       ctx.il.Emit(OpCodes.Box, origineType);
+
+                                               CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType);
+                                               CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType);
+
+                                               ctx.il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
+                                       } else {// reverse templateBinding
+                                               il.Emit (OpCodes.Ldstr, ma.memberName);//arg 3 of setValueWithReflexion
+                                               il.Emit (OpCodes.Call, CompilerServices.miSetValWithRefx);
+                                               continue;
+                                       }
+                                       il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes
+                               }
+                               #endregion
+                               il.Emit (OpCodes.Br, endMethod);
+                               il.MarkLabel (nextTest);
+
+                               i++;
+                       }
+
+                       il.MarkLabel (endMethod);
+                       il.Emit (OpCodes.Ret);
+
+                       //store and emit Add in ctx
+                       int dmIdx = cachedDelegates.Count;
+                       cachedDelegates.Add (dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>)));
+                       ctx.emitCachedDelegateHandlerAddition (dmIdx, CompilerServices.eiValueChange, origine);
+
+                       #if DEBUG_BINDING
+                       Debug.WriteLine("\tCrow property binding: " + dm.Name);
+                       #endif
+
+               }
+               void emitTemplateBindings(IMLContext ctx, Dictionary<string, List<MemberAddress>> bindings){
+                       //value changed dyn method
+                       DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged" + NewId,
+                               typeof (void), CompilerServices.argsValueChange, true);
+                       ILGenerator il = dm.GetILGenerator (256);
+
+                       //create parentchanged dyn meth in parallel to have only one loop over bindings
+                       DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged" + NewId,
+                               typeof (void),
+                               CompilerServices.argsBoundDSChange, true);
+                       ILGenerator ilPC = dmPC.GetILGenerator (256);
+
+                       il.Emit (OpCodes.Nop);
+                       ilPC.Emit (OpCodes.Nop);
+
+                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                       il.DeclareLocal (typeof(object));
+                       ilPC.DeclareLocal (typeof(object));//used for checking propery less bindings
+                       ilPC.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
+
+                       System.Reflection.Emit.Label cancel = ilPC.DefineLabel ();
+
+                       #region Unregister previous parent event handler
+                       //unregister previous parent handler if not null
+                       ilPC.Emit (OpCodes.Ldarg_2);//load old parent
+                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
+                       ilPC.Emit (OpCodes.Brfalse, cancel);//old parent is null
+
+                       ilPC.Emit (OpCodes.Ldarg_2);//load old parent
+                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
+                       //Load cached delegate
+                       ilPC.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
+                       ilPC.Emit(OpCodes.Ldfld, CompilerServices.fiTemplateBinding);
+
+                       //add template bindings dynValueChanged delegate to new parent event
+                       ilPC.Emit(OpCodes.Callvirt, CompilerServices.eiValueChange.RemoveMethod);//call remove event
+                       #endregion
+
+                       ilPC.MarkLabel(cancel);
+
+                       #region check if new parent is null
+                       cancel = ilPC.DefineLabel ();
+                       ilPC.Emit (OpCodes.Ldarg_2);//load datasource change arg
+                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       ilPC.Emit (OpCodes.Brfalse, cancel);//new ds is null
+                       #endregion
+
+                       int i = 0;
+                       foreach (KeyValuePair<string, List<MemberAddress>> bindingCase in bindings ) {
+
+                               System.Reflection.Emit.Label nextTest = il.DefineLabel ();
+
+                               #region member name test
+                               //load source member name
+                               il.Emit (OpCodes.Ldarg_1);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                               il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test
+                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                               il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case
+                               #endregion
+
+                               #region destination member affectations
+
+                               foreach (MemberAddress ma in bindingCase.Value) {
+                                       if (ma.Address.Count == 0){
+                                               Debug.WriteLine("\t\tBUG: reverse template binding in normal template binding");
+                                               continue;//template binding
+                                       }
+                                       //first we try to get memberInfo of new parent, if it doesn't exist, it's a propery less binding
+                                       ilPC.Emit (OpCodes.Ldarg_2);//load new parent onto the stack for handler addition
+                                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                                       ilPC.Emit (OpCodes.Stloc_0);//save new parent
+                                       //get parent type
+                                       ilPC.Emit (OpCodes.Ldloc_0);//push parent instance
+                                       ilPC.Emit (OpCodes.Ldstr, bindingCase.Key);//load member name
+                                       ilPC.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
+                                       ilPC.Emit (OpCodes.Stloc_1);//save memberInfo
+                                       ilPC.Emit (OpCodes.Ldloc_1);//push mi for test if null
+                                       System.Reflection.Emit.Label propLessReturn = ilPC.DefineLabel ();
+                                       ilPC.Emit (OpCodes.Brfalse, propLessReturn);
+
+
+                                       //first we have to load destination instance onto the stack, it is access
+                                       //with graphic tree functions deducted from nodes topology
+                                       il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
+                                       CompilerServices.emitGetChild (il, typeof(TemplatedControl), -1);
+                                       CompilerServices.emitGetInstance (il, ma.Address);
+
+                                       ilPC.Emit (OpCodes.Ldarg_2);//load destination instance to set actual value of member
+                                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                                       CompilerServices.emitGetChild (ilPC, typeof(TemplatedControl), -1);
+                                       CompilerServices.emitGetInstance (ilPC, ma.Address);
+
+                                       //load new value
+                                       il.Emit (OpCodes.Ldarg_1);
+                                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                                       //for the parent changed dyn meth we need to fetch actual value for initialisation thrue reflexion
+                                       ilPC.Emit (OpCodes.Ldloc_0);//push root instance of instanciator as parentChanged source
+                                       ilPC.Emit (OpCodes.Ldloc_1);//push mi for value fetching
+                                       ilPC.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
+
+                                       CompilerServices.emitConvert (il, ma.Property.PropertyType);
+                                       CompilerServices.emitConvert (ilPC, ma.Property.PropertyType);
+
+                                       il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
+                                       ilPC.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
+
+                                       ilPC.MarkLabel(propLessReturn);
+                               }
+                               #endregion
+                               il.Emit (OpCodes.Br, endMethod);
+                               il.MarkLabel (nextTest);
+
+                               i++;
+                       }
+                       //il.Emit (OpCodes.Pop);
+                       il.MarkLabel (endMethod);
+                       il.Emit (OpCodes.Ret);
+
+                       //store template bindings in instanciator
+                       templateBinding = dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>));
+
+                       #region emit LogicalParentChanged method
+
+                       //load new parent onto the stack for handler addition
+                       ilPC.Emit (OpCodes.Ldarg_2);
+                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+
+                       //Load cached delegate
+                       ilPC.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
+                       ilPC.Emit(OpCodes.Ldfld, CompilerServices.fiTemplateBinding);
+
+                       //add template bindings dynValueChanged delegate to new parent event
+                       ilPC.Emit(OpCodes.Callvirt, CompilerServices.eiValueChange.AddMethod);//call add event
+
+                       ilPC.MarkLabel (cancel);
+                       ilPC.Emit (OpCodes.Ret);
+
+                       //store dschange delegate in instatiator instance for access while instancing graphic object
+                       int delDSIndex = cachedDelegates.Count;
+                       cachedDelegates.Add(dmPC.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+                       #endregion
+
+                       ctx.emitCachedDelegateHandlerAddition(delDSIndex, CompilerServices.eiLogicalParentChanged);
+               }
+               /// <summary>
+               /// data source binding with known data type
+               /// </summary>
+               void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef, Type dsType)
+               {
+#if DEBUG_BINDING_FUNC_CALLS
+                       Console.WriteLine ($"emitDataSourceBindings with data type knows: {bindingDef}");
+#endif
+                       DynamicMethod dm = null;
+                       ILGenerator il = null;
+                       int dmVC = 0;
+                       PropertyInfo piSource = ctx.CurrentNodeType.GetProperty (bindingDef.SourceMember);
+                       //if no dataSource member name is provided, valuechange is not handle and datasource change
+                       //will be used as origine value
+                       string delName = "dyn_DSvalueChangedKnownType" + NewId;
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               #region create valuechanged method
+                               dm = new DynamicMethod (delName,
+                                       typeof (void),
+                                       CompilerServices.argsBoundValueChange, true);
+
+                               il = dm.GetILGenerator (256);
+
+                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                               il.DeclareLocal (typeof (object));
+
+                               il.Emit (OpCodes.Nop);
+
+                               //load value changed member name onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                               //test if it's the expected one
+                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);
+                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                               il.Emit (OpCodes.Brfalse, endMethod);
+                               //set destination member with valueChanged new value
+                               //load destination ref
+                               il.Emit (OpCodes.Ldarg_0);
+                               //load new value onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                               //by default, source value type is deducted from target member type to allow
+                               //memberless binding, if targetMember exists, it will be used to determine target
+                               //value type for conversion
+                               CompilerServices.emitConvert (il, piSource.PropertyType);
+
+                               if (!piSource.CanWrite)
+                                       throw new Exception ("Source member of bindind is read only:" + piSource.ToString ());
+
+                               il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+
+                               il.MarkLabel (endMethod);
+                               il.Emit (OpCodes.Ret);
+
+                               //vc dyn meth is stored in a cached list, it will be bound to datasource only
+                               //when datasource of source graphic object changed
+                               dmVC = dsValueChangedDynMeths.Count;
+                               dsValueChangedDynMeths.Add (dm);
+                               #endregion
+                       }
+
+                       #region emit dataSourceChanged event handler
+                       //now we create the datasource changed method that will init the destination member with
+                       //the actual value of the origin member of the datasource and then will bind the value changed
+                       //dyn methode.
+                       //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
+                       dm = new DynamicMethod ("dyn_dschanged" + NewId,
+                               typeof (void),
+                               CompilerServices.argsBoundDSChange, true);
+
+                       il = dm.GetILGenerator (256);
+
+                       il.DeclareLocal (typeof (object));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (MemberInfo));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
+                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
+                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
+                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Nop);
+
+                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
+
+                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
+
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               if (bindingDef.TwoWay) //remove handler
+                                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName + "_reverse", false);
+                               //test if new ds is null
+                               il.Emit (OpCodes.Ldloc_2);
+                               il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
+                               //test if new ds is of expected type
+                               il.Emit (OpCodes.Ldloc_2);
+                               il.Emit (OpCodes.Isinst, dsType);
+                               //il.Emit (OpCodes.Call, CompilerServices.miGetMDToken);
+                               //il.Emit (OpCodes.Ldc_I4, dsType.MetadataToken);
+                               il.Emit (OpCodes.Brfalse, newDSIsNull);
+                       }
+
+                       #region fetch initial Value
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               Type mbType;
+                               MemberInfo mi = CompilerServices.GetMemberInfo (dsType, bindingDef.TargetMember, out mbType);
+                               if (mi != null) {
+                                       il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
+                                       il.Emit (OpCodes.Ldloc_2);//load new ds
+                                       CompilerServices.emitGetMemberValue (il, dsType, mi);
+                                       if (mbType != piSource.PropertyType)
+                                               CompilerServices.emitConvert (il, mbType, piSource.PropertyType);
+                                       il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+                               }
+                       }
+                       #endregion
+
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               il.MarkLabel (cancelInit);
+                               //check if new dataSource implement IValueChange
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit (OpCodes.Isinst, typeof (IValueChange));
+                               il.Emit (OpCodes.Brfalse, cancel);
+
+                               il.Emit (OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
+                               il.Emit (OpCodes.Ldarg_1);//load datasource change source
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit (OpCodes.Ldc_I4, dmVC);//load index of dynmathod
+                               il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
+
+                               il.MarkLabel (cancel);
+
+                               if (bindingDef.TwoWay) {
+                                       il.Emit (OpCodes.Ldstr, delName + "_reverse");//load delName used for removing on ds changed
+                                       il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
+                                       il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
+                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
+                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member
+                                       il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
+                               }
+
+                       }
+                       il.MarkLabel (newDSIsNull);
+                       il.Emit (OpCodes.Ret);
+
+                       //store dschange delegate in instatiator instance for access while instancing graphic object
+                       int delDSIndex = cachedDelegates.Count;
+
+                       //Int32 fiLength = (Int32)il.GetType ().GetField ("code_len", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
+                       //byte [] bytes = (byte[])il.GetType ().GetField ("code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
+
+                       cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+                       #endregion
+
+                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+
+#if DEBUG_BINDING
+                       Debug.WriteLine("\tDataSource ValueChanged: " + delName);
+                       Debug.WriteLine("\tDataSource Changed: " + dm.Name);
+#endif
+               }
+
+               /// <summary>
+               /// create the valuechanged handler, the datasourcechanged handler and emit event handling
+               /// </summary>
+               void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef)
+               {
+                       Delegate del = emitDataSourceBindings (ctx.CurrentNodeType.GetProperty (bindingDef.SourceMember), bindingDef);
+
+                       //store dschange delegate in instatiator instance for access while instancing graphic object
+                       int delDSIndex = cachedDelegates.Count;
+                       cachedDelegates.Add (del);
+
+                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+               }
+
+               /// <summary>
+               /// create the valuechanged handler and the datasourcechanged handler and return the 
+               /// DataSourceChange delegate
+               /// </summary>
+               public Delegate emitDataSourceBindings (PropertyInfo piSource, BindingDefinition bindingDef){           
+
+#if DEBUG_BINDING_FUNC_CALLS
+                       Console.WriteLine ($"emitDataSourceBindings: {bindingDef}");
+#endif
+                       DynamicMethod dm = null;
+                       ILGenerator il = null;
+                       int dmVC = 0;
+
+                       //if no dataSource member name is provided, valuechange is not handle and datasource change
+                       //will be used as origine value
+                       string delName = $"dyn_DSvalueChanged_{bindingDef.SourceMember}_{bindingDef.TargetMember}_{NewId}";
+                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                       #region create valuechanged method
+                               dm = new DynamicMethod (delName,
+                                       typeof (void),
+                                       CompilerServices.argsBoundValueChange, true);
+
+                               il = dm.GetILGenerator (64);
+
+                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                               il.DeclareLocal (typeof(object));
+
+                               il.Emit (OpCodes.Nop);
+
+                               //load value changed member name onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                               //test if it's the expected one
+                               il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ? $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);
+                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                               il.Emit (OpCodes.Brfalse, endMethod);
+                               //set destination member with valueChanged new value
+                               //load destination ref
+                               il.Emit (OpCodes.Ldarg_0);
+                               //load new value onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                               //by default, source value type is deducted from target member type to allow
+                               //memberless binding, if targetMember exists, it will be used to determine target
+                               //value type for conversion
+                               CompilerServices.emitConvert (il, piSource.PropertyType);
+
+                               if (!piSource.CanWrite)
+                                       throw new Exception ("Source member of bindind is read only:" + piSource.ToString());
+
+                               il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+
+                               il.MarkLabel (endMethod);
+                               il.Emit (OpCodes.Ret);
+
+                               //vc dyn meth is stored in a cached list, it will be bound to datasource only
+                               //when datasource of source graphic object changed
+                               dmVC = dsValueChangedDynMeths.Count;
+                               dsValueChangedDynMeths.Add (dm);
+#endregion
+                       }
+
+                       #region emit dataSourceChanged event handler
+                       //now we create the datasource changed method that will init the destination member with
+                       //the actual value of the origin member of the datasource and then will bind the value changed
+                       //dyn methode.
+                       //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
+                       dm = new DynamicMethod ("dyn_dschanged" + NewId,
+                               typeof (void),
+                               CompilerServices.argsBoundDSChange, true);
+
+                       il = dm.GetILGenerator (64);
+
+                       il.DeclareLocal (typeof(object));//used for checking propery less bindings
+                       il.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
+                       il.DeclareLocal (typeof (MemberInfo));//used for binding with datasource.object.member (2 levels)
+                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
+                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
+                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Nop);
+
+                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
+
+                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
+
+                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                               if (bindingDef.TwoWay)//remove handler
+                                       emitRemoveOldDataSourceHandler(il, "ValueChanged", delName + "_reverse", false);
+
+                               il.Emit (OpCodes.Ldloc_2);
+                               il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
+                       }
+
+                       #region fetch initial Value
+                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                               il.Emit (OpCodes.Ldloc_2);
+                               if (bindingDef.HasUnresolvedTargetName) {
+                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetName);//load parent object
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
+                                       il.Emit (OpCodes.Stloc_3);
+                                       il.Emit (OpCodes.Ldloc_3);
+                                       il.Emit (OpCodes.Brfalse, cancelInit);//may be propertyLessBinding
+                                       il.Emit (OpCodes.Ldloc_2);//load datasource
+                                       il.Emit (OpCodes.Ldloc_3);//load first memberInfo
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
+                               } 
+                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name
+                               il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
+                               il.Emit (OpCodes.Stloc_1);//save memberInfo
+                               il.Emit (OpCodes.Ldloc_1);//push mi for test if null
+                               il.Emit (OpCodes.Brfalse, cancelInit);//propertyLessBinding
+                       }
+
+                       il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
+                       il.Emit (OpCodes.Ldloc_2);//load new datasource
+                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                               if (bindingDef.HasUnresolvedTargetName) {
+                                       il.Emit (OpCodes.Ldloc_3);
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
+                               }
+                               il.Emit (OpCodes.Ldloc_1);//push mi for value fetching
+                               il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
+                       }
+                       CompilerServices.emitConvert (il, piSource.PropertyType);
+                       il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+                       #endregion
+
+                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                               il.MarkLabel(cancelInit);
+                               //check if new dataSource implement IValueChange
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit (OpCodes.Isinst, typeof(IValueChange));
+                               il.Emit (OpCodes.Brfalse, cancel);
+
+                               il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
+                               il.Emit (OpCodes.Ldarg_1);//load datasource change source
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynMethod
+                               il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
+
+                               il.MarkLabel (cancel);
+
+                               if (bindingDef.TwoWay){
+                                       il.Emit (OpCodes.Ldstr, delName + "_reverse");//load delName used for removing on ds changed
+                                       il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
+                                       il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
+                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
+                                       il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ?
+                                               $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);//arg4: dest member
+                                       il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
+                               }
+
+                       }
+                       il.MarkLabel (newDSIsNull);
+                       il.Emit (OpCodes.Ret);
+
+#if DEBUG_BINDING
+                       Debug.WriteLine("\tDataSource ValueChanged: " + delName);
+                       Debug.WriteLine("\tDataSource Changed: " + dm.Name);
+#endif
+
+                       return dm.CreateDelegate (CompilerServices.ehTypeDSChange, this);
+#endregion
+               }
+
+               static void emitSetValue (ILGenerator il, MemberInfo mi)
+               {
+                       if (mi.MemberType == MemberTypes.Field)
+                               il.Emit (OpCodes.Stfld, mi as FieldInfo);
+                       else if (mi.MemberType == MemberTypes.Property) {
+                               MethodInfo mt = (mi as PropertyInfo).GetSetMethod ();
+                               il.Emit (mt.IsVirtual?OpCodes.Callvirt:OpCodes.Call, mt);
+                       } else
+                               throw new NotImplementedException ();
+               }
+               /// <summary>
+               /// Two way binding for datasource, graphicObj=>dataSource link, datasource value has priority
+               /// and will be set as init for source property (in emitDataSourceBindings func)
+               /// </summary>
+               /// <param name="delName">delegate name</param>
+               /// <param name="orig">Graphic object instance, source of binding</param>
+               /// <param name="origMember">Origin member name</param>
+               /// <param name="dest">datasource instance, target of the binding</param>
+               /// <param name="destMember">Destination member name</param>
+               static void dataSourceReverseBinding(string delName, IValueChange orig, string origMember, object dest, string destMember){
+                       Type tOrig = orig.GetType ();
+                       Type tDest = dest.GetType ();
+                       PropertyInfo piOrig = tOrig.GetProperty (origMember);
+                       List<MemberInfo> miDests = new List<MemberInfo> ();
+                       Type curType = tDest;
+                       foreach (string m in destMember.Split('.')) {
+                               MemberInfo miDest = curType.GetMember (m).FirstOrDefault ();
+                               if (miDest == null) {
+                                       Debug.WriteLine ($"Member '{destMember}' not found in new DataSource '{dest}' of '{orig}'");
+                                       return;
+                               }
+                               miDests.Add (miDest);
+                               curType = CompilerServices.GetMemberInfoType (miDest);
+                       }
+
+#if DEBUG_BINDING
+                       Debug.WriteLine ("DS Reverse binding: Member '{0}' found in new DS '{1}' of '{2}'", destMember, dest, orig);
+#endif
+
+#region ValueChanged emit
+                       DynamicMethod dm = new DynamicMethod (delName,
+                               typeof (void), CompilerServices.argsBoundValueChange, true);
+                       ILGenerator il = dm.GetILGenerator (64);
+
+
+                       Stack<LocalBuilder> locals = new Stack<LocalBuilder> ();
+
+                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Nop);
+
+                       //load value changed member name onto the stack
+                       il.Emit (OpCodes.Ldarg_2);
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                       //test if it's the expected one
+                       il.Emit (OpCodes.Ldstr, origMember);
+                       il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                       il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                       il.Emit (OpCodes.Brfalse, endMethod);
+                       //set destination member with valueChanged new value
+                       //load destination ref
+                       il.Emit (OpCodes.Ldarg_0);
+                       for (int i = 0; i < miDests.Count - 1; i++) {
+                               if (miDests [i].MemberType == MemberTypes.Field)
+                                       il.Emit (OpCodes.Ldflda, miDests [i] as FieldInfo);
+                               else if (miDests [i].MemberType == MemberTypes.Property) {
+                                       PropertyInfo pi = miDests [i] as PropertyInfo;
+                                       MethodInfo mi_g = pi.GetGetMethod ();
+                                       if (pi.PropertyType.IsValueType) {
+                                               il.Emit (OpCodes.Dup);//dup parent for calling property set afterward
+                                               il.Emit (mi_g.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_g);
+                                               LocalBuilder lb = il.DeclareLocal (pi.PropertyType);
+                                               il.Emit (OpCodes.Stloc, lb);
+                                               il.Emit (OpCodes.Ldloca, lb);
+                                               locals.Push (lb);
+                                       } else {
+                                               il.Emit (mi_g.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_g);
+                                       }
+                               } else
+                                       throw new NotImplementedException ();
+                       }
+
+                       //load new value onto the stack
+                       il.Emit (OpCodes.Ldarg_2);
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                       CompilerServices.emitConvert (il, piOrig.PropertyType, curType);
+
+                       emitSetValue (il, miDests.Last ());
+
+                       for (int i = miDests.Count -2; i >= 0; i--) {
+                               if (miDests [i].MemberType != MemberTypes.Property)
+                                       continue;
+                               PropertyInfo pi = miDests [i] as PropertyInfo;
+                               if (!pi.PropertyType.IsValueType)
+                                       continue;
+                               MethodInfo mi_s = pi.GetSetMethod ();
+                               il.Emit (OpCodes.Ldloc, locals.Pop());
+                               il.Emit (mi_s.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_s);
+                       }
+                       il.MarkLabel (endMethod);
+                       il.Emit (OpCodes.Ret);
+                       #endregion
+                       EventHandler<ValueChangeEventArgs> tmp = (EventHandler<ValueChangeEventArgs>)dm.CreateDelegate (typeof (EventHandler<ValueChangeEventArgs>), dest);
+                       orig.ValueChanged += tmp;
+               }
+               #endregion
+
+               /// <summary>
+               /// search for graphic object type in crow assembly, if not found,
+               /// search for type independently of namespace in all the loaded assemblies
+               /// </summary>
+               /// <remarks>
+               /// </remarks>
+               /// <returns>the corresponding type object</returns>
+               /// <param name="typeName">graphic object type name without its namespace</param>
+               Type tryGetGOType (string typeName){
+                       if (knownGOTypes.ContainsKey (typeName))
+                               return knownGOTypes [typeName];
+                       Type t = Type.GetType ("Crow." + typeName);
+                       if (t != null) {
+                               knownGOTypes.Add (typeName, t);
+                               return t;
+                       }                       
+                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
+                               if (a.IsDynamic)
+                                       continue;
+                               foreach (Type expT in a.GetExportedTypes ()) {
+                                       if (expT.Name != typeName)
+                                               continue;
+                                       knownGOTypes.Add (typeName, expT);
+                                       return expT;
+                               }
+                       }
+                       return null;
+               }
+       }
+}
+
diff --git a/Crow/src/IMLAttributes.cs b/Crow/src/IMLAttributes.cs
deleted file mode 100644 (file)
index 929fd4f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// IMLAttributes.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-
-namespace Crow
-{
-       public class DesignIgnore : Attribute
-       {               
-       }
-
-       public class DesignCategory : Attribute
-       {
-               public string Name { get; set; }
-
-               public DesignCategory (string name)
-               {
-                       Name = name;
-               }
-       }
-}
-
diff --git a/Crow/src/IObservableList.cs b/Crow/src/IObservableList.cs
new file mode 100644 (file)
index 0000000..311a21a
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+       public interface IObservableList {
+               event EventHandler<ListChangedEventArg> ListAdd;
+               event EventHandler<ListChangedEventArg> ListRemove;
+               event EventHandler<ListChangedEventArg> ListEdit;
+
+               void Insert ();
+               void Remove ();
+               void RaiseEdit ();
+       }
+}
+
diff --git a/Crow/src/IValueChange.cs b/Crow/src/IValueChange.cs
new file mode 100644 (file)
index 0000000..011f7e8
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (c) 20132020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+
+namespace Crow
+{
+       /// <summary>
+       /// implement `IValueChange` interface in object you want to bind to the interface.
+       /// For each property updated in code, raise a value change in the container class
+       /// to inform Crow binding system that the value has changed.
+       /// </summary>
+       public interface IValueChange
+       {
+               event EventHandler<ValueChangeEventArgs> ValueChanged;
+       }
+       /// <summary>
+       /// Container for net primitive value type implementing IValueChange
+       /// </summary>
+       public class ValueContainer<T> : IValueChange, IEquatable<T>//, IConvertible
+       {
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               T val;
+               public T Value {
+                       get => val;
+                       set {
+                               if (EqualityComparer<T>.Default.Equals (value, val))
+                                       return;
+                               val = value;
+                               ValueChanged?.Invoke (this, new Crow.ValueChangeEventArgs ("Value", val));
+                       }
+               }
+
+               public static implicit operator ValueContainer<T>(T v) => new ValueContainer<T> (v);
+               public static implicit operator T (ValueContainer<T> v) => v.Value;
+
+               public ValueContainer (T _val) { val = _val; }
+
+               public bool Equals (T other) => val.Equals (other);
+               public override bool Equals (object obj) => obj is ValueContainer<T> v && Equals (v);
+               public override int GetHashCode () => val.GetHashCode ();
+               public override string ToString () => val.ToString ();
+       }
+}
+
diff --git a/Crow/src/Instantiator.cs b/Crow/src/Instantiator.cs
deleted file mode 100644 (file)
index 760b5b1..0000000
+++ /dev/null
@@ -1,1465 +0,0 @@
-// Copyright (c) 2013-2019  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Text;
-using System.Xml;
-
-namespace Crow.IML {
-       public class InstantiatorException : Exception {
-               public string Path;
-               public InstantiatorException (string path, Exception innerException)
-                       : base ("ITor error:" + path, innerException){
-                       Path = path;
-               }
-       }
-       public delegate object InstanciatorInvoker(Interface iface);
-
-       /// <summary>
-       /// Reflexion being very slow, the settings of the starting values for widgets are set by a dynamic method.
-       /// This method is created on the first instacing and is recalled for further widget instancing.
-       /// 
-       /// It includes:
-       ///     - XML values setting
-       ///     - Default values (appearing as attribute in C#)  loading
-       ///     - Styling
-       /// 
-       /// Instantiators are shared amongs interfaces. Their are stored with their path as key, and inlined template
-       /// and itemtemplate are stored with a generated uuid
-       /// </summary>
-       public class Instantiator
-       {
-               #region Dynamic Method ID generation
-               static long curId = 0;
-               internal static long NewId {
-                       get { return curId++; }
-               }
-               #endregion
-
-               internal static Dictionary<string, Type> knownGOTypes = new Dictionary<string, Type> ();
-
-               public Type RootType;
-               InstanciatorInvoker loader;
-               protected Interface iface;
-
-               internal string sourcePath;
-
-               #if DESIGN_MODE
-               public static int NextInstantiatorID = 0;
-               public int currentInstantiatorID = 0;
-               int currentDesignID = 0;
-               internal string NextDesignID { get { return string.Format ("{0}_{1}",currentInstantiatorID, currentDesignID++); }}
-               #endif
-
-               #region CTOR
-               /// <summary>
-               /// Initializes a new instance of the Instantiator class.
-               /// </summary>
-               public Instantiator (Interface _iface, string path) : this (_iface, _iface.GetStreamFromPath(path), path) {
-                       
-               }
-               /// <summary>
-               /// Initializes a new instance of the Instantiator class.
-               /// </summary>
-               public Instantiator (Interface _iface, Stream stream, string srcPath = null)
-               {
-                       #if DESIGN_MODE
-                       currentInstantiatorID = NextInstantiatorID++;
-                       #endif
-                       iface = _iface;
-                       sourcePath = srcPath;
-                       #if DEBUG_LOAD
-                       Stopwatch loadingTime = Stopwatch.StartNew ();
-                       #endif
-                       try {
-                               using (XmlReader itr = XmlReader.Create (stream)) {
-                                       parseIML (itr);
-                               }
-                       } catch (Exception ex) {
-                               throw new InstantiatorException(sourcePath, ex);
-                       } finally {
-                               stream?.Dispose ();
-#if DEBUG_LOAD
-                               loadingTime.Stop ();
-                               using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
-                                       sw.WriteLine ($"ITOR;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
-                               }
-#endif
-                       }
-               }
-               /// <summary>
-               /// Initializes a new instance of the Instantiator class with an already openned xml reader
-               /// positionned on the start tag inside the itemTemplate
-               /// </summary>
-               public Instantiator (Interface _iface, XmlReader itr){
-                       #if DESIGN_MODE
-                       currentInstantiatorID = NextInstantiatorID++;
-                       #endif
-                       iface = _iface;
-                       parseIML (itr);
-               }
-               //TODO:check if still used
-               public Instantiator (Interface _iface, Type _root, InstanciatorInvoker _loader)
-               {
-                       #if DESIGN_MODE
-                       currentInstantiatorID = NextInstantiatorID++;
-                       #endif
-                       iface = _iface;
-                       RootType = _root;
-                       loader = _loader;
-               }
-               /// <summary>
-               /// Create a new instantiator from IML fragment provided directely as a string
-               /// </summary>
-               /// <returns>A new instantiator</returns>
-               /// <param name="fragment">IML string</param>
-               public static Instantiator CreateFromImlFragment (Interface _iface, string fragment)
-               {
-                       using (Stream s = new MemoryStream (Encoding.UTF8.GetBytes (fragment))) {
-                               return new Instantiator (_iface, s);
-                       }
-               }
-               #endregion
-
-               /// <summary>
-               /// Creates a new instance of the GraphicObject compiled in the instantiator
-               /// </summary>
-               /// <returns>The new graphic object instance</returns>
-               public Widget CreateInstance(){
-#if DEBUG_LOAD
-                       Stopwatch loadingTime = Stopwatch.StartNew ();
-                       GraphicObject o = loader (iface) as GraphicObject;
-                       loadingTime.Stop ();
-                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
-                               sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
-                       }
-                       return o;
-#else
-                       return loader (iface) as Widget;
-#endif
-               }
-               /// <summary>
-               /// Creates a new instance of T compiled in the instantiator
-               /// and bind it the an interface
-               /// </summary>
-               /// <returns>The new T instance</returns>
-               public T CreateInstance<T>(){
-#if DEBUG_LOAD
-                       Stopwatch loadingTime = Stopwatch.StartNew ();
-                       T i = (T)loader (iface);
-                       loadingTime.Stop ();
-                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
-                               sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
-                       }
-                       return i;
-#else
-                       return (T)loader (iface);
-#endif
-               }
-               List<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
-               List<Delegate> cachedDelegates = new List<Delegate>();
-               /// <summary>
-               /// store indices of template delegate to be handled by root parentChanged event
-               /// </summary>
-               List<int> templateCachedDelegateIndices = new List<int>();
-               /// <summary>
-               /// Store template bindings in the instantiator
-               /// </summary>
-               Delegate templateBinding;
-
-#if DESIGN_MODE
-               public List<DynamicMethod> DsValueChangedDynMeths =>dsValueChangedDynMeths;
-               public List<Delegate> CachedDelegates => cachedDelegates;
-               /// <summary>
-               /// store indices of template delegate to be handled by root parentChanged event
-               /// </summary>
-               public List<int> TemplateCachedDelegateIndices => templateCachedDelegateIndices;
-               /// <summary>
-               /// Store template bindings in the instantiator
-               /// </summary>
-               public Delegate TemplateBinding => templateBinding;
-
-#endif
-               #region IML parsing
-               /// <summary>
-               /// Parses IML and build a dynamic method that will be used to instantiate one or multiple occurences of the IML file or fragment
-               /// </summary>
-               void parseIML (XmlReader reader) {
-                       IMLContext ctx = new IMLContext (findRootType (reader));
-
-                       ctx.PushNode (ctx.RootType);
-                       emitLoader (reader, ctx);
-                       ctx.PopNode ();
-
-                       foreach (int idx in templateCachedDelegateIndices)
-                               ctx.emitCachedDelegateHandlerAddition(idx, CompilerServices.eiLogicalParentChanged);
-
-                       ctx.ResolveNamedTargets ();
-
-                       emitBindingDelegates (ctx);
-
-            ctx.il.Emit (OpCodes.Ldloc_0);//load root obj to return
-                       ctx.il.Emit(OpCodes.Ret);
-
-                       reader.Read ();//close tag
-                       RootType = ctx.RootType;
-                       loader = (InstanciatorInvoker)ctx.dm.CreateDelegate (typeof (InstanciatorInvoker), this);
-               }
-               /// <summary>
-               /// read first node to set GraphicObject class for loading
-               /// and let reader position on that node
-               /// </summary>
-               Type findRootType (XmlReader reader)
-               {
-                       string root = "Object";
-                       while (reader.NodeType != XmlNodeType.Element)
-                               reader.Read ();
-                       root = reader.Name;
-                       Type t = tryGetGOType (root);
-                       if (t == null)
-                               throw new Exception ("IML parsing error: undefined root type (" + root + ")");
-                       return t;
-               }
-               /// <summary>
-               /// main parsing entry point
-               /// </summary>
-               void emitLoader (XmlReader reader, IMLContext ctx)
-               {
-                       int curLine = ctx.curLine;
-
-                       #if DESIGN_MODE
-                       IXmlLineInfo li = (IXmlLineInfo)reader;
-                       ctx.curLine += li.LineNumber - 1;
-                       #endif
-
-                       string tmpXml = reader.ReadOuterXml ();
-
-                       if (ctx.nodesStack.Peek().HasTemplate)
-                               emitTemplateLoad (ctx, tmpXml);
-
-                       emitGOLoad (ctx, tmpXml);
-
-                       ctx.curLine = curLine;
-               }
-               /// <summary>
-               /// Parses the item template tag.
-               /// </summary>
-               /// <returns>the string triplet dataType, itemTmpID read as attribute of this tag</returns>
-               /// <param name="reader">current xml text reader</param>
-               /// <param name="itemTemplatePath">file containing the templates if its a dedicated one</param>
-               string[] parseItemTemplateTag (IMLContext ctx, XmlReader reader, string itemTemplatePath = "") {
-                       string dataType = "default", datas = "", path = "", dataTest = "TypeOf";
-                       while (reader.MoveToNextAttribute ()) {
-                               if (reader.Name == "DataType")
-                                       dataType = reader.Value;
-                               else if (reader.Name == "Data")
-                                       datas = reader.Value;
-                               else if (reader.Name == "Path")
-                                       path = reader.Value;
-                               else if (reader.Name == "DataTest")
-                                       dataTest = reader.Value;
-                       }
-                       reader.MoveToElement ();
-
-                       string itemTmpID = itemTemplatePath;
-
-                       if (string.IsNullOrEmpty (path)) {
-                               itemTmpID += Guid.NewGuid ().ToString ();
-                               iface.ItemTemplates [itemTmpID] =
-                                       new ItemTemplate (iface, new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataTest, dataType, datas);
-
-                       } else {
-                               if (!reader.IsEmptyElement)
-                                       throw new Exception ("ItemTemplate with Path attribute set may not include sub nodes");
-                               itemTmpID += path+dataType+datas;
-                               if (!iface.ItemTemplates.ContainsKey (itemTmpID))
-                                       iface.ItemTemplates [itemTmpID] =
-                                               new ItemTemplate (iface, path, ctx.CurrentNodeType, dataTest, dataType, datas);
-                       }
-                       return new string [] { dataType, itemTmpID, datas, dataTest };
-               }
-               /// <summary>
-               /// process template and item template definition prior to
-               /// other attributes or childs processing
-               /// </summary>
-               /// <param name="ctx">Loading Context</param>
-               /// <param name="tmpXml">xml fragment</param>
-               void emitTemplateLoad (IMLContext ctx, string tmpXml) {
-                       //if its a template, first read template elements
-                       using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
-                               List<string[]> itemTemplateIds = new List<string[]> ();
-                               bool inlineTemplate = false;
-
-                               reader.Read ();
-                               string templatePath = reader.GetAttribute ("Template");
-                               string itemTemplatePath = reader.GetAttribute ("ItemTemplate");
-
-                               int depth = reader.Depth + 1;
-                               while (reader.Read ()) {
-                                       if (!reader.IsStartElement () || reader.Depth > depth)
-                                               continue;
-                                       if (reader.Name == "Template") {
-                                               inlineTemplate = true;
-                                               #if DESIGN_MODE
-                                               ctx.il.Emit (OpCodes.Ldloc_0);
-                                               ctx.il.Emit (OpCodes.Ldc_I4_1);
-                                               ctx.il.Emit (OpCodes.Stfld, typeof(TemplatedControl).GetField("design_inlineTemplate"));
-                                               #endif
-                                               reader.Read ();
-                                               readChildren (reader, ctx, -1);
-                                       } else if (reader.Name == "ItemTemplate")
-                                               itemTemplateIds.Add (parseItemTemplateTag (ctx, reader));                                       
-                               }
-
-                               if (!inlineTemplate) {//load from path or default template
-
-                                       if (!string.IsNullOrEmpty (templatePath)) {
-                                               ctx.il.Emit (OpCodes.Ldloc_0);//Load  current templatedControl ref
-                                               //      ctx.il.Emit (OpCodes.Ldnull);//default template loading
-                                               //} else {
-                                               ctx.il.Emit (OpCodes.Ldarg_1);//load currentInterface
-                                               ctx.il.Emit (OpCodes.Ldstr, templatePath); //Load template path string
-                                               //get declaring type for search fallback assembly
-                                               ctx.il.Emit (OpCodes.Ldloc_0);
-                                               ctx.il.Emit (OpCodes.Call, CompilerServices.miGetType);
-                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miIFaceCreateTemplateInst);
-                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadTmp);//load template
-                                       }
-                               }
-                               if (itemTemplateIds.Count == 0) {
-                                       //try to load ItemTemplate(s) from ItemTemplate attribute of TemplatedGroup
-                                       if (!string.IsNullOrEmpty (itemTemplatePath)) {
-                                               //check if it is already loaded in cache as a single itemTemplate instantiator
-                                               if (iface.ItemTemplates.ContainsKey (itemTemplatePath)) {
-                                                       itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
-                                               } else {
-                                                       using (Stream stream = iface.GetTemplateStreamFromPath (itemTemplatePath, ctx.CurrentNodeType)) {
-                                                               //itemtemplate files may have multiple root nodes
-                                                               XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
-                                                               using (XmlReader itr = XmlReader.Create (stream, itrSettings)) {                                                                        
-                                                                       while (itr.Read ()) {
-                                                                               if (!itr.IsStartElement ())
-                                                                                       continue;
-                                                                               if (itr.NodeType == XmlNodeType.Element) {
-                                                                                       if (itr.Name != "ItemTemplate") {
-                                                                                               //the file contains a single template to use as default
-                                                                                               iface.ItemTemplates [itemTemplatePath] =
-                                                                                                       new ItemTemplate (iface, itr);
-                                                                                               itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "", "TypeOf" });
-                                                                                               break;//we should be at the end of the file
-                                                                                       }
-                                                                                       itemTemplateIds.Add (parseItemTemplateTag (ctx, itr, itemTemplatePath));
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                               if (!ctx.nodesStack.Peek ().IsTemplatedGroup)
-                                       return;
-                               //add the default item template if no default is defined
-                               if (!itemTemplateIds.Any(ids=>ids[0] == "default"))
-                                       itemTemplateIds.Add (new string [] { "default", "#Crow.DefaultItem.template", "", "TypeOf"});
-                               //get item templates 
-                               foreach (string [] iTempId in itemTemplateIds) {
-                                       ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
-                                       ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);//load ItemTemplates dic field
-
-                                       //prepare argument to add itemTemplate to templated group dic of ItemTemplates
-                                       ctx.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key
-                                       //load itemTemplate
-                                       ctx.il.Emit (OpCodes.Ldarg_1);//load currentInterface
-                                       ctx.il.Emit (OpCodes.Ldstr, iTempId [1]);//load path
-                                       //second arg is Type, to find assembly where to search if not in entry
-                                       ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
-                                       ctx.il.Emit (OpCodes.Call, CompilerServices.miGetType);
-                                       ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITemp);
-                                       ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miAddITemp);
-
-                                       if (!string.IsNullOrEmpty (iTempId [2])) {
-                                               //expand delegate creation
-                                               ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
-                                               ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);
-                                               ctx.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key
-                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITempFromDic);
-                                               ctx.il.Emit (OpCodes.Ldloc_0);//load root of treeView
-                                               ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miCreateExpDel);
-                                       }
-                               }
-                       }
-               }
-
-               #if DESIGN_MODE
-               void emitSetDesignAttribute (IMLContext ctx, string name, string value){
-                       //store member value in iml
-                       ctx.il.Emit (OpCodes.Ldloc_0);
-                       ctx.il.Emit (OpCodes.Ldfld, typeof(Widget).GetField("design_iml_values"));
-                       ctx.il.Emit (OpCodes.Ldstr, name);
-                       if (string.IsNullOrEmpty (value))
-                               ctx.il.Emit (OpCodes.Ldnull);
-                       else
-                               ctx.il.Emit (OpCodes.Ldstr, value);
-                       ctx.il.Emit (OpCodes.Call, CompilerServices.miDicStrStrAdd);
-               }
-               #endif
-
-               /// <summary>
-               /// process styling, attributes and children loading.
-               /// </summary>
-               /// <param name="ctx">parsing context</param>
-               /// <param name="tmpXml">xml fragment</param>
-               void emitGOLoad (IMLContext ctx, string tmpXml) {
-                       using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
-                               reader.Read ();
-
-#if DESIGN_MODE
-                               IXmlLineInfo li = (IXmlLineInfo)reader;
-                               ctx.il.Emit (OpCodes.Ldloc_0);
-                               ctx.il.Emit (OpCodes.Ldstr, this.NextDesignID);
-                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_id"));
-                               ctx.il.Emit (OpCodes.Ldloc_0);
-                               ctx.il.Emit (OpCodes.Ldc_I4, ctx.curLine + li.LineNumber);
-                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_line"));
-                               ctx.il.Emit (OpCodes.Ldloc_0);
-                               ctx.il.Emit (OpCodes.Ldc_I4, li.LinePosition);
-                               ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_column"));
-                               if (!string.IsNullOrEmpty (sourcePath)) {
-                                       ctx.il.Emit (OpCodes.Ldloc_0);
-                                       ctx.il.Emit (OpCodes.Ldstr, sourcePath);
-                                       ctx.il.Emit (OpCodes.Stfld, typeof(Widget).GetField("design_imlPath"));
-                               }
-#endif
-                               #region Styling and default values loading
-                               //first check for Style attribute then trigger default value loading
-                               if (reader.HasAttributes) {
-                                       string style = reader.GetAttribute ("Style");
-                                       if (!string.IsNullOrEmpty (style)) {
-                                               CompilerServices.EmitSetValue (ctx.il, CompilerServices.piStyle, style);
-#if DESIGN_MODE
-                                               emitSetDesignAttribute (ctx, "Style", style);
-#endif
-                                       }
-                                       //check for dataSourceType, if set, datasource bindings will use direct setter/getter
-                                       //instead of reflexion
-                                       string dataSourceType = reader.GetAttribute ("DataSourceType");
-                                       if (string.IsNullOrEmpty (dataSourceType)) {
-                                               //if not set but dataSource is not null, reset dsType to null
-                                               string ds = reader.GetAttribute ("DataSource");
-                                               if (!string.IsNullOrEmpty (ds)) 
-                                                       ctx.SetDataSourceTypeForCurrentNode (null);
-                                       } else
-                                               ctx.SetDataSourceTypeForCurrentNode(CompilerServices.getTypeFromName (dataSourceType));
-                               }
-                               ctx.il.Emit (OpCodes.Ldloc_0);
-                ctx.il.Emit (OpCodes.Call, CompilerServices.miLoadDefaultVals);
-#endregion
-
-
-                               #region Attributes reading
-                               if (reader.HasAttributes) {
-
-                                       while (reader.MoveToNextAttribute ()) {
-                                               if (reader.Name == "Style" || reader.Name == "DataSourceType" || reader.Name == "Template")
-                                                       continue;
-
-                                               #if DESIGN_MODE
-                                               emitSetDesignAttribute (ctx, reader.Name, reader.Value);
-                                               #endif
-
-                                               MemberInfo mi = ctx.CurrentNodeType.GetMember (reader.Name).FirstOrDefault ();
-                                               if (mi == null)
-                                                       throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNodeType.Name);
-
-                                               if (mi.MemberType == MemberTypes.Event) {
-                                                       foreach (string exp in reader.Value.Split (';')) {
-                                                               string trimed = exp.Trim();
-                                                               if (trimed.StartsWith ("{", StringComparison.Ordinal))
-                                                                       compileAndStoreDynHandler (ctx, mi as EventInfo, trimed.Substring (1, trimed.Length - 2));
-                                                               else
-                                                                       emitHandlerBinding (ctx, mi as EventInfo, trimed);
-                                                       }
-
-                                                       continue;
-                                               }
-                                               PropertyInfo pi = mi as PropertyInfo;
-                                               if (pi == null)
-                                                       throw new Exception ("Member '" + reader.Name + "' is not a property in " + ctx.CurrentNodeType.Name);
-
-                                               if (pi.Name == "Name")
-                                                       ctx.StoreCurrentName (reader.Value);
-
-                                               if (reader.Value.StartsWith ("{", StringComparison.Ordinal))
-                                                       readPropertyBinding (ctx, reader.Name, reader.Value.Substring (1, reader.Value.Length - 2));
-                                               else
-                                                       CompilerServices.EmitSetValue (ctx.il, pi, reader.Value);
-
-                                       }
-                                       reader.MoveToElement ();
-                               }
-                               #endregion
-
-                               readChildren (reader, ctx);
-
-                               ctx.nodesStack.ResetCurrentNodeIndex ();
-                       }
-               }
-               /// <summary>
-               /// Parse child node an generate corresponding msil
-               /// </summary>
-               void readChildren (XmlReader reader, IMLContext ctx, int startingIdx = 0)
-               {
-                       bool endTagReached = false;
-                       int nodeIdx = startingIdx;
-                       while (reader.Read ()) {
-                               switch (reader.NodeType) {
-                               case XmlNodeType.EndElement:
-                                       endTagReached = true;
-                                       break;
-                               case XmlNodeType.Element:
-                                       //skip Templates
-                                       if (reader.Name == "Template" ||
-                                           reader.Name == "ItemTemplate") {
-                                               reader.Skip ();
-                                               continue;
-                                       }
-
-                                       //push 2x current instance on stack for parenting and reseting loc0 to parent
-                                       //loc_0 will be used for child
-                                       ctx.il.Emit (OpCodes.Ldloc_0);
-                                       ctx.il.Emit (OpCodes.Ldloc_0);
-
-                                       Type t = tryGetGOType (reader.Name);
-                                       if (t == null)
-                                               throw new Exception (reader.Name + " type not found");
-                                       ConstructorInfo ci = t.GetConstructor (
-                                                                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,  
-                                               null, Type.EmptyTypes, null);
-                                       if (ci == null)
-                                               throw new Exception ("No default parameterless constructor found in " + t.Name);                                        
-                                       ctx.il.Emit (OpCodes.Newobj, ci);
-                                       ctx.il.Emit (OpCodes.Stloc_0);//child is now loc_0
-                                       CompilerServices.emitSetCurInterface (ctx.il);
-
-                                       ctx.nodesStack.Push (new Node (t, nodeIdx));
-                                       emitLoader (reader, ctx);
-                                       ctx.nodesStack.Pop ();
-
-                                       ctx.il.Emit (OpCodes.Ldloc_0);//load child on stack for parenting
-                                       ctx.il.Emit (OpCodes.Callvirt, ctx.nodesStack.Peek().GetAddMethod(nodeIdx));
-                                       ctx.il.Emit (OpCodes.Stloc_0); //reset local to current go
-
-                                       nodeIdx++;
-
-                                       break;
-                               }
-                               if (endTagReached)
-                                       break;
-                       }
-               }
-               #endregion
-               /// <summary>
-               /// Reads binding expression found as attribute value in iml
-               /// </summary>
-               /// <param name="ctx">IML Context</param>
-               /// <param name="sourceMember">IML Attribute name</param>
-               /// <param name="expression">Binding Expression with accollades trimed</param>
-               void readPropertyBinding (IMLContext ctx, string sourceMember, string expression)
-               {
-                       NodeAddress sourceNA = ctx.CurrentNodeAddress;
-                       BindingDefinition bindingDef = sourceNA.GetBindingDef (sourceMember, expression);
-
-#if DEBUG_BINDING
-                       Debug.WriteLine("Property Binding: " + bindingDef.ToString());
-#endif
-
-                       if (bindingDef.IsDataSourceBinding) {//bind on data source
-                               if (ctx.CurrentNodeHasDataSourceType)
-                                       emitDataSourceBindings (ctx, bindingDef, ctx.CurrentDataSourceType);
-                               else
-                                       emitDataSourceBindings (ctx, bindingDef);
-                       } else
-                               ctx.StorePropertyBinding (bindingDef);
-               }
-
-               #region Emit Helper
-               void dataSourceChangedEmitHelper(object dscSource, object dataSource, int dynMethIdx){
-                       if (dataSource is IValueChange)
-                               (dataSource as IValueChange).ValueChanged +=
-                                       (EventHandler<ValueChangeEventArgs>)dsValueChangedDynMeths [dynMethIdx].CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>), dscSource);
-               }
-               /// <summary> Emits remove old data source event handler.</summary>
-               void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){
-                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
-
-                       il.Emit (OpCodes.Ldarg_2);//load old parent
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
-                       il.Emit (OpCodes.Brfalse, cancel);//old parent is null
-
-                       //remove handler
-                       if (DSSide){//event is defined in the dataSource instance
-                               il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
-                       }else//the event is in the source
-                               il.Emit (OpCodes.Ldarg_1);//1st arg load old datasource
-                       il.Emit (OpCodes.Ldstr, eventName);//2nd arg event name
-                       il.Emit (OpCodes.Ldstr, delegateName);//3d arg: delegate name
-                       il.Emit (OpCodes.Call, CompilerServices.miRemEvtHdlByName);
-                       il.MarkLabel(cancel);
-               }
-               #endregion
-
-               #region Event Bindings
-               /// <summary>
-               /// Compile events expression in IML attributes, and store the result in the instanciator
-               /// Those handlers will be bound when instatiing
-               /// </summary>
-               void compileAndStoreDynHandler (IMLContext ctx, EventInfo sourceEvent, string expression)
-               {
-                       //store event handler dynamic method in instanciator
-                       int dmIdx = cachedDelegates.Count;
-                       cachedDelegates.Add (CompilerServices.compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress));
-                       ctx.emitCachedDelegateHandlerAddition(dmIdx, sourceEvent);
-               }
-               /// <summary> Emits handler method bindings </summary>
-               void emitHandlerBinding (IMLContext ctx, EventInfo sourceEvent, string expression){
-                       NodeAddress currentNode = ctx.CurrentNodeAddress;
-                       BindingDefinition bindingDef = currentNode.GetBindingDef (sourceEvent.Name, expression);
-
-                       #if DEBUG_BINDING
-                       Debug.WriteLine("Event Binding: " + bindingDef.ToString());
-                       #endif
-
-                       if (bindingDef.IsTemplateBinding | bindingDef.IsDataSourceBinding) {
-                               //we need to bind datasource method to source event
-                               DynamicMethod dm = new DynamicMethod ("dyn_dsORtmpChangedForHandler" + NewId,
-                                                          typeof(void),
-                                                          CompilerServices.argsBoundDSChange, true);
-
-                               ILGenerator il = dm.GetILGenerator (256);
-                               System.Reflection.Emit.Label cancel = il.DefineLabel ();
-
-                               il.DeclareLocal (typeof(MethodInfo));//used to cancel binding if method doesn't exist
-
-                               il.Emit (OpCodes.Nop);
-
-                               emitRemoveOldDataSourceHandler (il, sourceEvent.Name, bindingDef.TargetMember, false);
-
-
-                               //fetch method in datasource and test if it exist
-                               il.Emit (OpCodes.Ldarg_2);//load new datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                               il.Emit (OpCodes.Brfalse, cancel);//cancel if new datasource is null
-                               il.Emit (OpCodes.Ldarg_2);//load new datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load handler method name
-                               il.Emit (OpCodes.Call, CompilerServices.miGetMethInfoWithRefx);
-                               il.Emit (OpCodes.Stloc_0);//save MethodInfo                                          
-                il.Emit (OpCodes.Ldloc_0);//push mi for test if null
-                il.Emit (OpCodes.Brfalse, cancel);//cancel if null
-
-                il.Emit (OpCodes.Ldarg_1);//load datasource change source where the event is as 1st arg of handler.add
-                if (bindingDef.IsTemplateBinding)//fetch source instance with address
-                    CompilerServices.emitGetInstance (il, bindingDef.SourceNA);
-
-                //load handlerType of sourceEvent to create delegate (1st arg)
-                il.Emit (OpCodes.Ldtoken, sourceEvent.EventHandlerType);
-                il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-                il.Emit (OpCodes.Ldarg_2);//load new datasource where the method is defined
-                il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                il.Emit (OpCodes.Ldloc_0);//load methodInfo (3rd arg)
-
-                il.Emit (OpCodes.Call, CompilerServices.miCreateBoundDel);
-                il.Emit (OpCodes.Callvirt, sourceEvent.AddMethod);//call add event
-                                          
-                System.Reflection.Emit.Label finish = il.DefineLabel ();
-                il.Emit (OpCodes.Br, finish);
-                il.MarkLabel (cancel);
-                               #if DEBUG_BINDING
-                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' NOT FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
-                               #endif
-                               il.MarkLabel (finish);
-                               #if DEBUG_BINDING
-                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
-                               #endif
-                                              
-                               il.Emit (OpCodes.Ret);
-
-                               //store dschange delegate in instatiator instance for access while instancing graphic object
-                               int delDSIndex = cachedDelegates.Count;
-                               cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
-
-                               if (bindingDef.IsDataSourceBinding)
-                                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
-                               else //template handler binding, will be added to root parentChanged
-                                       templateCachedDelegateIndices.Add (delDSIndex);
-                       } else {//normal in tree handler binding, store until tree is complete (end of parse)
-                               ctx.UnresolvedTargets.Add (new EventBinding (
-                                       bindingDef.SourceNA, sourceEvent,
-                                       bindingDef.TargetNA, bindingDef.TargetMember, bindingDef.TargetName));
-                       }
-               }
-               #endregion
-
-               #region Property Bindings
-               /// <summary>
-               /// Create and store in the instanciator the ValueChanged delegates
-               /// those delegates uses grtree functions to set destination value so they don't
-               /// need to be bound to destination instance as in the ancient system.
-               /// </summary>
-               void emitBindingDelegates(IMLContext ctx){
-                       foreach (KeyValuePair<NodeAddress,Dictionary<string, List<MemberAddress>>> bindings in ctx.Bindings ) {
-                               if (bindings.Key.Count == 0)//template binding
-                                       emitTemplateBindings (ctx, bindings.Value);
-                               else
-                                       emitPropertyBindings (ctx,  bindings.Key, bindings.Value);
-                       }
-               }
-               void emitPropertyBindings(IMLContext ctx, NodeAddress origine, Dictionary<string, List<MemberAddress>> bindings){
-                       Type origineNodeType = origine.NodeType;
-
-                       //value changed dyn method
-                       DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId,
-                               typeof (void), CompilerServices.argsValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (256);
-
-                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
-
-                       il.DeclareLocal (typeof(object));
-
-                       il.Emit (OpCodes.Nop);
-
-                       int i = 0;
-                       foreach (KeyValuePair<string, List<MemberAddress>> bindingCase in bindings ) {
-
-                               System.Reflection.Emit.Label nextTest = il.DefineLabel ();
-
-                               #region member name test
-                               //load source member name
-                               il.Emit (OpCodes.Ldarg_1);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
-
-                               il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test
-                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
-                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
-                               il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case
-                               #endregion
-
-                               #region destination member affectations
-                               PropertyInfo piOrig = origineNodeType.GetProperty (bindingCase.Key);
-                               Type origineType = null;
-                               if (piOrig != null)
-                                       origineType = piOrig.PropertyType;
-                               foreach (MemberAddress ma in bindingCase.Value) {
-                                       //first we have to load destination instance onto the stack, it is access
-                                       //with graphic tree functions deducted from nodes topology
-                                       il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
-
-                                       NodeAddress destination = ma.Address;
-
-                                       if (destination.Count == 0){//template reverse binding
-                                               //fetch destination instance (which is the template root)
-                                               for (int j = 0; j < origine.Count ; j++)
-                                                       il.Emit(OpCodes.Callvirt, CompilerServices.miGetLogicalParent);
-                                       }else
-                                               CompilerServices.emitGetInstance (il, origine, destination);
-
-                                       if (origineType != null && destination.Count > 0){//else, prop less binding or reverse template bind, no init requiered
-                                               //for initialisation dynmeth, push destination instance loc_0 is root node in ctx
-                                               ctx.il.Emit(OpCodes.Ldloc_0);
-                                               CompilerServices.emitGetInstance (ctx.il, destination);
-
-                                               //init dynmeth: load actual value from origine
-                                               ctx.il.Emit (OpCodes.Ldloc_0);
-                                               CompilerServices.emitGetInstance (ctx.il, origine);
-                                               ctx.il.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
-                                       }
-                                       //load new value
-                                       il.Emit (OpCodes.Ldarg_1);
-                                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
-
-                                       if (origineType == null)//property less binding, no init
-                                               CompilerServices.emitConvert (il, ma.Property.PropertyType);
-                                       else if (destination.Count > 0) {
-                                               if (origineType.IsValueType)
-                                                       ctx.il.Emit(OpCodes.Box, origineType);
-
-                                               CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType);
-                                               CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType);
-
-                                               ctx.il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
-                                       } else {// reverse templateBinding
-                                               il.Emit (OpCodes.Ldstr, ma.memberName);//arg 3 of setValueWithReflexion
-                                               il.Emit (OpCodes.Call, CompilerServices.miSetValWithRefx);
-                                               continue;
-                                       }
-                                       il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes
-                               }
-                               #endregion
-                               il.Emit (OpCodes.Br, endMethod);
-                               il.MarkLabel (nextTest);
-
-                               i++;
-                       }
-
-                       il.MarkLabel (endMethod);
-                       il.Emit (OpCodes.Ret);
-
-                       //store and emit Add in ctx
-                       int dmIdx = cachedDelegates.Count;
-                       cachedDelegates.Add (dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>)));
-                       ctx.emitCachedDelegateHandlerAddition (dmIdx, CompilerServices.eiValueChange, origine);
-
-                       #if DEBUG_BINDING
-                       Debug.WriteLine("\tCrow property binding: " + dm.Name);
-                       #endif
-
-               }
-               void emitTemplateBindings(IMLContext ctx, Dictionary<string, List<MemberAddress>> bindings){
-                       //value changed dyn method
-                       DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged" + NewId,
-                               typeof (void), CompilerServices.argsValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (256);
-
-                       //create parentchanged dyn meth in parallel to have only one loop over bindings
-                       DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged" + NewId,
-                               typeof (void),
-                               CompilerServices.argsBoundDSChange, true);
-                       ILGenerator ilPC = dmPC.GetILGenerator (256);
-
-                       il.Emit (OpCodes.Nop);
-                       ilPC.Emit (OpCodes.Nop);
-
-                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
-
-                       il.DeclareLocal (typeof(object));
-                       ilPC.DeclareLocal (typeof(object));//used for checking propery less bindings
-                       ilPC.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
-
-                       System.Reflection.Emit.Label cancel = ilPC.DefineLabel ();
-
-                       #region Unregister previous parent event handler
-                       //unregister previous parent handler if not null
-                       ilPC.Emit (OpCodes.Ldarg_2);//load old parent
-                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
-                       ilPC.Emit (OpCodes.Brfalse, cancel);//old parent is null
-
-                       ilPC.Emit (OpCodes.Ldarg_2);//load old parent
-                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
-                       //Load cached delegate
-                       ilPC.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                       ilPC.Emit(OpCodes.Ldfld, CompilerServices.fiTemplateBinding);
-
-                       //add template bindings dynValueChanged delegate to new parent event
-                       ilPC.Emit(OpCodes.Callvirt, CompilerServices.eiValueChange.RemoveMethod);//call remove event
-                       #endregion
-
-                       ilPC.MarkLabel(cancel);
-
-                       #region check if new parent is null
-                       cancel = ilPC.DefineLabel ();
-                       ilPC.Emit (OpCodes.Ldarg_2);//load datasource change arg
-                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                       ilPC.Emit (OpCodes.Brfalse, cancel);//new ds is null
-                       #endregion
-
-                       int i = 0;
-                       foreach (KeyValuePair<string, List<MemberAddress>> bindingCase in bindings ) {
-
-                               System.Reflection.Emit.Label nextTest = il.DefineLabel ();
-
-                               #region member name test
-                               //load source member name
-                               il.Emit (OpCodes.Ldarg_1);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
-
-                               il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test
-                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
-                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
-                               il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case
-                               #endregion
-
-                               #region destination member affectations
-
-                               foreach (MemberAddress ma in bindingCase.Value) {
-                                       if (ma.Address.Count == 0){
-                                               Debug.WriteLine("\t\tBUG: reverse template binding in normal template binding");
-                                               continue;//template binding
-                                       }
-                                       //first we try to get memberInfo of new parent, if it doesn't exist, it's a propery less binding
-                                       ilPC.Emit (OpCodes.Ldarg_2);//load new parent onto the stack for handler addition
-                                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                                       ilPC.Emit (OpCodes.Stloc_0);//save new parent
-                                       //get parent type
-                                       ilPC.Emit (OpCodes.Ldloc_0);//push parent instance
-                                       ilPC.Emit (OpCodes.Ldstr, bindingCase.Key);//load member name
-                                       ilPC.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
-                                       ilPC.Emit (OpCodes.Stloc_1);//save memberInfo
-                                       ilPC.Emit (OpCodes.Ldloc_1);//push mi for test if null
-                                       System.Reflection.Emit.Label propLessReturn = ilPC.DefineLabel ();
-                                       ilPC.Emit (OpCodes.Brfalse, propLessReturn);
-
-
-                                       //first we have to load destination instance onto the stack, it is access
-                                       //with graphic tree functions deducted from nodes topology
-                                       il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
-                                       CompilerServices.emitGetChild (il, typeof(TemplatedControl), -1);
-                                       CompilerServices.emitGetInstance (il, ma.Address);
-
-                                       ilPC.Emit (OpCodes.Ldarg_2);//load destination instance to set actual value of member
-                                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                                       CompilerServices.emitGetChild (ilPC, typeof(TemplatedControl), -1);
-                                       CompilerServices.emitGetInstance (ilPC, ma.Address);
-
-                                       //load new value
-                                       il.Emit (OpCodes.Ldarg_1);
-                                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
-
-                                       //for the parent changed dyn meth we need to fetch actual value for initialisation thrue reflexion
-                                       ilPC.Emit (OpCodes.Ldloc_0);//push root instance of instanciator as parentChanged source
-                                       ilPC.Emit (OpCodes.Ldloc_1);//push mi for value fetching
-                                       ilPC.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
-
-                                       CompilerServices.emitConvert (il, ma.Property.PropertyType);
-                                       CompilerServices.emitConvert (ilPC, ma.Property.PropertyType);
-
-                                       il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
-                                       ilPC.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
-
-                                       ilPC.MarkLabel(propLessReturn);
-                               }
-                               #endregion
-                               il.Emit (OpCodes.Br, endMethod);
-                               il.MarkLabel (nextTest);
-
-                               i++;
-                       }
-                       //il.Emit (OpCodes.Pop);
-                       il.MarkLabel (endMethod);
-                       il.Emit (OpCodes.Ret);
-
-                       //store template bindings in instanciator
-                       templateBinding = dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>));
-
-                       #region emit LogicalParentChanged method
-
-                       //load new parent onto the stack for handler addition
-                       ilPC.Emit (OpCodes.Ldarg_2);
-                       ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-
-                       //Load cached delegate
-                       ilPC.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                       ilPC.Emit(OpCodes.Ldfld, CompilerServices.fiTemplateBinding);
-
-                       //add template bindings dynValueChanged delegate to new parent event
-                       ilPC.Emit(OpCodes.Callvirt, CompilerServices.eiValueChange.AddMethod);//call add event
-
-                       ilPC.MarkLabel (cancel);
-                       ilPC.Emit (OpCodes.Ret);
-
-                       //store dschange delegate in instatiator instance for access while instancing graphic object
-                       int delDSIndex = cachedDelegates.Count;
-                       cachedDelegates.Add(dmPC.CreateDelegate (CompilerServices.ehTypeDSChange, this));
-                       #endregion
-
-                       ctx.emitCachedDelegateHandlerAddition(delDSIndex, CompilerServices.eiLogicalParentChanged);
-               }
-               /// <summary>
-               /// data source binding with known data type
-               /// </summary>
-               void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef, Type dsType)
-               {
-#if DEBUG_BINDING_FUNC_CALLS
-                       Console.WriteLine ($"emitDataSourceBindings with data type knows: {bindingDef}");
-#endif
-                       DynamicMethod dm = null;
-                       ILGenerator il = null;
-                       int dmVC = 0;
-                       PropertyInfo piSource = ctx.CurrentNodeType.GetProperty (bindingDef.SourceMember);
-                       //if no dataSource member name is provided, valuechange is not handle and datasource change
-                       //will be used as origine value
-                       string delName = "dyn_DSvalueChangedKnownType" + NewId;
-                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
-                               #region create valuechanged method
-                               dm = new DynamicMethod (delName,
-                                       typeof (void),
-                                       CompilerServices.argsBoundValueChange, true);
-
-                               il = dm.GetILGenerator (256);
-
-                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
-
-                               il.DeclareLocal (typeof (object));
-
-                               il.Emit (OpCodes.Nop);
-
-                               //load value changed member name onto the stack
-                               il.Emit (OpCodes.Ldarg_2);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
-
-                               //test if it's the expected one
-                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);
-                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
-                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
-                               il.Emit (OpCodes.Brfalse, endMethod);
-                               //set destination member with valueChanged new value
-                               //load destination ref
-                               il.Emit (OpCodes.Ldarg_0);
-                               //load new value onto the stack
-                               il.Emit (OpCodes.Ldarg_2);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
-
-                               //by default, source value type is deducted from target member type to allow
-                               //memberless binding, if targetMember exists, it will be used to determine target
-                               //value type for conversion
-                               CompilerServices.emitConvert (il, piSource.PropertyType);
-
-                               if (!piSource.CanWrite)
-                                       throw new Exception ("Source member of bindind is read only:" + piSource.ToString ());
-
-                               il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-
-                               il.MarkLabel (endMethod);
-                               il.Emit (OpCodes.Ret);
-
-                               //vc dyn meth is stored in a cached list, it will be bound to datasource only
-                               //when datasource of source graphic object changed
-                               dmVC = dsValueChangedDynMeths.Count;
-                               dsValueChangedDynMeths.Add (dm);
-                               #endregion
-                       }
-
-                       #region emit dataSourceChanged event handler
-                       //now we create the datasource changed method that will init the destination member with
-                       //the actual value of the origin member of the datasource and then will bind the value changed
-                       //dyn methode.
-                       //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
-                       dm = new DynamicMethod ("dyn_dschanged" + NewId,
-                               typeof (void),
-                               CompilerServices.argsBoundDSChange, true);
-
-                       il = dm.GetILGenerator (256);
-
-                       il.DeclareLocal (typeof (object));//used for checking propery less bindings
-                       il.DeclareLocal (typeof (MemberInfo));//used for checking propery less bindings
-                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
-                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
-                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
-                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
-
-                       il.Emit (OpCodes.Nop);
-
-                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
-
-                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
-
-                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
-                               if (bindingDef.TwoWay) //remove handler
-                                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName + "_reverse", false);
-                               //test if new ds is null
-                               il.Emit (OpCodes.Ldloc_2);
-                               il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
-                               //test if new ds is of expected type
-                               il.Emit (OpCodes.Ldloc_2);
-                               il.Emit (OpCodes.Isinst, dsType);
-                               //il.Emit (OpCodes.Call, CompilerServices.miGetMDToken);
-                               //il.Emit (OpCodes.Ldc_I4, dsType.MetadataToken);
-                               il.Emit (OpCodes.Brfalse, newDSIsNull);
-                       }
-
-                       #region fetch initial Value
-                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
-                               Type mbType;
-                               MemberInfo mi = CompilerServices.GetMemberInfo (dsType, bindingDef.TargetMember, out mbType);
-                               if (mi != null) {
-                                       il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
-                                       il.Emit (OpCodes.Ldloc_2);//load new ds
-                                       CompilerServices.emitGetMemberValue (il, dsType, mi);
-                                       if (mbType != piSource.PropertyType)
-                                               CompilerServices.emitConvert (il, mbType, piSource.PropertyType);
-                                       il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-                               }
-                       }
-                       #endregion
-
-                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
-                               il.MarkLabel (cancelInit);
-                               //check if new dataSource implement IValueChange
-                               il.Emit (OpCodes.Ldloc_2);//load new datasource
-                               il.Emit (OpCodes.Isinst, typeof (IValueChange));
-                               il.Emit (OpCodes.Brfalse, cancel);
-
-                               il.Emit (OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                               il.Emit (OpCodes.Ldarg_1);//load datasource change source
-                               il.Emit (OpCodes.Ldloc_2);//load new datasource
-                               il.Emit (OpCodes.Ldc_I4, dmVC);//load index of dynmathod
-                               il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
-
-                               il.MarkLabel (cancel);
-
-                               if (bindingDef.TwoWay) {
-                                       il.Emit (OpCodes.Ldstr, delName + "_reverse");//load delName used for removing on ds changed
-                                       il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
-                                       il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
-                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
-                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member
-                                       il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
-                               }
-
-                       }
-                       il.MarkLabel (newDSIsNull);
-                       il.Emit (OpCodes.Ret);
-
-                       //store dschange delegate in instatiator instance for access while instancing graphic object
-                       int delDSIndex = cachedDelegates.Count;
-
-                       //Int32 fiLength = (Int32)il.GetType ().GetField ("code_len", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
-                       //byte [] bytes = (byte[])il.GetType ().GetField ("code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
-
-                       cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
-                       #endregion
-
-                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
-
-#if DEBUG_BINDING
-                       Debug.WriteLine("\tDataSource ValueChanged: " + delName);
-                       Debug.WriteLine("\tDataSource Changed: " + dm.Name);
-#endif
-               }
-
-               /// <summary>
-               /// create the valuechanged handler, the datasourcechanged handler and emit event handling
-               /// </summary>
-               void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef)
-               {
-                       Delegate del = emitDataSourceBindings (ctx.CurrentNodeType.GetProperty (bindingDef.SourceMember), bindingDef);
-
-                       //store dschange delegate in instatiator instance for access while instancing graphic object
-                       int delDSIndex = cachedDelegates.Count;
-                       cachedDelegates.Add (del);
-
-                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
-               }
-
-               /// <summary>
-               /// create the valuechanged handler and the datasourcechanged handler and return the 
-               /// DataSourceChange delegate
-               /// </summary>
-               public Delegate emitDataSourceBindings (PropertyInfo piSource, BindingDefinition bindingDef){           
-
-#if DEBUG_BINDING_FUNC_CALLS
-                       Console.WriteLine ($"emitDataSourceBindings: {bindingDef}");
-#endif
-                       DynamicMethod dm = null;
-                       ILGenerator il = null;
-                       int dmVC = 0;
-
-                       //if no dataSource member name is provided, valuechange is not handle and datasource change
-                       //will be used as origine value
-                       string delName = $"dyn_DSvalueChanged_{bindingDef.SourceMember}_{bindingDef.TargetMember}_{NewId}";
-                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                       #region create valuechanged method
-                               dm = new DynamicMethod (delName,
-                                       typeof (void),
-                                       CompilerServices.argsBoundValueChange, true);
-
-                               il = dm.GetILGenerator (64);
-
-                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
-
-                               il.DeclareLocal (typeof(object));
-
-                               il.Emit (OpCodes.Nop);
-
-                               //load value changed member name onto the stack
-                               il.Emit (OpCodes.Ldarg_2);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
-
-                               //test if it's the expected one
-                               il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ? $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);
-                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
-                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
-                               il.Emit (OpCodes.Brfalse, endMethod);
-                               //set destination member with valueChanged new value
-                               //load destination ref
-                               il.Emit (OpCodes.Ldarg_0);
-                               //load new value onto the stack
-                               il.Emit (OpCodes.Ldarg_2);
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
-
-                               //by default, source value type is deducted from target member type to allow
-                               //memberless binding, if targetMember exists, it will be used to determine target
-                               //value type for conversion
-                               CompilerServices.emitConvert (il, piSource.PropertyType);
-
-                               if (!piSource.CanWrite)
-                                       throw new Exception ("Source member of bindind is read only:" + piSource.ToString());
-
-                               il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-
-                               il.MarkLabel (endMethod);
-                               il.Emit (OpCodes.Ret);
-
-                               //vc dyn meth is stored in a cached list, it will be bound to datasource only
-                               //when datasource of source graphic object changed
-                               dmVC = dsValueChangedDynMeths.Count;
-                               dsValueChangedDynMeths.Add (dm);
-#endregion
-                       }
-
-                       #region emit dataSourceChanged event handler
-                       //now we create the datasource changed method that will init the destination member with
-                       //the actual value of the origin member of the datasource and then will bind the value changed
-                       //dyn methode.
-                       //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
-                       dm = new DynamicMethod ("dyn_dschanged" + NewId,
-                               typeof (void),
-                               CompilerServices.argsBoundDSChange, true);
-
-                       il = dm.GetILGenerator (64);
-
-                       il.DeclareLocal (typeof(object));//used for checking propery less bindings
-                       il.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
-                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
-                       il.DeclareLocal (typeof (MemberInfo));//used for binding with datasource.object.member (2 levels)
-                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
-                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
-                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
-
-                       il.Emit (OpCodes.Nop);
-
-                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
-
-                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
-
-                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               if (bindingDef.TwoWay)//remove handler
-                                       emitRemoveOldDataSourceHandler(il, "ValueChanged", delName + "_reverse", false);
-
-                               il.Emit (OpCodes.Ldloc_2);
-                               il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
-                       }
-
-                       #region fetch initial Value
-                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               il.Emit (OpCodes.Ldloc_2);
-                               if (bindingDef.HasUnresolvedTargetName) {
-                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetName);//load parent object
-                                       il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
-                                       il.Emit (OpCodes.Stloc_3);
-                                       il.Emit (OpCodes.Ldloc_3);
-                                       il.Emit (OpCodes.Brfalse, cancelInit);//may be propertyLessBinding
-                                       il.Emit (OpCodes.Ldloc_2);//load datasource
-                                       il.Emit (OpCodes.Ldloc_3);//load first memberInfo
-                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
-                               } 
-                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name
-                               il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
-                               il.Emit (OpCodes.Stloc_1);//save memberInfo
-                               il.Emit (OpCodes.Ldloc_1);//push mi for test if null
-                               il.Emit (OpCodes.Brfalse, cancelInit);//propertyLessBinding
-                       }
-
-                       il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
-                       il.Emit (OpCodes.Ldloc_2);//load new datasource
-                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               if (bindingDef.HasUnresolvedTargetName) {
-                                       il.Emit (OpCodes.Ldloc_3);
-                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
-                               }
-                               il.Emit (OpCodes.Ldloc_1);//push mi for value fetching
-                               il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
-                       }
-                       CompilerServices.emitConvert (il, piSource.PropertyType);
-                       il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-                       #endregion
-
-                       if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               il.MarkLabel(cancelInit);
-                               //check if new dataSource implement IValueChange
-                               il.Emit (OpCodes.Ldloc_2);//load new datasource
-                               il.Emit (OpCodes.Isinst, typeof(IValueChange));
-                               il.Emit (OpCodes.Brfalse, cancel);
-
-                               il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                               il.Emit (OpCodes.Ldarg_1);//load datasource change source
-                               il.Emit (OpCodes.Ldloc_2);//load new datasource
-                               il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynMethod
-                               il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
-
-                               il.MarkLabel (cancel);
-
-                               if (bindingDef.TwoWay){
-                                       il.Emit (OpCodes.Ldstr, delName + "_reverse");//load delName used for removing on ds changed
-                                       il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
-                                       il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
-                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
-                                       il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ?
-                                               $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);//arg4: dest member
-                                       il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
-                               }
-
-                       }
-                       il.MarkLabel (newDSIsNull);
-                       il.Emit (OpCodes.Ret);
-
-#if DEBUG_BINDING
-                       Debug.WriteLine("\tDataSource ValueChanged: " + delName);
-                       Debug.WriteLine("\tDataSource Changed: " + dm.Name);
-#endif
-
-                       return dm.CreateDelegate (CompilerServices.ehTypeDSChange, this);
-#endregion
-               }
-
-               static void emitSetValue (ILGenerator il, MemberInfo mi)
-               {
-                       if (mi.MemberType == MemberTypes.Field)
-                               il.Emit (OpCodes.Stfld, mi as FieldInfo);
-                       else if (mi.MemberType == MemberTypes.Property) {
-                               MethodInfo mt = (mi as PropertyInfo).GetSetMethod ();
-                               il.Emit (mt.IsVirtual?OpCodes.Callvirt:OpCodes.Call, mt);
-                       } else
-                               throw new NotImplementedException ();
-               }
-               /// <summary>
-               /// Two way binding for datasource, graphicObj=>dataSource link, datasource value has priority
-               /// and will be set as init for source property (in emitDataSourceBindings func)
-               /// </summary>
-               /// <param name="delName">delegate name</param>
-               /// <param name="orig">Graphic object instance, source of binding</param>
-               /// <param name="origMember">Origin member name</param>
-               /// <param name="dest">datasource instance, target of the binding</param>
-               /// <param name="destMember">Destination member name</param>
-               static void dataSourceReverseBinding(string delName, IValueChange orig, string origMember, object dest, string destMember){
-                       Type tOrig = orig.GetType ();
-                       Type tDest = dest.GetType ();
-                       PropertyInfo piOrig = tOrig.GetProperty (origMember);
-                       List<MemberInfo> miDests = new List<MemberInfo> ();
-                       Type curType = tDest;
-                       foreach (string m in destMember.Split('.')) {
-                               MemberInfo miDest = curType.GetMember (m).FirstOrDefault ();
-                               if (miDest == null) {
-                                       Debug.WriteLine ($"Member '{destMember}' not found in new DataSource '{dest}' of '{orig}'");
-                                       return;
-                               }
-                               miDests.Add (miDest);
-                               curType = CompilerServices.GetMemberInfoType (miDest);
-                       }
-
-#if DEBUG_BINDING
-                       Debug.WriteLine ("DS Reverse binding: Member '{0}' found in new DS '{1}' of '{2}'", destMember, dest, orig);
-#endif
-
-#region ValueChanged emit
-                       DynamicMethod dm = new DynamicMethod (delName,
-                               typeof (void), CompilerServices.argsBoundValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (64);
-
-
-                       Stack<LocalBuilder> locals = new Stack<LocalBuilder> ();
-
-                       System.Reflection.Emit.Label endMethod = il.DefineLabel ();
-
-                       il.Emit (OpCodes.Nop);
-
-                       //load value changed member name onto the stack
-                       il.Emit (OpCodes.Ldarg_2);
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
-
-                       //test if it's the expected one
-                       il.Emit (OpCodes.Ldstr, origMember);
-                       il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
-                       il.Emit (OpCodes.Call, CompilerServices.stringEquals);
-                       il.Emit (OpCodes.Brfalse, endMethod);
-                       //set destination member with valueChanged new value
-                       //load destination ref
-                       il.Emit (OpCodes.Ldarg_0);
-                       for (int i = 0; i < miDests.Count - 1; i++) {
-                               if (miDests [i].MemberType == MemberTypes.Field)
-                                       il.Emit (OpCodes.Ldflda, miDests [i] as FieldInfo);
-                               else if (miDests [i].MemberType == MemberTypes.Property) {
-                                       PropertyInfo pi = miDests [i] as PropertyInfo;
-                                       MethodInfo mi_g = pi.GetGetMethod ();
-                                       if (pi.PropertyType.IsValueType) {
-                                               il.Emit (OpCodes.Dup);//dup parent for calling property set afterward
-                                               il.Emit (mi_g.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_g);
-                                               LocalBuilder lb = il.DeclareLocal (pi.PropertyType);
-                                               il.Emit (OpCodes.Stloc, lb);
-                                               il.Emit (OpCodes.Ldloca, lb);
-                                               locals.Push (lb);
-                                       } else {
-                                               il.Emit (mi_g.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_g);
-                                       }
-                               } else
-                                       throw new NotImplementedException ();
-                       }
-
-                       //load new value onto the stack
-                       il.Emit (OpCodes.Ldarg_2);
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
-
-                       CompilerServices.emitConvert (il, piOrig.PropertyType, curType);
-
-                       emitSetValue (il, miDests.Last ());
-
-                       for (int i = miDests.Count -2; i >= 0; i--) {
-                               if (miDests [i].MemberType != MemberTypes.Property)
-                                       continue;
-                               PropertyInfo pi = miDests [i] as PropertyInfo;
-                               if (!pi.PropertyType.IsValueType)
-                                       continue;
-                               MethodInfo mi_s = pi.GetSetMethod ();
-                               il.Emit (OpCodes.Ldloc, locals.Pop());
-                               il.Emit (mi_s.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi_s);
-                       }
-                       il.MarkLabel (endMethod);
-                       il.Emit (OpCodes.Ret);
-                       #endregion
-                       EventHandler<ValueChangeEventArgs> tmp = (EventHandler<ValueChangeEventArgs>)dm.CreateDelegate (typeof (EventHandler<ValueChangeEventArgs>), dest);
-                       orig.ValueChanged += tmp;
-               }
-               #endregion
-
-               /// <summary>
-               /// search for graphic object type in crow assembly, if not found,
-               /// search for type independently of namespace in all the loaded assemblies
-               /// </summary>
-               /// <remarks>
-               /// </remarks>
-               /// <returns>the corresponding type object</returns>
-               /// <param name="typeName">graphic object type name without its namespace</param>
-               Type tryGetGOType (string typeName){
-                       if (knownGOTypes.ContainsKey (typeName))
-                               return knownGOTypes [typeName];
-                       Type t = Type.GetType ("Crow." + typeName);
-                       if (t != null) {
-                               knownGOTypes.Add (typeName, t);
-                               return t;
-                       }                       
-                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
-                               if (a.IsDynamic)
-                                       continue;
-                               foreach (Type expT in a.GetExportedTypes ()) {
-                                       if (expT.Name != typeName)
-                                               continue;
-                                       knownGOTypes.Add (typeName, expT);
-                                       return expT;
-                               }
-                       }
-                       return null;
-               }
-       }
-}
-
diff --git a/Crow/src/LayoutingEventArgs.cs b/Crow/src/LayoutingEventArgs.cs
deleted file mode 100644 (file)
index 9254aec..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// LayoutingEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class LayoutingEventArgs: EventArgs
-       {
-               public LayoutingType  LayoutType;
-
-               public LayoutingEventArgs (LayoutingType  _layoutType) : base()
-               {
-                       LayoutType = _layoutType;
-               }
-       }
-}
-
diff --git a/Crow/src/Measure.cs b/Crow/src/Measure.cs
deleted file mode 100644 (file)
index c77d66b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
-       /// <summary>
-       /// Measurement unit
-       /// </summary>
-       public enum Unit {Undefined, Pixel, Percent, Inherit }
-       /// <summary>
-       /// Measure class allow proportional sizes as well as stretched and fit on content.
-       /// </summary>
-       public struct Measure
-       {
-               /// <summary>
-               /// Integer value of the measure
-               /// </summary>
-               public int Value;
-               /// <summary>
-               /// Measurement unit
-               /// </summary>
-               public Unit Units;
-
-               /// <summary>
-               /// Fit on content, this special measure is defined as a fixed integer set to -1 pixel
-               /// </summary>
-               public static Measure Fit = new Measure(-1,Unit.Percent);
-               /// <summary>
-               /// Stretched into parent client area. This special measure is defined as a proportional cote
-               /// set to 100 Percents
-               /// </summary>
-               public static Measure Stretched = new Measure(100, Unit.Percent);
-               public static Measure Inherit = new Measure (0, Unit.Inherit);
-               #region CTOR
-               public Measure (int _value, Unit _units = Unit.Pixel)
-               {
-                       Value = _value;
-                       Units = _units;
-               }
-               #endregion
-
-               /// <summary>
-               /// True is size is fixed in pixels, this means not proportional, stretched nor fit.
-               /// </summary>
-               public bool IsFixed { get { return Units == Unit.Pixel; }}
-               public bool IsFit { get { return Value == -1 && Units == Unit.Percent; }}
-               public bool IsRelativeToParent { get { return Value >= 0 && Units == Unit.Percent; }}
-               #region Operators
-               public static implicit operator int(Measure m){
-                       return m.Value;
-               }
-               public static implicit operator Measure(int i){
-                       return new Measure(i);
-               }
-               public static implicit operator string(Measure m){
-                       return m.ToString();
-               }
-               public static implicit operator Measure(string s){
-                       return Measure.Parse(s);
-               }
-
-               public static bool operator ==(Measure m1, Measure m2){
-                       return m1.Value == m2.Value && m1.Units == m2.Units;
-               }
-               public static bool operator !=(Measure m1, Measure m2){
-                       return !(m1.Value == m2.Value && m1.Units == m2.Units);
-               }
-               #endregion
-
-               #region Object overrides
-               public override int GetHashCode ()
-               {
-                       return Value.GetHashCode ();
-               }
-               public override bool Equals (object obj)
-               {
-                       return (obj == null || obj.GetType() != typeof(Measure)) ?
-                               false :
-                               this == (Measure)obj;
-               }
-               public override string ToString ()
-               {
-                       return Units == Unit.Inherit ? "Inherit" :
-                               Value == -1 ? "Fit" :
-                               Units == Unit.Percent ? Value == 100 ? "Stretched" :
-                               Value.ToString () + "%" : Value.ToString ();
-               }
-               #endregion
-
-               public static Measure Parse(string s){
-                       if (string.IsNullOrEmpty (s))
-                               return default(Measure);
-
-                       string st = s.Trim ();
-                       int tmp = 0;
-
-                       if (string.Equals ("Inherit", st, StringComparison.Ordinal))
-                               return Measure.Inherit;
-                       else if (string.Equals ("Fit", st, StringComparison.Ordinal))
-                               return Measure.Fit;
-                       else if (string.Equals ("Stretched", s, StringComparison.Ordinal))
-                               return Measure.Stretched;                       
-                       else {
-                               if (st.EndsWith ("%", StringComparison.Ordinal)) {
-                                       if (int.TryParse (s.Substring(0, st.Length - 1), out tmp))
-                                               return new Measure (tmp, Unit.Percent);
-                               }else if (int.TryParse (s, out tmp))
-                                       return new Measure (tmp);
-                       }
-
-                       throw new Exception ("Error parsing Measure.");
-               }
-
-       }
-}
diff --git a/Crow/src/MouseCursorChangedEventArgs.cs b/Crow/src/MouseCursorChangedEventArgs.cs
deleted file mode 100644 (file)
index 5e58b86..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// MouseCursorChangedEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class MouseCursorChangedEventArgs : EventArgs
-       {
-               public MouseCursor NewCursor;
-               public MouseCursorChangedEventArgs (MouseCursor newCursor) : base()
-               {
-                       NewCursor = newCursor;
-               }
-       }
-}
diff --git a/Crow/src/Point.cs b/Crow/src/Point.cs
deleted file mode 100644 (file)
index 02f12e2..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Crow
-{
-    public struct Point
-    {
-               public int X;
-               public int Y;
-
-               public Point (int x, int y)
-               {
-                       X = x;
-                       Y = y;
-               }
-
-               public int Length => (int)Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
-               public double LengthD => Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
-               public Point Normalized {
-                       get {
-                               int l = Length;
-                               return new Point (X / l, Y / l);
-                       }
-               }
-               public static implicit operator PointD (Point p) => new PointD (p.X, p.Y);
-               public static implicit operator Point (int i) => new Point (i, i);
-
-               public static Point operator + (Point p1, Point p2) => new Point (p1.X + p2.X, p1.Y + p2.Y);
-               public static Point operator + (Point p, int i) => new Point (p.X + i, p.Y + i);
-               public static Point operator - (Point p1, Point p2) => new Point (p1.X - p2.X, p1.Y - p2.Y);
-               public static Point operator - (Point p, int i) => new Point (p.X - i, p.Y - i);
-               public static Point operator * (Point p1, Point p2) => new Point (p1.X * p2.X, p1.Y * p2.Y);
-               public static Point operator * (Point p, int d) => new Point (p.X * d, p.Y * d);
-               public static Point operator / (Point p1, Point p2) => new Point (p1.X / p2.X, p1.Y / p2.Y);
-               public static Point operator / (Point p, int d) => new Point (p.X / d, p.Y / d);
-
-               public static bool operator == (Point s1, Point s2) => s1.X == s2.X && s1.Y == s2.Y;
-               public static bool operator == (Point s, int i) => s.X == i && s.Y == i;
-               public static bool operator != (Point s1, Point s2) => !(s1.X == s2.X && s1.Y == s2.Y);
-               public static bool operator != (Point s, int i) => !(s.X == i && s.Y == i);
-               public static bool operator > (Point p1, Point p2) => p1.X > p2.X && p1.Y > p2.Y;
-               public static bool operator > (Point s, int i) => s.X > i && s.Y > i;
-               public static bool operator < (Point p1, Point p2) => p1.X < p2.X && p1.Y < p2.Y;
-               public static bool operator < (Point s, int i) => s.X < i && s.Y < i;
-               public static bool operator >= (Point p1, Point p2) => p1.X >= p2.X && p1.Y >= p2.Y;
-               public static bool operator >= (Point s, int i) => s.X >= i && s.Y >= i;
-               public static bool operator <= (Point p1, Point p2) => p1.X <= p2.X && p1.Y <= p2.Y;
-               public static bool operator <= (Point s, int i) => s.X <= i && s.Y <= i;
-
-               public override string ToString () => string.Format ("{0},{1}", X, Y);
-               public override bool Equals (object obj) => obj is Point ? this == (Point)obj :
-                       obj is Point && (Point)this == (Point)obj;
-               public static Point Parse (string s)
-               {
-                       if (string.IsNullOrEmpty (s))
-                               return default (Point);
-                       string [] d = s.Trim ().Split (',');
-                       if (d.Length == 2)
-                               return new Point (int.Parse (d [0]), int.Parse (d [1]));
-                       else if (d.Length == 1) {
-                               int tmp = int.Parse (d [0]);
-                               return new Point (tmp, tmp);
-                       }
-                       throw new Exception ("Crow.PointD Parsing Error: " + s);
-               }
-
-               public override int GetHashCode ()
-               {
-#pragma warning disable RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »
-                       unchecked {
-                               var hashCode = 1861411795;
-                               hashCode = hashCode * -1521134295 + X.GetHashCode ();
-
-                               hashCode = hashCode * -1521134295 + Y.GetHashCode ();
-                               return hashCode;
-                       }
-#pragma warning restore RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »    }
-               }
-       }
-}
diff --git a/Crow/src/PointD.cs b/Crow/src/PointD.cs
deleted file mode 100644 (file)
index d70e5b8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow {
-       public struct PointD {
-               public double X;
-               public double Y;
-               public PointD (double x, double y)
-               {
-                       X = x;
-                       Y = y;
-               }
-
-               public double Length => Math.Sqrt (Math.Pow (X, 2) + Math.Pow (Y, 2));
-               public PointD Normalized {
-                       get {
-                               double l = Length;
-                               return new PointD (X / l, Y / l);
-                       }
-               }
-               public static implicit operator Point (PointD p) => new Point ((int)Math.Round (p.X), (int)Math.Round (p.Y));
-               public static implicit operator PointD (double i) => new PointD (i, i);
-
-               public static PointD operator + (PointD p1, PointD p2) => new PointD (p1.X + p2.X, p1.Y + p2.Y);
-               public static PointD operator + (PointD p, double i) => new PointD (p.X + i, p.Y + i);
-               public static PointD operator - (PointD p1, PointD p2) => new PointD (p1.X - p2.X, p1.Y - p2.Y);
-               public static PointD operator - (PointD p, double i) => new PointD (p.X - i, p.Y - i);
-               public static PointD operator * (PointD p1, PointD p2) => new PointD (p1.X * p2.X, p1.Y * p2.Y);
-               public static PointD operator * (PointD p, double d) => new PointD (p.X * d, p.Y * d);
-               public static PointD operator / (PointD p1, PointD p2) => new PointD (p1.X / p2.X, p1.Y / p2.Y);
-               public static PointD operator / (PointD p, double d) => new PointD (p.X / d, p.Y / d);
-
-               public static bool operator == (PointD s1, PointD s2) => s1.X == s2.X && s1.Y == s2.Y;
-               public static bool operator == (PointD s, double i) => s.X == i && s.Y == i;
-               public static bool operator != (PointD s1, PointD s2) => !(s1.X == s2.X && s1.Y == s2.Y);
-               public static bool operator != (PointD s, double i) => !(s.X == i && s.Y == i);
-               public static bool operator > (PointD p1, PointD p2) => p1.X > p2.X && p1.Y > p2.Y;
-               public static bool operator > (PointD s, double i) => s.X > i && s.Y > i;
-               public static bool operator < (PointD p1, PointD p2) => p1.X < p2.X && p1.Y < p2.Y;
-               public static bool operator < (PointD s, double i) => s.X < i && s.Y < i;
-               public static bool operator >= (PointD p1, PointD p2) => p1.X >= p2.X && p1.Y >= p2.Y;
-               public static bool operator >= (PointD s, double i) => s.X >= i && s.Y >= i;
-               public static bool operator <= (PointD p1, PointD p2) => p1.X <= p2.X && p1.Y <= p2.Y;
-               public static bool operator <= (PointD s, double i) => s.X <= i && s.Y <= i;
-
-               public override string ToString () => string.Format ("{0},{1}", X, Y);
-               public override bool Equals (object obj) => obj is PointD ? this == (PointD)obj :
-                       obj is Point && (Point)this == (Point)obj;
-               public static PointD Parse (string s)
-               {
-                       if (string.IsNullOrEmpty (s))
-                               return default (PointD);
-                       string [] d = s.Trim ().Split (',');
-                       if (d.Length == 2)
-                               return new PointD (double.Parse (d [0]), double.Parse (d [1]));
-                       else if (d.Length == 1) {
-                               double tmp = double.Parse (d [0]);
-                               return new PointD (tmp, tmp);
-                       }
-                       throw new Exception ("Crow.PointD Parsing Error: " + s);
-               }
-
-               public override int GetHashCode ()
-               {
-#pragma warning disable RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »
-                       unchecked {
-                               var hashCode = 1861411795;
-                               hashCode = hashCode * -1521134295 + X.GetHashCode ();
-
-                               hashCode = hashCode * -1521134295 + Y.GetHashCode ();
-                               return hashCode;
-                       }
-#pragma warning restore RECS0025 // Champ autre qu’en lecture seule référencé dans « GetHashCode() »    }
-               }
-       }
-}
\ No newline at end of file
diff --git a/Crow/src/Rectangle.cs b/Crow/src/Rectangle.cs
deleted file mode 100644 (file)
index a0e5ccf..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Runtime.InteropServices;
-
-namespace Crow {
-       [StructLayout(LayoutKind.Sequential)]
-       public struct Rectangle
-    {
-               public static readonly Rectangle Zero = new Rectangle (0, 0, 0, 0);
-
-               public int X, Y, Width, Height;
-
-               #region ctor
-               public Rectangle(Point p, Size s): this (p.X, p.Y, s.Width, s.Height) { }
-               public Rectangle(Size s) : this (0, 0, s.Width, s.Height) { }
-        public Rectangle(int x, int y, int width, int height) {
-                       X = x;
-                       Y = y;
-                       Width = width;
-                       Height = height;
-        }
-               #endregion
-
-               #region PROPERTIES
-               [XmlIgnore]public int Left{
-                       get => X;
-            set { X = value; }
-        }
-               [XmlIgnore]public int Top{
-            get => Y;
-            set { Y = value; }
-        }
-               [XmlIgnore] public int Right => X + Width;
-               [XmlIgnore]public int Bottom => Y + Height;
-               [XmlIgnore]public Size Size{
-                       get => new Size (Width, Height);
-            set {
-                Width = value.Width;
-                Height = value.Height;
-            }
-        }
-               [XmlIgnore]
-               public SizeD SizeD => new SizeD (Width, Height); 
-               [XmlIgnore]public Point Position{
-                       get => new Point (X, Y);
-                       set {
-                               X = value.X;
-                               Y = value.Y;
-                       }
-               }
-               [XmlIgnore]public Point TopLeft{
-                       get => new Point (X, Y);
-                       set {
-                X = value.X;
-                Y = value.Y;
-            }
-        }
-               [XmlIgnore] public Point TopRight => new Point (Right, Y);
-               [XmlIgnore] public Point BottomLeft => new Point (X, Bottom);
-               [XmlIgnore] public Point BottomRight => new Point (Right, Bottom);        
-               [XmlIgnore] public Point Center => new Point (Left + Width / 2, Top + Height / 2);
-               [XmlIgnore] public Point CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0);
-
-               #endregion
-
-               #region FUNCTIONS
-               public void Inflate(int xDelta, int yDelta)
-        {
-            this.X -= xDelta;
-            this.Width += 2 * xDelta;
-            this.Y -= yDelta;
-            this.Height += 2 * yDelta;
-        }
-               public void Inflate(int delta)
-               {
-                       Inflate (delta, delta);
-               }
-               public Rectangle Inflated (int delta) => Inflated (delta, delta);
-               public Rectangle Inflated (int deltaX, int deltaY) {
-                       Rectangle r = this;
-                       r.Inflate (deltaX, deltaY);
-                       return r;
-               }
-               public bool ContainsOrIsEqual (Point p) => (p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height);
-               public bool ContainsOrIsEqual (Rectangle r) => r.TopLeft >= this.TopLeft && r.BottomRight <= this.BottomRight;
-        public bool Intersect(Rectangle r)
-        {
-            int maxLeft = Math.Max(this.Left, r.Left);
-            int minRight = Math.Min(this.Right, r.Right);
-            int maxTop = Math.Max(this.Top, r.Top);
-            int minBottom = Math.Min(this.Bottom, r.Bottom);
-
-                       return (maxLeft < minRight) && (maxTop < minBottom);
-        }
-        public Rectangle Intersection(Rectangle r)
-        {
-            Rectangle result = new Rectangle();
-            
-            if (r.Left >= Left)
-                result.Left = r.Left;
-            else
-                result.TopLeft = TopLeft;
-
-            if (r.Right >= Right)
-                result.Width = Right - result.Left;
-            else
-                result.Width = r.Right - result.Left;
-
-            if (r.Top >= Top)
-                result.Top = r.Top;
-            else
-                result.Top = Top;
-
-            if (r.Bottom >= Bottom)
-                result.Height = Bottom - result.Top;
-            else
-                result.Height = r.Bottom - result.Top;
-
-            return result;
-        }
-               #endregion
-
-        #region operators
-        public static Rectangle operator +(Rectangle r1, Rectangle r2)
-        {
-            int x = Math.Min(r1.X, r2.X);
-            int y = Math.Min(r1.Y, r2.Y);
-            int x2 = Math.Max(r1.Right, r2.Right);
-            int y2 = Math.Max(r1.Bottom, r2.Bottom);
-            return new Rectangle(x, y, x2 - x, y2 - y);
-        }
-               public static Rectangle operator + (Rectangle r, Point p) => new Rectangle (r.X + p.X, r.Y + p.Y, r.Width, r.Height);
-               public static Rectangle operator - (Rectangle r, Point p) => new Rectangle (r.X - p.X, r.Y - p.Y, r.Width, r.Height);
-               public static bool operator == (Rectangle r1, Rectangle r2) => r1.TopLeft == r2.TopLeft && r1.Size == r2.Size;
-               public static bool operator != (Rectangle r1, Rectangle r2) => !(r1.TopLeft == r2.TopLeft && r1.Size == r2.Size);
-
-               public static implicit operator Rectangle (RectangleD r) => new Rectangle ((int)Math.Round(r.X), (int)Math.Round (r.Y),
-                       (int)Math.Round (r.Width), (int)Math.Round (r.Height));
-               #endregion
-
-               public override string ToString () => $"{X},{Y},{Width},{Height}";        
-        public static Rectangle Parse(string s)
-        {
-            string[] d = s.Split(new char[] { ',' });
-            return new Rectangle(
-                int.Parse(d[0]),
-                int.Parse(d[1]),
-                int.Parse(d[2]),
-                int.Parse(d[3]));
-        }
-               public override int GetHashCode ()
-               {
-                       unchecked // Overflow is fine, just wrap
-                       {
-                               int hash = 17;
-                               // Suitable nullity checks etc, of course :)
-                               hash = hash * 23 + X.GetHashCode();
-                               hash = hash * 23 + Y.GetHashCode();
-                               hash = hash * 23 + Width.GetHashCode();
-                               hash = hash * 23 + Height.GetHashCode();
-                               return hash;
-                       }
-               }
-               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (Rectangle)) ?
-                               false : this == (Rectangle)obj;
-    }
-}
diff --git a/Crow/src/RectangleD.cs b/Crow/src/RectangleD.cs
deleted file mode 100644 (file)
index 817b3ad..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Runtime.InteropServices;
-
-namespace Crow {
-       [StructLayout(LayoutKind.Sequential)]
-       public struct RectangleD
-    {
-               public static readonly RectangleD Zero = new RectangleD (0, 0, 0, 0);
-
-               public double X, Y, Width, Height;
-
-               #region ctor
-               public RectangleD(PointD p, Size s): this (p.X, p.Y, s.Width, s.Height) { }
-               public RectangleD(SizeD s) : this (0, 0, s.Width, s.Height) { }
-        public RectangleD(double x, double y, double width, double height) {
-                       X = x;
-                       Y = y;
-                       Width = width;
-                       Height = height;
-        }
-               #endregion
-
-               #region PROPERTIES
-               [XmlIgnore]public double Left{
-                       get => X;
-            set { X = value; }
-        }
-               [XmlIgnore]public double Top{
-            get => Y;
-            set { Y = value; }
-        }
-               [XmlIgnore] public double Right => X + Width;
-               [XmlIgnore]public double Bottom => Y + Height;
-               [XmlIgnore]public SizeD Size{
-                       get => new SizeD (Width, Height);
-            set {
-                Width = value.Width;
-                Height = value.Height;
-            }
-        }
-               [XmlIgnore]public PointD Position{
-                       get => new PointD (X, Y);
-                       set {
-                               X = value.X;
-                               Y = value.Y;
-                       }
-               }
-               [XmlIgnore]public PointD TopLeft{
-                       get => new PointD (X, Y);
-                       set {
-                X = value.X;
-                Y = value.Y;
-            }
-        }
-               [XmlIgnore] public PointD TopRight => new PointD (Right, Y);
-               [XmlIgnore] public PointD BottomLeft => new PointD (X, Bottom);
-               [XmlIgnore] public PointD BottomRight => new PointD (Right, Bottom);        
-               [XmlIgnore] public PointD Center => new PointD (Left + Width / 2, Top + Height / 2);
-               [XmlIgnore] public PointD CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0);
-
-               #endregion
-
-               #region FUNCTIONS
-               public void Inflate(double xDelta, double yDelta)
-        {
-            this.X -= xDelta;
-            this.Width += 2 * xDelta;
-            this.Y -= yDelta;
-            this.Height += 2 * yDelta;
-        }
-               public void Inflate(double delta)
-               {
-                       Inflate (delta, delta);
-               }
-               public RectangleD Inflated (double delta) => Inflated (delta, delta);
-               public RectangleD Inflated (double deltaX, double deltaY) {
-                       RectangleD r = this;
-                       r.Inflate (deltaX, deltaY);
-                       return r;
-               }
-               public bool ContainsOrIsEqual (PointD p) => (p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height);
-               public bool ContainsOrIsEqual (RectangleD r) => r.TopLeft >= this.TopLeft && r.BottomRight <= this.BottomRight;
-        public bool Intersect(RectangleD r)
-        {
-            double maxLeft = Math.Max(this.Left, r.Left);
-            double minRight = Math.Min(this.Right, r.Right);
-            double maxTop = Math.Max(this.Top, r.Top);
-            double minBottom = Math.Min(this.Bottom, r.Bottom);
-
-                       return (maxLeft < minRight) && (maxTop < minBottom);
-        }
-        public RectangleD Intersection(RectangleD r)
-        {
-            RectangleD result = new RectangleD();
-            
-            if (r.Left >= Left)
-                result.Left = r.Left;
-            else
-                result.TopLeft = TopLeft;
-
-            if (r.Right >= Right)
-                result.Width = Right - result.Left;
-            else
-                result.Width = r.Right - result.Left;
-
-            if (r.Top >= Top)
-                result.Top = r.Top;
-            else
-                result.Top = Top;
-
-            if (r.Bottom >= Bottom)
-                result.Height = Bottom - result.Top;
-            else
-                result.Height = r.Bottom - result.Top;
-
-            return result;
-        }
-               #endregion
-
-        #region operators
-        public static RectangleD operator +(RectangleD r1, RectangleD r2)
-        {
-            double x = Math.Min(r1.X, r2.X);
-            double y = Math.Min(r1.Y, r2.Y);
-            double x2 = Math.Max(r1.Right, r2.Right);
-            double y2 = Math.Max(r1.Bottom, r2.Bottom);
-            return new RectangleD(x, y, x2 - x, y2 - y);
-        }
-               public static RectangleD operator + (RectangleD r, PointD p) => new RectangleD (r.X + p.X, r.Y + p.Y, r.Width, r.Height);
-               public static RectangleD operator - (RectangleD r, PointD p) => new RectangleD (r.X - p.X, r.Y - p.Y, r.Width, r.Height);
-               public static bool operator == (RectangleD r1, RectangleD r2) => r1.TopLeft == r2.TopLeft && r1.Size == r2.Size;
-               public static bool operator != (RectangleD r1, RectangleD r2) => !(r1.TopLeft == r2.TopLeft && r1.Size == r2.Size);
-
-               public static implicit operator RectangleD(Rectangle r) => new RectangleD(r.X,r.Y,r.Width,r.Height);
-        #endregion        
-
-               public override string ToString () => $"{X},{Y},{Width},{Height}";        
-        public static RectangleD Parse(string s)
-        {
-            string[] d = s.Split(new char[] { ',' });
-            return new RectangleD(
-                double.Parse(d[0]),
-                double.Parse(d[1]),
-                double.Parse(d[2]),
-                double.Parse(d[3]));
-        }
-               public override int GetHashCode ()
-               {
-                       unchecked // Overflow is fine, just wrap
-                       {
-                               int hash = 17;
-                               // Suitable nullity checks etc, of course :)
-                               hash = hash * 23 + X.GetHashCode();
-                               hash = hash * 23 + Y.GetHashCode();
-                               hash = hash * 23 + Width.GetHashCode();
-                               hash = hash * 23 + Height.GetHashCode();
-                               return hash;
-                       }
-               }
-               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (RectangleD)) ?
-                               false : this == (RectangleD)obj;
-    }
-}
index 8c0b4f27bb3aab55b799bbccd46a720b44d8e461..25e2334bb7fdba6133bada52962907c3be0b466d 100644 (file)
@@ -1,28 +1,6 @@
-//
-// ReflexionExtensions.cs
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Reflection;
diff --git a/Crow/src/ScrollingEventArgs.cs b/Crow/src/ScrollingEventArgs.cs
deleted file mode 100644 (file)
index 3ff4206..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// ScrollingEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class ScrollingEventArgs: EventArgs
-       {
-               public Orientation  Direction;
-
-               public ScrollingEventArgs (Orientation  _direction) : base()
-               {
-                       Direction = _direction;
-               }
-       }
-}
-
diff --git a/Crow/src/SelectionChangeEventArgs.cs b/Crow/src/SelectionChangeEventArgs.cs
deleted file mode 100644 (file)
index 988a697..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// SelectionChangeEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class SelectionChangeEventArgs: EventArgs
-       {               
-               public object NewValue;
-
-
-               public SelectionChangeEventArgs (object _newValue) : base()
-               {
-                       NewValue = _newValue;
-               }
-       }
-}
-
diff --git a/Crow/src/Size.cs b/Crow/src/Size.cs
deleted file mode 100644 (file)
index 77347f0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-namespace Crow
-{
-    public struct Size
-    {
-               public static Size Zero => new Size (0, 0);
-
-               public int Width, Height;
-
-               #region CTOR
-               public Size (int width, int height)
-               {
-                       Width = width;
-                       Height = height;
-               }
-               public Size (int size)
-               {
-                       Width = size;
-                       Height = size;
-               }
-               #endregion
-
-               #region operators
-               public static implicit operator Rectangle(Size s)=> new Rectangle (s);
-        public static implicit operator Size(int i)=> new Size(i, i);
-               public static implicit operator string(Size s)=> s.ToString ();
-               public static implicit operator Size(string s)=> string.IsNullOrEmpty (s) ? Zero : Parse (s);
-
-               public static bool operator == (Size s1, Size s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
-               public static bool operator != (Size s1, Size s2) => (s1.Width != s2.Width || s1.Height != s2.Height);
-               public static bool operator > (Size s1, Size s2) => (s1.Width > s2.Width && s1.Height > s2.Height);
-               public static bool operator >= (Size s1, Size s2) => (s1.Width >= s2.Width && s1.Height >= s2.Height);
-               public static bool operator < (Size s1, Size s2) => (s1.Width < s2.Width) ? s1.Height <= s2.Height :
-                                                                                                                               (s1.Width == s2.Width && s1.Height < s2.Height);
-               public static bool operator < (Size s, int i) => s.Width < i && s.Height < i;
-               public static bool operator <= (Size s, int i) => s.Width <= i && s.Height <= i;
-               public static bool operator > (Size s, int i) => s.Width > i && s.Height > i;
-               public static bool operator >= (Size s, int i) => s.Width >= i && s.Height >= i;
-               public static bool operator <= (Size s1, Size s2) => (s1.Width <= s2.Width && s1.Height <= s2.Height);
-               public static bool operator == (Size s, int i) => (s.Width == i && s.Height == i);
-               public static bool operator != (Size s, int i) => (s.Width != i || s.Height != i);
-               public static Size operator + (Size s1, Size s2) => new Size (s1.Width + s2.Width, s1.Height + s2.Height);
-               public static Size operator + (Size s, int i) => new Size (s.Width + i, s.Height + i);
-               public static Size operator * (Size s, int i) => new Size (s.Width * i, s.Height * i);
-               public static Size operator / (Size s, int i) => new Size (s.Width / i, s.Height / i);
-               #endregion
-
-               public override int GetHashCode ()
-               {
-                       unchecked // Overflow is fine, just wrap
-                       {
-                               int hash = 17;
-                               // Suitable nullity checks etc, of course :)
-                               hash = hash * 23 + Width.GetHashCode();
-                               hash = hash * 23 + Height.GetHashCode();
-                               return hash;
-                       }
-               }
-               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (Size)) ? false : this == (Size)obj;
-               public override string ToString () => $"{Width},{Height}";
-               public static Size Parse(string s)
-               {
-                       string[] d = s.Split(new char[] { ',' });
-                       return d.Length == 1 ? new Size(int.Parse(d[0])) : new Size(
-                               int.Parse(d[0]),
-                               int.Parse(d[1]));
-               }
-       }
-}
diff --git a/Crow/src/SizeD.cs b/Crow/src/SizeD.cs
deleted file mode 100644 (file)
index 2dbdb02..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-namespace Crow
-{
-       public struct SizeD {
-               public static SizeD Zero => new SizeD (0, 0);
-
-               public double Width, Height;
-
-               #region CTOR
-               public SizeD (double width, double height)
-               {
-                       Width = width;
-                       Height = height;
-               }
-               public SizeD (double size)
-               {
-                       Width = size;
-                       Height = size;
-               }
-               #endregion
-
-               #region operators
-               public static implicit operator RectangleD (SizeD s) => new RectangleD (s);
-               public static implicit operator SizeD (double i) => new SizeD (i, i);
-               public static implicit operator string (SizeD s) => s.ToString ();
-               public static implicit operator SizeD (string s) => string.IsNullOrEmpty (s) ? Zero : Parse (s);
-
-               public static bool operator == (SizeD s1, SizeD s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
-               public static bool operator != (SizeD s1, SizeD s2) => (s1.Width == s2.Width && s1.Height == s2.Height);
-               public static bool operator > (SizeD s1, SizeD s2) => (s1.Width > s2.Width && s1.Height > s2.Height);
-               public static bool operator >= (SizeD s1, SizeD s2) => (s1.Width >= s2.Width && s1.Height >= s2.Height);
-               public static bool operator < (SizeD s1, SizeD s2) => (s1.Width < s2.Width) ? s1.Height <= s2.Height :
-                                                                                                                               (s1.Width == s2.Width && s1.Height < s2.Height);
-               public static bool operator < (SizeD s, double i) => s.Width < i && s.Height < i;
-               public static bool operator <= (SizeD s, double i) => s.Width <= i && s.Height <= i;
-               public static bool operator > (SizeD s, double i) => s.Width > i && s.Height > i;
-               public static bool operator >= (SizeD s, double i) => s.Width >= i && s.Height >= i;
-               public static bool operator <= (SizeD s1, SizeD s2) => (s1.Width <= s2.Width && s1.Height <= s2.Height);
-               public static bool operator == (SizeD s, double i) => (s.Width == i && s.Height == i);
-               public static bool operator != (SizeD s, double i) => (s.Width == i && s.Height == i);
-               public static SizeD operator + (SizeD s1, SizeD s2) => new SizeD (s1.Width + s2.Width, s1.Height + s2.Height);
-               public static SizeD operator + (SizeD s, double i) => new SizeD (s.Width + i, s.Height + i);
-               public static SizeD operator * (SizeD s, double i) => new SizeD (s.Width * i, s.Height * i);
-               public static SizeD operator / (SizeD s, double i) => new SizeD (s.Width / i, s.Height / i);
-               #endregion
-
-               public override int GetHashCode ()
-               {
-                       unchecked // Overflow is fine, just wrap
-                       {
-                               int hash = 17;
-                               // Suitable nullity checks etc, of course :)
-                               hash = hash * 23 + Width.GetHashCode ();
-                               hash = hash * 23 + Height.GetHashCode ();
-                               return hash;
-                       }
-               }
-               public override bool Equals (object obj) => (obj == null || obj.GetType () != typeof (SizeD)) ? false : this == (SizeD)obj;
-               public override string ToString () => $"{Width},{Height}";
-               public static SizeD Parse (string s)
-               {
-                       string [] d = s.Split (new char [] { ',' });
-                       return d.Length == 1 ? new SizeD (double.Parse (d [0])) : new SizeD (
-                               double.Parse (d [0]),
-                               double.Parse (d [1]));
-               }
-       }
-}
diff --git a/Crow/src/Style.cs b/Crow/src/Style.cs
deleted file mode 100644 (file)
index ded06b6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-
-namespace Crow
-{
-       public struct FileLocation {
-               public string FilePath;
-               public int Line;
-               public int Column;
-               public int Length;
-
-               public FileLocation(string filePath, int line, int column, int length = 0){
-                       FilePath = filePath;
-                       Line = line;
-                       Column = column;
-                       Length = length;
-               }
-               public override string ToString ()
-               {
-                       return string.Format ("{0} ({1},{2})", FilePath, Line, Column);
-               }
-       }
-       public class Style : Dictionary<string, object>
-       {
-               #if DESIGN_MODE
-               public Dictionary<string, FileLocation> Locations = new Dictionary<string, FileLocation>();
-               #endif
-               //public Dictionary<string, Style> SubStyles;//TODO:implement substyles for all tags inside a style
-               public Style () : base()
-               {
-               }
-
-       }
-}
-
diff --git a/Crow/src/StyleReader.cs b/Crow/src/StyleReader.cs
deleted file mode 100644 (file)
index 77b8967..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using System.Text.RegularExpressions;
-using Crow.Coding;
-
-namespace Crow
-{
-       /// <summary>
-       /// Parser for style files.
-       /// </summary>
-       //TODO: style key shared by different class may use only first encouneter class setter, which can cause bug.
-       public class StyleReader : StreamReader
-       {
-               enum States { init, classNames, members, value, endOfStatement }
-
-               States curState = States.init;
-
-               int column = 1;
-               int line = 1;
-
-               #region Character ValidityCheck
-               static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
-               static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");                                                                                                                      
-               static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
-               static Regex rxDecimal = new Regex(@"[0-9]+");
-               static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
-
-               public bool nextCharIsValidCharStartName
-               {
-                       get { return rxNameStartChar.IsMatch(new string(new char[]{PeekChar()})); }
-               }
-               public bool nextCharIsValidCharName
-               {
-                       get { return rxNameChar.IsMatch(new string(new char[]{PeekChar()})); }
-               }
-               #endregion
-
-               char ReadChar () {
-                       column++;
-                       return (Char)Read();
-               }
-               char PeekChar () {
-                       return (Char)Peek();
-               }
-               void SkipWhiteSpaceAndLineBreak (){
-                       while (!EndOfStream){                           
-                               if (!PeekChar ().IsWhiteSpaceOrNewLine ())
-                                       break;
-                               if (ReadChar () == '\n') {
-                                       line++;
-                                       column = 0;
-                               }
-                       }
-               }
-
-               public StyleReader (Dictionary<string, Style> styling, Stream stream, string resId)
-                       : base(stream)
-               {                       
-                       string styleKey = resId.Substring (0, resId.Length - 6);
-                       string token = "";
-                       List<string> targetsClasses = new List<string> ();
-                       string currentProperty = "";
-
-                       while (!EndOfStream) {
-                               SkipWhiteSpaceAndLineBreak ();
-                               if (EndOfStream)
-                                       break;
-
-                               switch (Peek()) {
-                               case '/':
-                                       ReadChar ();
-                                       if (PeekChar () != '/')
-                                               throw new ParserException (line, column, "Unexpected char '/'", resId);
-                                       ReadLine ();
-                                       break;
-                               case ',':
-                                       ReadChar ();
-                                       if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
-                                               throw new ParserException (line, column, "Unexpected char ','", resId);
-                                       targetsClasses.Add (token);
-                                       token = "";
-                                       curState = States.classNames;
-                                       break;
-                               case '{':
-                                       ReadChar ();
-                                       if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
-                                               throw new ParserException (line, column, "Unexpected char '{'", resId);
-                                       targetsClasses.Add (token);
-                                       token = "";
-                                       curState = States.members;
-                                       break;
-                               case '}':
-                                       ReadChar ();
-                                       if (curState != States.members)
-                                               throw new ParserException (line, column, "Unexpected char '}'", resId);
-                                       curState = States.classNames;
-                                       targetsClasses.Clear ();
-                                       break;
-                               case '=':
-                                       ReadChar ();
-                                       if (!(curState == States.init || curState == States.members))
-                                               throw new ParserException (line, column, "Unexpected char '='", resId);
-                                       currentProperty = token;
-                                       token = "";
-                                       curState = States.value;
-                                       break;
-                               case '"':
-                                       if (curState != States.value)
-                                               throw new ParserException (line, column, "Unexpected char '\"'", resId);                                        
-                                       ReadChar ();
-
-                                       while (!EndOfStream) {
-                                               char c = PeekChar();
-                                               if (c == '\"') {
-                                                       ReadChar ();
-                                                       break;
-                                               }
-                                               token += ReadChar();
-                                               if (c == '\\' && !EndOfStream)
-                                                       token += ReadChar();                                            
-                                       }
-                                       curState = States.endOfStatement;
-                                       break;
-                               case ';':
-                                       if (curState != States.endOfStatement)
-                                               throw new ParserException (line, column, "Unexpected end of statement", resId);                                 
-                                       ReadChar ();
-                                       foreach (string tc in targetsClasses) {
-                                               if (!styling.ContainsKey (tc))
-                                                       styling [tc] = new Style ();
-                                               else if (styling [tc].ContainsKey (currentProperty))
-                                                       continue;
-                                               styling [tc] [currentProperty] = token;
-                                               #if DESIGN_MODE
-                                               styling [tc].Locations[currentProperty] = new FileLocation(resId, line, column - token.Length - 1, token.Length);
-                                               #endif
-                                               //System.Diagnostics.Debug.WriteLine ("Style: {3} : {0}.{1} = {2}", tc, currentProperty, token, resId);
-                                       }
-                                       token = "";
-                                       curState = States.members;
-                                       break;
-                               default:
-                                       if (curState == States.value)
-                                               throw new ParserException (line, column, "expecting value enclosed in '\"'", resId);
-                                       if (curState == States.endOfStatement)
-                                               throw new ParserException (line, column, "expecting end of statement", resId);
-
-                                       if (nextCharIsValidCharStartName) {
-                                               token += ReadChar();
-                                               while (nextCharIsValidCharName)
-                                                       token += ReadChar();
-                                       }
-                                       break;
-                               }
-                       }
-               }
-       }
-}
diff --git a/Crow/src/TextChangeEventArgs.cs b/Crow/src/TextChangeEventArgs.cs
deleted file mode 100644 (file)
index 33ca405..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// TextChangeEventArgs.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public class TextChangeEventArgs: EventArgs
-       {
-               public String Text;
-
-               public TextChangeEventArgs (string _newValue) : base()
-               {
-                       Text = _newValue;
-               }
-       }
-}
-
diff --git a/Crow/src/ValueChangeEventArgs.cs b/Crow/src/ValueChangeEventArgs.cs
deleted file mode 100644 (file)
index 854e2cd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
-       /// <summary>
-       /// Arguments for the ValueChange event used for Binding
-       /// </summary>
-       public class ValueChangeEventArgs: EventArgs
-       {
-               /// <summary>The name of the member whose value has changed</summary>
-               public string MemberName;
-               /// <summary>New value for that member</summary>
-               public object NewValue;
-
-               /// <summary>
-               /// Initializes a new instance of the <see cref="T:Crow.ValueChangeEventArgs"/> class.
-               /// </summary>
-               /// <param name="_memberName">Member name.</param>
-               /// <param name="_newValue">New value.</param>
-               public ValueChangeEventArgs (string _memberName, object _newValue) : base()
-               {
-                       MemberName = _memberName;
-                       NewValue = _newValue;
-               }
-       }
-}
-
diff --git a/Crow/src/Widgets/IValueChange.cs b/Crow/src/Widgets/IValueChange.cs
deleted file mode 100644 (file)
index 7e18e5e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// IValueChange.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-
-namespace Crow
-{
-       public interface IValueChange
-       {
-               event EventHandler<ValueChangeEventArgs> ValueChanged;
-       }
-}
-
diff --git a/Crow/src/styling/Style.cs b/Crow/src/styling/Style.cs
new file mode 100644 (file)
index 0000000..ded06b6
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+
+namespace Crow
+{
+       public struct FileLocation {
+               public string FilePath;
+               public int Line;
+               public int Column;
+               public int Length;
+
+               public FileLocation(string filePath, int line, int column, int length = 0){
+                       FilePath = filePath;
+                       Line = line;
+                       Column = column;
+                       Length = length;
+               }
+               public override string ToString ()
+               {
+                       return string.Format ("{0} ({1},{2})", FilePath, Line, Column);
+               }
+       }
+       public class Style : Dictionary<string, object>
+       {
+               #if DESIGN_MODE
+               public Dictionary<string, FileLocation> Locations = new Dictionary<string, FileLocation>();
+               #endif
+               //public Dictionary<string, Style> SubStyles;//TODO:implement substyles for all tags inside a style
+               public Style () : base()
+               {
+               }
+
+       }
+}
+
diff --git a/Crow/src/styling/StyleReader.cs b/Crow/src/styling/StyleReader.cs
new file mode 100644 (file)
index 0000000..77b8967
--- /dev/null
@@ -0,0 +1,164 @@
+// Copyright (c) 2013-2020  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using Crow.Coding;
+
+namespace Crow
+{
+       /// <summary>
+       /// Parser for style files.
+       /// </summary>
+       //TODO: style key shared by different class may use only first encouneter class setter, which can cause bug.
+       public class StyleReader : StreamReader
+       {
+               enum States { init, classNames, members, value, endOfStatement }
+
+               States curState = States.init;
+
+               int column = 1;
+               int line = 1;
+
+               #region Character ValidityCheck
+               static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+               static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");                                                                                                                      
+               static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
+               static Regex rxDecimal = new Regex(@"[0-9]+");
+               static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");
+
+               public bool nextCharIsValidCharStartName
+               {
+                       get { return rxNameStartChar.IsMatch(new string(new char[]{PeekChar()})); }
+               }
+               public bool nextCharIsValidCharName
+               {
+                       get { return rxNameChar.IsMatch(new string(new char[]{PeekChar()})); }
+               }
+               #endregion
+
+               char ReadChar () {
+                       column++;
+                       return (Char)Read();
+               }
+               char PeekChar () {
+                       return (Char)Peek();
+               }
+               void SkipWhiteSpaceAndLineBreak (){
+                       while (!EndOfStream){                           
+                               if (!PeekChar ().IsWhiteSpaceOrNewLine ())
+                                       break;
+                               if (ReadChar () == '\n') {
+                                       line++;
+                                       column = 0;
+                               }
+                       }
+               }
+
+               public StyleReader (Dictionary<string, Style> styling, Stream stream, string resId)
+                       : base(stream)
+               {                       
+                       string styleKey = resId.Substring (0, resId.Length - 6);
+                       string token = "";
+                       List<string> targetsClasses = new List<string> ();
+                       string currentProperty = "";
+
+                       while (!EndOfStream) {
+                               SkipWhiteSpaceAndLineBreak ();
+                               if (EndOfStream)
+                                       break;
+
+                               switch (Peek()) {
+                               case '/':
+                                       ReadChar ();
+                                       if (PeekChar () != '/')
+                                               throw new ParserException (line, column, "Unexpected char '/'", resId);
+                                       ReadLine ();
+                                       break;
+                               case ',':
+                                       ReadChar ();
+                                       if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
+                                               throw new ParserException (line, column, "Unexpected char ','", resId);
+                                       targetsClasses.Add (token);
+                                       token = "";
+                                       curState = States.classNames;
+                                       break;
+                               case '{':
+                                       ReadChar ();
+                                       if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token))
+                                               throw new ParserException (line, column, "Unexpected char '{'", resId);
+                                       targetsClasses.Add (token);
+                                       token = "";
+                                       curState = States.members;
+                                       break;
+                               case '}':
+                                       ReadChar ();
+                                       if (curState != States.members)
+                                               throw new ParserException (line, column, "Unexpected char '}'", resId);
+                                       curState = States.classNames;
+                                       targetsClasses.Clear ();
+                                       break;
+                               case '=':
+                                       ReadChar ();
+                                       if (!(curState == States.init || curState == States.members))
+                                               throw new ParserException (line, column, "Unexpected char '='", resId);
+                                       currentProperty = token;
+                                       token = "";
+                                       curState = States.value;
+                                       break;
+                               case '"':
+                                       if (curState != States.value)
+                                               throw new ParserException (line, column, "Unexpected char '\"'", resId);                                        
+                                       ReadChar ();
+
+                                       while (!EndOfStream) {
+                                               char c = PeekChar();
+                                               if (c == '\"') {
+                                                       ReadChar ();
+                                                       break;
+                                               }
+                                               token += ReadChar();
+                                               if (c == '\\' && !EndOfStream)
+                                                       token += ReadChar();                                            
+                                       }
+                                       curState = States.endOfStatement;
+                                       break;
+                               case ';':
+                                       if (curState != States.endOfStatement)
+                                               throw new ParserException (line, column, "Unexpected end of statement", resId);                                 
+                                       ReadChar ();
+                                       foreach (string tc in targetsClasses) {
+                                               if (!styling.ContainsKey (tc))
+                                                       styling [tc] = new Style ();
+                                               else if (styling [tc].ContainsKey (currentProperty))
+                                                       continue;
+                                               styling [tc] [currentProperty] = token;
+                                               #if DESIGN_MODE
+                                               styling [tc].Locations[currentProperty] = new FileLocation(resId, line, column - token.Length - 1, token.Length);
+                                               #endif
+                                               //System.Diagnostics.Debug.WriteLine ("Style: {3} : {0}.{1} = {2}", tc, currentProperty, token, resId);
+                                       }
+                                       token = "";
+                                       curState = States.members;
+                                       break;
+                               default:
+                                       if (curState == States.value)
+                                               throw new ParserException (line, column, "expecting value enclosed in '\"'", resId);
+                                       if (curState == States.endOfStatement)
+                                               throw new ParserException (line, column, "expecting end of statement", resId);
+
+                                       if (nextCharIsValidCharStartName) {
+                                               token += ReadChar();
+                                               while (nextCharIsValidCharName)
+                                                       token += ReadChar();
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       }
+}