From 42d9e260840d46ab9d960ae45d71dc47a03fb6cf Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Mon, 14 Sep 2015 12:30:20 +0200 Subject: [PATCH] Clear Bindings when GraphicObject is destroyed --- src/CompilerServices/CompilerServices.cs | 38 ++++++--------------- src/GraphicObjects/GraphicObject.cs | 42 ++++++++++++++++++++++-- src/GraphicObjects/Group.cs | 6 ++++ src/GraphicObjects/PrivateContainer.cs | 7 ++++ src/OpenTKGameWindow.cs | 5 ++- 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index f383c8ee..b6a43eb1 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -12,32 +12,6 @@ namespace go { public static class CompilerServices { - public static void createDynHandler(string eventName, - object dstObj, Type handlerArgsType, string destProp, string src) - { - Type dstType = dstObj.GetType (); - - Type[] args = {typeof(object), handlerArgsType}; - DynamicMethod hello = new DynamicMethod("dynHandle", - typeof(void), - args, - dstType.Module); - - MethodInfo dstMi = dstType.GetProperty (destProp).GetSetMethod (); - FieldInfo srcFi = typeof(go.Color).GetField (src, BindingFlags.Static|BindingFlags.Public); - ILGenerator il = hello.GetILGenerator(256); - - il.Emit(OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldsfld, srcFi); - il.Emit(OpCodes.Callvirt, dstMi); - il.Emit(OpCodes.Ret); - //hello.DefineParameter(1, ParameterAttributes.In, "instance"); - //hello.DefineParameter(2, ParameterAttributes.In, "value"); - FieldInfo fi = getEventHandlerField (dstType, eventName); - Delegate del = hello.CreateDelegate(fi.FieldType); - fi.SetValue(dstObj, del); - - } static int dynHandleCpt = 0; /// /// Compile events expression in GOML attributes @@ -60,6 +34,10 @@ namespace go typeof(void), args, srcType.Module); + + es.Source.DynamicMethodIds.Add (dynHandleCpt); + + dynHandleCpt++; #region IL generation ILGenerator il = dm.GetILGenerator(256); @@ -155,7 +133,7 @@ namespace go #endregion - FieldInfo evtFi = getEventHandlerField (srcType, es.MemberName); + FieldInfo evtFi = GetEventHandlerField (srcType, es.MemberName); Delegate del = dm.CreateDelegate(evtFi.FieldType); evtFi.SetValue(es.Source, del); } @@ -269,6 +247,10 @@ namespace go args, srcType.Module, true); + (binding.Source as GraphicObject).DynamicMethodIds.Add (dynHandleCpt); + + dynHandleCpt++; + //register target object reference int dstIdx = Interface.References.IndexOf(binding.Source); @@ -385,7 +367,7 @@ namespace go } #endregion - public static FieldInfo getEventHandlerField(Type type, string eventName) + public static FieldInfo GetEventHandlerField(Type type, string eventName) { FieldInfo fi; Type ty = type; diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index f8ffb511..c9f7a39f 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -21,6 +21,8 @@ namespace go { public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange { + internal List DynamicMethodIds = new List (); + #region IValueChange implementation public event EventHandler ValueChanged; public virtual void NotifyValueChanged(string MemberName, object _value) @@ -304,7 +306,17 @@ namespace go get { return _minimumSize; } set { _minimumSize = value; } } - [XmlIgnore]public object DataSource; + object dataSource; + + [XmlIgnore]public object DataSource { + set { + dataSource = value; + } + get { + return dataSource == null ? + Parent is GraphicObject ? (Parent as GraphicObject).DataSource : null : dataSource; + } + } #endregion /// @@ -632,7 +644,7 @@ namespace go using (ImageSurface draw = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { using (Context gr = new Context (draw)) { - gr.Antialias = Antialias.Subpixel; + gr.Antialias = Antialias.Gray; onDraw (gr); } draw.Flush (); @@ -917,5 +929,31 @@ namespace go } #endregion + /// + /// Remove dynamic delegates by ids from dataSource + /// and delete ref of this in Shared interface refs + /// + public virtual void ClearBinding(){ + if (this.DataSource == null) + return; + object ds = this.DataSource; + Type dataSourceType = ds.GetType (); + EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged"); + FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged"); + MulticastDelegate multicastDelegate = evtFi.GetValue (ds) as MulticastDelegate; + if (multicastDelegate != null){ + foreach (Delegate d in multicastDelegate.GetInvocationList()) + { + string dn = d.Method.Name; + if (!dn.StartsWith ("dynHandle_")) + continue; + int did = int.Parse (dn.Substring (10)); + if (this.DynamicMethodIds.Contains(did)) + evtInfo.RemoveEventHandler (ds, d); + } + } + + Interface.References.Remove (this); + } } } diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index d9e35aa8..87a9ee5c 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -278,5 +278,11 @@ namespace go } #endregion + + public override void ClearBinding(){ + foreach (GraphicObject c in children) + c.ClearBinding (); + base.ClearBinding (); + } } } diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index b6391621..010fca71 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -146,6 +146,13 @@ namespace go child.checkHoverWidget (e); } #endregion + + public override void ClearBinding () + { + if (child != null) + child.ClearBinding (); + base.ClearBinding (); + } } } diff --git a/src/OpenTKGameWindow.cs b/src/OpenTKGameWindow.cs index 355ae304..a50a05be 100755 --- a/src/OpenTKGameWindow.cs +++ b/src/OpenTKGameWindow.cs @@ -86,13 +86,16 @@ namespace go public void DeleteWidget(GraphicObject g) { g.Visible = false;//trick to ensure clip is added to refresh zone + g.ClearBinding(); GraphicObjects.Remove (g); } /// Remove all Graphic objects from top container public void ClearInterface() { - foreach (GraphicObject g in GraphicObjects) + foreach (GraphicObject g in GraphicObjects) { g.Visible = false; + g.ClearBinding (); + } GraphicObjects.Clear (); } public void Quit () -- 2.47.3