]> O.S.I.I.S - jp/crow.git/commitdiff
use LogicalParent in binding, debug Parenting and DS changes in several classes
authorjpbruyere <jp.bruyere@hotmail.com>
Tue, 27 Dec 2016 15:20:19 +0000 (16:20 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Tue, 27 Dec 2016 15:20:19 +0000 (16:20 +0100)
src/CompilerServices/CompilerServices.cs
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/Group.cs
src/GraphicObjects/PrivateContainer.cs
src/GraphicObjects/TabItem.cs
src/GraphicObjects/TemplatedGroup.cs
src/IML/BindingDefinition.cs
src/Instantiator.cs
src/Interface.cs

index b7d24184cd8a466d76e9ecd8994f3a9166013b53..2a472f3ce81ea322525652d7a3652f94b06cf5d1 100644 (file)
@@ -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)
index a2f9be7c793a97e9657ced606608a766b2bc52e3..1be9d4cfd658506520d19378c5855ec99493c812 100644 (file)
@@ -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<LayoutingEventArgs> LayoutChanged;
                public event EventHandler<DataSourceChangeEventArgs> DataSourceChanged;
                public event EventHandler<DataSourceChangeEventArgs> ParentChanged;
+               public event EventHandler<DataSourceChangeEventArgs> 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 ()
                {
index da42b8f53c203248a7bc8ecdc5b49437ebdf040b..a285e28214222bdaf5d73a796f6d025413159c33 100644 (file)
@@ -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)
index 06f0c2132368bfbde5d483f7044c89cefd9163ea..0afefeb910dacd90b3cc3a0407e71fb8a5d77747 100644 (file)
@@ -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)
index 078fd04d7dadbc9cdaa10bc5a0142df3019c28ef..cd57b2211594e9809d2ea39f147a63440b11efbe 100644 (file)
@@ -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)
index 7b7f897c82b8958da3cec32f1283d6890ae3a950..1664f67134c0e5f97c1c1ba7ea7f9a08d5dba49d 100644 (file)
@@ -42,7 +42,6 @@ namespace Crow
                public event EventHandler<SelectionChangeEventArgs> 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);
index 59b45167bcb9864e5bff83c4b80a86db3a762a60..eadbc9df04b656705ead9b943c5d86bbd4d7dd10 100644 (file)
@@ -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;
+               }
        }
 }
 
index a0f8fe75c17bf871a8eacbe8fc6f781716959e6f..4415609b0630242ad10f315b11bc2ef59e420592 100644 (file)
@@ -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
                /// </summary>
                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<ValueChangeEventArgs>));
 
-                       #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"));
                }
                /// <summary>
                /// create the valuechanged handler, the datasourcechanged handler and emit event handling
@@ -956,7 +963,7 @@ namespace Crow
                #endregion
 
                /// <summary> 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));
index 941b96f93f5b3db74bc6dfb7cdc50e4c95b1aba0..6547b0e5f7d964bcd0360b27e7b00a831e0bc559 100644 (file)
@@ -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);
                        }