]> O.S.I.I.S - jp/crow.git/commitdiff
wip
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 11 Feb 2020 09:49:09 +0000 (10:49 +0100)
committerj-p <jp_bruyere@hotmail.com>
Sat, 9 May 2020 22:50:02 +0000 (00:50 +0200)
29 files changed:
Crow/Crow.csproj
Crow/src/BmpPicture.cs [deleted file]
Crow/src/Colors.cs
Crow/src/CompilerServices/CompilerServices.cs [deleted file]
Crow/src/ExtensionsMethods.cs
Crow/src/Fill/BmpPicture.cs [new file with mode: 0644]
Crow/src/Fill/Fill.cs
Crow/src/Fill/Picture.cs [new file with mode: 0644]
Crow/src/Fill/SolidColor.cs [new file with mode: 0644]
Crow/src/Fill/SvgPicture.cs [new file with mode: 0644]
Crow/src/IML/CompilerServices.cs [new file with mode: 0644]
Crow/src/Instantiator.cs
Crow/src/Interface.cs
Crow/src/Measure.cs
Crow/src/Picture.cs [deleted file]
Crow/src/Point.cs
Crow/src/PointD.cs
Crow/src/SolidColor.cs [deleted file]
Crow/src/SvgPicture.cs [deleted file]
Crow/src/Widgets/Group.cs
Crow/src/Widgets/TemplatedGroup.cs
Crow/src/Widgets/Widget.cs
Crow/src/debug/DbgLogViewer.cs
Crow/src/debug/DebugLogger.cs
Samples/HelloWorld/HelloWorld.csproj
Samples/HelloWorld/ILView.cs [new file with mode: 0644]
Samples/HelloWorld/main.cs
Samples/HelloWorld/ui/helloworld.crow
Samples/common/ui/Interfaces/Divers/0.crow

index 27feb880c221cf7e4ba8acd0a0b72e40cf8beaab..521683f36d5ef014d02ae26debbfc1cc0ed3681d 100644 (file)
@@ -3,7 +3,7 @@
        <PropertyGroup>
                <TargetFramework>netstandard2.0</TargetFramework>
                
-               <ReleaseVersion>$(CrowVersion)</ReleaseVersion>
+               <ReleaseVersion>0.8.0</ReleaseVersion>
                <AssemblyVersion>$(CrowVersion)</AssemblyVersion>
                
                <Title>C# Rapid Open Widget Toolkit</Title>
@@ -36,7 +36,7 @@
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
                <DebugType>full</DebugType>
-               <DefineConstants>DEBUG;TRACE;MEASURE_TIME;_DEBUG_DISPOSE;_DEBUG_BINDING;DESIGN_MODE;_DEBUG_CLIP_RECTANGLE;_DEBUG_FOCUS;_DEBUG_DRAGNDROP;_DEBUG_LOG</DefineConstants>
+               <DefineConstants>DEBUG;TRACE;MEASURE_TIME;_DEBUG_DISPOSE;_DEBUG_BINDING;DESIGN_MODE;_DEBUG_CLIP_RECTANGLE;_DEBUG_FOCUS;DEBUG_DRAGNDROP;_DEBUG_LOG</DefineConstants>
                <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
        </PropertyGroup>
        <ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
