]> O.S.I.I.S - jp/crow.git/commitdiff
name search into template from binding, uniformisation will folow
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 9 Jun 2020 23:41:33 +0000 (01:41 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 9 Jun 2020 23:41:33 +0000 (01:41 +0200)
Crow/src/IML/BindingDefinition.cs
Crow/src/IML/BindingMember.cs
Crow/src/IML/CompilerServices.cs
Crow/src/IML/IMLAttributes.cs
Crow/src/IML/IMLContext.cs
Crow/src/IML/Instantiator.cs
Crow/src/IML/NodeAddress.cs
Crow/src/Widgets/Shape.cs
Crow/src/Widgets/TemplatedControl.cs
Samples/ShowCase/ShowCase.cs
Samples/common/ui/Interfaces/TemplatedControl/testCheckbox.crow

index 9cbaf62bbaf5c10279a77426b1cf1453cc3349cc..887536bd82de54ae5869b7961ca5cc60c0654e05 100644 (file)
@@ -1,28 +1,6 @@
-//
-// BindingDefinition.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;
 
@@ -33,7 +11,7 @@ namespace Crow.IML
        /// </summary>
        public class BindingDefinition
        {
-               public NodeAddress SourceNA = null;//the widget declaring this binding in a member
+               public NodeAddress SourceNA = null;//the widget declaring this binding in one of its member
                public string SourceMember = "";//the member where the binding string has been found
                public NodeAddress TargetNA = null;//
                public string TargetMember = "";
index f6cc047df0ec45edc21b0ba3403b4cc28ce2677b..0678fb3228079e2b301a767000aa84a89c179600 100644 (file)
@@ -120,8 +120,10 @@ namespace Crow.IML
                /// </summary>
                /// <param name="il">current MSIL generator</param>
                /// <param name="cancel">cancel branching in MSIL if something go wrong</param>
-               public void emitGetTarget(ILGenerator il, System.Reflection.Emit.Label cancel){
-
+               /// <param name="currentNode">if levelUp is 0, node is templated target is not simple name, name
+               /// is search in the current node template content, which is avoid normaly.</param>
+               public void emitGetTarget(ILGenerator il, System.Reflection.Emit.Label cancel, NodeAddress currentNode = null)
+               {
                        if (IsTemplateBinding) {
                                System.Reflection.Emit.Label nextLogicParent = il.DefineLabel ();
                                il.MarkLabel (nextLogicParent);
@@ -141,7 +143,11 @@ namespace Crow.IML
 
                        if (!string.IsNullOrEmpty (Tokens [0])) {//find by name
                                il.Emit (OpCodes.Ldstr, Tokens [0]);
-                               il.Emit (OpCodes.Callvirt, CompilerServices.miFindByName);
+                               if (LevelsUp == 0 && currentNode[currentNode.Count-1].HasTemplate)
+                                       //search in template
+                                       il.Emit (OpCodes.Callvirt, CompilerServices.miFindByNameInTemplate);
+                               else                            
+                                       il.Emit (OpCodes.Callvirt, CompilerServices.miFindByName);
                                il.Emit (OpCodes.Dup);
                                il.Emit (OpCodes.Brfalse, cancel);
                        }
index ea25e9bbc372ee2a6104f83d75cb86ffc37ed688..9a1eced6b9e153ea90f85187e74b9113f65f58c2 100644 (file)
@@ -48,7 +48,7 @@ namespace Crow.IML
                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 miCompileDynEventHandler = typeof(Instantiator).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);
@@ -69,6 +69,7 @@ namespace Crow.IML
 
                internal static FieldInfo miSetCurIface = typeof(Widget).GetField ("IFace", BindingFlags.Public | BindingFlags.Instance);
                internal static MethodInfo miFindByName = typeof (Widget).GetMethod ("FindByName");
+               internal static MethodInfo miFindByNameInTemplate = typeof (TemplatedControl).GetMethod ("FindByNameInTemplate");
                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");
@@ -711,7 +712,7 @@ namespace Crow.IML
                                il.Emit (OpCodes.Unbox_Any, dstType);
                        } else{
                                LocalBuilder lbOrig = il.DeclareLocal (typeof (object));
-                               il.Emit (OpCodes.Stloc, lbOrig); //save orig value in loc0
+                               il.Emit (OpCodes.Stloc, lbOrig); //save orig value in loc
                                //first check if not null
                                il.Emit (OpCodes.Ldloc, lbOrig);
                                il.Emit (OpCodes.Dup);
@@ -803,123 +804,6 @@ namespace Crow.IML
                        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
index 929fd4f8f8324adbecc43cf9473f180e83865b67..b983d1a6aeb87666a80ff956ba543b74985fccf2 100644 (file)
@@ -1,28 +1,7 @@
-//
-// IMLAttributes.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;
 
 namespace Crow
index 3aab2158cd7689d97c591731b87c67d739bd385c..5d66a5e0ac327e1604a14afa23522227cc125108 100644 (file)
@@ -221,24 +221,5 @@ namespace Crow.IML
                        il.Emit (OpCodes.Call, CompilerServices.miCreateDel);
                        il.Emit (OpCodes.Callvirt, bd.SourceEvent.AddMethod);//call add event
                }
-//             public void emitHandlerMethodAddition(EventBinding bd){
-//                     //fetch source instance with address for handler addition (as 1st arg of handler.add)
-//                     il.Emit (OpCodes.Ldloc_0);//push root
-//                     CompilerServices.emitGetInstance (il, bd.SourceNA);
-//
-//                     //load handlerType of sourceEvent to create handler delegate (1st arg)
-//                     il.Emit (OpCodes.Ldtoken, bd.SourceEvent.EventHandlerType);
-//                     il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-//                     //load target the where the method is defined (2nd arg)
-//                     il.Emit (OpCodes.Ldloc_0);
-//                     CompilerServices.emitGetInstance (il, bd.TargetNA);
-//                     //load methodInfo (3rd arg)
-//                     il.Emit (OpCodes.Ldstr, bd.TargetMember);
-//
-//                     il.Emit (OpCodes.Callvirt, CompilerServices.miCreateDel);
-//
-//                     il.Emit (OpCodes.Callvirt, bd.SourceEvent.AddMethod);//call add event
-//             }
-//
        }
 }
\ No newline at end of file
index c1a11f039f6f9f2d541f805bbd3e4894952a0865..ca41eec10de6a96464dc1aefecc681c037f83b3c 100644 (file)
@@ -13,6 +13,9 @@ using System.Text;
 using System.Xml;
 
 namespace Crow.IML {
+       using Label = System.Reflection.Emit.Label;
+
+
        public class InstantiatorException : Exception {
                public string Path;
                public InstantiatorException (string path, Exception innerException)
@@ -466,10 +469,9 @@ namespace Crow.IML {
 #if DESIGN_MODE
                                                emitSetDesignAttribute (ctx, reader.Name, reader.Value);
 #endif
-
                                                string imlValue = reader.Value;
                                                StringBuilder styledValue = new StringBuilder();
-
+                                               //styling constants expansion
                                                int vPtr = 0;
                                                while (vPtr < imlValue.Length) {
                                                        if (imlValue [vPtr] == '$') {
@@ -610,6 +612,12 @@ namespace Crow.IML {
                }
 
                #region Emit Helper
+               /// <summary>
+               /// Create delegate from cached dyn method, delegate is bound to the datasource change sender.
+               /// </summary>
+               /// <param name="dscSource">data source change sender</param>
+               /// <param name="dataSource">new Data source.</param>
+               /// <param name="dynMethIdx">Dyn meth index in the dsValueChangedDynMeths array</param>
                void dataSourceChangedEmitHelper(object dscSource, object dataSource, int dynMethIdx){
                        if (dataSource is IValueChange)
                                (dataSource as IValueChange).ValueChanged +=
@@ -617,7 +625,7 @@ namespace Crow.IML {
                }
                /// <summary> Emits remove old data source event handler.</summary>
                void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){
-                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
+                       Label cancel = il.DefineLabel ();
 
                        il.Emit (OpCodes.Ldarg_2);//load old parent
                        il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS);
@@ -645,9 +653,128 @@ namespace Crow.IML {
                {
                        //store event handler dynamic method in instanciator
                        int dmIdx = cachedDelegates.Count;
-                       cachedDelegates.Add (CompilerServices.compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress));
+                       cachedDelegates.Add (compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress));
                        ctx.emitCachedDelegateHandlerAddition(dmIdx, sourceEvent);
                }
+               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 (64);
+
+                       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 ();
+
+                               Label cancel = il.DefineLabel ();
+                               Label cancelFinalSet = il.DefineLabel ();
+                               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, currentNode);
+                               #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);
+                                       CompilerServices.emitConvert (il, lopPI.PropertyType);
+                                       //if (lopPI.PropertyType.IsValueType)
+                                       //      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> Emits handler method bindings </summary>
                void emitHandlerBinding (IMLContext ctx, EventInfo sourceEvent, string expression){
                        NodeAddress currentNode = ctx.CurrentNodeAddress;
@@ -663,7 +790,7 @@ namespace Crow.IML {
                                                           typeof(void),
                                                           CompilerServices.argsBoundDSChange, true);
 
-                               ILGenerator il = dm.GetILGenerator (256);
+                               ILGenerator il = dm.GetILGenerator (64);
                                System.Reflection.Emit.Label cancel = il.DefineLabel ();
 
                                il.DeclareLocal (typeof(MethodInfo));//used to cancel binding if method doesn't exist
@@ -672,7 +799,6 @@ namespace Crow.IML {
 
                                emitRemoveOldDataSourceHandler (il, sourceEvent.Name, bindingDef.TargetMember, false);
 
-
                                //fetch method in datasource and test if it exist
                                il.Emit (OpCodes.Ldarg_2);//load new datasource
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
@@ -748,7 +874,7 @@ namespace Crow.IML {
                        //value changed dyn method
                        DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId,
                                typeof (void), CompilerServices.argsValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (256);
+                       ILGenerator il = dm.GetILGenerator (64);
 
                        System.Reflection.Emit.Label endMethod = il.DefineLabel ();
 
@@ -846,13 +972,13 @@ namespace Crow.IML {
                        //value changed dyn method
                        DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged" + NewId,
                                typeof (void), CompilerServices.argsValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (256);
+                       ILGenerator il = dm.GetILGenerator (64);
 
                        //create parentchanged dyn meth in parallel to have only one loop over bindings
                        DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged" + NewId,
                                typeof (void),
                                CompilerServices.argsBoundDSChange, true);
-                       ILGenerator ilPC = dmPC.GetILGenerator (256);
+                       ILGenerator ilPC = dmPC.GetILGenerator (64);
 
                        il.Emit (OpCodes.Nop);
                        ilPC.Emit (OpCodes.Nop);
@@ -1012,16 +1138,14 @@ namespace Crow.IML {
                                        typeof (void),
                                        CompilerServices.argsBoundValueChange, true);
 
-                               il = dm.GetILGenerator (256);
+                               il = dm.GetILGenerator (64);
 
-                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+                               Label endMethod = il.DefineLabel ();
 
                                il.DeclareLocal (typeof (object));
 
-                               il.Emit (OpCodes.Nop);
-
                                //load value changed member name onto the stack
-                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldarg_2);//TODO:check _2??? not _1??
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
 
                                //test if it's the expected one
@@ -1065,16 +1189,15 @@ namespace Crow.IML {
                                typeof (void),
                                CompilerServices.argsBoundDSChange, true);
 
-                       il = dm.GetILGenerator (256);
+                       il = dm.GetILGenerator (64);
 
                        il.DeclareLocal (typeof (object));//used for checking propery less bindings
                        il.DeclareLocal (typeof (MemberInfo));//used for checking propery less bindings
                        il.DeclareLocal (typeof (object));//new datasource store, save one field access
-                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
-                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
-                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
+                       Label cancel = il.DefineLabel ();
+                       Label newDSIsNull = il.DefineLabel ();
+                       Label cancelInit = il.DefineLabel ();
 
-                       il.Emit (OpCodes.Nop);
 
                        il.Emit (OpCodes.Ldarg_2);//load datasource change arg
                        il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
@@ -1157,6 +1280,7 @@ namespace Crow.IML {
                }
 
                /// <summary>
+               /// data source binding with unknown data type.
                /// create the valuechanged handler, the datasourcechanged handler and emit event handling
                /// </summary>
                void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef)
@@ -1191,15 +1315,12 @@ namespace Crow.IML {
                                dm = new DynamicMethod (delName,
                                        typeof (void),
                                        CompilerServices.argsBoundValueChange, true);
-
                                il = dm.GetILGenerator (64);
 
-                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+                               Label endMethod = il.DefineLabel ();
 
                                il.DeclareLocal (typeof(object));
 
-                               il.Emit (OpCodes.Nop);
-
                                //load value changed member name onto the stack
                                il.Emit (OpCodes.Ldarg_2);
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
@@ -1392,8 +1513,6 @@ namespace Crow.IML {
 
                        System.Reflection.Emit.Label endMethod = il.DefineLabel ();
 
-                       il.Emit (OpCodes.Nop);
-
                        //load value changed member name onto the stack
                        il.Emit (OpCodes.Ldarg_2);
                        il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
@@ -1468,9 +1587,7 @@ namespace Crow.IML {
                                knownGOTypes.Add (typeName, t);
                                return t;
                        }                       
-                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
-                               if (a.IsDynamic)
-                                       continue;
+                       foreach (Assembly a in Interface.crowAssemblies) {
                                foreach (Type expT in a.GetExportedTypes ()) {
                                        if (expT.Name != typeName)
                                                continue;
index 55ef21b0eb357113e7a970dbe6cc1cc0ef6f3668..2d41aced43508d687859a843229bb4c0d43afe86 100644 (file)
@@ -1,28 +1,6 @@
-//
-// NodeAddress.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;
@@ -83,30 +61,30 @@ namespace Crow.IML
                /// </summary>
                public BindingDefinition GetBindingDef(string sourceMember, string expression){
                        BindingDefinition bindingDef = new BindingDefinition(this, sourceMember);
-                       if (string.IsNullOrEmpty (expression)) {
+                       if (string.IsNullOrEmpty (expression)) 
                                return bindingDef;
-                       } else {
-                               if (expression.StartsWith ("²", StringComparison.Ordinal)) {
-                                       bindingDef.TwoWay = true;
-                                       expression = expression.Substring (1);
-                               }
 
-                               string exp = expression;
-                               bindingDef.TargetNA = this.ResolveExpression (ref exp);
+                       if (expression.StartsWith ("²", StringComparison.Ordinal)) {
+                               bindingDef.TwoWay = true;
+                               expression = expression.Substring (1);
+                       }
 
-                               string [] bindTrg = exp.Split ('.');
+                       string exp = expression;
+                       bindingDef.TargetNA = this.ResolveExpression (ref exp);
 
-                               if (bindTrg.Length == 0)
-                                       throw new Exception ("invalid binding expression: " + expression);
-                               if (bindTrg.Length == 1)
-                                       bindingDef.TargetMember = bindTrg [0];
-                               else {
-                                       if (!string.IsNullOrEmpty(bindTrg[0]))//searchByName
-                                               bindingDef.TargetName = bindTrg[0];
+                       string [] bindTrg = exp.Split ('.');
 
-                                       bindingDef.TargetMember = exp.Substring (bindTrg[0].Length + 1);
-                               }
+                       if (bindTrg.Length == 0)
+                               throw new Exception ("invalid binding expression: " + expression);
+                       if (bindTrg.Length == 1)
+                               bindingDef.TargetMember = bindTrg [0];
+                       else {
+                               if (!string.IsNullOrEmpty(bindTrg[0]))//searchByName
+                                       bindingDef.TargetName = bindTrg[0];
+
+                               bindingDef.TargetMember = exp.Substring (bindTrg[0].Length + 1);
                        }
+                       
 
                        return bindingDef;
                }
index 7f43061dec98a58515f67bd5de3a5571c4c00c7f..979d9c4ac39365b445b8fb1c8ec6fd8c98229cb4 100644 (file)
@@ -164,7 +164,7 @@ namespace Crow
                /// </summary>
                /// <value>The width of the stoke.</value>
                [DefaultValue (1.0)]
-               public double StokeWidth {
+               public double StrokeWidth {
                        get { return strokeWidth; }
                        set {
                                if (strokeWidth == value)
index ae2967d0d282ee447317f810a2c073fb0c27a98c..b20813126ffbdc505ff7e6246704e8c4480741b5 100644 (file)
@@ -79,7 +79,7 @@ namespace Crow
                /// <returns>widget identified by name, or null if not found</returns>
                /// <param name="nameToFind">widget's name to find</param>
                public override Widget FindByName (string nameToFind) => nameToFind == this.Name ? this : null;
-
+               public Widget FindByNameInTemplate (string nameToFind) => child?.FindByName (nameToFind);
                /// <summary>
                ///onDraw is overrided to prevent default drawing of background, template top container
                ///may have a binding to root background or a fixed one.
index 48e209ec2e3cb321fcf978d54d0a6d97c08a28a9..dd0b77c9b8298cb8127bc471ce4ae16b47992dfa 100644 (file)
@@ -239,9 +239,8 @@ namespace ShowCase
                        try {
                                lock (UpdateMutex) {
                                        Instantiator inst = null;
-                                       using (MemoryStream ms = new MemoryStream (Encoding.UTF8.GetBytes (source))) {
+                                       using (MemoryStream ms = new MemoryStream (Encoding.UTF8.GetBytes (source))) 
                                                inst = new Instantiator (this, ms);
-                                       }
                                        g = inst.CreateInstance ();
                                        crowContainer.SetChild (g);
                                        g.DataSource = this;
index b5eb0fc7ddd1b32459acfbb25944ccb1a1445f7f..6e627506124ae737b835ccf2c659f2d8dc648c12 100644 (file)
                        </HorizontalStack>
                </Template>
        </CheckBox>
-       <CheckBox Background="Jet" Height="30" Width="60" Checked="{Background=SeaGreen}" >
+       <CheckBox Background="Jet" Height="30" Width="60"       
+                                               Checked="{sh.HorizontalAlignment=Right};{Background=SeaGreen}"
+                                               Unchecked="{sh.HorizontalAlignment=Left};{Background=Jet}">
                <Template>
                        <Group  Background="{./Background}" Margin="0" CornerRadius="100">
                                <Shape Name="sh" HorizontalAlignment="Left" Width="{./Height}" Foreground="Grey" Size="16,16" Path="A 8,8,7.5,0,6.3 f O 1,1,1,1 G "/>
-                               <Shape Visible="{./IsChecked}" HorizontalAlignment="Right" Width="{./Height}" Foreground="Grey" Size="16,16" Path="A 8,8,7.5,0,6.3 f O 1,1,1,1 G "/>
                        </Group>
                </Template>
        </CheckBox>
+       
 </VerticalStack>