From: Jean-Philippe Bruyère Date: Tue, 9 Jun 2020 23:41:33 +0000 (+0200) Subject: name search into template from binding, uniformisation will folow X-Git-Tag: v0.9.5-beta~113^2~11 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=46104d8683a8b4ada088e1a023480bb64299acaf;p=jp%2Fcrow.git name search into template from binding, uniformisation will folow --- diff --git a/Crow/src/IML/BindingDefinition.cs b/Crow/src/IML/BindingDefinition.cs index 9cbaf62b..887536bd 100644 --- a/Crow/src/IML/BindingDefinition.cs +++ b/Crow/src/IML/BindingDefinition.cs @@ -1,28 +1,6 @@ -// -// BindingDefinition.cs +// Copyright (c) 2013-2020 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// 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 /// 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 = ""; diff --git a/Crow/src/IML/BindingMember.cs b/Crow/src/IML/BindingMember.cs index f6cc047d..0678fb32 100644 --- a/Crow/src/IML/BindingMember.cs +++ b/Crow/src/IML/BindingMember.cs @@ -120,8 +120,10 @@ namespace Crow.IML /// /// current MSIL generator /// cancel branching in MSIL if something go wrong - public void emitGetTarget(ILGenerator il, System.Reflection.Emit.Label cancel){ - + /// 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. + 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); } diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index ea25e9bb..9a1eced6 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -48,7 +48,7 @@ namespace Crow.IML internal static MethodInfo miGetColCount = typeof(System.Collections.ICollection).GetProperty("Count").GetGetMethod(); internal static MethodInfo miGetDelegateListItem = typeof(List).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).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); - } /// /// MSIL helper, go n levels up diff --git a/Crow/src/IML/IMLAttributes.cs b/Crow/src/IML/IMLAttributes.cs index 929fd4f8..b983d1a6 100644 --- a/Crow/src/IML/IMLAttributes.cs +++ b/Crow/src/IML/IMLAttributes.cs @@ -1,28 +1,7 @@ -// -// IMLAttributes.cs +// Copyright (c) 2013-2020 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// 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 diff --git a/Crow/src/IML/IMLContext.cs b/Crow/src/IML/IMLContext.cs index 3aab2158..5d66a5e0 100644 --- a/Crow/src/IML/IMLContext.cs +++ b/Crow/src/IML/IMLContext.cs @@ -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 diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs index c1a11f03..ca41eec1 100644 --- a/Crow/src/IML/Instantiator.cs +++ b/Crow/src/IML/Instantiator.cs @@ -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 + /// + /// Create delegate from cached dyn method, delegate is bound to the datasource change sender. + /// + /// data source change sender + /// new Data source. + /// Dyn meth index in the dsValueChangedDynMeths array void dataSourceChangedEmitHelper(object dscSource, object dataSource, int dynMethIdx){ if (dataSource is IValueChange) (dataSource as IValueChange).ValueChanged += @@ -617,7 +625,7 @@ namespace Crow.IML { } /// Emits remove old data source event handler. 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); + } + /// Emits handler method bindings 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 { } /// + /// data source binding with unknown data type. /// create the valuechanged handler, the datasourcechanged handler and emit event handling /// 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; diff --git a/Crow/src/IML/NodeAddress.cs b/Crow/src/IML/NodeAddress.cs index 55ef21b0..2d41aced 100644 --- a/Crow/src/IML/NodeAddress.cs +++ b/Crow/src/IML/NodeAddress.cs @@ -1,28 +1,6 @@ -// -// NodeAddress.cs +// Copyright (c) 2013-2020 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// 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 /// 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; } diff --git a/Crow/src/Widgets/Shape.cs b/Crow/src/Widgets/Shape.cs index 7f43061d..979d9c4a 100644 --- a/Crow/src/Widgets/Shape.cs +++ b/Crow/src/Widgets/Shape.cs @@ -164,7 +164,7 @@ namespace Crow /// /// The width of the stoke. [DefaultValue (1.0)] - public double StokeWidth { + public double StrokeWidth { get { return strokeWidth; } set { if (strokeWidth == value) diff --git a/Crow/src/Widgets/TemplatedControl.cs b/Crow/src/Widgets/TemplatedControl.cs index ae2967d0..b2081312 100644 --- a/Crow/src/Widgets/TemplatedControl.cs +++ b/Crow/src/Widgets/TemplatedControl.cs @@ -79,7 +79,7 @@ namespace Crow /// widget identified by name, or null if not found /// widget's name to find public override Widget FindByName (string nameToFind) => nameToFind == this.Name ? this : null; - + public Widget FindByNameInTemplate (string nameToFind) => child?.FindByName (nameToFind); /// ///onDraw is overrided to prevent default drawing of background, template top container ///may have a binding to root background or a fixed one. diff --git a/Samples/ShowCase/ShowCase.cs b/Samples/ShowCase/ShowCase.cs index 48e209ec..dd0b77c9 100644 --- a/Samples/ShowCase/ShowCase.cs +++ b/Samples/ShowCase/ShowCase.cs @@ -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; diff --git a/Samples/common/ui/Interfaces/TemplatedControl/testCheckbox.crow b/Samples/common/ui/Interfaces/TemplatedControl/testCheckbox.crow index b5eb0fc7..6e627506 100644 --- a/Samples/common/ui/Interfaces/TemplatedControl/testCheckbox.crow +++ b/Samples/common/ui/Interfaces/TemplatedControl/testCheckbox.crow @@ -19,12 +19,14 @@ - + +