diff --git a/Crow/src/BmpPicture.cs b/Crow/src/BmpPicture.cs
deleted file mode 100644 (file)
index a67f66f..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// BmpPicture.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.IO;
-using System.Runtime.InteropServices;
-using Crow.Cairo;
-
-namespace Crow
-{
-
-       /// <summary>
-       /// Derived from FILL for loading and drawing bitmaps in the interface
-       /// </summary>
-       public class BmpPicture : Picture
-       {
-               byte[] image = null;
-
-               #region CTOR
-               /// <summary>
-               /// Initializes a new instance of BmpPicture.
-               /// </summary>
-               public BmpPicture ()
-               {}
-               /// <summary>
-               /// Initializes a new instance of BmpPicture by loading the image pointed by the path argument
-               /// </summary>
-               /// <param name="path">image path, may be embedded</param>
-               public BmpPicture (string path) : base(path)
-               {
-                       Load ();
-               }
-               #endregion
-               /// <summary>
-               /// load the image for rendering from the path given as argument
-               /// </summary>
-               /// <param name="path">image path, may be embedded</param>
-               void Load ()
-               {                       
-                       if (sharedResources.ContainsKey (Path)) {
-                               sharedPicture sp = sharedResources [Path];
-                               image = (byte[])sp.Data;
-                               Dimensions = sp.Dims;
-                               return;
-                       }
-                       using (Stream stream = Interface.StaticGetStreamFromPath (Path)) {
-                               using (StbImage stbi = new StbImage (stream)) {
-                                       image = new byte [stbi.Size];
-                                       //rgba to argb for cairo.
-                                       for (int i = 0; i < stbi.Size; i+=4) {
-                                               image [i] = Marshal.ReadByte (stbi.Handle, i + 2);
-                                               image [i + 1] = Marshal.ReadByte (stbi.Handle, i + 1);
-                                               image [i + 2] = Marshal.ReadByte (stbi.Handle, i);
-                                               image [i + 3] = Marshal.ReadByte (stbi.Handle, i + 3);
-                                       }
-                                       Dimensions = new Size (stbi.Width, stbi.Height);
-                               }
-
-                               //loadBitmap (new System.Drawing.Bitmap (stream));      
-                       }
-                       sharedResources [Path] = new sharedPicture (image, Dimensions);
-               }
-
-
-
-               //load image via System.Drawing.Bitmap, cairo load png only
-               /*void loadBitmap (System.Drawing.Bitmap bitmap)
-               {
-                       if (bitmap == null)
-                               return;
-
-                       System.Drawing.Imaging.BitmapData data = bitmap.LockBits
-                               (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height),
-                                       System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
-
-                       Dimensions = new Size (bitmap.Width, bitmap.Height);
-
-                       int stride = data.Stride;
-                       int bitmapSize = Math.Abs (data.Stride) * bitmap.Height;
-
-                       image = new byte[bitmapSize];
-                       System.Runtime.InteropServices.Marshal.Copy (data.Scan0, image, 0, bitmapSize);
-
-                       bitmap.UnlockBits (data);           
-               }*/
-
-               #region implemented abstract members of Fill
-
-               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
-               {
-                       float widthRatio = 1f;
-                       float heightRatio = 1f;
-
-                       if (Scaled){
-                               widthRatio = (float)bounds.Width / Dimensions.Width;
-                               heightRatio = (float)bounds.Height / Dimensions.Height;
-                       }
-
-                       if (KeepProportions) {
-                               if (widthRatio < heightRatio)
-                                       heightRatio = widthRatio;
-                               else
-                                       widthRatio = heightRatio;
-                       }
-
-                       using (ImageSurface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) {
-                               using (Context gr = new Context (tmp)) {
-                                       gr.Translate (bounds.Left, bounds.Top);
-                                       gr.Scale (widthRatio, heightRatio);
-                                       gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2);
-
-                                       using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
-                                               Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
-                                               gr.SetSourceSurface (imgSurf, 0,0);
-                                               gr.Paint ();
-                                       }
-                               }
-                               ctx.SetSource (tmp);
-                       }                               
-               }
-               #endregion
-
-               /// <summary>
-               /// paint the image in the rectangle given in arguments according
-               /// to the Scale and keepProportion parameters.
-               /// </summary>
-               /// <param name="gr">drawing Backend context</param>
-               /// <param name="rect">bounds of the target surface to paint</param>
-               /// <param name="subPart">used for svg only</param>
-               public override void Paint (Context gr, Rectangle rect, string subPart = "")
-               {
-                       float widthRatio = 1f;
-                       float heightRatio = 1f;
-
-                       if (Scaled){
-                               widthRatio = (float)rect.Width / Dimensions.Width;
-                               heightRatio = (float)rect.Height / Dimensions.Height;
-                       }
-
-                       if (KeepProportions) {
-                               if (widthRatio < heightRatio)
-                                       heightRatio = widthRatio;
-                               else
-                                       widthRatio = heightRatio;
-                       }
-
-                       gr.Save ();
-
-                       gr.Translate (rect.Left,rect.Top);
-                       gr.Scale (widthRatio, heightRatio);
-                       gr.Translate ((rect.Width/widthRatio - Dimensions.Width)/2, (rect.Height/heightRatio - Dimensions.Height)/2);
-                       
-                       using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
-                               Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
-                               gr.SetSourceSurface (imgSurf, 0,0);
-                               gr.Paint ();
-                       }
-                       gr.Restore ();
-               }
-       }
-}
-
index 8cec2f4e71aa1bdd8c320454359fcfd5c3fd9ffd..8af93517f9117070f06e87cd601332f55ef2a533 100644 (file)
@@ -1,38 +1,10 @@
-//
-// Colors.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.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using System.Reflection;
-using System.Diagnostics;
-
-
 
 namespace Crow
 {
diff --git a/Crow/src/CompilerServices/CompilerServices.cs b/Crow/src/CompilerServices/CompilerServices.cs
deleted file mode 100644 (file)
index 86e7a7a..0000000
+++ /dev/null
@@ -1,1047 +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.Reflection.Emit;
-using System.Reflection;
-using System.Diagnostics;
-using System.Linq;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Xml;
-using Crow.IML;
-using System.Text;
-
-namespace Crow.IML
-{
-       public static class CompilerServices
-       {
-               /// <summary>
-               /// known types cache, prevent rewalking all the assemblies of the domain
-               /// the key is the type simple name
-               /// </summary>
-               internal static Dictionary<string, Type> knownTypes = new Dictionary<string, Type> ();
-               /// <summary>
-               /// known extension methods.
-               /// key is type dot memberName.
-               /// </summary>
-               internal static Dictionary<string, MethodInfo> knownExtMethods = new Dictionary<string, MethodInfo> ();
-
-               internal static MethodInfo stringEquals = typeof (string).GetMethod("Equals", new Type [3] { typeof (string), typeof (string), typeof (StringComparison) });
-               internal static MethodInfo miObjToString = typeof(object).GetMethod("ToString");
-               internal static MethodInfo miGetType = typeof(object).GetMethod("GetType");
-               internal static MethodInfo miParseEnum = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
-                       Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null);
-
-               internal static MethodInfo miGetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
-               internal static MethodInfo miGetEvent = typeof(Type).GetMethod("GetEvent", new Type[] {typeof(string)});
-
-               internal static MethodInfo miMIInvoke = typeof(MethodInfo).GetMethod ("Invoke", new Type[] {
-                       typeof(object),
-                       typeof(object[])
-               });
-
-               internal static MethodInfo miCreateBoundDel = typeof(Delegate).GetMethod ("CreateDelegate", new Type[] { typeof(Type), typeof(object), typeof(MethodInfo) });//create bound delegate
-               internal static MethodInfo miGetColCount = typeof(System.Collections.ICollection).GetProperty("Count").GetGetMethod();
-               internal static MethodInfo miGetDelegateListItem = typeof(List<Delegate>).GetMethod("get_Item", new Type[] { typeof(Int32) });
-
-               internal static MethodInfo miCompileDynEventHandler = typeof(CompilerServices).GetMethod ("compileDynEventHandler", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miRemEvtHdlByName = typeof(CompilerServices).GetMethod("removeEventHandlerByName", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miRemEvtHdlByTarget = typeof(CompilerServices).GetMethod("removeEventHandlerByTarget", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miGetMethInfoWithRefx = typeof(CompilerServices).GetMethod ("getMethodInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miGetMembIinfoWithRefx = typeof(CompilerServices).GetMethod("getMemberInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miSetValWithRefx = typeof(CompilerServices).GetMethod("setValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miGetValWithRefx = typeof(CompilerServices).GetMethod("getValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miCreateDel = typeof(CompilerServices).GetMethod ("createDel", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miGetImplOp = typeof(CompilerServices).GetMethod ("getImplicitOp", BindingFlags.Static | BindingFlags.NonPublic);
-               internal static MethodInfo miGetDataTypeAndFetch = typeof(CompilerServices).GetMethod("getDataTypeAndFetch", BindingFlags.Static | BindingFlags.NonPublic);
-
-
-               internal static MethodInfo miGoUpLevels = typeof(CompilerServices).GetMethod("goUpNbLevels", BindingFlags.Static | BindingFlags.NonPublic);
-
-               internal static FieldInfo fiCachedDel = typeof(Instantiator).GetField("cachedDelegates", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static FieldInfo fiTemplateBinding = typeof(Instantiator).GetField("templateBinding", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static MethodInfo miDSChangeEmitHelper = typeof(Instantiator).GetMethod("dataSourceChangedEmitHelper", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static MethodInfo miDSReverseBinding = typeof(Instantiator).GetMethod("dataSourceReverseBinding", BindingFlags.Static | BindingFlags.NonPublic);
-
-               internal static FieldInfo miSetCurIface = typeof(Widget).GetField ("IFace", BindingFlags.Public | BindingFlags.Instance);
-               internal static MethodInfo miFindByName = typeof (Widget).GetMethod ("FindByName");
-               internal static MethodInfo miGetGObjItem = typeof(List<Widget>).GetMethod("get_Item", new Type[] { typeof(Int32) });
-               internal static MethodInfo miLoadDefaultVals = typeof (Widget).GetMethod ("loadDefaultValues");
-               internal static PropertyInfo piStyle = typeof (Widget).GetProperty ("Style");
-               internal static MethodInfo miGetLogicalParent = typeof(Widget).GetProperty("LogicalParent").GetGetMethod();
-               internal static MethodInfo miGetDataSource = typeof(Widget).GetProperty("DataSource").GetGetMethod ();
-               internal static EventInfo eiLogicalParentChanged = typeof(Widget).GetEvent("LogicalParentChanged");
-
-               internal static MethodInfo miIFaceLoad = typeof(Interface).GetMethod ("CreateInstance", BindingFlags.Instance | BindingFlags.Public);
-               internal static MethodInfo miIFaceCreateTemplateInst = typeof (Interface).GetMethod ("CreateTemplateInstance", BindingFlags.Instance | BindingFlags.Public);
-               internal static MethodInfo miGetITemp = typeof(Interface).GetMethod ("GetItemTemplate", BindingFlags.Instance | BindingFlags.Public);
-
-               internal static MethodInfo miAddITemp = typeof(Dictionary<string, ItemTemplate>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) });
-               internal static MethodInfo miGetITempFromDic = typeof(Dictionary<string, ItemTemplate>).GetMethod ("get_Item", new Type[] { typeof(string) });
-               internal static FieldInfo fldItemTemplates = typeof(TemplatedGroup).GetField("ItemTemplates");
-               internal static MethodInfo miLoadPage = typeof(TemplatedGroup).GetMethod ("loadPage", BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public);
-               internal static MethodInfo miIsAlreadyExpanded = typeof(TemplatedGroup).GetMethod("emitHelperIsAlreadyExpanded", BindingFlags.Instance | BindingFlags.NonPublic);
-               
-               internal static MethodInfo miCreateExpDel = typeof(ItemTemplate).GetMethod ("CreateExpandDelegate");
-               internal static FieldInfo fiFetchMethodName = typeof(ItemTemplate).GetField("fetchMethodName", BindingFlags.Instance | BindingFlags.NonPublic);
-
-               #if DESIGN_MODE
-               internal static MethodInfo miDicStrStrAdd = typeof(Dictionary<string, string>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(string) });
-               #endif
-
-               #region tree handling methods
-               internal static FieldInfo fiChild = typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static MethodInfo miSetChild = typeof (Container).GetMethod ("SetChild");
-               internal static MethodInfo miAddChild = typeof (Group).GetMethod ("AddChild");
-               internal static FieldInfo fiChildren = typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static MethodInfo miLoadTmp = typeof (TemplatedControl).GetMethod ("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic);
-               internal static PropertyInfo piContent = typeof(TemplatedContainer).GetProperty ("Content");
-               internal static MethodInfo miAddItem = typeof (TemplatedGroup).GetMethod ("AddItem", BindingFlags.Instance | BindingFlags.Public);
-               internal static MethodInfo miGetItems = typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ();
-               #endregion
-
-               #region ValueChange & DSChange Reflexion member info
-               internal static EventInfo eiValueChange = typeof (IValueChange).GetEvent ("ValueChanged");
-               internal static MethodInfo miInvokeValueChange = eiValueChange.EventHandlerType.GetMethod ("Invoke");
-               internal static Type [] argsBoundValueChange = { typeof (object), typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
-               internal static Type [] argsValueChange = { typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
-               internal static FieldInfo fiVCNewValue = typeof (ValueChangeEventArgs).GetField ("NewValue");
-               internal static FieldInfo fiVCMbName = typeof (ValueChangeEventArgs).GetField ("MemberName");
-
-               internal static EventInfo eiDSChange = typeof (Widget).GetEvent ("DataSourceChanged");
-               internal static MethodInfo miInvokeDSChange = eiDSChange.EventHandlerType.GetMethod ("Invoke");
-               internal static Type [] argsBoundDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType };
-               internal static FieldInfo fiDSCNewDS = typeof (DataSourceChangeEventArgs).GetField ("NewDataSource");
-               internal static FieldInfo fiDSCOldDS = typeof (DataSourceChangeEventArgs).GetField ("OldDataSource");
-               internal static Type ehTypeDSChange = eiDSChange.EventHandlerType;
-               #endregion
-
-               /// <summary>
-               /// Loc0 is the current graphic object and arg2 of loader is the current interface
-               /// </summary>
-               /// <param name="il">Il.</param>
-               public static void emitSetCurInterface(ILGenerator il){
-                       il.Emit (OpCodes.Ldloc_0);
-                       il.Emit (OpCodes.Ldarg_1);
-                       il.Emit (OpCodes.Stfld, miSetCurIface);
-               }
-
-               public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
-                       il.Emit (OpCodes.Ldloc_0);
-
-                       if (val == null) {
-                               il.Emit (OpCodes.Ldnull);
-                               il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
-                               return;
-                       }
-                       Type dvType = val.GetType ();
-
-            if (dvType.IsValueType) {
-                               if (pi.PropertyType.IsValueType) {
-                    if (pi.PropertyType.IsEnum) {
-                                               if (pi.PropertyType != dvType)
-                                                       throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName);
-                                               il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
-                                       } else {
-                                               switch (Type.GetTypeCode (dvType)) {
-                                               case TypeCode.Boolean:
-                                                       if ((bool)val == true)
-                                                               il.Emit (OpCodes.Ldc_I4_1);
-                                                       else
-                                                               il.Emit (OpCodes.Ldc_I4_0);
-                                                       break;
-//                                             case TypeCode.Empty:
-//                                                     break;
-//                                             case TypeCode.Object:
-//                                                     break;
-//                                             case TypeCode.DBNull:
-//                                                     break;
-//                                             case TypeCode.SByte:
-//                                                     break;
-//                                             case TypeCode.Decimal:
-//                                                     break;
-//                                             case TypeCode.DateTime:
-//                                                     break;
-                                               case TypeCode.Char:
-                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToChar (val));
-                                                       break;
-                                               case TypeCode.Byte:
-                                               case TypeCode.Int16:
-                                               case TypeCode.Int32:
-                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
-                                                       break;
-                                               case TypeCode.UInt16:
-                                               case TypeCode.UInt32:
-                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (val));
-                                                       break;
-                                               case TypeCode.Int64:
-                                                       il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (val));
-                                                       break;
-                                               case TypeCode.UInt64:
-                                                       il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (val));
-                                                       break;
-                                               case TypeCode.Single:
-                                                       il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (val));
-                                                       break;
-                                               case TypeCode.Double:
-                                                       il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (val));
-                                                       break;
-                                               case TypeCode.String:
-                                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));
-                                                       break;
-                                               default:
-                                                       il.Emit (OpCodes.Pop);
-                                                       return;
-                                               }
-                                       }
-                               } else
-                                       throw new Exception ("Expecting valuetype in default values for: " + pi.Name);
-                       }else{
-                               //surely a class or struct
-                               if (dvType != typeof(string))
-                                       throw new Exception ("Expecting String in default values for: " + pi.Name);
-                               if (pi.PropertyType == typeof(string))
-                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));
-                               else if (pi.PropertyType.IsEnum) {
-                                       //load type of enum
-                                       il.Emit(OpCodes.Ldtoken, pi.PropertyType);
-                                       il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-                                       //load enum value name
-                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:implement here string format?
-                                       //load false
-                                       il.Emit (OpCodes.Ldc_I4_0);
-                                       il.Emit (OpCodes.Call, CompilerServices.miParseEnum);
-
-                                       if (CompilerServices.miParseEnum.ReturnType != pi.PropertyType)
-                                               il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
-                               } else {
-                                       MethodInfo miParse = pi.PropertyType.GetMethod
-                                               ("Parse", BindingFlags.Static | BindingFlags.Public,
-                                                       Type.DefaultBinder, new Type [] {typeof (string)},null);
-                                       if (miParse == null)
-                                               throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName);
-
-                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
-                                       il.Emit (OpCodes.Call, miParse);
-
-                                       if (miParse.ReturnType != pi.PropertyType)
-                                               il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
-                               }
-                       }
-            il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
-               }
-
-               #region conversions
-
-               internal static MethodInfo GetConvertMethod (Type targetType)
-               {
-                       string name;
-
-                       if (targetType == typeof (bool))
-                               name = "ToBoolean";
-                       else if (targetType == typeof (byte))
-                               name = "ToByte";
-                       else if (targetType == typeof (short))
-                               name = "ToInt16";
-                       else if (targetType == typeof (int))
-                               name = "ToInt32";
-                       else if (targetType == typeof (uint))
-                               name = "ToUInt32";
-                       else if (targetType == typeof (long))
-                               name = "ToInt64";
-                       else if (targetType == typeof (double))
-                               name = "ToDouble";
-                       else if (targetType == typeof (float))
-                               name = "ToSingle";
-                       else if (targetType == typeof (string))
-                               return typeof (object).GetMethod ("ToString", Type.EmptyTypes);
-                       else //try to find implicit convertion
-                               throw new NotImplementedException (string.Format ("Conversion to {0} is not implemented.", targetType.Name));
-
-                       return typeof (Convert).GetMethod (name, BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object) }, null);
-               }
-               #endregion
-
-               #region Reflexion helpers
-               static MemberInfo getMemberInfoWithReflexion(object instance, string member){
-            Type t = instance.GetType();
-#if DEBUG_BINDING_FUNC_CALLS
-                       Console.WriteLine ($"getMemberInfoWithReflexion ({instance},{member}); type:{t}");
-#endif
-            MemberInfo mi = t.GetMember (member)?.FirstOrDefault();
-                       if (mi == null)
-                               mi = CompilerServices.SearchExtMethod (t, member);
-                       return mi;
-               }
-               static MethodInfo getMethodInfoWithReflexion(object instance, string method){
-#if DEBUG_BINDING_FUNC_CALLS
-            Console.WriteLine ($"getMethodInfoWithReflexion ({instance},{method}); type:{instance.GetType ()}");
-#endif
-            return instance.GetType ().GetMethod (method, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
-               }
-               /// <summary>
-               /// set value, convert if required
-               /// </summary>
-               /// <param name="dest">Destination instance</param>
-               /// <param name="value">Value</param>
-               /// <param name="destMember">Destination member</param>
-               static void setValueWithReflexion(object dest, object value, string destMember){
-#if DEBUG_BINDING_FUNC_CALLS
-            Console.WriteLine ($"setValueWithReflexion (dest:{dest},value:{value},member:{destMember});");
-#endif
-            Type destType = null;
-                       Type origType = null;
-                       object convertedVal = null;
-
-                       MemberInfo miDest = getMemberInfoWithReflexion (dest, destMember);
-
-                       if (miDest == null) {
-                               Debug.WriteLine ("Reverse template binding error: " + destMember + " not found in " + dest);
-                               return;
-                       }
-
-                       destType = CompilerServices.GetMemberInfoType (miDest);
-
-                       try {
-                               if (value != null) {
-                                       if (destType == typeof (object))//TODO: check that test of destType is not causing problems
-                                               convertedVal = value;
-                                       else {
-                                               origType = value.GetType ();
-                                               if (destType.IsAssignableFrom (origType))
-                                                       convertedVal = Convert.ChangeType (value, destType);
-                                               else if (origType == typeof(string) & destType.IsPrimitive)
-                                                       convertedVal = Convert.ChangeType(value, destType);
-                                               else if (origType.IsPrimitive & destType.IsPrimitive)
-                                                       convertedVal = GetConvertMethod (destType).Invoke (null, new Object[] { value });
-                                               else
-                                                       convertedVal = getImplicitOp (origType, destType).Invoke (value, null);
-                                       }
-                               }
-                       } catch (Exception ex) {
-                               Debug.WriteLine (ex.ToString ());
-                               return;
-                       }
-
-                       if (miDest.MemberType == MemberTypes.Property)
-                               (miDest as PropertyInfo).SetValue (dest, convertedVal);
-                       else if (miDest.MemberType == MemberTypes.Field)
-                               (miDest as FieldInfo).SetValue (dest, convertedVal);
-               }
-               /// <summary>
-               /// Gets value with reflexion, return empty string ("") for string and object and return
-               /// default value for valueType data.
-               /// </summary>
-               static object getValueWithReflexion(object instance, MemberInfo mi){
-#if DEBUG_BINDING_FUNC_CALLS
-            Console.WriteLine ($"getValueWithReflexion ({instance},{mi});");
-#endif
-            object tmp = null;
-                       Type dstType = null;
-                       if (mi == null)
-                               return null;
-                       try {
-                               if (mi.MemberType == MemberTypes.Property) {
-                                       PropertyInfo pi = mi as PropertyInfo;
-                                       tmp = pi.GetValue (instance);
-                                       dstType = pi.PropertyType;
-                               }else if (mi.MemberType == MemberTypes.Field) {
-                                       FieldInfo fi = mi as FieldInfo;
-                                       tmp = fi.GetValue (instance);
-                                       dstType = fi.FieldType;
-                               }else if (mi.MemberType == MemberTypes.Method) {
-                                       MethodInfo gi = mi as MethodInfo;
-                                       if (gi.IsStatic)
-                                               tmp = gi.Invoke(null, new object[] {instance});
-                                       else
-                                               tmp = gi.Invoke(instance, null);
-                                       dstType = gi.ReturnType;
-                               }
-                               if (tmp != null)
-                                       return tmp;
-                               if (dstType == typeof(string) || dstType == typeof (object))//TODO:object should be allowed to return null and not ""
-                                       return "";
-                               if (dstType.IsValueType)
-                                       return Activator.CreateInstance (dstType);                              
-                       } catch (Exception ex) {
-                               Debug.WriteLine (ex.ToString ());
-                               return "";
-                       }
-
-                       return null;
-               }
-               internal static MethodInfo SearchExtMethod (Type t, string methodName)
-               {
-                       string key = t.Name + "." + methodName;
-                       if (knownExtMethods.ContainsKey (key))
-                               return knownExtMethods [key];
-
-                       //Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}");
-
-                       MethodInfo mi = null;
-                       mi = GetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName);
-                       if (mi == null)
-                               mi = GetExtensionMethods (t.Module.Assembly, t, methodName);
-
-                       //add key even if mi is null to prevent searching again and again for propertyless bindings
-                       knownExtMethods.Add (key, mi);
-                       return mi;
-               }
-
-               public static MethodInfo GetExtensionMethods (Assembly assembly, Type extendedType, string methodName)
-               {
-                       foreach (Type t in assembly.GetTypes ().Where
-                                       (ty => ty.IsDefined (typeof (ExtensionAttribute), false))) {
-                               foreach (MethodInfo mi in t.GetMethods 
-                                       (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where
-                                               (m=> m.Name == methodName && m.IsDefined (typeof (ExtensionAttribute), false) &&
-                                                m.GetParameters ().Length == 1)) {
-                                       Type curType = extendedType;
-                                       while (curType != null) {
-                                               if (mi.GetParameters () [0].ParameterType == curType)
-                                                       return mi;
-                                               curType = curType.BaseType;
-                                       }                                               
-                               }
-                       
-                       }
-                       return null;
-               }
-               /// <summary>
-               /// retrieve event handler in class or ancestors
-               /// </summary>
-               static FieldInfo getEventHandlerField (Type type, string eventName)
-               {
-                       FieldInfo fi;
-                       Type ty = type;
-                       do {
-                               fi = ty.GetField (eventName,
-                                       BindingFlags.NonPublic |
-                                       BindingFlags.Instance |
-                                       BindingFlags.GetField);
-                               ty = ty.BaseType;
-                               if (ty == null)
-                                       break;
-                       } while (fi == null);
-                       return fi;
-               }
-               /// <summary>
-               /// search for an implicit conversion method in origine or destination classes
-               /// </summary>
-               static MethodInfo getImplicitOp(Type origType, Type dstType){
-                       foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
-                               if (mi.Name == "op_Implicit") {
-                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
-                                               return mi;
-                               }
-                       }
-                       foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
-                               if (mi.Name == "op_Implicit") {
-                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
-                                               return mi;
-                               }
-                       }
-                       return null;
-               }
-#endregion
-
-               /// <summary>
-               /// Emits tree parsing command to fetch dest instance starting from orig node
-               /// </summary>
-               internal static void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){
-                       int ptr = 0;
-                       while (orig [ptr] == dest [ptr]) {
-                               ptr++;
-                               if (ptr == orig.Count || ptr == dest.Count)
-                                       break;
-                       }
-                       for (int i = 0; i < orig.Count - ptr; i++)
-                               il.Emit (OpCodes.Callvirt, CompilerServices.miGetLogicalParent);
-                       while (ptr < dest.Count) {
-                               emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index);
-                               ptr++;
-                       }
-               }
-               /// <summary>
-               /// Emits tree parsing commands to get child starting at root node
-               /// </summary>
-               /// <param name="il">MSIL generator</param>
-               /// <param name="dest">Absolute Node Address of the instance to get</param>
-               internal static void emitGetInstance (ILGenerator il, NodeAddress dest){
-                       if (dest == null)
-                               return;
-                       for (int i = 0; i < dest.Count - 1; i++)
-                               emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
-               }
-               /// <summary>
-               /// Emits msil to fetch chil instance of current GraphicObject on the stack
-               /// </summary>
-               /// <param name="il">Il generator</param>
-               /// <param name="parentType">Parent type</param>
-               /// <param name="index">Index of child, -1 for template root</param>
-               internal static void emitGetChild(ILGenerator il, Type parentType, int index){
-                       if (typeof (Group).IsAssignableFrom (parentType)) {
-                               il.Emit (OpCodes.Ldfld, fiChildren);
-                               il.Emit(OpCodes.Ldc_I4, index);
-                               il.Emit (OpCodes.Callvirt, miGetGObjItem);
-                               return;
-                       }
-                       if (typeof(Container).IsAssignableFrom (parentType) || index < 0) {
-                               il.Emit (OpCodes.Ldfld, fiChild);
-                               return;
-                       }
-                       if (typeof(TemplatedContainer).IsAssignableFrom (parentType)) {
-                               il.Emit (OpCodes.Callvirt, piContent.GetGetMethod());
-                               return;
-                       }
-                       if (typeof(TemplatedGroup).IsAssignableFrom (parentType)) {
-                               il.Emit (OpCodes.Callvirt, miGetItems);
-                               il.Emit(OpCodes.Ldc_I4, index);
-                               il.Emit (OpCodes.Callvirt, miGetGObjItem);
-                               return;
-                       }
-               }
-
-               /// <summary>
-               /// Emit MSIL for conversion from orig type to dest type
-               /// </summary>
-               internal static void emitConvert(ILGenerator il, Type origType, Type destType){
-                       if (destType == typeof(object))
-                               return;
-                       if (destType == typeof (string)) {
-                               System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
-                               System.Reflection.Emit.Label endConvert = il.DefineLabel ();
-                               il.Emit (OpCodes.Dup);
-                               il.Emit (OpCodes.Brfalse, emitNullStr);
-                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
-                               il.Emit (OpCodes.Br, endConvert);
-                               il.MarkLabel (emitNullStr);
-                               il.Emit (OpCodes.Pop);//remove null string from stack
-                               il.Emit (OpCodes.Ldstr, "");//replace with empty string
-                               il.MarkLabel (endConvert);
-                       } else if ((origType.IsEnum || origType == typeof (Enum)) && destType.IsEnum) {
-                               il.Emit (OpCodes.Unbox_Any, destType);
-                               return;
-                       } else if (origType.IsValueType) {
-                               if (destType != origType) {
-                                       MethodInfo miIO = getImplicitOp (origType, destType);
-                                       if (miIO != null) {
-                                               System.Reflection.Emit.Label emitCreateDefault = il.DefineLabel ();
-                                               System.Reflection.Emit.Label emitContinue = il.DefineLabel ();
-                                               LocalBuilder lbStruct = il.DeclareLocal (origType);
-                                               il.Emit (OpCodes.Dup);
-                                               il.Emit (OpCodes.Brfalse, emitCreateDefault);
-                                               il.Emit (OpCodes.Unbox_Any, origType);
-                                               il.Emit (OpCodes.Br, emitContinue);
-                                               il.MarkLabel (emitCreateDefault);
-                                               il.Emit (OpCodes.Pop);//pop null value
-                                               il.Emit (OpCodes.Ldloca, lbStruct);
-                                               il.Emit (OpCodes.Initobj, origType);
-                                               il.Emit (OpCodes.Ldloc, lbStruct);
-                                               il.MarkLabel (emitContinue);
-                                               il.Emit (OpCodes.Call, miIO);
-                                       } else {
-                                               MethodInfo miconv = CompilerServices.GetConvertMethod (destType);
-                                               if (miconv.IsStatic)
-                                                       il.Emit (OpCodes.Call, miconv);
-                                               else
-                                                       il.Emit (OpCodes.Callvirt, miconv);
-                                       }
-                               } else
-                                       il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
-                       } else {
-                               if (destType.IsAssignableFrom (origType))
-                                       il.Emit (OpCodes.Castclass, destType);
-                               else {
-                                       if (origType == typeof (string)) {
-                                               //search dest type for parse method
-                                               MethodInfo miParse = destType.GetMethod
-                                                                                               ("Parse", BindingFlags.Static | BindingFlags.Public,
-                                                                                                       Type.DefaultBinder, new Type [] { typeof (string) }, null);
-                                               if (miParse == null)
-                                                       throw new Exception ("no Parse method found for: " + destType.FullName);
-                                               il.Emit (OpCodes.Call, miParse);
-                                       }
-                                       //implicit conversion can't be defined from or to object base class,
-                                       //so we will check if object underlying type is one of the implicit converter of destType
-                                       else if (origType == typeof (object)) {//test all implicit converter to destType on obj
-                                               System.Reflection.Emit.Label emitTestNextImpOp;
-                                               System.Reflection.Emit.Label emitImpOpFound = il.DefineLabel ();
-                                               foreach (MethodInfo mi in destType.GetMethods (BindingFlags.Public | BindingFlags.Static)) {
-                                                       if (mi.Name == "op_Implicit") {
-                                                               if (mi.GetParameters () [0].ParameterType == destType)
-                                                                       continue;
-                                                               emitTestNextImpOp = il.DefineLabel ();
-                                                               il.Emit (OpCodes.Dup);
-                                                               il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
-                                                               il.Emit (OpCodes.Brfalse, emitTestNextImpOp);
-                                                               if (mi.GetParameters () [0].ParameterType.IsValueType)
-                                                                       il.Emit (OpCodes.Unbox_Any, mi.GetParameters () [0].ParameterType);
-                                                               else
-                                                                       il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
-
-                                                               il.Emit (OpCodes.Call, mi);
-                                                               il.Emit (OpCodes.Br, emitImpOpFound);
-
-                                                               il.MarkLabel (emitTestNextImpOp);
-                                                       }
-                                               }
-                                               //il.Emit (OpCodes.Br, emitImpOpNotFound);
-                                               il.MarkLabel (emitImpOpFound);
-                                       } else {//search both orig and dest types for implicit operators
-                                               MethodInfo miIO = getImplicitOp (origType, destType);
-                                               if (miIO != null)
-                                                       il.Emit (OpCodes.Call, miIO);
-                                       }
-                               }
-                       }
-               }
-               /// <summary>
-               /// check type of current object on the stack and convert to dest type,
-               /// use loc_0 so store it as object!!!
-               /// </summary>
-               internal static void emitConvert(ILGenerator il, Type dstType){
-                       System.Reflection.Emit.Label endConvert = il.DefineLabel ();
-                       System.Reflection.Emit.Label convert = il.DefineLabel ();
-
-                       il.Emit (OpCodes.Dup);
-                       il.Emit (OpCodes.Isinst, dstType);
-                       il.Emit (OpCodes.Brfalse, convert);
-
-                       if (dstType.IsValueType)
-                               il.Emit (OpCodes.Unbox_Any, dstType);
-                       else
-                               il.Emit (OpCodes.Isinst, dstType);
-                       il.Emit (OpCodes.Br, endConvert);
-
-                       il.MarkLabel (convert);
-
-                       if (dstType == typeof(string)) {
-                               System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
-                               il.Emit (OpCodes.Dup);
-                               il.Emit (OpCodes.Brfalse, emitNullStr);
-                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
-                               il.Emit (OpCodes.Br, endConvert);
-                               il.MarkLabel (emitNullStr);
-                               il.Emit (OpCodes.Pop);//remove null string from stack
-                               il.Emit (OpCodes.Ldstr, "");//replace with empty string
-                       } else if (dstType.IsPrimitive) {
-                //il.Emit (OpCodes.Unbox_Any, dstType);
-                MethodInfo miconv = CompilerServices.GetConvertMethod(dstType);
-                if (miconv.IsStatic)
-                    il.Emit(OpCodes.Call, miconv);
-                else
-                    il.Emit(OpCodes.Callvirt, miconv);
-                       } else if (dstType.IsValueType) {
-                               il.Emit (OpCodes.Unbox_Any, dstType);
-                       } else{
-                               il.Emit (OpCodes.Stloc_0); //save orig value in loc0
-                               //first check if not null
-                               il.Emit (OpCodes.Ldloc_0);
-                               il.Emit (OpCodes.Dup);
-                               il.Emit (OpCodes.Brfalse, endConvert);
-                               il.Emit (OpCodes.Callvirt, miGetType);
-                               il.Emit (OpCodes.Ldtoken, dstType);//push destination property type for testing
-                               il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-                               il.Emit (OpCodes.Call, miGetImplOp);
-                               il.Emit (OpCodes.Dup);
-                               convert = il.DefineLabel ();
-                               il.Emit (OpCodes.Brtrue, convert);
-                               il.Emit (OpCodes.Pop);
-                               il.Emit (OpCodes.Ldloc_0);
-                               il.Emit (OpCodes.Isinst, dstType);
-                               il.Emit (OpCodes.Br, endConvert);
-
-                               il.MarkLabel (convert);
-                               il.Emit (OpCodes.Ldnull);//null instance for invoke
-                               il.Emit (OpCodes.Ldc_I4_1);
-                               il.Emit(OpCodes.Newarr, typeof (object));
-                               il.Emit (OpCodes.Dup);//duplicate the array ref
-                               il.Emit (OpCodes.Ldc_I4_0);//push the index 0
-                               il.Emit (OpCodes.Ldloc_0);//push the orig value to convert
-                               il.Emit (OpCodes.Stelem, typeof (object));//set the array element at index 0
-                               il.Emit (OpCodes.Callvirt, miMIInvoke);
-                       }
-
-                       il.MarkLabel (endConvert);
-               }
-
-               /// <summary>
-               /// Removes delegate from event handler by name
-               /// </summary>
-               static void removeEventHandlerByName(object instance, string eventName, string delegateName){
-                       Type t = instance.GetType ();
-                       FieldInfo fiEvt = getEventHandlerField (t, eventName);
-                       if (fiEvt == null) {
-#if DEBUG_BINDING
-                               Debug.WriteLine ("RemoveHandlerByName: Event '" + eventName + "' not found in " + instance);
-#endif
-                               return;
-                       }
-                       EventInfo eiEvt = t.GetEvent (eventName);
-                       MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
-                       if (multiDel != null) {
-                               foreach (Delegate d in multiDel.GetInvocationList()) {
-                                       if (d.Method.Name == delegateName) {
-                                               eiEvt.RemoveEventHandler (instance, d);
-#if DEBUG_BINDING
-                                               Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
-#endif
-                                       }
-                               }
-                       }
-               }
-               /// <summary>
-               /// Removes delegate from event handler by searching for the object they are bond to
-               /// </summary>
-               static void removeEventHandlerByTarget(object instance, string eventName, object target){
-                       Type t = instance.GetType ();
-                       FieldInfo fiEvt = getEventHandlerField (t, eventName);
-                       EventInfo eiEvt = t.GetEvent (eventName);
-                       MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
-                       if (multiDel != null) {
-                               foreach (Delegate d in multiDel.GetInvocationList()) {
-                                       if (d.Target == target) {
-                                               eiEvt.RemoveEventHandler (instance, d);
-#if DEBUG_BINDING
-                                               Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
-#endif
-                                       }
-                               }
-                       }
-               }
-               /// <summary>
-               /// create delegate helper
-               /// </summary>
-               static Delegate createDel(object instance, Type eventType, string method){
-                       Type t = instance.GetType ();
-                       MethodInfo mi = t.GetMethod (method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
-                       if (mi == null) {
-                               Debug.WriteLine ("Handler Method '{0}' not found in '{1}'", method, t);
-                               return null;
-                       }
-                       return Delegate.CreateDelegate (eventType, instance, mi);
-               }
-
-               internal static Delegate compileDynEventHandler(EventInfo sourceEvent, string expression, NodeAddress currentNode = null){
-#if DEBUG_BINDING
-                       Debug.WriteLine ("\tCompile Event {0}: {1}", sourceEvent.Name, expression);
-#endif
-
-                       Type lopType = null;
-
-                       if (currentNode == null)
-                               lopType = sourceEvent.DeclaringType;
-                       else
-                               lopType = currentNode.NodeType;
-
-#region Retrieve EventHandler parameter type
-                       MethodInfo evtInvoke = sourceEvent.EventHandlerType.GetMethod ("Invoke");
-                       ParameterInfo [] evtParams = evtInvoke.GetParameters ();
-                       Type handlerArgsType = evtParams [1].ParameterType;
-#endregion
-
-                       Type [] args = { typeof (object), handlerArgsType };
-                       DynamicMethod dm = new DynamicMethod ("dyn_eventHandler",
-                               typeof(void),
-                               args, true);
-                       ILGenerator il = dm.GetILGenerator (256);
-                       il.Emit (OpCodes.Nop);
-
-                       string [] srcLines = expression.Trim ().Split (new char [] { ';' });
-
-                       foreach (string srcLine in srcLines) {
-                               if (string.IsNullOrEmpty (srcLine))
-                                       continue;
-                               string [] operandes = srcLine.Trim ().Split (new char [] { '=' });
-                               if (operandes.Length != 2) //not an affectation
-                                       throw new NotSupportedException ();
-
-                               System.Reflection.Emit.Label cancel = il.DefineLabel ();
-                               System.Reflection.Emit.Label cancelFinalSet = il.DefineLabel ();
-                               System.Reflection.Emit.Label success = il.DefineLabel ();
-
-                               BindingMember lop = new BindingMember (operandes [0].Trim ());
-                               BindingMember rop = new BindingMember (operandes [1].Trim ());
-
-                               il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
-
-#region Left operande
-                               PropertyInfo lopPI = null;
-
-                               //in dyn handler, no datasource binding, so single name in expression are also handled as current node property
-                               if (lop.IsSingleName)
-                                       lopPI = lopType.GetProperty (lop.Tokens [0]);
-                               else if (lop.IsCurrentNodeProperty)
-                                       lopPI = lopType.GetProperty (lop.Tokens [1]);
-                               else
-                                       lop.emitGetTarget (il, cancel);
-#endregion
-
-#region RIGHT OPERANDES
-                               if (rop.IsStringConstant){
-                                       il.Emit (OpCodes.Ldstr, rop.Tokens[0]);
-                                       lop.emitSetProperty (il);
-                               }else if (rop.IsSingleName && rop.Tokens[0] == "this"){
-                                       il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
-                                       lop.emitSetProperty (il);
-                               }else if (rop.LevelsUp ==0 && !string.IsNullOrEmpty(rop.Tokens[0])) {//parsable constant depending on lop type
-                                       //if left operand is member of current node, it's easy to fetch type, else we should use reflexion in msil
-                                       if (lopPI == null){//accept GraphicObj members, but it's restricive
-                                               //TODO: we should get the parse method by reflexion, or something else
-                                               lopPI = typeof(Widget).GetProperty (lop.Tokens [lop.Tokens.Length-1]);
-                                               if (lopPI == null)
-                                                       throw new NotSupportedException ();
-                                       }
-
-                                       MethodInfo lopParseMi = CompilerServices.miParseEnum;
-                                       if (lopPI.PropertyType.IsEnum){
-                                               //load type of enum
-                                               il.Emit(OpCodes.Ldtoken, lopPI.PropertyType);
-                                               il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-                                               //load enum value name
-                                               il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
-                                               //load false
-                                               il.Emit (OpCodes.Ldc_I4_0);
-                                       }else{
-                                               lopParseMi = lopPI.PropertyType.GetMethod ("Parse");
-                                               if (lopParseMi == null)
-                                                       throw new Exception (string.Format
-                                                               ("IML: no static 'Parse' method found in: {0}", lopPI.PropertyType.Name));
-
-                                               il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
-                                       }
-                    if (lopParseMi.IsStatic)
-                                           il.Emit (OpCodes.Call, lopParseMi);
-                    else
-                        il.Emit(OpCodes.Callvirt, lopParseMi);
-                    //il.Emit (OpCodes.Unbox_Any, lopPI.PropertyType);
-                    //emit left operand assignment
-                    il.Emit (OpCodes.Callvirt, lopPI.GetSetMethod());
-                               } else {//tree parsing and propert gets
-                                       il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
-
-                                       rop.emitGetTarget (il, cancelFinalSet);
-                                       rop.emitGetProperty (il, cancelFinalSet);
-                                       lop.emitSetProperty (il);
-                               }
-#endregion
-
-                               il.Emit (OpCodes.Br, success);
-
-                               il.MarkLabel (cancelFinalSet);
-                               il.Emit (OpCodes.Pop);  //pop null MemberInfo on the stack causing cancelation
-                               il.MarkLabel (cancel);
-                               il.Emit (OpCodes.Pop);  //pop null instance on the stack causing cancelation
-                               il.MarkLabel (success);
-                       }
-
-                       il.Emit (OpCodes.Ret);
-
-                       return dm.CreateDelegate (sourceEvent.EventHandlerType);
-               }
-
-               /// <summary>
-               /// MSIL helper, go n levels up
-               /// </summary>
-               /// <returns><c>true</c>, if logical parents are not null</returns>
-               /// <param name="instance">Start Instance</param>
-               /// <param name="levelCount">Levels to go upward</param>
-               internal static ILayoutable goUpNbLevels(ILayoutable instance, int levelCount){
-                       ILayoutable tmp = instance;
-                       int i = 0;
-                       while (tmp != null && i < levelCount) {
-                               tmp = tmp.LogicalParent;
-                               i++;
-                       }
-                       return tmp;
-               }
-               /// <summary>
-               /// Splits expression on semicolon but ignore those between accolades
-               /// </summary>
-               internal static string[] splitOnSemiColumnOutsideAccolades (string expression){
-                       List<String> exps = new List<string>();
-                       int accCount = 0;
-                       int expPtr = 0;
-                       for (int c = 0; c < expression.Length; c++) {
-                               switch (expression[c]){
-                               case '{':
-                                       accCount++;
-                                       break;
-                               case '}':
-                                       accCount--;
-                                       break;
-                               case ';':
-                                       if (accCount > 0)
-                                               break;
-                                       exps.Add(expression.Substring(expPtr, c - expPtr - 1));
-                                       expPtr = c + 1;
-                                       break;
-                               }
-                       }
-                       if (exps.Count == 0)
-                               exps.Add(expression);
-                       return exps.ToArray ();
-               }
-               /// <summary>
-               /// Try to get the type named strDataType, search first in crow assembly then in
-               /// entry assembly.
-               /// </summary>
-               /// <returns>the corresponding type object if found</returns>
-               /// <param name="strDataType">type name</param>
-               internal static Type getTypeFromName (string strDataType){
-                       if (knownTypes.ContainsKey (strDataType))
-                               return knownTypes [strDataType];
-                       Type dataType = Type.GetType(strDataType);
-                       if (dataType != null) {
-                               knownTypes.Add (strDataType, dataType);
-                               return dataType;
-                       }
-                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ()) {
-                               if (a.IsDynamic)
-                                       continue;
-                               foreach (Type expT in a.GetExportedTypes ()) {
-                                       if (expT.Name != strDataType && expT.FullName != strDataType)
-                                               continue;
-                                       if (!knownTypes.ContainsKey(strDataType))
-                                               knownTypes.Add (strDataType, expT);
-                                       return expT;
-                               }
-                       }
-                       knownTypes.Add (strDataType, null);
-                       return null;
-               }
-
-               //get value from member of object
-               internal static object getDataTypeAndFetch (object data, string fetchMethod){
-                       Type dataType = data.GetType();
-                       //Console.WriteLine ($"get data type and fetch {data}.{fetchMethod}");
-                       MethodInfo miGetDatas = dataType.GetMethod (fetchMethod, new Type[] {});
-                       if (miGetDatas == null)
-                               miGetDatas = CompilerServices.SearchExtMethod (dataType, fetchMethod);
-
-                       if (miGetDatas == null) {//in last resort, search among properties
-                               PropertyInfo piDatas = dataType.GetProperty (fetchMethod);
-                               if (piDatas == null) {
-                                       FieldInfo fiDatas = dataType.GetField (fetchMethod);
-                                       if (fiDatas == null)//and among fields
-                                               throw new Exception ("Fetch data member not found in ItemTemplate: " + fetchMethod);
-                                       return fiDatas.GetValue (data);
-                               }
-                               miGetDatas = piDatas.GetGetMethod ();
-                               if (miGetDatas == null)
-                                       throw new Exception ("Read only property for fetching data in ItemTemplate: " + fetchMethod);
-                       }
-                       return miGetDatas.IsStatic ?
-                               miGetDatas.Invoke (null, new object [] { data }) : miGetDatas.Invoke (data, null);
-               }
-               //TODO:memberinfo found here must be cached
-               internal static object getValue (Type dataType, object data, string member)
-               {
-                       //Console.WriteLine ($"get value: {dataType} ; {data} ; {member}");
-
-                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
-                       if (miGetDatas != null)
-                               return miGetDatas.Invoke (data, null);
-                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
-                       if (mbi == null) {
-                               MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member);
-                               if (miExt == null)//and among fields
-                                       throw new Exception ($"member {member} not found in {dataType}");
-                               return miExt.Invoke (null, new object [] { data });
-                       }
-                       if (mbi.MemberType == MemberTypes.Property) {
-                               miGetDatas = (mbi as PropertyInfo)?.GetGetMethod ();
-                               if (miGetDatas == null)
-                                       throw new Exception ($"no getter found for property {member} in {dataType}");
-                               return miGetDatas.Invoke (data, null);
-                       }
-
-                       FieldInfo fi = mbi as FieldInfo;
-                       if (fi == null)
-                               throw new Exception ($"member {member} not found in {dataType}");
-
-                       return fi.GetValue (data);
-               }
-               internal static MemberInfo GetMemberInfo (Type dataType, string member, out Type returnType)
-               {
-                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
-                       if (miGetDatas != null) {
-                               returnType = miGetDatas.ReturnType;
-                               return miGetDatas;
-                       }
-
-                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
-                       if (mbi == null)
-                               miGetDatas = CompilerServices.SearchExtMethod (dataType, member);
-                       else {
-                               if (mbi is FieldInfo) {
-                                       FieldInfo fi = mbi as FieldInfo;
-                                       returnType = fi.FieldType;
-                                       return mbi;
-                               }
-                               if (mbi.MemberType == MemberTypes.Property)
-                                       miGetDatas = (mbi as PropertyInfo).GetGetMethod ();
-                               else
-                                       miGetDatas = mbi as MethodInfo;
-                       }
-                       returnType = miGetDatas?.ReturnType;
-                       return miGetDatas;
-
-               }
-               internal static void emitGetMemberValue (ILGenerator il, Type dataType, MemberInfo mi)
-               {
-                       switch (mi.MemberType) {
-                       case MemberTypes.Method:
-                               MethodInfo mim = mi as MethodInfo;
-                               if (mim.IsStatic)
-                                       il.Emit (OpCodes.Call, mim);
-                               else
-                                       il.Emit (OpCodes.Callvirt, mim);
-                               break;
-                       case MemberTypes.Field:
-                               il.Emit (OpCodes.Ldfld, mi as FieldInfo);
-                               break;
-                       }
-               }
-               //object is already on the stack
-               internal static void emitGetMemberValue (ILGenerator il, Type dataType, string member)
-               {
-                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
-                       if (miGetDatas != null) {
-                               il.Emit (OpCodes.Callvirt, miGetDatas);
-                               return;
-                       }
-                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
-                       if (mbi == null) {
-                               MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member);
-                               if (miExt == null)//and among fields
-                                       throw new Exception ($"member {member} not found in {dataType}");
-                               il.Emit (OpCodes.Call, miExt);
-                               return;
-                       }
-                       if (mbi.MemberType == MemberTypes.Property) {
-                               miGetDatas = (mbi as PropertyInfo)?.GetGetMethod ();
-                               if (miGetDatas == null)
-                                       throw new Exception ($"no getter found for property {member} in {dataType}");
-                               il.Emit (OpCodes.Callvirt, miGetDatas);
-                               return;
-                       }
-
-                       FieldInfo fi = mbi as FieldInfo;
-                       if (fi == null)
-                               throw new Exception ($"member {member} not found in {dataType}");
-
-                       il.Emit (OpCodes.Ldfld, fi);
-               }
-
-               //helper to get member info underlying type.
-               internal static Type GetMemberInfoType (MemberInfo mi) =>
-                               mi.MemberType == MemberTypes.Field ? (mi as FieldInfo).FieldType :
-                               mi.MemberType == MemberTypes.Property ? (mi as PropertyInfo).PropertyType :
-                               mi.MemberType == MemberTypes.Method ? (mi as MethodInfo).ReturnType : null;
-       }
-}
-
index 001573714d93501cf310c152c669ffe31235a558..69edfe8e42aafb338df6298a963ef9ec5325f20a 100644 (file)
@@ -1,28 +1,6 @@
-//
-// ExtensionsMethods.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.Linq.Expressions;
diff --git a/Crow/src/Fill/BmpPicture.cs b/Crow/src/Fill/BmpPicture.cs
new file mode 100644 (file)
index 0000000..a67f66f
--- /dev/null
@@ -0,0 +1,185 @@
+//
+// BmpPicture.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.IO;
+using System.Runtime.InteropServices;
+using Crow.Cairo;
+
+namespace Crow
+{
+
+       /// <summary>
+       /// Derived from FILL for loading and drawing bitmaps in the interface
+       /// </summary>
+       public class BmpPicture : Picture
+       {
+               byte[] image = null;
+
+               #region CTOR
+               /// <summary>
+               /// Initializes a new instance of BmpPicture.
+               /// </summary>
+               public BmpPicture ()
+               {}
+               /// <summary>
+               /// Initializes a new instance of BmpPicture by loading the image pointed by the path argument
+               /// </summary>
+               /// <param name="path">image path, may be embedded</param>
+               public BmpPicture (string path) : base(path)
+               {
+                       Load ();
+               }
+               #endregion
+               /// <summary>
+               /// load the image for rendering from the path given as argument
+               /// </summary>
+               /// <param name="path">image path, may be embedded</param>
+               void Load ()
+               {                       
+                       if (sharedResources.ContainsKey (Path)) {
+                               sharedPicture sp = sharedResources [Path];
+                               image = (byte[])sp.Data;
+                               Dimensions = sp.Dims;
+                               return;
+                       }
+                       using (Stream stream = Interface.StaticGetStreamFromPath (Path)) {
+                               using (StbImage stbi = new StbImage (stream)) {
+                                       image = new byte [stbi.Size];
+                                       //rgba to argb for cairo.
+                                       for (int i = 0; i < stbi.Size; i+=4) {
+                                               image [i] = Marshal.ReadByte (stbi.Handle, i + 2);
+                                               image [i + 1] = Marshal.ReadByte (stbi.Handle, i + 1);
+                                               image [i + 2] = Marshal.ReadByte (stbi.Handle, i);
+                                               image [i + 3] = Marshal.ReadByte (stbi.Handle, i + 3);
+                                       }
+                                       Dimensions = new Size (stbi.Width, stbi.Height);
+                               }
+
+                               //loadBitmap (new System.Drawing.Bitmap (stream));      
+                       }
+                       sharedResources [Path] = new sharedPicture (image, Dimensions);
+               }
+
+
+
+               //load image via System.Drawing.Bitmap, cairo load png only
+               /*void loadBitmap (System.Drawing.Bitmap bitmap)
+               {
+                       if (bitmap == null)
+                               return;
+
+                       System.Drawing.Imaging.BitmapData data = bitmap.LockBits
+                               (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height),
+                                       System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+
+                       Dimensions = new Size (bitmap.Width, bitmap.Height);
+
+                       int stride = data.Stride;
+                       int bitmapSize = Math.Abs (data.Stride) * bitmap.Height;
+
+                       image = new byte[bitmapSize];
+                       System.Runtime.InteropServices.Marshal.Copy (data.Scan0, image, 0, bitmapSize);
+
+                       bitmap.UnlockBits (data);           
+               }*/
+
+               #region implemented abstract members of Fill
+
+               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
+               {
+                       float widthRatio = 1f;
+                       float heightRatio = 1f;
+
+                       if (Scaled){
+                               widthRatio = (float)bounds.Width / Dimensions.Width;
+                               heightRatio = (float)bounds.Height / Dimensions.Height;
+                       }
+
+                       if (KeepProportions) {
+                               if (widthRatio < heightRatio)
+                                       heightRatio = widthRatio;
+                               else
+                                       widthRatio = heightRatio;
+                       }
+
+                       using (ImageSurface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) {
+                               using (Context gr = new Context (tmp)) {
+                                       gr.Translate (bounds.Left, bounds.Top);
+                                       gr.Scale (widthRatio, heightRatio);
+                                       gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2);
+
+                                       using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
+                                               Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
+                                               gr.SetSourceSurface (imgSurf, 0,0);
+                                               gr.Paint ();
+                                       }
+                               }
+                               ctx.SetSource (tmp);
+                       }                               
+               }
+               #endregion
+
+               /// <summary>
+               /// paint the image in the rectangle given in arguments according
+               /// to the Scale and keepProportion parameters.
+               /// </summary>
+               /// <param name="gr">drawing Backend context</param>
+               /// <param name="rect">bounds of the target surface to paint</param>
+               /// <param name="subPart">used for svg only</param>
+               public override void Paint (Context gr, Rectangle rect, string subPart = "")
+               {
+                       float widthRatio = 1f;
+                       float heightRatio = 1f;
+
+                       if (Scaled){
+                               widthRatio = (float)rect.Width / Dimensions.Width;
+                               heightRatio = (float)rect.Height / Dimensions.Height;
+                       }
+
+                       if (KeepProportions) {
+                               if (widthRatio < heightRatio)
+                                       heightRatio = widthRatio;
+                               else
+                                       widthRatio = heightRatio;
+                       }
+
+                       gr.Save ();
+
+                       gr.Translate (rect.Left,rect.Top);
+                       gr.Scale (widthRatio, heightRatio);
+                       gr.Translate ((rect.Width/widthRatio - Dimensions.Width)/2, (rect.Height/heightRatio - Dimensions.Height)/2);
+                       
+                       using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
+                               Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
+                               gr.SetSourceSurface (imgSurf, 0,0);
+                               gr.Paint ();
+                       }
+                       gr.Restore ();
+               }
+       }
+}
+
index 719002d2bb0fcde76823f2f76d375ad692a512b9..6ff2bb7c986294c3de2beb8516ecf2a4777678c8 100644 (file)
@@ -31,16 +31,15 @@ namespace Crow
                            s.EndsWith (".gif", true, System.Globalization.CultureInfo.InvariantCulture))
                                return Picture.Parse (s);
 
