-//
-// 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;
/// </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 = "";
/// </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);
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);
}
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);
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");
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);
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
-//
-// 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
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
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)
#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] == '$') {
}
#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 +=
}
/// <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);
{
//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;
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
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);
//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 ();
//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);
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
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);
}
/// <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)
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);
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);
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;
-//
-// 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;
/// </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;
}
/// </summary>
/// <value>The width of the stoke.</value>
[DefaultValue (1.0)]
- public double StokeWidth {
+ public double StrokeWidth {
get { return strokeWidth; }
set {
if (strokeWidth == value)
/// <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.
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;
</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>