From 1215ebc77047d44cc157b8773d5b7dd5f628f874 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 1 Dec 2011 16:49:50 +0000 Subject: [PATCH 1/5] Object: Use the type as top-level key for properties hash Types could use same param_spec object so their PropertyInfo objects shouldn't be mixed, otherwise we could get type mismatch errors like the one in: http://mail.gnome.org/archives/banshee-list/2011-November/msg00141.html This should be the final part of: https://bugzilla.novell.com/show_bug.cgi?id=442068 --- glib/Object.cs | 55 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/glib/Object.cs b/glib/Object.cs index 06ed9e4ac..0efdcc432 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -151,13 +151,14 @@ namespace GLib { } } - // Key: The pointer to the ParamSpec of the property - // Value: The corresponding PropertyInfo object - static Dictionary properties; - static Dictionary Properties { + // Key: The Type for the set of properties + // Value->SubKey: The pointer to the ParamSpec of the property + // Value->SubValue: The corresponding PropertyInfo object + static Dictionary> properties; + static Dictionary> Properties { get { if (properties == null) - properties = new Dictionary (); + properties = new Dictionary> (); return properties; } } @@ -307,7 +308,13 @@ namespace GLib { PropertyAttribute property_attr = attr as PropertyAttribute; try { IntPtr param_spec = RegisterProperty (gtype, property_attr.Name, property_attr.Nickname, property_attr.Blurb, idx, (GType) pinfo.PropertyType, pinfo.CanRead, pinfo.CanWrite); - Properties.Add (param_spec, pinfo); + Type type = (Type)gtype; + Dictionary gtype_properties; + if (!Properties.TryGetValue (type, out gtype_properties)) { + gtype_properties = new Dictionary (); + Properties [type] = gtype_properties; + } + gtype_properties.Add (param_spec, pinfo); idx++; } catch (ArgumentException) { throw new InvalidOperationException (String.Format ("GLib.PropertyAttribute cannot be applied to property {0} of type {1} because the return type of the property is not supported", pinfo.Name, t.FullName)); @@ -321,11 +328,18 @@ namespace GLib { static void GetPropertyCallback (IntPtr handle, uint property_id, ref GLib.Value value, IntPtr param_spec) { - if (!Properties.ContainsKey (param_spec)) + GLib.Object obj = GLib.Object.GetObject (handle, false); + var type = (Type)obj.LookupGType (); + + Dictionary props; + if (!Properties.TryGetValue (type, out props)) return; - GLib.Object obj = GLib.Object.GetObject (handle, false); - value.Val = Properties [param_spec].GetValue (obj, new object [0]); + PropertyInfo prop; + if (!props.TryGetValue (param_spec, out prop)) + return; + + value.Val = prop.GetValue (obj, new object [0]); } static GetPropertyDelegate get_property_handler; @@ -352,11 +366,18 @@ namespace GLib { o.Raw = handle; } } - if (!Properties.ContainsKey (param_spec)) + GLib.Object obj = GLib.Object.GetObject (handle, false); + var type = (Type)obj.LookupGType (); + + Dictionary props; + if (!Properties.TryGetValue (type, out props)) return; - GLib.Object obj = GLib.Object.GetObject (handle, false); - Properties [param_spec].SetValue (obj, value.Val, new object [0]); + PropertyInfo prop; + if (!props.TryGetValue (param_spec, out prop)) + return; + + prop.SetValue (obj, value.Val, new object [0]); } static SetPropertyDelegate set_property_handler; @@ -405,8 +426,14 @@ namespace GLib { if (declared_prop == null) continue; IntPtr param_spec = FindInterfaceProperty (adapter.GType, property_attr.Name); - - Properties [param_spec] = declared_prop; + + Type type = (Type)adapter.GType; + Dictionary props; + if (!Properties.TryGetValue (type, out props)) { + props = new Dictionary (); + Properties [type] = props; + } + props [param_spec] = declared_prop; } } } From 91dda7f5be5de101437ca0c44bad4d8df21caffe Mon Sep 17 00:00:00 2001 From: Bertrand Lorentz Date: Sat, 3 Dec 2011 16:18:24 +0100 Subject: [PATCH 2/5] Object: Fix registration of inherited interface properties We need to add inherited interface properties in the Properties hash, so we remove the DeclaredOnly flag when looking for interface properties in the type. We also need to use the type itself as the hash key, and not the adapter type. --- glib/Object.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/glib/Object.cs b/glib/Object.cs index 0efdcc432..7750d06d4 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -422,16 +422,15 @@ namespace GLib { if (attrs.Length == 0) continue; PropertyAttribute property_attr = attrs [0]; - PropertyInfo declared_prop = t.GetProperty (p.Name, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); + PropertyInfo declared_prop = t.GetProperty (p.Name, BindingFlags.Public | BindingFlags.Instance); if (declared_prop == null) continue; IntPtr param_spec = FindInterfaceProperty (adapter.GType, property_attr.Name); - Type type = (Type)adapter.GType; Dictionary props; - if (!Properties.TryGetValue (type, out props)) { + if (!Properties.TryGetValue (t, out props)) { props = new Dictionary (); - Properties [type] = props; + Properties [t] = props; } props [param_spec] = declared_prop; } From d239b5cc4ed6f4274b1ad9632be28b55ddecf79b Mon Sep 17 00:00:00 2001 From: Bertrand Lorentz Date: Sat, 3 Dec 2011 16:24:23 +0100 Subject: [PATCH 3/5] Object: Remove some trailing whitespace, no real code change --- glib/Object.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glib/Object.cs b/glib/Object.cs index 7750d06d4..1cd05830d 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -289,7 +289,7 @@ namespace GLib { IntPtr declaring_class = gtype.GetClassPtr (); ParamSpec pspec = new ParamSpec ("gtk-sharp-managed-instance", "", "", GType.Pointer, ParamFlags.Writable | ParamFlags.ConstructOnly); g_object_class_install_property (declaring_class, idx, pspec.Handle); - idx++; + idx++; } foreach (PropertyInfo pinfo in t.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)) { @@ -335,7 +335,7 @@ namespace GLib { if (!Properties.TryGetValue (type, out props)) return; - PropertyInfo prop; + PropertyInfo prop; if (!props.TryGetValue (param_spec, out prop)) return; @@ -373,7 +373,7 @@ namespace GLib { if (!Properties.TryGetValue (type, out props)) return; - PropertyInfo prop; + PropertyInfo prop; if (!props.TryGetValue (param_spec, out prop)) return; From 0de6e9869d5ece36b2ed92980f33577c2d06843d Mon Sep 17 00:00:00 2001 From: Bertrand Lorentz Date: Sat, 3 Dec 2011 16:25:08 +0100 Subject: [PATCH 4/5] ParamSpec: Add override modifier to the ToString method This remove a compilation warning. --- glib/ParamSpec.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/ParamSpec.cs b/glib/ParamSpec.cs index 74134eaf8..f75e99d78 100644 --- a/glib/ParamSpec.cs +++ b/glib/ParamSpec.cs @@ -116,7 +116,7 @@ namespace GLib { } } - public string ToString () + public override string ToString () { GParamSpec spec = (GParamSpec) Marshal.PtrToStructure (Handle, typeof (GParamSpec)); GType valtype= new GType (spec.value_type); From 2297695fd2fb296aadd225af303eda7931ec2189 Mon Sep 17 00:00:00 2001 From: Bertrand Lorentz Date: Sat, 3 Dec 2011 16:30:23 +0100 Subject: [PATCH 5/5] sample: Make the CustomScrollableWidget sample more elaborate Make the custom widget a generic class, and add and use a derived class. Also add a second instance of the custom widget, to better test the interface properties support. --- sample/CustomScrollableWidget.cs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sample/CustomScrollableWidget.cs b/sample/CustomScrollableWidget.cs index 768fc9bed..4c28161dc 100644 --- a/sample/CustomScrollableWidget.cs +++ b/sample/CustomScrollableWidget.cs @@ -9,14 +9,25 @@ class CustomScrollableWidgetTest { Window win = new Window ("Custom Scrollable Widget Test"); win.DeleteEvent += new DeleteEventHandler (OnQuit); + VPaned paned = new VPaned (); + ScrolledWindow scroll = new ScrolledWindow (); scroll.HscrollbarPolicy = PolicyType.Automatic; scroll.VscrollbarPolicy = PolicyType.Automatic; - CustomScrollableWidget cw = new CustomScrollableWidget ("This one label that is repeated"); + var cw = new DerivedScrollableWidget ("This one label that is repeated"); scroll.Add (cw); + paned.Pack1 (scroll, true, false); + + scroll = new ScrolledWindow (); + scroll.HscrollbarPolicy = PolicyType.Automatic; + scroll.VscrollbarPolicy = PolicyType.Automatic; - win.Add (scroll); + var cw2 = new DerivedScrollableWidget ("Another label that is repeated"); + scroll.Add (cw2); + paned.Pack2 (scroll, true, false); + + win.Add (paned); win.DefaultWidth = 200; win.DefaultHeight = 200; win.ShowAll (); @@ -36,7 +47,13 @@ abstract class CustomBase : Widget { } } -class CustomScrollableWidget : CustomBase, ScrollableImplementor { +class DerivedScrollableWidget : CustomScrollableWidget +{ + public DerivedScrollableWidget (string label) : base (label) + { } +} + +class CustomScrollableWidget : CustomBase, ScrollableImplementor { private int num_rows = 20; private string label; private Pango.Layout layout; @@ -166,8 +183,6 @@ class CustomScrollableWidget : CustomBase, ScrollableImplementor { if (hadjustment.Value + hadjustment.PageSize > hadjustment.Upper) { hadjustment.Value = hadjustment.Upper - hadjustment.PageSize; } - Console.WriteLine (String.Format ("H adj={0} upper={1} PageSize={2} PageInc={3}", - HadjustmentValue, hadjustment.Upper, hadjustment.PageSize, hadjustment.PageIncrement)); hadjustment.Change (); } @@ -177,8 +192,6 @@ class CustomScrollableWidget : CustomBase, ScrollableImplementor { if (vadjustment.Value + vadjustment.PageSize > vadjustment.Upper) { vadjustment.Value = vadjustment.Upper - vadjustment.PageSize; } - Console.WriteLine (String.Format ("V adj={0} upper={1} PageSize={2} PageInc={3}", - VadjustmentValue, vadjustment.Upper, vadjustment.PageSize, vadjustment.PageIncrement)); vadjustment.Change (); } }