-                       return (SolidColor)SolidColor.Parse (s);
+                       return new SolidColor((Color)Color.Parse (s));
                }
                public static implicit operator Color(Fill c){
                        SolidColor sc = c as SolidColor;
-                       return sc == null ? default(Color) : sc.color;
+                       return sc == null ? default : sc.color;
                }
                public static implicit operator Fill(Color c){
                        return new SolidColor (c);
                }
-
        }
 }
 
diff --git a/Crow/src/Fill/Picture.cs b/Crow/src/Fill/Picture.cs
new file mode 100644 (file)
index 0000000..2a71d6b
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// Picture.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.IO;
+using Crow.Cairo;
+using System.Collections.Generic;
+
+namespace Crow
+{
+       /// <summary>
+       /// store data and dimensions for resource sharing
+       /// </summary>
+       internal class sharedPicture {
+               //TODO: restructure this whith clever conceptual classes
+               public object Data;
+               public Size Dims;
+               public sharedPicture (object _data, Size _dims){
+                       Data = _data;
+                       Dims = _dims;
+               }
+       }
+       /// <summary>
+       /// virtual class for loading and drawing picture in the interface
+       /// 
+       /// Every loaded resources are stored in a dictonary with their path as key and shared
+       /// among interface elements
+       /// </summary>
+       public abstract class Picture : Fill
+       {
+               /// <summary>
+               /// share a single store for picture resources among usage in different controls
+               /// </summary>
+               internal static Dictionary<string, sharedPicture> sharedResources = new Dictionary<string, sharedPicture>();
+
+               /// <summary>
+               /// path of the picture
+               /// </summary>
+               public string Path;
+               /// <summary>
+               /// unscaled dimensions fetched on loading
+               /// </summary>
+               public Size Dimensions;
+               /// <summary>
+               /// if true and image has to be scalled, it will be scaled in both direction
+               /// equaly
+               /// </summary>
+               public bool KeepProportions = false;
+               /// <summary>
+               /// allow or not the picture to be scalled on request by the painter
+               /// </summary>
+               public bool Scaled = true;
+
+               #region CTOR
+               /// <summary>
+               /// Initializes a new instance of Picture.
+               /// </summary>
+               public Picture ()
+               {
+               }
+               /// <summary>
+               /// Initializes a new instance of Picture by loading the image pointed by the path argument
+               /// </summary>
+               /// <param name="path">image path, may be embedded</param>
+               public Picture (string path)
+               {
+                       Path = path;
+               }
+               #endregion
+
+               #region Image Loading
+               /// <summary>
+               /// load the image for rendering from the stream given as argument
+               /// </summary>
+               /// <param name="stream">picture stream</param>
+               //public abstract void Load(Interface iface, string path);
+               #endregion
+
+               /// <summary>
+               /// abstract method to paint the image in the rectangle given in arguments according
+               /// to the Scale and keepProportion parameters.
+               /// </summary>
+               /// <param name="gr">drawing Backend context</param>
+               /// <param name="rect">bounds of the target surface to paint</param>
+               /// <param name="subPart">used for svg only</param>
+               public abstract void Paint(Context ctx, Rectangle rect, string subPart = "");
+
+               #region Operators
+               public static implicit operator Picture(string path)
+               {
+                       if (string.IsNullOrEmpty (path))
+                               return null;
+                       
+                       Picture _pic = null;
+
+                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) 
+                               _pic = new SvgPicture (path);
+                       else 
+                               _pic = new BmpPicture (path);
+
+                       return _pic;
+               }
+               public static implicit operator string(Picture _pic)
+               {
+                       return _pic == null ? null : _pic.Path;
+               }
+               #endregion
+
+               public static new object Parse(string path)
+               {
+                       if (string.IsNullOrEmpty (path))
+                               return null;
+                       
+                       Picture _pic = null;
+
+                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) 
+                               _pic = new SvgPicture (path);
+                       else 
+                               _pic = new BmpPicture (path);
+
+                       return _pic;
+               }
+               public override string ToString ()
+               {
+                       return Path;
+               }
+       }
+}
+
diff --git a/Crow/src/Fill/SolidColor.cs b/Crow/src/Fill/SolidColor.cs
new file mode 100644 (file)
index 0000000..f3e37d2
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// SolidColor.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 System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+using System.Reflection;
+using System.Diagnostics;
+using Crow.Cairo;
+
+
+
+namespace Crow
+{
+       public class SolidColor : Fill
+    {
+               public Color color = Color.Transparent;
+               #region CTOR
+               public SolidColor(Color c)
+               {
+                       color = c;
+               }
+               #endregion
+
+               #region implemented abstract members of Fill
+               public override void SetAsSource (Context ctx, Rectangle bounds = default)
+               {
+                       ctx.SetSourceRGBA (color.R, color.G, color.B, color.A);
+               }
+               public static new object Parse(string s)
+               {
+                       return new SolidColor((Color)s);
+               }
+               #endregion
+
+               #region Operators
+        public static implicit operator Color(SolidColor c) => c.color;        
+               public static implicit operator SolidColor(Color c) => new SolidColor (c);
+
+               public static bool operator ==(SolidColor left, SolidColor right) => left?.color == right?.color;               
+               public static bool operator !=(SolidColor left, SolidColor right) => left?.color != right?.color;
+
+               public override int GetHashCode ()
+               {
+                       return color.GetHashCode();
+               }
+               public override bool Equals (object obj)
+               {
+                       if (obj is Color)
+                               return color == (Color)obj;
+                       if (obj is SolidColor)
+                               return color == (obj as SolidColor).color;
+                       return false;                   
+               }
+//             public static bool operator ==(SolidColor c, string n)
+//             {
+//                     return c.color.Name == n ? true : false;
+//             }
+//             public static bool operator !=(SolidColor c, string n)
+//             {
+//                     return c.color.Name == n ? false : true;
+//             }
+//             public static bool operator ==(string n, SolidColor c)
+//             {
+//                     return c.color.Name == n ? true : false;
+//             }
+//             public static bool operator !=(string n, SolidColor c)
+//             {
+//                     return c.color.Name == n ? false : true;
+//             }
+               public static SolidColor operator *(SolidColor c, Double f)
+               {
+                       return new SolidColor(new Color(c.color.R,c.color.G,c.color.B,c.color.A * f));
+               }
+               public static SolidColor operator +(SolidColor c1, SolidColor c2)
+               {
+                       return new SolidColor(new Color(c1.color.R + c2.color.R,c1.color.G + c2.color.G,c1.color.B + c2.color.B,c1.color.A + c2.color.A));
+               }
+               public static SolidColor operator -(SolidColor c1, SolidColor c2)
+               {
+                       return new SolidColor(new Color(c1.color.R - c2.color.R,c1.color.G - c2.color.G,c1.color.B - c2.color.B,c1.color.A - c2.color.A));
+               }
+               #endregion                                      
+
+               public override string ToString()
+               {
+                       return color.ToString ();
+               }
+    }
+}
diff --git a/Crow/src/Fill/SvgPicture.cs b/Crow/src/Fill/SvgPicture.cs
new file mode 100644 (file)
index 0000000..33f6895
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// SvgPicture.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.IO;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// Derived from FILL for loading and drawing SVG images in the interface
+       /// </summary>
+       public class SvgPicture : Picture
+       {
+               Rsvg.Handle hSVG;
+
+               #region CTOR
+               /// <summary>
+               /// Initializes a new instance of SvgPicture.
+               /// </summary>
+               public SvgPicture ()
+               {}
+               /// <summary>
+               /// Initializes a new instance of SvgPicture by loading the SVG file pointed by the path argument
+               /// </summary>
+               /// <param name="path">image path, may be embedded</param>
+               public SvgPicture (string path) : base(path)
+               {
+                       Load ();
+               }
+               #endregion
+
+               void Load ()
+               {                       
+                       if (sharedResources.ContainsKey (Path)) {
+                               sharedPicture sp = sharedResources [Path];
+                               hSVG = (Rsvg.Handle)sp.Data;
+                               Dimensions = sp.Dims;
+                               return;
+                       }
+                       using (Stream stream = Interface.StaticGetStreamFromPath (Path)) {
+                               using (MemoryStream ms = new MemoryStream ()) {
+                                       stream.CopyTo (ms);
+
+                                       hSVG = new Rsvg.Handle (ms.ToArray ());
+                                       Dimensions = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height);
+                               }
+                       }
+                       sharedResources [Path] = new sharedPicture (hSVG, Dimensions);
+               }
+
+               public void LoadSvgFragment (string fragment) {                 
+                       hSVG = new Rsvg.Handle (System.Text.Encoding.Unicode.GetBytes(fragment));
+                       Dimensions = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height);
+               }
+
+               #region implemented abstract members of Fill
+
+               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
+               {
+                       float widthRatio = 1f;
+                       float heightRatio = 1f;
+
+                       if (Scaled){
+                               widthRatio = (float)bounds.Width / Dimensions.Width;
+                               heightRatio = (float)bounds.Height / Dimensions.Height;
+                       }
+
+                       if (KeepProportions) {
+                               if (widthRatio < heightRatio)
+                                       heightRatio = widthRatio;
+                               else
+                                       widthRatio = heightRatio;
+                       }
+
+                       using (ImageSurface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) {
+                               using (Context gr = new Context (tmp)) {
+                                       gr.Translate (bounds.Left, bounds.Top);
+                                       gr.Scale (widthRatio, heightRatio);
+                                       gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2);
+
+                                       hSVG.RenderCairo (gr);
+                               }
+                               ctx.SetSource (tmp);
+                       }       
+               }
+               #endregion
+
+               /// <summary>
+               /// paint the image in the rectangle given in arguments according
+               /// to the Scale and keepProportion parameters.
+               /// </summary>
+               /// <param name="gr">drawing Backend context</param>
+               /// <param name="rect">bounds of the target surface to paint</param>
+               /// <param name="subPart">limit rendering to svg part named 'subPart'</param>
+               public override void Paint (Context gr, Rectangle rect, string subPart = "")
+               {
+                       if (hSVG == null)
+                               return;
+                       float widthRatio = 1f;
+                       float heightRatio = 1f;
+
+                       if (Scaled) {
+                               widthRatio = (float)rect.Width / Dimensions.Width;
+                               heightRatio = (float)rect.Height / Dimensions.Height;
+                       }
+                       if (KeepProportions) {
+                               if (widthRatio < heightRatio)
+                                       heightRatio = widthRatio;
+                               else
+                                       widthRatio = heightRatio;
+                       }
+                               
+                       gr.Save ();
+
+                       gr.Translate (rect.Left,rect.Top);
+                       gr.Scale (widthRatio, heightRatio);
+                       gr.Translate (((float)rect.Width/widthRatio - Dimensions.Width)/2f, ((float)rect.Height/heightRatio - Dimensions.Height)/2f);
+
+                       if (string.IsNullOrEmpty (subPart))
+                               hSVG.RenderCairo (gr);
+                       else
+                               hSVG.RenderCairoSub (gr, "#" + subPart);
+                       
+                       gr.Restore ();                  
+               }
+       }
+}
+
diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs
new file mode 100644 (file)
index 0000000..6ea3c95
--- /dev/null
@@ -0,0 +1,1102 @@
+// 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.Reflection.Emit;
+using System.Reflection;
+using System.Diagnostics;
+using System.Linq;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using Crow.IML;
+using System.Text;
+
+namespace Crow.IML
+{
+       public static class CompilerServices
+       {
+               /// <summary>
+               /// known types cache, prevent rewalking all the assemblies of the domain
+               /// the key is the type simple name
+               /// </summary>
+               internal static Dictionary<string, Type> knownTypes = new Dictionary<string, Type> ();
+               /// <summary>
+               /// known extension methods.
+               /// key is type dot memberName.
+               /// </summary>
+               internal static Dictionary<string, MethodInfo> knownExtMethods = new Dictionary<string, MethodInfo> ();
+
+               internal static MethodInfo stringEquals = typeof (string).GetMethod("Equals", new Type [3] { typeof (string), typeof (string), typeof (StringComparison) });
+               internal static MethodInfo miObjToString = typeof(object).GetMethod("ToString");
+               internal static MethodInfo miGetType = typeof(object).GetMethod("GetType");
+               internal static MethodInfo miParseEnum = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
+                       Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null);
+
+               internal static MethodInfo miGetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
+               internal static MethodInfo miGetEvent = typeof(Type).GetMethod("GetEvent", new Type[] {typeof(string)});
+
+               internal static MethodInfo miMIInvoke = typeof(MethodInfo).GetMethod ("Invoke", new Type[] {
+                       typeof(object),
+                       typeof(object[])
+               });
+
+               internal static MethodInfo miCreateBoundDel = typeof(Delegate).GetMethod ("CreateDelegate", new Type[] { typeof(Type), typeof(object), typeof(MethodInfo) });//create bound delegate
+               internal static MethodInfo miGetColCount = typeof(System.Collections.ICollection).GetProperty("Count").GetGetMethod();
+               internal static MethodInfo miGetDelegateListItem = typeof(List<Delegate>).GetMethod("get_Item", new Type[] { typeof(Int32) });
+
+               internal static MethodInfo miCompileDynEventHandler = typeof(CompilerServices).GetMethod ("compileDynEventHandler", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miRemEvtHdlByName = typeof(CompilerServices).GetMethod("removeEventHandlerByName", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miRemEvtHdlByTarget = typeof(CompilerServices).GetMethod("removeEventHandlerByTarget", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miGetMethInfoWithRefx = typeof(CompilerServices).GetMethod ("getMethodInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miGetMembIinfoWithRefx = typeof(CompilerServices).GetMethod("getMemberInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miSetValWithRefx = typeof(CompilerServices).GetMethod("setValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miGetValWithRefx = typeof(CompilerServices).GetMethod("getValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miCreateDel = typeof(CompilerServices).GetMethod ("createDel", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miGetImplOp = typeof(CompilerServices).GetMethod ("getImplicitOp", BindingFlags.Static | BindingFlags.NonPublic);
+               internal static MethodInfo miGetDataTypeAndFetch = typeof(CompilerServices).GetMethod("getDataTypeAndFetch", BindingFlags.Static | BindingFlags.NonPublic);
+
+
+               internal static MethodInfo miGoUpLevels = typeof(CompilerServices).GetMethod("goUpNbLevels", BindingFlags.Static | BindingFlags.NonPublic);
+
+               internal static FieldInfo fiCachedDel = typeof(Instantiator).GetField("cachedDelegates", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static FieldInfo fiTemplateBinding = typeof(Instantiator).GetField("templateBinding", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static MethodInfo miDSChangeEmitHelper = typeof(Instantiator).GetMethod("dataSourceChangedEmitHelper", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static MethodInfo miDSReverseBinding = typeof(Instantiator).GetMethod("dataSourceReverseBinding", BindingFlags.Static | BindingFlags.NonPublic);
+
+               internal static FieldInfo miSetCurIface = typeof(Widget).GetField ("IFace", BindingFlags.Public | BindingFlags.Instance);
+               internal static MethodInfo miFindByName = typeof (Widget).GetMethod ("FindByName");
+               internal static MethodInfo miGetGObjItem = typeof(List<Widget>).GetMethod("get_Item", new Type[] { typeof(Int32) });
+               internal static MethodInfo miLoadDefaultVals = typeof (Widget).GetMethod ("loadDefaultValues");
+               internal static PropertyInfo piStyle = typeof (Widget).GetProperty ("Style");
+               internal static MethodInfo miGetLogicalParent = typeof(Widget).GetProperty("LogicalParent").GetGetMethod();
+               internal static MethodInfo miGetDataSource = typeof(Widget).GetProperty("DataSource").GetGetMethod ();
+               internal static EventInfo eiLogicalParentChanged = typeof(Widget).GetEvent("LogicalParentChanged");
+
+               internal static MethodInfo miIFaceLoad = typeof(Interface).GetMethod ("CreateInstance", BindingFlags.Instance | BindingFlags.Public);
+               internal static MethodInfo miIFaceCreateTemplateInst = typeof (Interface).GetMethod ("CreateTemplateInstance", BindingFlags.Instance | BindingFlags.Public);
+               internal static MethodInfo miGetITemp = typeof(Interface).GetMethod ("GetItemTemplate", BindingFlags.Instance | BindingFlags.Public);
+
+               internal static MethodInfo miAddITemp = typeof(Dictionary<string, ItemTemplate>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) });
+               internal static MethodInfo miGetITempFromDic = typeof(Dictionary<string, ItemTemplate>).GetMethod ("get_Item", new Type[] { typeof(string) });
+               internal static FieldInfo fldItemTemplates = typeof(TemplatedGroup).GetField("ItemTemplates");
+               internal static MethodInfo miLoadPage = typeof(TemplatedGroup).GetMethod ("loadPage", BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public);
+               internal static MethodInfo miIsAlreadyExpanded = typeof(TemplatedGroup).GetMethod("emitHelperIsAlreadyExpanded", BindingFlags.Instance | BindingFlags.NonPublic);
+               
+               internal static MethodInfo miCreateExpDel = typeof(ItemTemplate).GetMethod ("CreateExpandDelegate");
+               internal static FieldInfo fiFetchMethodName = typeof(ItemTemplate).GetField("fetchMethodName", BindingFlags.Instance | BindingFlags.NonPublic);
+
+               #if DESIGN_MODE
+               internal static MethodInfo miDicStrStrAdd = typeof(Dictionary<string, string>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(string) });
+               #endif
+
+               #region tree handling methods
+               internal static FieldInfo fiChild = typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static MethodInfo miSetChild = typeof (Container).GetMethod ("SetChild");
+               internal static MethodInfo miAddChild = typeof (Group).GetMethod ("AddChild");
+               internal static FieldInfo fiChildren = typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static MethodInfo miLoadTmp = typeof (TemplatedControl).GetMethod ("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic);
+               internal static PropertyInfo piContent = typeof(TemplatedContainer).GetProperty ("Content");
+               internal static MethodInfo miAddItem = typeof (TemplatedGroup).GetMethod ("AddItem", BindingFlags.Instance | BindingFlags.Public);
+               internal static MethodInfo miGetItems = typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ();
+               #endregion
+
+               #region ValueChange & DSChange Reflexion member info
+               internal static EventInfo eiValueChange = typeof (IValueChange).GetEvent ("ValueChanged");
+               internal static MethodInfo miInvokeValueChange = eiValueChange.EventHandlerType.GetMethod ("Invoke");
+               internal static Type [] argsBoundValueChange = { typeof (object), typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
+               internal static Type [] argsValueChange = { typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
+               internal static FieldInfo fiVCNewValue = typeof (ValueChangeEventArgs).GetField ("NewValue");
+               internal static FieldInfo fiVCMbName = typeof (ValueChangeEventArgs).GetField ("MemberName");
+
+               internal static EventInfo eiDSChange = typeof (Widget).GetEvent ("DataSourceChanged");
+               internal static MethodInfo miInvokeDSChange = eiDSChange.EventHandlerType.GetMethod ("Invoke");
+               internal static Type [] argsBoundDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType };
+               internal static FieldInfo fiDSCNewDS = typeof (DataSourceChangeEventArgs).GetField ("NewDataSource");
+               internal static FieldInfo fiDSCOldDS = typeof (DataSourceChangeEventArgs).GetField ("OldDataSource");
+               internal static Type ehTypeDSChange = eiDSChange.EventHandlerType;
+               #endregion
+
+               /// <summary>
+               /// Loc0 is the current graphic object and arg2 of loader is the current interface
+               /// </summary>
+               /// <param name="il">Il.</param>
+               public static void emitSetCurInterface(ILGenerator il){
+                       il.Emit (OpCodes.Ldloc_0);
+                       il.Emit (OpCodes.Ldarg_1);
+                       il.Emit (OpCodes.Stfld, miSetCurIface);
+               }
+
+               public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
+                       il.Emit (OpCodes.Ldloc_0);
+
+                       if (val == null) {
+                               il.Emit (OpCodes.Ldnull);
+                               il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+                               return;
+                       }
+                       Type dvType = val.GetType ();
+
+            if (dvType.IsValueType) {
+                               if (pi.PropertyType.IsValueType) {
+                    if (pi.PropertyType.IsEnum) {
+                                               if (pi.PropertyType != dvType)
+                                                       throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName);
+                                               il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+                                       } else {
+                                               switch (Type.GetTypeCode (dvType)) {
+                                               case TypeCode.Boolean:
+                                                       if ((bool)val == true)
+                                                               il.Emit (OpCodes.Ldc_I4_1);
+                                                       else
+                                                               il.Emit (OpCodes.Ldc_I4_0);
+                                                       break;
+//                                             case TypeCode.Empty:
+//                                                     break;
+//                                             case TypeCode.Object:
+//                                                     break;
+//                                             case TypeCode.DBNull:
+//                                                     break;
+//                                             case TypeCode.SByte:
+//                                                     break;
+//                                             case TypeCode.Decimal:
+//                                                     break;
+//                                             case TypeCode.DateTime:
+//                                                     break;
+                                               case TypeCode.Char:
+                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToChar (val));
+                                                       break;
+                                               case TypeCode.Byte:
+                                               case TypeCode.Int16:
+                                               case TypeCode.Int32:
+                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+                                                       break;
+                                               case TypeCode.UInt16:
+                                               case TypeCode.UInt32:
+                                                       il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (val));
+                                                       break;
+                                               case TypeCode.Int64:
+                                                       il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (val));
+                                                       break;
+                                               case TypeCode.UInt64:
+                                                       il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (val));
+                                                       break;
+                                               case TypeCode.Single:
+                                                       il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (val));
+                                                       break;
+                                               case TypeCode.Double:
+                                                       il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (val));
+                                                       break;
+                                               case TypeCode.String:
+                                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+                                                       break;
+                                               default:
+                                                       il.Emit (OpCodes.Pop);
+                                                       return;
+                                               }
+                                       }
+                               } else
+                                       throw new Exception ("Expecting valuetype in default values for: " + pi.Name);
+                       }else{
+                               //surely a class or struct
+                               if (dvType != typeof(string))
+                                       throw new Exception ("Expecting String in default values for: " + pi.Name);
+                               if (pi.PropertyType == typeof(string))
+                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+                               else if (pi.PropertyType.IsEnum) {
+                                       //load type of enum
+                                       il.Emit(OpCodes.Ldtoken, pi.PropertyType);
+                                       il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                                       //load enum value name
+                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:implement here string format?
+                                       //load false
+                                       il.Emit (OpCodes.Ldc_I4_0);
+                                       il.Emit (OpCodes.Call, CompilerServices.miParseEnum);
+
+                                       if (CompilerServices.miParseEnum.ReturnType != pi.PropertyType)
+                                               il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+                               } else {
+                                       MethodInfo miParse = pi.PropertyType.GetMethod
+                                               ("Parse", BindingFlags.Static | BindingFlags.Public,
+                                                       Type.DefaultBinder, new Type [] {typeof (string)},null);
+                                       if (miParse == null)
+                                               throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName);
+
+                                       il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
+                                       il.Emit (OpCodes.Call, miParse);
+
+                                       if (miParse.ReturnType != pi.PropertyType)
+                                               il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+                               }
+                       }
+            il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+               }
+
+               #region conversions
+
+               internal static MethodInfo GetConvertMethod (Type targetType)
+               {
+                       string name;
+
+                       if (targetType == typeof (bool))
+                               name = "ToBoolean";
+                       else if (targetType == typeof (byte))
+                               name = "ToByte";
+                       else if (targetType == typeof (short))
+                               name = "ToInt16";
+                       else if (targetType == typeof (int))
+                               name = "ToInt32";
+                       else if (targetType == typeof (uint))
+                               name = "ToUInt32";
+                       else if (targetType == typeof (long))
+                               name = "ToInt64";
+                       else if (targetType == typeof (double))
+                               name = "ToDouble";
+                       else if (targetType == typeof (float))
+                               name = "ToSingle";
+                       else if (targetType == typeof (string))
+                               return typeof (object).GetMethod ("ToString", Type.EmptyTypes);
+                       else //try to find implicit convertion
+                               throw new NotImplementedException (string.Format ("Conversion to {0} is not implemented.", targetType.Name));
+
+                       return typeof (Convert).GetMethod (name, BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object) }, null);
+               }
+               #endregion
+
+               #region Reflexion helpers
+               static MemberInfo getMemberInfoWithReflexion(object instance, string member){
+            Type t = instance.GetType();
+#if DEBUG_BINDING_FUNC_CALLS
+                       Console.WriteLine ($"getMemberInfoWithReflexion ({instance},{member}); type:{t}");
+#endif
+            MemberInfo mi = t.GetMember (member)?.FirstOrDefault();
+                       if (mi == null)
+                               mi = CompilerServices.SearchExtMethod (t, member);
+                       return mi;
+               }
+               static MethodInfo getMethodInfoWithReflexion(object instance, string method){
+#if DEBUG_BINDING_FUNC_CALLS
+            Console.WriteLine ($"getMethodInfoWithReflexion ({instance},{method}); type:{instance.GetType ()}");
+#endif
+            return instance.GetType ().GetMethod (method, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+               }
+               /// <summary>
+               /// set value, convert if required
+               /// </summary>
+               /// <param name="dest">Destination instance</param>
+               /// <param name="value">Value</param>
+               /// <param name="destMember">Destination member</param>
+               static void setValueWithReflexion(object dest, object value, string destMember){
+#if DEBUG_BINDING_FUNC_CALLS
+            Console.WriteLine ($"setValueWithReflexion (dest:{dest},value:{value},member:{destMember});");
+#endif
+            Type destType = null;
+                       Type origType = null;
+                       object convertedVal = null;
+
+                       MemberInfo miDest = getMemberInfoWithReflexion (dest, destMember);
+
+                       if (miDest == null) {
+                               Debug.WriteLine ("Reverse template binding error: " + destMember + " not found in " + dest);
+                               return;
+                       }
+
+                       destType = CompilerServices.GetMemberInfoType (miDest);
+
+                       try {
+                               if (value != null) {
+                                       if (destType == typeof (object))//TODO: check that test of destType is not causing problems
+                                               convertedVal = value;
+                                       else {
+                                               origType = value.GetType ();
+                                               if (destType.IsAssignableFrom (origType))
+                                                       convertedVal = Convert.ChangeType (value, destType);
+                                               else if (origType == typeof(string) & destType.IsPrimitive)
+                                                       convertedVal = Convert.ChangeType(value, destType);
+                                               else if (origType.IsPrimitive & destType.IsPrimitive)
+                                                       convertedVal = GetConvertMethod (destType).Invoke (null, new Object[] { value });
+                                               else
+                                                       convertedVal = getImplicitOp (origType, destType).Invoke (value, null);
+                                       }
+                               }
+                       } catch (Exception ex) {
+                               Debug.WriteLine (ex.ToString ());
+                               return;
+                       }
+
+                       if (miDest.MemberType == MemberTypes.Property)
+                               (miDest as PropertyInfo).SetValue (dest, convertedVal);
+                       else if (miDest.MemberType == MemberTypes.Field)
+                               (miDest as FieldInfo).SetValue (dest, convertedVal);
+               }
+               /// <summary>
+               /// Gets value with reflexion, return empty string ("") for string and object and return
+               /// default value for valueType data.
+               /// </summary>
+               static object getValueWithReflexion(object instance, MemberInfo mi){
+#if DEBUG_BINDING_FUNC_CALLS
+            Console.WriteLine ($"getValueWithReflexion ({instance},{mi});");
+#endif
+            object tmp = null;
+                       Type dstType = null;
+                       if (mi == null)
+                               return null;
+                       try {
+                               if (mi.MemberType == MemberTypes.Property) {
+                                       PropertyInfo pi = mi as PropertyInfo;
+                                       tmp = pi.GetValue (instance);
+                                       dstType = pi.PropertyType;
+                               }else if (mi.MemberType == MemberTypes.Field) {
+                                       FieldInfo fi = mi as FieldInfo;
+                                       tmp = fi.GetValue (instance);
+                                       dstType = fi.FieldType;
+                               }else if (mi.MemberType == MemberTypes.Method) {
+                                       MethodInfo gi = mi as MethodInfo;
+                                       if (gi.IsStatic)
+                                               tmp = gi.Invoke(null, new object[] {instance});
+                                       else
+                                               tmp = gi.Invoke(instance, null);
+                                       dstType = gi.ReturnType;
+                               }
+                               if (tmp != null)
+                                       return tmp;
+                               if (dstType == typeof(string) || dstType == typeof (object))//TODO:object should be allowed to return null and not ""
+                                       return "";
+                               if (dstType.IsValueType)
+                                       return Activator.CreateInstance (dstType);                              
+                       } catch (Exception ex) {
+                               Debug.WriteLine (ex.ToString ());
+                               return "";
+                       }
+
+                       return null;
+               }
+               internal static MethodInfo SearchExtMethod (Type t, string methodName)
+               {
+                       string key = t.Name + "." + methodName;
+                       if (knownExtMethods.ContainsKey (key))
+                               return knownExtMethods [key];
+
+                       //Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}");
+
+                       MethodInfo mi = null;
+                       mi = GetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName);
+                       if (mi == null)
+                               mi = GetExtensionMethods (t.Module.Assembly, t, methodName);
+
+                       //add key even if mi is null to prevent searching again and again for propertyless bindings
+                       knownExtMethods.Add (key, mi);
+                       return mi;
+               }
+
+               public static MethodInfo GetExtensionMethods (Assembly assembly, Type extendedType, string methodName)
+               {
+                       foreach (Type t in assembly.GetTypes ().Where
+                                       (ty => ty.IsDefined (typeof (ExtensionAttribute), false))) {
+                               foreach (MethodInfo mi in t.GetMethods 
+                                       (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where
+                                               (m=> m.Name == methodName && m.IsDefined (typeof (ExtensionAttribute), false) &&
+                                                m.GetParameters ().Length == 1)) {
+                                       Type curType = extendedType;
+                                       while (curType != null) {
+                                               if (mi.GetParameters () [0].ParameterType == curType)
+                                                       return mi;
+                                               curType = curType.BaseType;
+                                       }                                               
+                               }
+                       
+                       }
+                       return null;
+               }
+               /// <summary>
+               /// retrieve event handler in class or ancestors
+               /// </summary>
+               static FieldInfo getEventHandlerField (Type type, string eventName)
+               {
+                       FieldInfo fi;
+                       Type ty = type;
+                       do {
+                               fi = ty.GetField (eventName,
+                                       BindingFlags.NonPublic |
+                                       BindingFlags.Instance |
+                                       BindingFlags.GetField);
+                               ty = ty.BaseType;
+                               if (ty == null)
+                                       break;
+                       } while (fi == null);
+                       return fi;
+               }
+               /// <summary>
+               /// search for an implicit conversion method in origine or destination classes
+               /// </summary>
+               static MethodInfo getImplicitOp(Type origType, Type dstType){
+                       foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+                               if (mi.Name == "op_Implicit") {
+                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+                                               return mi;
+                               }
+                       }
+                       foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+                               if (mi.Name == "op_Implicit") {
+                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+                                               return mi;
+                               }
+                       }
+                       return null;
+               }
+               #endregion
+
+               /// <summary>
+               /// Emits tree parsing command to fetch dest instance starting from orig node
+               /// </summary>
+               internal static void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){
+                       int ptr = 0;
+                       while (orig [ptr] == dest [ptr]) {
+                               ptr++;
+                               if (ptr == orig.Count || ptr == dest.Count)
+                                       break;
+                       }
+                       for (int i = 0; i < orig.Count - ptr; i++)
+                               il.Emit (OpCodes.Callvirt, CompilerServices.miGetLogicalParent);
+                       while (ptr < dest.Count) {
+                               emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index);
+                               ptr++;
+                       }
+               }
+               /// <summary>
+               /// Emits tree parsing commands to get child starting at root node
+               /// </summary>
+               /// <param name="il">MSIL generator</param>
+               /// <param name="dest">Absolute Node Address of the instance to get</param>
+               internal static void emitGetInstance (ILGenerator il, NodeAddress dest){
+                       if (dest == null)
+                               return;
+                       for (int i = 0; i < dest.Count - 1; i++)
+                               emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
+               }
+               /// <summary>
+               /// Emits msil to fetch chil instance of current GraphicObject on the stack
+               /// </summary>
+               /// <param name="il">Il generator</param>
+               /// <param name="parentType">Parent type</param>
+               /// <param name="index">Index of child, -1 for template root</param>
+               internal static void emitGetChild(ILGenerator il, Type parentType, int index){
+                       if (typeof (Group).IsAssignableFrom (parentType)) {
+                               il.Emit (OpCodes.Ldfld, fiChildren);
+                               il.Emit(OpCodes.Ldc_I4, index);
+                               il.Emit (OpCodes.Callvirt, miGetGObjItem);
+                               return;
+                       }
+                       if (typeof(Container).IsAssignableFrom (parentType) || index < 0) {
+                               il.Emit (OpCodes.Ldfld, fiChild);
+                               return;
+                       }
+                       if (typeof(TemplatedContainer).IsAssignableFrom (parentType)) {
+                               il.Emit (OpCodes.Callvirt, piContent.GetGetMethod());
+                               return;
+                       }
+                       if (typeof(TemplatedGroup).IsAssignableFrom (parentType)) {
+                               il.Emit (OpCodes.Callvirt, miGetItems);
+                               il.Emit(OpCodes.Ldc_I4, index);
+                               il.Emit (OpCodes.Callvirt, miGetGObjItem);
+                               return;
+                       }
+               }
+
+               /// <summary>
+               /// Emit MSIL for conversion from orig type to dest type
+               /// </summary>
+               internal static void emitConvert(ILGenerator il, Type origType, Type destType){
+                       if (destType == typeof(object))
+                               return;
+                       if (destType == typeof (string)) {
+                               System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
+                               System.Reflection.Emit.Label endConvert = il.DefineLabel ();
+                               il.Emit (OpCodes.Dup);
+                               il.Emit (OpCodes.Brfalse, emitNullStr);
+                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+                               il.Emit (OpCodes.Br, endConvert);
+                               il.MarkLabel (emitNullStr);
+                               il.Emit (OpCodes.Pop);//remove null string from stack
+                               il.Emit (OpCodes.Ldstr, "");//replace with empty string
+                               il.MarkLabel (endConvert);
+                       } else if ((origType.IsEnum || origType == typeof (Enum)) && destType.IsEnum) {//TODO:double check this (multiple IsEnum test, no check of enum underlying type
+                               il.Emit (OpCodes.Unbox_Any, destType);
+                               return;
+                       } else if (origType.IsValueType) {
+                               if (destType != origType) {
+                                       MethodInfo miIO = getImplicitOp (origType, destType);
+                                       if (miIO != null) {
+                                               System.Reflection.Emit.Label emitCreateDefault = il.DefineLabel ();
+                                               System.Reflection.Emit.Label emitContinue = il.DefineLabel ();
+                                               LocalBuilder lbStruct = il.DeclareLocal (origType);
+                                               il.Emit (OpCodes.Dup);
+                                               il.Emit (OpCodes.Brfalse, emitCreateDefault);
+                                               il.Emit (OpCodes.Unbox_Any, origType);
+                                               il.Emit (OpCodes.Br, emitContinue);
+                                               il.MarkLabel (emitCreateDefault);
+                                               il.Emit (OpCodes.Pop);//pop null value
+                                               il.Emit (OpCodes.Ldloca, lbStruct);
+                                               il.Emit (OpCodes.Initobj, origType);
+                                               il.Emit (OpCodes.Ldloc, lbStruct);
+                                               il.MarkLabel (emitContinue);
+                                               il.Emit (OpCodes.Call, miIO);
+                                       } else {
+                                               MethodInfo miconv = CompilerServices.GetConvertMethod (destType);
+                                               if (miconv.IsStatic)
+                                                       il.Emit (OpCodes.Call, miconv);
+                                               else
+                                                       il.Emit (OpCodes.Callvirt, miconv);
+                                       }
+                               } else
+                                       il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+                       } else {
+                               if (destType.IsAssignableFrom (origType))
+                                       il.Emit (OpCodes.Castclass, destType);
+                               else {
+                                       if (origType == typeof (string)) {
+                                               //search dest type for parse method
+                                               MethodInfo miParse = destType.GetMethod
+                                                                                               ("Parse", BindingFlags.Static | BindingFlags.Public,
+                                                                                                       Type.DefaultBinder, new Type [] { typeof (string) }, null);
+                                               if (miParse == null)
+                                                       throw new Exception ("no Parse method found for: " + destType.FullName);
+                                               il.Emit (OpCodes.Call, miParse);
+                                       }
+                                       //implicit conversion can't be defined from or to object base class,
+                                       //so we will check if object underlying type is one of the implicit converter of destType
+                                       else if (origType == typeof (object)) {//test all implicit converter to destType on obj
+                                               System.Reflection.Emit.Label emitTestNextImpOp;
+                                               System.Reflection.Emit.Label emitImpOpFound = il.DefineLabel ();
+                                               foreach (MethodInfo mi in destType.GetMethods (BindingFlags.Public | BindingFlags.Static)) {
+                                                       if (mi.Name == "op_Implicit") {
+                                                               if (mi.GetParameters () [0].ParameterType == destType)
+                                                                       continue;
+                                                               emitTestNextImpOp = il.DefineLabel ();
+                                                               il.Emit (OpCodes.Dup);
+                                                               il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
+                                                               il.Emit (OpCodes.Brfalse, emitTestNextImpOp);
+                                                               if (mi.GetParameters () [0].ParameterType.IsValueType)
+                                                                       il.Emit (OpCodes.Unbox_Any, mi.GetParameters () [0].ParameterType);
+                                                               else
+                                                                       il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
+
+                                                               il.Emit (OpCodes.Call, mi);
+                                                               il.Emit (OpCodes.Br, emitImpOpFound);
+
+                                                               il.MarkLabel (emitTestNextImpOp);
+                                                       }
+                                               }
+                                               //il.Emit (OpCodes.Br, emitImpOpNotFound);
+                                               il.MarkLabel (emitImpOpFound);
+                                       } else {//search both orig and dest types for implicit operators
+                                               MethodInfo miIO = getImplicitOp (origType, destType);
+                                               if (miIO != null)
+                                                       il.Emit (OpCodes.Call, miIO);
+                                       }
+                               }
+                       }
+               }
+               internal static bool isValueType (object obj) => obj.GetType ().IsValueType;
+               /// <summary>
+               /// check type of current object on the stack and convert to dest type,
+               /// use loc_0 so store it as object!!!
+               /// </summary>
+               internal static void emitConvert(ILGenerator il, Type dstType){
+                       System.Reflection.Emit.Label endConvert = il.DefineLabel ();
+                       System.Reflection.Emit.Label convert = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Dup);
+                       il.Emit (OpCodes.Isinst, dstType);
+                       il.Emit (OpCodes.Brfalse, convert);
+
+                       if (dstType.IsValueType)
+                               il.Emit (OpCodes.Unbox_Any, dstType);
+                       else
+                               il.Emit (OpCodes.Isinst, dstType);
+                       il.Emit (OpCodes.Br, endConvert);
+
+                       il.MarkLabel (convert);
+
+                       if (dstType == typeof (string)) {
+                               System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
+                               il.Emit (OpCodes.Dup);
+                               il.Emit (OpCodes.Brfalse, emitNullStr);
+                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+                               il.Emit (OpCodes.Br, endConvert);
+                               il.MarkLabel (emitNullStr);
+                               il.Emit (OpCodes.Pop);//remove null string from stack
+                               il.Emit (OpCodes.Ldstr, "");//replace with empty string
+                       } else if (dstType.IsPrimitive) {
+                               //il.Emit (OpCodes.Unbox_Any, dstType);
+                               MethodInfo miconv = CompilerServices.GetConvertMethod (dstType);
+                               if (miconv.IsStatic)
+                                       il.Emit (OpCodes.Call, miconv);
+                               else
+                                       il.Emit (OpCodes.Callvirt, miconv);
+                       }else if (dstType.IsValueType) {
+                               System.Reflection.Emit.Label endConvert2 = il.DefineLabel ();
+                               il.Emit (OpCodes.Dup);
+                               il.Emit (OpCodes.Call, typeof (CompilerServices).GetMethod ("isValueType", BindingFlags.Static | BindingFlags.NonPublic));
+                               System.Reflection.Emit.Label convertToValueType = il.DefineLabel ();
+                               il.Emit (OpCodes.Brfalse, convertToValueType);
+
+                               il.Emit (OpCodes.Unbox_Any, dstType);
+                               il.Emit (OpCodes.Br, endConvert);
+
+                               il.MarkLabel (convertToValueType);
+                               //il.EmitWriteLine ($"convertToValueType:{dstType}");
+
+                               //check if null
+                               il.Emit (OpCodes.Dup);
+                               LocalBuilder lbOrig = il.DeclareLocal (typeof (object));
+                               LocalBuilder lbMI = il.DeclareLocal (typeof (MethodInfo));
+                               il.Emit (OpCodes.Stloc, lbOrig);
+                               il.Emit (OpCodes.Ldloc, lbOrig);
+
+                               //il.Emit (OpCodes.Ldloc, lbOrig);
+                               //il.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (object) }));
+                               il.Emit (OpCodes.Brfalse, endConvert2);
+                               //il.EmitWriteLine ($"search for implOp:{dstType}");
+                               il.Emit (OpCodes.Ldloc, lbOrig);
+                               il.Emit (OpCodes.Callvirt, miGetType);
+                               il.Emit (OpCodes.Ldtoken, dstType);//push destination property type for testing
+                               il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                               il.Emit (OpCodes.Call, miGetImplOp);
+                               il.Emit (OpCodes.Stloc, lbMI);
+                               il.Emit (OpCodes.Ldloc, lbMI);
+                               convert = il.DefineLabel ();
+                               il.Emit (OpCodes.Brtrue, convert);
+                               //il.Emit (OpCodes.Ldloc, lbOrig);
+                               il.Emit (OpCodes.Isinst, dstType);
+                               il.Emit (OpCodes.Br, endConvert2);
+
+                               il.MarkLabel (convert);
+                               //il.EmitWriteLine ($"implOp found, calling:{dstType}");
+                               il.Emit (OpCodes.Pop);
+                               il.Emit (OpCodes.Ldloc, lbMI);
+                               il.Emit (OpCodes.Ldnull);//null instance for invoke
+                               il.Emit (OpCodes.Ldc_I4_1);
+                               il.Emit (OpCodes.Newarr, typeof (object));
+                               il.Emit (OpCodes.Dup);//duplicate the array ref
+                               il.Emit (OpCodes.Ldc_I4_0);//push the index 0
+                               il.Emit (OpCodes.Ldloc, lbOrig);//push the orig value to convert
+                               il.Emit (OpCodes.Stelem, typeof (object));//set the array element at index 0
+                               il.Emit (OpCodes.Callvirt, miMIInvoke);
+                               il.MarkLabel (endConvert2);
+                               il.Emit (OpCodes.Unbox_Any, dstType);
+                       } else{
+                               LocalBuilder lbOrig = il.DeclareLocal (typeof (object));
+                               il.Emit (OpCodes.Stloc, lbOrig); //save orig value in loc0
+                               //first check if not null
+                               il.Emit (OpCodes.Ldloc, lbOrig);
+                               il.Emit (OpCodes.Dup);
+                               il.Emit (OpCodes.Brfalse, endConvert);
+                               il.Emit (OpCodes.Callvirt, miGetType);
+                               il.Emit (OpCodes.Ldtoken, dstType);//push destination property type for testing
+                               il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                               il.Emit (OpCodes.Call, miGetImplOp);
+                               il.Emit (OpCodes.Dup);
+                               convert = il.DefineLabel ();
+                               il.Emit (OpCodes.Brtrue, convert);
+                               il.Emit (OpCodes.Pop);
+                               il.Emit (OpCodes.Ldloc, lbOrig);
+                               il.Emit (OpCodes.Isinst, dstType);
+                               il.Emit (OpCodes.Br, endConvert);
+
+                               il.MarkLabel (convert);
+                               il.Emit (OpCodes.Ldnull);//null instance for invoke
+                               il.Emit (OpCodes.Ldc_I4_1);
+                               il.Emit(OpCodes.Newarr, typeof (object));
+                               il.Emit (OpCodes.Dup);//duplicate the array ref
+                               il.Emit (OpCodes.Ldc_I4_0);//push the index 0
+                               il.Emit (OpCodes.Ldloc, lbOrig);//push the orig value to convert
+                               il.Emit (OpCodes.Stelem, typeof (object));//set the array element at index 0
+                               il.Emit (OpCodes.Callvirt, miMIInvoke);
+
+                               //if (dstType.IsValueType)
+                               //      il.Emit (OpCodes.Unbox_Any, dstType);
+
+                       }
+
+                       il.MarkLabel (endConvert);
+               }
+
+               /// <summary>
+               /// Removes delegate from event handler by name
+               /// </summary>
+               static void removeEventHandlerByName(object instance, string eventName, string delegateName){
+                       Type t = instance.GetType ();
+                       FieldInfo fiEvt = getEventHandlerField (t, eventName);
+                       if (fiEvt == null) {
+#if DEBUG_BINDING
+                               Debug.WriteLine ("RemoveHandlerByName: Event '" + eventName + "' not found in " + instance);
+#endif
+                               return;
+                       }
+                       EventInfo eiEvt = t.GetEvent (eventName);
+                       MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
+                       if (multiDel != null) {
+                               foreach (Delegate d in multiDel.GetInvocationList()) {
+                                       if (d.Method.Name == delegateName) {
+                                               eiEvt.RemoveEventHandler (instance, d);
+#if DEBUG_BINDING
+                                               Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
+#endif
+                                       }
+                               }
+                       }
+               }
+               /// <summary>
+               /// Removes delegate from event handler by searching for the object they are bond to
+               /// </summary>
+               static void removeEventHandlerByTarget(object instance, string eventName, object target){
+                       Type t = instance.GetType ();
+                       FieldInfo fiEvt = getEventHandlerField (t, eventName);
+                       EventInfo eiEvt = t.GetEvent (eventName);
+                       MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
+                       if (multiDel != null) {
+                               foreach (Delegate d in multiDel.GetInvocationList()) {
+                                       if (d.Target == target) {
+                                               eiEvt.RemoveEventHandler (instance, d);
+#if DEBUG_BINDING
+                                               Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
+#endif
+                                       }
+                               }
+                       }
+               }
+               /// <summary>
+               /// create delegate helper
+               /// </summary>
+               static Delegate createDel(object instance, Type eventType, string method){
+                       Type t = instance.GetType ();
+                       MethodInfo mi = t.GetMethod (method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+                       if (mi == null) {
+                               Debug.WriteLine ("Handler Method '{0}' not found in '{1}'", method, t);
+                               return null;
+                       }
+                       return Delegate.CreateDelegate (eventType, instance, mi);
+               }
+
+               internal static Delegate compileDynEventHandler(EventInfo sourceEvent, string expression, NodeAddress currentNode = null){
+#if DEBUG_BINDING
+                       Debug.WriteLine ("\tCompile Event {0}: {1}", sourceEvent.Name, expression);
+#endif
+
+                       Type lopType = null;
+
+                       if (currentNode == null)
+                               lopType = sourceEvent.DeclaringType;
+                       else
+                               lopType = currentNode.NodeType;
+
+#region Retrieve EventHandler parameter type
+                       MethodInfo evtInvoke = sourceEvent.EventHandlerType.GetMethod ("Invoke");
+                       ParameterInfo [] evtParams = evtInvoke.GetParameters ();
+                       Type handlerArgsType = evtParams [1].ParameterType;
+#endregion
+
+                       Type [] args = { typeof (object), handlerArgsType };
+                       DynamicMethod dm = new DynamicMethod ("dyn_eventHandler",
+                               typeof(void),
+                               args, true);
+                       ILGenerator il = dm.GetILGenerator (256);
+                       il.Emit (OpCodes.Nop);
+
+                       string [] srcLines = expression.Trim ().Split (new char [] { ';' });
+
+                       foreach (string srcLine in srcLines) {
+                               if (string.IsNullOrEmpty (srcLine))
+                                       continue;
+                               string [] operandes = srcLine.Trim ().Split (new char [] { '=' });
+                               if (operandes.Length != 2) //not an affectation
+                                       throw new NotSupportedException ();
+
+                               System.Reflection.Emit.Label cancel = il.DefineLabel ();
+                               System.Reflection.Emit.Label cancelFinalSet = il.DefineLabel ();
+                               System.Reflection.Emit.Label success = il.DefineLabel ();
+
+                               BindingMember lop = new BindingMember (operandes [0].Trim ());
+                               BindingMember rop = new BindingMember (operandes [1].Trim ());
+
+                               il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
+
+#region Left operande
+                               PropertyInfo lopPI = null;
+
+                               //in dyn handler, no datasource binding, so single name in expression are also handled as current node property
+                               if (lop.IsSingleName)
+                                       lopPI = lopType.GetProperty (lop.Tokens [0]);
+                               else if (lop.IsCurrentNodeProperty)
+                                       lopPI = lopType.GetProperty (lop.Tokens [1]);
+                               else
+                                       lop.emitGetTarget (il, cancel);
+#endregion
+
+#region RIGHT OPERANDES
+                               if (rop.IsStringConstant){
+                                       il.Emit (OpCodes.Ldstr, rop.Tokens[0]);
+                                       lop.emitSetProperty (il);
+                               }else if (rop.IsSingleName && rop.Tokens[0] == "this"){
+                                       il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
+                                       lop.emitSetProperty (il);
+                               }else if (rop.LevelsUp ==0 && !string.IsNullOrEmpty(rop.Tokens[0])) {//parsable constant depending on lop type
+                                       //if left operand is member of current node, it's easy to fetch type, else we should use reflexion in msil
+                                       if (lopPI == null){//accept GraphicObj members, but it's restricive
+                                               //TODO: we should get the parse method by reflexion, or something else
+                                               lopPI = typeof(Widget).GetProperty (lop.Tokens [lop.Tokens.Length-1]);
+                                               if (lopPI == null)
+                                                       throw new NotSupportedException ();
+                                       }
+
+                                       MethodInfo lopParseMi = CompilerServices.miParseEnum;
+                                       if (lopPI.PropertyType.IsEnum){
+                                               //load type of enum
+                                               il.Emit(OpCodes.Ldtoken, lopPI.PropertyType);
+                                               il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                                               //load enum value name
+                                               il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
+                                               //load false
+                                               il.Emit (OpCodes.Ldc_I4_0);
+                                       }else{
+                                               lopParseMi = lopPI.PropertyType.GetMethod ("Parse");
+                                               if (lopParseMi == null)
+                                                       throw new Exception (string.Format
+                                                               ("IML: no static 'Parse' method found in: {0}", lopPI.PropertyType.Name));
+
+                                               il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
+                                       }
+                    if (lopParseMi.IsStatic)
+                                           il.Emit (OpCodes.Call, lopParseMi);
+                    else
+                        il.Emit(OpCodes.Callvirt, lopParseMi);
+                    //il.Emit (OpCodes.Unbox_Any, lopPI.PropertyType);
+                    //emit left operand assignment
+                    il.Emit (OpCodes.Callvirt, lopPI.GetSetMethod());
+                               } else {//tree parsing and propert gets
+                                       il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
+
+                                       rop.emitGetTarget (il, cancelFinalSet);
+                                       rop.emitGetProperty (il, cancelFinalSet);
+                                       lop.emitSetProperty (il);
+                               }
+#endregion
+
+                               il.Emit (OpCodes.Br, success);
+
+                               il.MarkLabel (cancelFinalSet);
+                               il.Emit (OpCodes.Pop);  //pop null MemberInfo on the stack causing cancelation
+                               il.MarkLabel (cancel);
+                               il.Emit (OpCodes.Pop);  //pop null instance on the stack causing cancelation
+                               il.MarkLabel (success);
+                       }
+
+                       il.Emit (OpCodes.Ret);
+
+                       return dm.CreateDelegate (sourceEvent.EventHandlerType);
+               }
+
+               /// <summary>
+               /// MSIL helper, go n levels up
+               /// </summary>
+               /// <returns><c>true</c>, if logical parents are not null</returns>
+               /// <param name="instance">Start Instance</param>
+               /// <param name="levelCount">Levels to go upward</param>
+               internal static ILayoutable goUpNbLevels(ILayoutable instance, int levelCount){
+                       ILayoutable tmp = instance;
+                       int i = 0;
+                       while (tmp != null && i < levelCount) {
+                               tmp = tmp.LogicalParent;
+                               i++;
+                       }
+                       return tmp;
+               }
+               /// <summary>
+               /// Splits expression on semicolon but ignore those between accolades
+               /// </summary>
+               internal static string[] splitOnSemiColumnOutsideAccolades (string expression){
+                       List<String> exps = new List<string>();
+                       int accCount = 0;
+                       int expPtr = 0;
+                       for (int c = 0; c < expression.Length; c++) {
+                               switch (expression[c]){
+                               case '{':
+                                       accCount++;
+                                       break;
+                               case '}':
+                                       accCount--;
+                                       break;
+                               case ';':
+                                       if (accCount > 0)
+                                               break;
+                                       exps.Add(expression.Substring(expPtr, c - expPtr - 1));
+                                       expPtr = c + 1;
+                                       break;
+                               }
+                       }
+                       if (exps.Count == 0)
+                               exps.Add(expression);
+                       return exps.ToArray ();
+               }
+               /// <summary>
+               /// Try to get the type named strDataType, search first in crow assembly then in
+               /// entry assembly.
+               /// </summary>
+               /// <returns>the corresponding type object if found</returns>
+               /// <param name="strDataType">type name</param>
+               internal static Type getTypeFromName (string strDataType){
+                       if (knownTypes.ContainsKey (strDataType))
+                               return knownTypes [strDataType];
+                       Type dataType = Type.GetType(strDataType);
+                       if (dataType != null) {
+                               knownTypes.Add (strDataType, dataType);
+                               return dataType;
+                       }
+                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ()) {
+                               if (a.IsDynamic)
+                                       continue;
+                               foreach (Type expT in a.GetExportedTypes ()) {
+                                       if (expT.Name != strDataType && expT.FullName != strDataType)
+                                               continue;
+                                       if (!knownTypes.ContainsKey(strDataType))
+                                               knownTypes.Add (strDataType, expT);
+                                       return expT;
+                               }
+                       }
+                       knownTypes.Add (strDataType, null);
+                       return null;
+               }
+
+               //get value from member of object
+               internal static object getDataTypeAndFetch (object data, string fetchMethod){
+                       Type dataType = data.GetType();
+                       //Console.WriteLine ($"get data type and fetch {data}.{fetchMethod}");
+                       MethodInfo miGetDatas = dataType.GetMethod (fetchMethod, new Type[] {});
+                       if (miGetDatas == null)
+                               miGetDatas = CompilerServices.SearchExtMethod (dataType, fetchMethod);
+
+                       if (miGetDatas == null) {//in last resort, search among properties
+                               PropertyInfo piDatas = dataType.GetProperty (fetchMethod);
+                               if (piDatas == null) {
+                                       FieldInfo fiDatas = dataType.GetField (fetchMethod);
+                                       if (fiDatas == null)//and among fields
+                                               throw new Exception ("Fetch data member not found in ItemTemplate: " + fetchMethod);
+                                       return fiDatas.GetValue (data);
+                               }
+                               miGetDatas = piDatas.GetGetMethod ();
+                               if (miGetDatas == null)
+                                       throw new Exception ("Read only property for fetching data in ItemTemplate: " + fetchMethod);
+                       }
+                       return miGetDatas.IsStatic ?
+                               miGetDatas.Invoke (null, new object [] { data }) : miGetDatas.Invoke (data, null);
+               }
+               //TODO:memberinfo found here must be cached
+               internal static object getValue (Type dataType, object data, string member)
+               {
+                       //Console.WriteLine ($"get value: {dataType} ; {data} ; {member}");
+
+                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
+                       if (miGetDatas != null)
+                               return miGetDatas.Invoke (data, null);
+                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
+                       if (mbi == null) {
+                               MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member);
+                               if (miExt == null)//and among fields
+                                       throw new Exception ($"member {member} not found in {dataType}");
+                               return miExt.Invoke (null, new object [] { data });
+                       }
+                       if (mbi.MemberType == MemberTypes.Property) {
+                               miGetDatas = (mbi as PropertyInfo)?.GetGetMethod ();
+                               if (miGetDatas == null)
+                                       throw new Exception ($"no getter found for property {member} in {dataType}");
+                               return miGetDatas.Invoke (data, null);
+                       }
+
+                       FieldInfo fi = mbi as FieldInfo;
+                       if (fi == null)
+                               throw new Exception ($"member {member} not found in {dataType}");
+
+                       return fi.GetValue (data);
+               }
+               internal static MemberInfo GetMemberInfo (Type dataType, string member, out Type returnType)
+               {
+                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
+                       if (miGetDatas != null) {
+                               returnType = miGetDatas.ReturnType;
+                               return miGetDatas;
+                       }
+
+                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
+                       if (mbi == null)
+                               miGetDatas = CompilerServices.SearchExtMethod (dataType, member);
+                       else {
+                               if (mbi is FieldInfo) {
+                                       FieldInfo fi = mbi as FieldInfo;
+                                       returnType = fi.FieldType;
+                                       return mbi;
+                               }
+                               if (mbi.MemberType == MemberTypes.Property)
+                                       miGetDatas = (mbi as PropertyInfo).GetGetMethod ();
+                               else
+                                       miGetDatas = mbi as MethodInfo;
+                       }
+                       returnType = miGetDatas?.ReturnType;
+                       return miGetDatas;
+
+               }
+               internal static void emitGetMemberValue (ILGenerator il, Type dataType, MemberInfo mi)
+               {
+                       switch (mi.MemberType) {
+                       case MemberTypes.Method:
+                               MethodInfo mim = mi as MethodInfo;
+                               if (mim.IsStatic)
+                                       il.Emit (OpCodes.Call, mim);
+                               else
+                                       il.Emit (OpCodes.Callvirt, mim);
+                               break;
+                       case MemberTypes.Field:
+                               il.Emit (OpCodes.Ldfld, mi as FieldInfo);
+                               break;
+                       }
+               }
+               //object is already on the stack
+               internal static void emitGetMemberValue (ILGenerator il, Type dataType, string member)
+               {
+                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
+                       if (miGetDatas != null) {
+                               il.Emit (OpCodes.Callvirt, miGetDatas);
+                               return;
+                       }
+                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
+                       if (mbi == null) {
+                               MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member);
+                               if (miExt == null)//and among fields
+                                       throw new Exception ($"member {member} not found in {dataType}");
+                               il.Emit (OpCodes.Call, miExt);
+                               return;
+                       }
+                       if (mbi.MemberType == MemberTypes.Property) {
+                               miGetDatas = (mbi as PropertyInfo)?.GetGetMethod ();
+                               if (miGetDatas == null)
+                                       throw new Exception ($"no getter found for property {member} in {dataType}");
+                               il.Emit (OpCodes.Callvirt, miGetDatas);
+                               return;
+                       }
+
+                       FieldInfo fi = mbi as FieldInfo;
+                       if (fi == null)
+                               throw new Exception ($"member {member} not found in {dataType}");
+
+                       il.Emit (OpCodes.Ldfld, fi);
+               }
+
+               //helper to get member info underlying type.
+               internal static Type GetMemberInfoType (MemberInfo mi) =>
+                               mi.MemberType == MemberTypes.Field ? (mi as FieldInfo).FieldType :
+                               mi.MemberType == MemberTypes.Property ? (mi as PropertyInfo).PropertyType :
+                               mi.MemberType == MemberTypes.Method ? (mi as MethodInfo).ReturnType : null;
+       }
+}
+
index 20ca1ff8033b3590d56e6586a9ecf5b1c957aa4c..760b5b1a8c5a4a8a7accb9768fa0889a55df9696 100644 (file)
@@ -174,6 +174,19 @@ namespace Crow.IML {
                /// </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
@@ -446,7 +459,7 @@ namespace Crow.IML {
                                                ctx.SetDataSourceTypeForCurrentNode(CompilerServices.getTypeFromName (dataSourceType));
                                }
                                ctx.il.Emit (OpCodes.Ldloc_0);
-                ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadDefaultVals);
+                ctx.il.Emit (OpCodes.Call, CompilerServices.miLoadDefaultVals);
 #endregion
 
 
