From: jpbruyere Date: Tue, 27 Dec 2016 15:20:19 +0000 (+0100) Subject: use LogicalParent in binding, debug Parenting and DS changes in several classes X-Git-Tag: v0.5.1~63^2~5 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=2b4455e6bf46809f699a3fcf1d51e8e99fbcf6f8;p=jp%2Fcrow.git use LogicalParent in binding, debug Parenting and DS changes in several classes --- diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index b7d24184..2a472f3c 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -643,6 +643,38 @@ namespace Crow public static Type getEventHandlerType(object instance, string eventName){ return instance.GetType ().GetEvent (eventName).EventHandlerType; } + public static void setValueWithReflexion(object dest, object value, string destMember){ + Type destType = null; + Type origType = null; + object convertedVal = null; + + MemberInfo miDest = getMemberInfoWithReflexion (dest, destMember); + + if (miDest == null) { + Debug.WriteLine ("Reverse template binding error: " + destMember + " not found in " + dest); + return; + } + + if (miDest.MemberType == MemberTypes.Property) + destType =(miDest as PropertyInfo).PropertyType; + else if (miDest.MemberType == MemberTypes.Field) + destType =(miDest as FieldInfo).FieldType; + + if (value != null) { + origType = value.GetType (); + if (destType.IsAssignableFrom (origType)) + convertedVal = Convert.ChangeType (value, destType); + else if (origType.IsPrimitive & destType.IsPrimitive) + convertedVal = GetConvertMethod (destType).Invoke (null, new Object[] { value }); + else + convertedVal = getImplicitOp (origType, destType).Invoke (value, null); + } + + if (miDest.MemberType == MemberTypes.Property) + (miDest as PropertyInfo).SetValue (dest, convertedVal); + else if (miDest.MemberType == MemberTypes.Field) + (miDest as FieldInfo).SetValue (dest, convertedVal); + } public static object getValueWithReflexion(object instance, MemberInfo mi){ object tmp = null; Type dstType = null; @@ -674,7 +706,7 @@ namespace Crow break; } for (int i = 0; i < orig.Count - ptr; i++) - il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("Parent").GetGetMethod ()); + il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("LogicalParent").GetGetMethod ()); while (ptr < dest.Count) { emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index); ptr++; @@ -812,8 +844,12 @@ namespace Crow MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate; if (multiDel != null) { foreach (Delegate d in multiDel.GetInvocationList()) { - if (d.Method.Name == delegateName) + if (d.Method.Name == delegateName) { eiEvt.RemoveEventHandler (instance, d); + #if DEBUG_BINDING + Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName); + #endif + } } } } @@ -827,13 +863,21 @@ namespace Crow MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate; if (multiDel != null) { foreach (Delegate d in multiDel.GetInvocationList()) { - if (d.Target == target) + if (d.Target == target) { eiEvt.RemoveEventHandler (instance, d); + #if DEBUG_BINDING + Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName); + #endif + } } } } public 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) diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index a2f9be7c..1be9d4cf 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -140,9 +140,12 @@ namespace Crow return; if (logicalParent != null) (logicalParent as GraphicObject).DataSourceChanged -= onLogicalParentDataSourceChanged; + DataSourceChangeEventArgs dsce = new DataSourceChangeEventArgs (LogicalParent, null); logicalParent = value; + dsce.NewDataSource = LogicalParent; if (logicalParent != null) (logicalParent as GraphicObject).DataSourceChanged += onLogicalParentDataSourceChanged; + onLogicalParentChanged (this, dsce); } } [XmlIgnore]public virtual Rectangle ClientRectangle { @@ -186,6 +189,7 @@ namespace Crow public event EventHandler LayoutChanged; public event EventHandler DataSourceChanged; public event EventHandler ParentChanged; + public event EventHandler LogicalParentChanged; #endregion #region public properties @@ -535,37 +539,30 @@ namespace Crow [XmlAttributeAttribute][DefaultValue(null)] public virtual object DataSource { set { - if (dataSource == value) + if (DataSource == value) return; - DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (dataSource, value); + DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (DataSource, null); dataSource = value; + dse.NewDataSource = DataSource; OnDataSourceChanged (this, dse); NotifyValueChanged ("DataSource", DataSource); } get { - return dataSource == null ? LogicalParent == null ? null : - LogicalParent is GraphicObject ? - (LogicalParent as GraphicObject).DataSource : null : dataSource; + return dataSource == null ? + LogicalParent == null ? null : + LogicalParent is GraphicObject ? (LogicalParent as GraphicObject).DataSource : null : + dataSource; } } protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){ - ILayoutable tmp = Parent; - if (tmp == null) { - Debug.WriteLine ("parent is null for: " + this.ToString ()); - return; - } - while (tmp != sender) { - if (!(tmp as GraphicObject).localDataSourceIsNull) { - OnDataSourceChanged (sender, e); - return; - } - tmp = tmp.Parent; - } + if (localDataSourceIsNull) + OnDataSourceChanged (this, e); } internal bool localDataSourceIsNull { get { return dataSource == null; } } + internal bool localLogicalParentIsNull { get { return logicalParent == null; } } public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){ DataSourceChanged.Raise (this, e); @@ -1254,9 +1251,13 @@ namespace Crow Disabled.Raise (this, e); } protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) { - ParentChanged.Raise (sender, e); + ParentChanged.Raise (this, e); + if (logicalParent == null) + LogicalParentChanged.Raise (this, e); + } + protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) { + LogicalParentChanged.Raise (this, e); } - #region IXmlSerializable public virtual System.Xml.Schema.XmlSchema GetSchema () { diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index da42b8f5..a285e282 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -93,9 +93,9 @@ namespace Crow #region GraphicObject overrides public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) { - base.OnDataSourceChanged (sender, e); + base.OnDataSourceChanged (this, e); foreach (GraphicObject g in children) - if (g.localDataSourceIsNull) + if (g.localDataSourceIsNull & g.localLogicalParentIsNull) g.OnDataSourceChanged (sender, e); } public override GraphicObject FindByName (string nameToFind) diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 06f0c213..0afefeb9 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -80,9 +80,9 @@ namespace Crow } public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) { - base.OnDataSourceChanged (sender, e); + base.OnDataSourceChanged (this, e); if (child != null) - if (child.localDataSourceIsNull) + if (child.localDataSourceIsNull & child.localLogicalParentIsNull) child.OnDataSourceChanged (sender, e); } public override bool UpdateLayout (LayoutingType layoutType) diff --git a/src/GraphicObjects/TabItem.cs b/src/GraphicObjects/TabItem.cs index 078fd04d..cd57b221 100644 --- a/src/GraphicObjects/TabItem.cs +++ b/src/GraphicObjects/TabItem.cs @@ -46,7 +46,13 @@ namespace Crow return _contentContainer == null ? null : _contentContainer.Child; } set { + if (Content != null) { + Content.LogicalParent = null; + _contentContainer.SetChild (null); + } _contentContainer.SetChild(value); + if (value != null) + value.LogicalParent = this; } } protected override void loadTemplate(GraphicObject template = null) diff --git a/src/GraphicObjects/TemplatedGroup.cs b/src/GraphicObjects/TemplatedGroup.cs index 7b7f897c..1664f671 100644 --- a/src/GraphicObjects/TemplatedGroup.cs +++ b/src/GraphicObjects/TemplatedGroup.cs @@ -42,7 +42,6 @@ namespace Crow public event EventHandler SelectedItemChanged; #endregion - Group _list; IList data; int _selectedIndex; Color selBackground, selForeground; @@ -160,10 +159,12 @@ namespace Crow public virtual void AddItem(GraphicObject g){ items.AddChild (g); + g.LogicalParent = this; NotifyValueChanged ("HasChildren", true); } public virtual void RemoveItem(GraphicObject g) { + g.LogicalParent = null; items.RemoveChild (g); if (items.Children.Count == 0) NotifyValueChanged ("HasChildren", false); diff --git a/src/IML/BindingDefinition.cs b/src/IML/BindingDefinition.cs index 59b45167..eadbc9df 100644 --- a/src/IML/BindingDefinition.cs +++ b/src/IML/BindingDefinition.cs @@ -64,6 +64,21 @@ namespace Crow.IML TargetNA = newTargetNA; TargetName = ""; } + + public override string ToString () + { + string tmp = string.Format ("Source:{0}.{1}", SourceNA, SourceMember); + if (TwoWay) + tmp += " <=> "; + else + tmp += " <= "; + + if (string.IsNullOrEmpty (TargetName)) + tmp += string.Format ("Target:{0}.{1}]", TargetNA, TargetMember); + else + tmp += string.Format ("Target:{0}.{1}.{2}]", TargetNA, TargetName, TargetMember); + return tmp; + } } } diff --git a/src/Instantiator.cs b/src/Instantiator.cs index a0f8fe75..4415609b 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -110,7 +110,7 @@ namespace Crow ctx.nodesStack.Pop (); foreach (int idx in templateCachedDelegateIndices) - ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("ParentChanged")); + ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("LogicalParentChanged")); ctx.ResolveNamedTargets (); @@ -418,9 +418,6 @@ namespace Crow /// void compileAndStoreDynHandler (Context ctx, EventInfo sourceEvent, string expression) { - #if DEBUG_BINDING - Debug.WriteLine ("\tCompile Event Source "); - #endif //store event handler dynamic method in instanciator int dmIdx = cachedDelegates.Count; cachedDelegates.Add (CompilerServices.compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress)); @@ -444,7 +441,7 @@ namespace Crow il.Emit (OpCodes.Nop); - emitRemoveOldDataSourceHandler(il, sourceEvent.Name, bindingDef.TargetMember); + emitRemoveOldDataSourceHandler (il, sourceEvent.Name, bindingDef.TargetMember, false); //fetch method in datasource and test if it exist il.Emit (OpCodes.Ldarg_2);//load new datasource @@ -477,7 +474,7 @@ namespace Crow System.Reflection.Emit.Label finish = il.DefineLabel (); il.Emit (OpCodes.Br, finish); il.MarkLabel (cancel); - il.EmitWriteLine (sourcePath + ": Handler method not found: " + bindingDef.TargetMember); + il.EmitWriteLine (string.Format ("Handler method '{0}' not found. {1}={2} ", bindingDef.TargetMember, sourceEvent.Name, expression)); il.MarkLabel (finish); il.Emit (OpCodes.Ret); @@ -545,17 +542,20 @@ namespace Crow if (piOrig != null) origineType = piOrig.PropertyType; foreach (MemberAddress ma in bindingCase.Value) { - if (ma.Address.Count == 0) - continue;//template binding //first we have to load destination instance onto the stack, it is access //with graphic tree functions deducted from nodes topology il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event NodeAddress destination = ma.Address; - CompilerServices.emitGetInstance (il, origine, destination); + if (destination.Count == 0){//template reverse binding + //fetch destination instance (which is the template root) + for (int j = 0; j < origine.Count ; j++) + il.Emit(OpCodes.Callvirt, typeof(GraphicObject).GetProperty("LogicalParent").GetGetMethod()); + }else + CompilerServices.emitGetInstance (il, origine, destination); - if (origineType != null){//prop less binding, no init requiered + if (origineType != null && destination.Count > 0){//else, prop less binding or reverse template bind, no init requiered //for initialisation dynmeth, push destination instance loc_0 is root node in ctx ctx.il.Emit(OpCodes.Ldloc_0); CompilerServices.emitGetInstance (ctx.il, destination); @@ -571,13 +571,18 @@ namespace Crow if (origineType == null)//property less binding, no init CompilerServices.emitConvert (il, ma.Property.PropertyType); - else { + else if (destination.Count > 0) { if (origineType.IsValueType) ctx.il.Emit(OpCodes.Box, origineType); + CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType); CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType); ctx.il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value + } else {// reverse templateBinding + il.Emit (OpCodes.Ldstr, ma.memberName);//arg 3 of setValueWithReflexion + il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("setValueWithReflexion", BindingFlags.Static | BindingFlags.Public)); + continue; } il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes } @@ -603,7 +608,7 @@ namespace Crow ILGenerator il = dm.GetILGenerator (256); //create parentchanged dyn meth in parallel to have only one loop over bindings - DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndParentChanged", + DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged", typeof (void), CompilerServices.argsBoundDSChange, true); ILGenerator ilPC = dmPC.GetILGenerator (256); @@ -663,8 +668,10 @@ namespace Crow #region destination member affectations foreach (MemberAddress ma in bindingCase.Value) { - if (ma.Address.Count == 0) + if (ma.Address.Count == 0){ + Debug.WriteLine("\t\tBUG: reverse template binding in normal template binding"); continue;//template binding + } //first we try to get memberInfo of new parent, if it doesn't exist, it's a propery less binding ilPC.Emit (OpCodes.Ldarg_2);//load new parent onto the stack for handler addition ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); @@ -728,7 +735,7 @@ namespace Crow //store template bindings in instanciator templateBinding = dm.CreateDelegate (typeof(EventHandler)); - #region emit ParentChanged method + #region emit LogicalParentChanged method //load new parent onto the stack for handler addition ilPC.Emit (OpCodes.Ldarg_2); @@ -749,7 +756,7 @@ namespace Crow cachedDelegates.Add(dmPC.CreateDelegate (CompilerServices.ehTypeDSChange, this)); #endregion - ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("ParentChanged")); + ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("LogicalParentChanged")); } /// /// create the valuechanged handler, the datasourcechanged handler and emit event handling @@ -956,7 +963,7 @@ namespace Crow #endregion /// Emits remove old data source event handler./summary> - void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName){ + void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){ System.Reflection.Emit.Label cancel = il.DefineLabel (); il.Emit (OpCodes.Ldarg_2);//load old parent @@ -964,8 +971,11 @@ namespace Crow il.Emit (OpCodes.Brfalse, cancel);//old parent is null //remove handler - il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource - il.Emit (OpCodes.Ldfld, typeof (DataSourceChangeEventArgs).GetField ("OldDataSource")); + if (DSSide){//event is defined in the dataSource instance + il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource + il.Emit (OpCodes.Ldfld, typeof (DataSourceChangeEventArgs).GetField ("OldDataSource")); + }else//the event is in the source + il.Emit (OpCodes.Ldarg_1);//1st arg load old datasource il.Emit (OpCodes.Ldstr, eventName);//2nd arg event name il.Emit (OpCodes.Ldstr, delegateName);//3d arg: delegate name il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("RemoveEventHandlerByName", BindingFlags.Static | BindingFlags.Public)); diff --git a/src/Interface.cs b/src/Interface.cs index 941b96f9..6547b0e5 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -518,6 +518,7 @@ namespace Crow //TODO:parent is not reset to null because object will be added //to ObjectToRedraw list, and without parent, it fails GraphicObject g = GraphicTree [i]; + g.DataSource = null; g.Visible = false; GraphicTree.RemoveAt (0); }