@@ -811,12 +824,12 @@ namespace Crow.IML {
                }
                void emitTemplateBindings(IMLContext ctx, Dictionary<string, List<MemberAddress>> bindings){
                        //value changed dyn method
-                       DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged",
+                       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",
+                       DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged" + NewId,
                                typeof (void),
                                CompilerServices.argsBoundDSChange, true);
                        ILGenerator ilPC = dmPC.GetILGenerator (256);
@@ -1108,6 +1121,10 @@ namespace Crow.IML {
 
                        //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
 
@@ -1199,7 +1216,7 @@ namespace Crow.IML {
 #endregion
                        }
 
-#region emit dataSourceChanged event handler
+                       #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.
@@ -1413,7 +1430,7 @@ namespace Crow.IML {
                        EventHandler<ValueChangeEventArgs> tmp = (EventHandler<ValueChangeEventArgs>)dm.CreateDelegate (typeof (EventHandler<ValueChangeEventArgs>), dest);
                        orig.ValueChanged += tmp;
                }
-#endregion
+               #endregion
 
                /// <summary>
                /// search for graphic object type in crow assembly, if not found,
index a71e4825729d8c642801c38a203202329a819242..5fc2c2fb4c368e5bc0a9a4fc80b2f5a538965de3 100644 (file)
@@ -495,11 +495,11 @@ namespace Crow
                /// <param name="path">path of the iml file to load</param>
                public virtual Widget CreateInstance (string path)
                {
-                       try {
+                       //try {
                                return GetInstantiator (path).CreateInstance ();
-                       } catch (Exception ex) {
-                               throw new Exception ("Error loading <" + path + ">:", ex);
-                       }
+                       //} catch (Exception ex) {
+                       //      throw new Exception ("Error loading <" + path + ">:", ex);
+                       //}
                }
                /// <summary>
                /// Create an instance of a GraphicObject linked to this interface but not added to the GraphicTree
@@ -508,13 +508,13 @@ namespace Crow
                /// <param name="path">path of the iml file to load</param>
                public virtual Widget CreateTemplateInstance (string path, Type declaringType)
                {
-                       try {
+//                     try {
                                if (!Templates.ContainsKey (path))
                                        Templates [path] = new Instantiator (this, GetTemplateStreamFromPath(path, declaringType), path);
                                return Templates [path].CreateInstance ();
-                       } catch (Exception ex) {
-                               throw new Exception ("Error loading Template <" + path + ">:", ex);
-                       }
+                       //} catch (Exception ex) {
+                       //      throw new Exception ("Error loading Template <" + path + ">:", ex);
+                       //}
                }
                /// <summary>
                /// Fetch instantiator from cache or create it.
index c40c670318bcf1f2a66eedb6955198eb41187e4b..c77d66bdd1438b0edccd639bd67dda26ccd88b14 100644 (file)
@@ -1,28 +1,6 @@
-//
-// Measure.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;
 
diff --git a/Crow/src/Picture.cs b/Crow/src/Picture.cs
deleted file mode 100644 (file)
index 2a71d6b..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// Picture.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.IO;
-using Crow.Cairo;
-using System.Collections.Generic;
-
-namespace Crow
-{
-       /// <summary>
-       /// store data and dimensions for resource sharing
-       /// </summary>
-       internal class sharedPicture {
-               //TODO: restructure this whith clever conceptual classes
-               public object Data;
-               public Size Dims;
-               public sharedPicture (object _data, Size _dims){
-                       Data = _data;
-                       Dims = _dims;
-               }
-       }
-       /// <summary>
-       /// virtual class for loading and drawing picture in the interface
-       /// 
-       /// Every loaded resources are stored in a dictonary with their path as key and shared
-       /// among interface elements
-       /// </summary>
-       public abstract class Picture : Fill
-       {
-               /// <summary>
-               /// share a single store for picture resources among usage in different controls
-               /// </summary>
-               internal static Dictionary<string, sharedPicture> sharedResources = new Dictionary<string, sharedPicture>();
-
-               /// <summary>
-               /// path of the picture
-               /// </summary>
-               public string Path;
-               /// <summary>
-               /// unscaled dimensions fetched on loading
-               /// </summary>
-               public Size Dimensions;
-               /// <summary>
-               /// if true and image has to be scalled, it will be scaled in both direction
-               /// equaly
-               /// </summary>
-               public bool KeepProportions = false;
-               /// <summary>
-               /// allow or not the picture to be scalled on request by the painter
-               /// </summary>
-               public bool Scaled = true;
-
-               #region CTOR
-               /// <summary>
-               /// Initializes a new instance of Picture.
-               /// </summary>
-               public Picture ()
-               {
-               }
-               /// <summary>
-               /// Initializes a new instance of Picture by loading the image pointed by the path argument
-               /// </summary>
-               /// <param name="path">image path, may be embedded</param>
-               public Picture (string path)
-               {
-                       Path = path;
-               }
-               #endregion
-
-               #region Image Loading
-               /// <summary>
-               /// load the image for rendering from the stream given as argument
-               /// </summary>
-               /// <param name="stream">picture stream</param>
-               //public abstract void Load(Interface iface, string path);
-               #endregion
-
-               /// <summary>
-               /// abstract method to paint the image in the rectangle given in arguments according
-               /// to the Scale and keepProportion parameters.
-               /// </summary>
-               /// <param name="gr">drawing Backend context</param>
-               /// <param name="rect">bounds of the target surface to paint</param>
-               /// <param name="subPart">used for svg only</param>
-               public abstract void Paint(Context ctx, Rectangle rect, string subPart = "");
-
-               #region Operators
-               public static implicit operator Picture(string path)
-               {
-                       if (string.IsNullOrEmpty (path))
-                               return null;
-                       
-                       Picture _pic = null;
-
-                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) 
-                               _pic = new SvgPicture (path);
-                       else 
-                               _pic = new BmpPicture (path);
-
-                       return _pic;
-               }
-               public static implicit operator string(Picture _pic)
-               {
-                       return _pic == null ? null : _pic.Path;
-               }
-               #endregion
-
-               public static new object Parse(string path)
-               {
-                       if (string.IsNullOrEmpty (path))
-                               return null;
-                       
-                       Picture _pic = null;
-
-                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) 
-                               _pic = new SvgPicture (path);
-                       else 
-                               _pic = new BmpPicture (path);
-
-                       return _pic;
-               }
-               public override string ToString ()
-               {
-                       return Path;
-               }
-       }
-}
-
index 83ae76512aaf08f8297bfb9a97967d1c4820195a..02f12e2fb1b9c051a33c42d3e3383f4e00d4aa5b 100644 (file)
@@ -53,7 +53,7 @@ namespace Crow
                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 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)
index 9db0a184e39a34c14eeb8e5ac16900ac59daa0e8..d70e5b82987a1e3d9a0cb0dc72dec8d36a9a5edd 100644 (file)
@@ -46,7 +46,7 @@ namespace Crow {
                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 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)
diff --git a/Crow/src/SolidColor.cs b/Crow/src/SolidColor.cs
deleted file mode 100644 (file)
index 5c8ebb7..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// SolidColor.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 System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using System.Reflection;
-using System.Diagnostics;
-using Crow.Cairo;
-
-
-
-namespace Crow
-{
-       public class SolidColor : Fill
-    {
-               public Color color = Color.Transparent;
-               #region CTOR
-               public SolidColor(Color c)
-               {
-                       color = c;
-               }
-               #endregion
-
-               #region implemented abstract members of Fill
-
-               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
-               {
-                       ctx.SetSourceRGBA (color.R, color.G, color.B, color.A);
-               }
-               public static new object Parse(string s)
-               {
-                       return new SolidColor((Color)s);
-               }
-               #endregion
-
-               #region Operators
-        public static implicit operator Color(SolidColor c)
-        {
-                       return c.color;
-        }
-               public static implicit operator SolidColor(Color c)
-               {
-                       return new SolidColor (c);
-               }
-               public static bool operator ==(SolidColor left, SolidColor right)
-               {
-                       return left is SolidColor ? right is SolidColor ? true : false :
-                               left.color == right.color ? true : false;
-               }
-               public static bool operator !=(SolidColor left, SolidColor right)
-               {
-                       return left is SolidColor ? right is SolidColor ? false : true :
-                               left.color == right.color ? false : true;
-
-               }
-               public override int GetHashCode ()
-               {
-                       return color.GetHashCode();
-               }
-               public override bool Equals (object obj)
-               {
-                       if (obj is Crow.Color)
-                               return color == (Color)obj;
-                       if (obj is SolidColor)
-                               return color == (obj as SolidColor).color;
-                       return false;                   
-               }
-//             public static bool operator ==(SolidColor c, string n)
-//             {
-//                     return c.color.Name == n ? true : false;
-//             }
-//             public static bool operator !=(SolidColor c, string n)
-//             {
-//                     return c.color.Name == n ? false : true;
-//             }
-//             public static bool operator ==(string n, SolidColor c)
-//             {
-//                     return c.color.Name == n ? true : false;
-//             }
-//             public static bool operator !=(string n, SolidColor c)
-//             {
-//                     return c.color.Name == n ? false : true;
-//             }
-               public static SolidColor operator *(SolidColor c, Double f)
-               {
-                       return new SolidColor(new Color(c.color.R,c.color.G,c.color.B,c.color.A * f));
-               }
-               public static SolidColor operator +(SolidColor c1, SolidColor c2)
-               {
-                       return new SolidColor(new Color(c1.color.R + c2.color.R,c1.color.G + c2.color.G,c1.color.B + c2.color.B,c1.color.A + c2.color.A));
-               }
-               public static SolidColor operator -(SolidColor c1, SolidColor c2)
-               {
-                       return new SolidColor(new Color(c1.color.R - c2.color.R,c1.color.G - c2.color.G,c1.color.B - c2.color.B,c1.color.A - c2.color.A));
-               }
-               #endregion                                      
-
-               public override string ToString()
-               {
-                       return color.ToString ();
-               }
-    }
-}
diff --git a/Crow/src/SvgPicture.cs b/Crow/src/SvgPicture.cs
deleted file mode 100644 (file)
index 33f6895..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// SvgPicture.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.IO;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// Derived from FILL for loading and drawing SVG images in the interface
-       /// </summary>
-       public class SvgPicture : Picture
-       {
-               Rsvg.Handle hSVG;
-
-               #region CTOR
-               /// <summary>
-               /// Initializes a new instance of SvgPicture.
-               /// </summary>
-               public SvgPicture ()
-               {}
-               /// <summary>
-               /// Initializes a new instance of SvgPicture by loading the SVG file pointed by the path argument
-               /// </summary>
-               /// <param name="path">image path, may be embedded</param>
-               public SvgPicture (string path) : base(path)
-               {
-                       Load ();
-               }
-               #endregion
-
-               void Load ()
-               {                       
-                       if (sharedResources.ContainsKey (Path)) {
-                               sharedPicture sp = sharedResources [Path];
-                               hSVG = (Rsvg.Handle)sp.Data;
-                               Dimensions = sp.Dims;
-                               return;
-                       }
-                       using (Stream stream = Interface.StaticGetStreamFromPath (Path)) {
-                               using (MemoryStream ms = new MemoryStream ()) {
-                                       stream.CopyTo (ms);
-
-                                       hSVG = new Rsvg.Handle (ms.ToArray ());
-                                       Dimensions = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height);
-                               }
-                       }
-                       sharedResources [Path] = new sharedPicture (hSVG, Dimensions);
-               }
-
-               public void LoadSvgFragment (string fragment) {                 
-                       hSVG = new Rsvg.Handle (System.Text.Encoding.Unicode.GetBytes(fragment));
-                       Dimensions = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height);
-               }
-
-               #region implemented abstract members of Fill
-
-               public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle))
-               {
-                       float widthRatio = 1f;
-                       float heightRatio = 1f;
-
-                       if (Scaled){
-                               widthRatio = (float)bounds.Width / Dimensions.Width;
-                               heightRatio = (float)bounds.Height / Dimensions.Height;
-                       }
-
-                       if (KeepProportions) {
-                               if (widthRatio < heightRatio)
-                                       heightRatio = widthRatio;
-                               else
-                                       widthRatio = heightRatio;
-                       }
-
-                       using (ImageSurface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) {
-                               using (Context gr = new Context (tmp)) {
-                                       gr.Translate (bounds.Left, bounds.Top);
-                                       gr.Scale (widthRatio, heightRatio);
-                                       gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2);
-
-                                       hSVG.RenderCairo (gr);
-                               }
-                               ctx.SetSource (tmp);
-                       }       
-               }
-               #endregion
-
-               /// <summary>
-               /// paint the image in the rectangle given in arguments according
-               /// to the Scale and keepProportion parameters.
-               /// </summary>
-               /// <param name="gr">drawing Backend context</param>
-               /// <param name="rect">bounds of the target surface to paint</param>
-               /// <param name="subPart">limit rendering to svg part named 'subPart'</param>
-               public override void Paint (Context gr, Rectangle rect, string subPart = "")
-               {
-                       if (hSVG == null)
-                               return;
-                       float widthRatio = 1f;
-                       float heightRatio = 1f;
-
-                       if (Scaled) {
-                               widthRatio = (float)rect.Width / Dimensions.Width;
-                               heightRatio = (float)rect.Height / Dimensions.Height;
-                       }
-                       if (KeepProportions) {
-                               if (widthRatio < heightRatio)
-                                       heightRatio = widthRatio;
-                               else
-                                       widthRatio = heightRatio;
-                       }
-                               
-                       gr.Save ();
-
-                       gr.Translate (rect.Left,rect.Top);
-                       gr.Scale (widthRatio, heightRatio);
-                       gr.Translate (((float)rect.Width/widthRatio - Dimensions.Width)/2f, ((float)rect.Height/heightRatio - Dimensions.Height)/2f);
-
-                       if (string.IsNullOrEmpty (subPart))
-                               hSVG.RenderCairo (gr);
-                       else
-                               hSVG.RenderCairoSub (gr, "#" + subPart);
-                       
-                       gr.Restore ();                  
-               }
-       }
-}
-
index 6db541d6bf34333cbac54e8c2d8da1c9ce24a4ff..b2f6f41867e80591be9820daf3a2a16656da4f56 100644 (file)
@@ -97,6 +97,7 @@ namespace Crow
 
                        Children.Remove(child);
                        child.Parent = null;
+                       child.LogicalParent = null;
 
                        childrenRWLock.ExitWriteLock ();
 
index 54e3e760640f955f47e223797dfa23754b3734fa..da2c1f87e526b0f2475d79d5a83dd739972d99de 100644 (file)
@@ -339,13 +339,13 @@ namespace Crow {
                /// Items loading thread
                /// </summary>
                void loading(){
-                       try {
+                       //try {
                                loadPage (data, items, dataTest);
-                       } catch {
+                       /*} catch (Exception ex) {
                                if (Monitor.IsEntered (IFace.LayoutMutex))
                                        Monitor.Exit (IFace.LayoutMutex);
-                               Console.WriteLine ("loading thread aborted");
-                       }
+                               Console.WriteLine ("loading thread aborted: " + ex.ToString());
+                       }*/
 
                }
 //                     //if (!ItemTemplates.ContainsKey ("default"))
@@ -363,10 +363,13 @@ namespace Crow {
                void cancelLoadingThread(){
                        if (loadingThread == null)
                                return;
-
                        bool updateMx = Monitor.IsEntered (IFace.UpdateMutex);
                        bool layoutMx = Monitor.IsEntered (IFace.LayoutMutex);
 
+#if DEBUG_LOG
+                       DebugLog.AddEvent (DbgEvtType.TGCancelLoadingThread, this);
+#endif
+
                        if (layoutMx)
                                Monitor.Exit (IFace.LayoutMutex);
                        if (updateMx)
index 0ca6598b4e9458a0d5b2d9a61268e638dd9fb847..8596a86f5a677c3c460d522c90019128e6c58659 100644 (file)
@@ -951,7 +951,7 @@ namespace Crow
                                        rootDataLevel = true;
 
                                #if DEBUG_LOG
-                               DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOLockLayouting, this);
+                               DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOLockUpdate, this);
                                #endif
                                lock (IFace.UpdateMutex) {
                                        OnDataSourceChanged (this, dse);
@@ -1156,12 +1156,12 @@ namespace Crow
                        il.Emit(OpCodes.Ret);
                        #endregion
 
-                       try {
+                       //try {
                                IFace.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker));
                                IFace.DefaultValuesLoader[styleKey] (this);
-                       } catch (Exception ex) {
+                       /*} catch (Exception ex) {
                                throw new Exception ("Error applying style <" + styleKey + ">:", ex);
-                       }
+                       }*/
 
                        #if DEBUG_LOG
                        dbgEvt.end = DebugLog.chrono.ElapsedTicks;
@@ -1457,6 +1457,9 @@ namespace Crow
 #endif
                        if (Parent == null)
                                return;
+#if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent (DbgEvtType.GOLockLayouting, this);
+#endif
                        lock (IFace.LayoutMutex) {
                                //prevent queueing same LayoutingType for this
                                layoutType &= (~RegisteredLayoutings);
@@ -1494,6 +1497,9 @@ namespace Crow
                                if (layoutType.HasFlag (LayoutingType.ArrangeChildren))
                                        IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this));
                        }
+#if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+#endif
                }
 
                /// <summary> trigger dependant sizing component update </summary>
@@ -1594,7 +1600,7 @@ namespace Crow
                                        else if (Width == Measure.Stretched)
                                                Slot.Width = Parent.ClientRectangle.Width;
                                        else
-                                               Slot.Width = (int)Math.Round ((double)(Parent.ClientRectangle.Width * Width) / 100.0);
+                                               Slot.Width = (int)Math.Round ((double)(Parent.ClientRectangle.Width * Width) / 100.0);
 
                                        if (Slot.Width < 0)
                                                return false;
index 4ff6082e1c098016819af90b6c6218ab7ee179f7..dad155c7c4bdf68867a08af004b89c82bb038b4d 100644 (file)
@@ -130,7 +130,7 @@ namespace Crow
 
                long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0, visibleTicks = 0;
                int currentLine = -1;
-               int visibleLines;
+               int visibleLines = 1;
 
                public string LogFile {
                        get { return logFile; }
@@ -141,7 +141,6 @@ namespace Crow
 
                                loadDebugFile ();
 
-
                                NotifyValueChanged ("LogFile", logFile);
                                RegisterForGraphicUpdate ();
                        }
@@ -230,8 +229,6 @@ namespace Crow
 
                                        leftMargin = 2.5 + maxNameWidth;
 
-                                       fe = gr.FontExtents;
-
                                        topMargin = 2.0 * fe.Height;
 
                                        updateVisibleLines ();
@@ -241,7 +238,7 @@ namespace Crow
 
                }
                void updateVisibleLines(){
-                       visibleLines = (int)Math.Floor (((double)ClientRectangle.Height - topMargin) / fe.Height);
+                       visibleLines = fe.Height < 1 ? 1 : (int)Math.Floor (((double)ClientRectangle.Height - topMargin) / fe.Height);
                        NotifyValueChanged ("VisibleLines", visibleLines);
                        updateMaxScrollY ();
                }
@@ -280,10 +277,15 @@ namespace Crow
                        get { return base.Font; }
                        set {
                                base.Font = value;
+                               using (Context gr = new Context (IFace.surf)) {
+                                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                                       gr.SetFontSize (Font.Size);
+
+                                       fe = gr.FontExtents;
+                               }
                                loadDebugFile ();
                        }
                }
-
                public override int ScrollY {
                        get {
                                return base.ScrollY;
@@ -359,7 +361,7 @@ namespace Crow
 
                                        Color c = Color.Black;
 
-                                       if (evt.type == DbgEvtType.GOProcessLayouting) {                                                        
+                                       if (evt.type == DbgEvtType.GOProcessLayouting) {
                                                switch (evt.data.result) {
                                                case LayoutingQueueItem.Result.Success:
                                                        c = Crow.Color.Green;
@@ -374,11 +376,13 @@ namespace Crow
                                                        c = Crow.Color.Orange;
                                                        break;
                                                }
-                                       } else if (colors.ContainsKey (evt.type))
+                                       } else if (evt.type.HasFlag (DbgEvtType.GOLock))
+                                               c = Color.BlueViolet;
+                                       else if (colors.ContainsKey (evt.type))
                                                c = colors [evt.type];
-                                       else
-                                               System.Diagnostics.Debugger.Break ();
-
+                                       //else
+                                       //      System.Diagnostics.Debugger.Break ();
+                                       c = c.AdjustAlpha (0.2);
                                        gr.SetSourceColor (c);
 
                                        gr.Rectangle (x, penY, w, fe.Height);
index bfe1948f9bb1e9bd5cc10726e7cccf26ef704d61..37842e22d762362097bc4ed03333616a18240887 100644 (file)
@@ -49,27 +49,34 @@ namespace Crow
                IFaceEndDrawing                                 = 0x0106,
                IFaceUpdate                                             = 0x0107,
                //10 nth bit set for graphic obj
-               GraphicObject                                   = 0x0200,
-               GOClassCreation                                 = 0x0201,
-               GOInitialization                                = 0x0202,
-               GOClippingRegistration                  = 0x0203,
-               GORegisterClip                                  = 0x0204,
-               GORegisterForGraphicUpdate              = 0x0205,
-               GOEnqueueForRepaint                             = 0x0206,
-               GOLayouting                                             = 0x0400,
-               GORegisterLayouting                             = 0x0607,
-               GOProcessLayoutingWithNoParent  = 0x0608,
-               GOProcessLayouting                              = 0x0609,
-               GODraw                                                  = 0x020a,
-               GORecreateCache                                 = 0x020b,
-               GOUpdateCacheAndPaintOnCTX              = 0x020c,
-               GOPaint                                                 = 0x020d,
-               GONewDataSource                                 = 0x020e,
+               GraphicObject                                   = 0x0100,
+               Warning                                                 = 0x4000,
+               Error                                                   = 0x8000,
+               GOClassCreation                                 = GraphicObject | 0x01,
+               GOInitialization                                = GraphicObject | 0x02,
+               GOClippingRegistration                  = GraphicObject | 0x03,
+               GORegisterClip                                  = GraphicObject | 0x04,
+               GORegisterForGraphicUpdate              = GraphicObject | 0x05,
+               GOEnqueueForRepaint                             = GraphicObject | 0x06,
+               GONewDataSource                                 = GraphicObject | 0x07,
+               GOLayouting                                             = 0x0200,
+               Drawing                                                 = 0x0400,
                GOLock                                                  = 0x0800,
-               GOLockUpdate                                    = 0x0a01,
-               GOLockClipping                                  = 0x0a02,
-               GOLockRender                                    = 0x0a03,
-               GOLockLayouting                                 = 0x0a04,
+               TemplatedGroup                                  = 0x1000,
+               GORegisterLayouting                     = GraphicObject | GOLayouting | 0x01,
+               GOProcessLayouting                              = GraphicObject | GOLayouting | 0x02,
+               GOProcessLayoutingWithNoParent  = Warning | GraphicObject | GOLayouting | 0x01,
+               GODraw                                                  = GraphicObject | Drawing | 0x01,
+               GORecreateCache                                 = GraphicObject | Drawing | 0x02,
+               GOUpdateCacheAndPaintOnCTX              = GraphicObject | Drawing | 0x03,
+               GOPaint                                                 = GraphicObject | Drawing | 0x04,
+
+               GOLockUpdate                                    = GraphicObject | GOLock | 0x01,
+               GOLockClipping                                  = GraphicObject | GOLock | 0x02,
+               GOLockRender                                    = GraphicObject | GOLock | 0x03,
+               GOLockLayouting                                 = GraphicObject | GOLock | 0x04,
+
+               TGCancelLoadingThread                   = GraphicObject | TemplatedGroup | 0x01,
        }
 
        /// <summary>
index 448fb4354449b3e267ebab9a6b1d4c6050947e5b..908af2fc64cd8ec414bfb52b93e0b3f892ab3846 100644 (file)
@@ -7,7 +7,8 @@
   </PropertyGroup>
             
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DefineConstants>TRACE;DEBUG;NETFRAMEWORK;NET471</DefineConstants>
+    <DebugType>full</DebugType>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
   </PropertyGroup>
   <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
     <Reference Include="System" />
@@ -22,4 +23,7 @@
       <LogicalName>HelloWorld.%(Filename)%(Extension)</LogicalName>
     </EmbeddedResource>                
   </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Mono.Cecil" Version="0.11.1" />
+  </ItemGroup>
 </Project>
diff --git a/Samples/HelloWorld/ILView.cs b/Samples/HelloWorld/ILView.cs
new file mode 100644 (file)
index 0000000..9bac229
--- /dev/null
@@ -0,0 +1,15 @@
+// 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;
+using Crow;
+
+namespace HelloWorld
+{
+       public class ILView : Widget
+       {
+               public ILView ()
+               {
+               }
+       }
+}
index 14a1a2adcbbfb386f87312e3aba21a3d3cfdaa2e..c407b04e6cf0488e7bd4a1276d337777e3d94946 100644 (file)
@@ -1,5 +1,9 @@
 using System;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
 using Crow;
+using Crow.IML;
 
 namespace HelloWorld
 {
@@ -10,6 +14,7 @@ namespace HelloWorld
                                vke.Run ();
                        }
                }
+               
                protected override void Startup ()
                {
                        CMDQuit = new Command (new Action (() => running = false)) { Caption = "Quit", Icon = new SvgPicture ("#Crow.Icons.exit-symbol.svg") };
@@ -19,6 +24,17 @@ namespace HelloWorld
                        w.DataSource = this;
                }
 
+               public SolidColor testColor = Color.Red;
+               public SolidColor TestColor {
+                       get => testColor;
+                       set {
+                               if (testColor == value)
+                                       return;
+                               testColor = value;
+                               NotifyValueChanged ("TestColor", testColor);
+                       }
+               }
+
                Color [] colors = { Color.Blue, Color.DarkGoldenRod, Color.Red, Color.Azure, Color.Brown, Color.Black, Color.White, Color.Pink };
                int ptr = 0;
 
@@ -37,6 +53,48 @@ namespace HelloWorld
                        if (ptr == colors.Length)
                                ptr = 0;
                }
+               public override bool OnKeyDown (Key key)
+               {
+                       switch (key) {
+                       case Key.d:
+                               dump ();
+                               break;
+                       case Key.space:
+                               TestColor = Color.Green;
+                               break;
+                       default:
+                               return base.OnKeyDown (key);
+                       }
+                       return true;
+               }
+
+               void dump ()
+               {
+                       Instantiator inst = Instantiators ["#HelloWorld.helloworld.crow"];
+
+                       foreach (Delegate cd in inst.CachedDelegates) {
+                               FieldInfo mb = typeof(Delegate).GetField("original_method_info", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
+
+                               DynamicMethod dynMethod = mb.GetValue (cd) as DynamicMethod;
+                               /*Console.WriteLine (typeof (ILGenerator).GetFields (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField));
+
+                               var ilgen = dynMethod.GetILGenerator ();
+                                
+
+
+*/
+
+                               MethodBody body = dynMethod.GetMethodBody ();
+
+                               byte [] il = body.GetILAsByteArray ();
+                               foreach (byte b in il) {
+                                       Console.Write ($"{b:x2} ");
+                                       //Console.WriteLine (b);
+                               }
+
+                       }
+
+               }
 
        }
 }
index d150136e2064a7f0a8535ede48bad60b9b9238fd..1bc9601f3e15e743ad4ff9aaed1ef0a4e1dfa0c5 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0"?>
-
-    <VerticalStack>
-        <Label Text="Hello World" Font="mono, 20"/>
-        <Image Path="#Crow.Icons.crow.svg"/>
-        <CheckBox/>
-    </VerticalStack>
-
-
+<VerticalStack>
+       <TextBox Text="{TestColor}"/>
+       <ColorPicker CurrentColor="{²TestColor}" />
+</VerticalStack>
+<!--<ScrollBar Orientation="Vertical" Height="Stretched" Width="10" />-->
\ No newline at end of file
index d083946c10b4fad49fc9ede1fc179eba32921d7d..4b6c50fbf141f3ff36256b3bfc0230be0e0c2a87 100644 (file)
-<?xml version="1.0"?>
-<Window Caption="Showcase" Height="90%" Width="90%">
-       <HorizontalStack >
+<?xml version="1.0" encoding="UTF-8"?>
+<Window Caption="Showcase" Height="90%" Width="90%" Background="Jet">
+       <HorizontalStack>
                <VerticalStack Width="30%" Margin="5">
                        <GroupBox Caption="Performance" Height="Fit">
-                               <VerticalStack DataSource="{drawingMeasure}" Width="90%" Height="Fit" Spacing="2" >
+                               <VerticalStack DataSource="{drawingMeasure}" Width="90%" Height="Fit" Spacing="2">
                                        <HorizontalStack Height="Fit" Tooltip="Frame per second">
-                                               <Label Text="Fps:" Style="FpsLabel"/>
-                                               <Label Text="{minimum}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Fps:" />
+                                               <Label Style="FpsDisp" Text="{minimum}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit" Tooltip="Minimum Frame per second">
-                                               <Label Text="Min:" Style="FpsLabel"/>
-                                               <Label Text="{fpsMin}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Min:" />
+                                               <Label Style="FpsDisp" Text="{fpsMin}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit" Tooltip="Maximum Frame per second">
-                                               <Label Text="Max:" Style="FpsLabel"/>
-                                               <Label Text="{fpsMax}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Max:" />
+                                               <Label Style="FpsDisp" Text="{fpsMax}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit" Tooltip="Update loop duration">
-                                               <Label Text="Update:" Style="FpsLabel"/>
-                                               <Label Text="{update}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Update:" />
+                                               <Label Style="FpsDisp" Text="{update}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit" Tooltip="Layouting process duration">
-                                               <Label Text="Layouting:" Style="FpsLabel"/>
-                                               <Label Text="{layouting}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Layouting:" />
+                                               <Label Style="FpsDisp" Text="{layouting}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit" Tooltip="Clipping duration">
-                                               <Label Text="Clipping:" Style="FpsLabel"/>
-                                               <Label Text="{clipping}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Clipping:" />
+                                               <Label Style="FpsDisp" Text="{clipping}" />
                                        </HorizontalStack>
                                        <HorizontalStack Height="Fit">
-                                               <Label Text="Drawing:" Style="FpsLabel"/>
-                                               <Label Text="{drawing}" Style="FpsDisp"/>
+                                               <Label Style="FpsLabel" Text="Drawing:" />
+                                               <Label Style="FpsDisp" Text="{drawing}" />
                                        </HorizontalStack>
                                </VerticalStack>
                        </GroupBox>
-                       <Label Width="Stretched" Margin="3" Background="DimGrey"/>
-                       <TextBox Text="TextBox" Multiline="true" Margin="3"/>
+                       <Label Width="Stretched" Margin="3" Background="DimGrey" />
+                       <TextBox Text="TextBox" Multiline="true" Margin="3" />
                        <HorizontalStack Height="Fit" Margin="5" Background="DimGrey" CornerRadius="10">
                                <VerticalStack Spacing="5" Width="50%">
-                                       <CheckBox Fit="true" Caption="test"/>
-                                       <CheckBox Fit="true"/>
-                                       <CheckBox Fit="true"/>
-                                       <CheckBox Fit="true" IsChecked="true"/>
+                                       <CheckBox Fit="true" Caption="test" />
+                                       <CheckBox Fit="true" />
+                                       <CheckBox Fit="true" />
+                                       <CheckBox Fit="true" IsChecked="true" />
                                </VerticalStack>
                                <VerticalStack Spacing="5" Width="50%">
-                                       <RadioButton Fit="true"/>
-                                       <RadioButton Fit="true" IsChecked="true"/>
-                                       <RadioButton Fit="true"/>
-                                       <RadioButton Fit="true"/>
+                                       <RadioButton Fit="true" />
+                                       <RadioButton Fit="true" IsChecked="true" />
+                                       <RadioButton Fit="true" />
+                                       <RadioButton Fit="true" />
                                </VerticalStack>
                        </HorizontalStack>
                        <HorizontalStack Height="Fit" Margin="5">
-                               <Label Text="MouseEvents" Width="50%" Margin="3" Focusable="true"
-                                       Background="Jet"
-                                       Foreground="DimGrey"
-                                       TextAlignment="Center"
-                                       MouseEnter="{Foreground=White}"
-                                       MouseLeave="{Foreground=DimGrey}"
-                                       MouseDown="{Background=DarkRed}"
-                                       MouseClick="{Foreground=Green}"
-                                       MouseDoubleClick="{Foreground=Yellow}"
-                                       MouseUp="{Background=Jet}"/>
-                               <Label Text="MouseEvents" Width="50%" Margin="3"
-                                       Background="Jet"
-                                       Foreground="DimGrey"
-                                       TextAlignment="Center"
-                                       MouseClick="{Foreground=Green}"
-                                       MouseDoubleClick="{Foreground=Yellow}"
-                                       MouseEnter="{Foreground=White}"
-                                       MouseLeave="{Foreground=DimGrey}"
-                                       MouseDown="{Background=SeaGreen}"
-                                       MouseUp="{Background=DimGrey}"/>
+                               <Label Text="MouseEvents" Width="50%" Margin="3" Focusable="true" Background="Jet" Foreground="DimGrey" TextAlignment="Center" MouseEnter="{Foreground=White}" MouseLeave="{Foreground=DimGrey}" MouseDown="{Background=DarkRed}" MouseClick="{Foreground=Green}" MouseDoubleClick="{Foreground=Yellow}" MouseUp="{Background=Jet}" />
+                               <Label Text="MouseEvents" Width="50%" Margin="3" Background="Jet" Foreground="DimGrey" TextAlignment="Center" MouseClick="{Foreground=Green}" MouseDoubleClick="{Foreground=Yellow}" MouseEnter="{Foreground=White}" MouseLeave="{Foreground=DimGrey}" MouseDown="{Background=SeaGreen}" MouseUp="{Background=DimGrey}" />
                        </HorizontalStack>
                        <GroupBox Caption="Templated controls" Height="Fit" Margin="5">
                                <HorizontalStack Height="Fit">
                                        <VerticalStack Width="50%">
-                                               <CheckBox IsChecked="true" Style="CheckBox2"/>
-                                               <CheckBox Style="CheckBox2"/>
-                                               <CheckBox Style="CheckBox2"/>
-                                               <CheckBox Style="CheckBox2"/>
+                                               <CheckBox Style="CheckBox2" IsChecked="true" />
+                                               <CheckBox Style="CheckBox2" />
+                                               <CheckBox Style="CheckBox2" />
+                                               <CheckBox Style="CheckBox2" />
                                        </VerticalStack>
-                                       <Splitter/>
+                                       <Splitter />
                                        <VerticalStack Width="50%">
-                                               <RadioButton Style="RadioButton2"/>
-                                               <RadioButton Style="RadioButton2"/>
-                                               <RadioButton Style="RadioButton2"/>
-                                               <RadioButton Style="RadioButton2"/>
+                                               <RadioButton Style="RadioButton2" />
+                                               <RadioButton Style="RadioButton2" />
+                                               <RadioButton Style="RadioButton2" />
+                                               <RadioButton Style="RadioButton2" />
                                        </VerticalStack>
                                </HorizontalStack>
                        </GroupBox>
                        <HorizontalStack Height="Fit">
-                               <Label Text="Spinner"/>
-                               <Spinner Fit="true"/>
+                               <Label Text="Spinner" />
+                               <Spinner Fit="true" />
                        </HorizontalStack>
                        <HorizontalStack Height="Fit">
-                               <Button Caption="Button"/>
-                               <Button Caption="Button" IsEnabled="false"/>
+                               <Button Caption="Button">
+                                       <Label Font="{./Font}" Name="caption" Margin="3" Foreground="LightGrey" Text="{./Caption}" />
+                               </Button>
+                               <Button Caption="Button" IsEnabled="false">
+                                       <Label Font="{./Font}" Name="caption" Margin="3" Foreground="LightGrey" Text="{./Caption}" />
+                               </Button>
                        </HorizontalStack>
                </VerticalStack>
-               <Splitter/>
+               <Splitter />
                <VerticalStack Width="40%" Margin="5" Spacing="5">
                        <Expandable>
-                               <Image Path="#Crow.Icons.crow.svg"/>
+                               <Image Path="#Crow.Icons.crow.svg" />
                        </Expandable>
-                       <Popper>
-                               <Border Fit="True" Background="DimGrey" CornerRadius="0" BorderWidth="1">
-                                       <Image Path="#Crow.Icons.crow.svg" Width="100" Height="100" Margin="10"
-                                               MouseEnter="{Background=LightGrey}"
-                                               MouseLeave="{Background=Transparent}"/>
-                               </Border>
-                       </Popper>
-                       <Slider Height="10" Width="90%"/>
+                       <Popper />
+                       <Slider Height="10" Width="90%" />
                        <Container Height="Fit" Width="200" Background="DimGrey" Margin="2" CornerRadius="5">
-                               <ProgressBar Background="DimGrey" Height="10" Value="50"/>
+                               <ProgressBar Background="DimGrey" Height="10" Value="50" />
                        </Container>
                        <Image Path="#Crow.Icons.crow.svg" Width="60" Height="60" Background="LightGrey" />
-<!--                   <TabView Name="tabview1"
-                               Height="120" Orientation="Horizontal" Spacing="15">
-                               <TabItem Name="TabItem1" Caption="Tab 1" Margin="0">
-                                       <VerticalStack Fit="true">
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                       </VerticalStack>
-                               </TabItem>
-                               <TabItem Name="TabItem2" Caption="Tab 2" Background="Grey">
-                                       <VerticalStack Fit="true">
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                       </VerticalStack>
-                               </TabItem>
-                               <TabItem Name="TabItem3" Caption="Tab 3" Background="Grey">
-                                       <Container Margin="5" CornerRadius="2">
-                                               <TextBox Height="Stretched" Margin="5" Multiline="true" TextAlignment="TopLeft"/>
-                                       </Container>
-                               </TabItem>
-                       </TabView>-->
-                       <MessageBox Movable="false"/>
+                       <MessageBox Movable="false" />
                        <ColorPicker CurrentColor="{²../go.Background}" Name="colorPicker" Margin="5" />
-                       <Widget Name="go" Width="100" Height="60" Background="{../../colorList.SelectedItem}"/>
-                       <Label Text="{../colorPicker.CurrentColor}"/>
+                       <Widget Name="go" Width="100" Height="60" Background="{../../colorList.SelectedItem}" />
+                       <Label Text="{../colorPicker.CurrentColor}" />
                </VerticalStack>
-               <Splitter/>
+               <Splitter />
                <VerticalStack Width="30%" Margin="5">
-<!--                   <Border Margin="5" Height="Fit">
-                               <Label Width="Stretched" Margin="1" Text="{../../dv.SelectedItem}"/>
-                       </Border>
-                       <Border Margin="5" Height="30%">
-                               <DirectoryView Name="dv" CurrentDirectory="/" Margin="1"/>
-                       </Border>
-                       <Splitter/>-->
-                       <ListBox Name="colorList" Data="{TestList}" Margin="5"
-                                        ItemTemplate="Interfaces/colorItem.crow"
-                                        Template="#Crow.ScrollingListBox.template"
-                                        />
+                       <ListBox Name="colorList" Data="{TestList}" Margin="5" ItemTemplate="Interfaces/colorItem.crow" />
                </VerticalStack>
        </HorizontalStack>
 </Window>
\ No newline at end of file