diff --git a/ChangeLog b/ChangeLog index 6d0720d46..8c9c55785 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2003-08-26 Gonzalo Paniagua Javier + + * gconf/GConf/Value.cs: implemented support for lists. + + * glib/ListBase.cs: implemented the IDisposable stuff and created a + new method, FreeList, to free the list when needed. + + * glade/HandlerNotFoundException.cs: make it derive from + SystemException. Don't override Message, the message is created in the + .ctor. + 2003-08-26 Martin Willemoes Hansen * sources/makefile diff --git a/gconf/GConf/Value.cs b/gconf/GConf/Value.cs index 9489bd184..e46ef603e 100644 --- a/gconf/GConf/Value.cs +++ b/gconf/GConf/Value.cs @@ -1,6 +1,7 @@ namespace GConf { using System; + using System.Collections; using System.Runtime.InteropServices; internal enum ValueType @@ -49,6 +50,8 @@ namespace GConf return ValueType.Float; } else if (data is bool) { return ValueType.Bool; + } else if (data is ICollection) { + return ValueType.List; } else { return ValueType.Invalid; } @@ -63,6 +66,12 @@ namespace GConf Set (data, type); } + [DllImport("gconf-2")] + static extern IntPtr gconf_value_set_list_nocopy (IntPtr value, IntPtr list); + + [DllImport("gconf-2")] + static extern IntPtr gconf_value_set_list_type (IntPtr value, ValueType vtype); + void Set (object data, ValueType type) { if (data == null) @@ -82,10 +91,41 @@ namespace GConf case ValueType.Bool: gconf_value_set_bool (Raw, (bool) data); break; + case ValueType.List: + ValueType listType; + GLib.SList list = GetListFromCollection ((ICollection) data, out listType); + gconf_value_set_list_type (Raw, listType); + gconf_value_set_list_nocopy (Raw, list.Handle); + break; default: throw new InvalidValueTypeException (); } } + + GLib.SList GetListFromCollection (ICollection data, out ValueType listType) + { + object [] arr = (object []) Array.CreateInstance (typeof (object), data.Count); + data.CopyTo (arr, 0); + + listType = ValueType.Invalid; + GLib.SList list = new GLib.SList (IntPtr.Zero); + GC.SuppressFinalize (list); + + foreach (object o in arr) { + ValueType type = LookupType (o); + if (listType == ValueType.Invalid) + listType = type; + + if (listType == ValueType.Invalid || type != listType) + throw new InvalidValueTypeException (); + + Value v = new Value (o); + GC.SuppressFinalize (v); + list.Append (v.Raw); + } + + return list; + } [DllImport("gconf-2")] static extern IntPtr gconf_value_get_string (IntPtr value); @@ -99,6 +139,9 @@ namespace GConf [DllImport("gconf-2")] static extern bool gconf_value_get_bool (IntPtr value); + [DllImport("gconf-2")] + static extern IntPtr gconf_value_get_list (IntPtr value); + public object Get () { switch (val_type) @@ -111,11 +154,44 @@ namespace GConf return gconf_value_get_float (Raw); case ValueType.Bool: return gconf_value_get_bool (Raw); + case ValueType.List: + GLib.SList list = new GLib.SList (gconf_value_get_list (Raw), typeof (Value)); + Array result = Array.CreateInstance (GetListType (), list.Count); + int i = 0; + foreach (Value v in list) { + ((IList) result) [i] = v.Get (); + v.managed = false; // This is the trick to prevent a crash + i++; + } + + return result; default: throw new InvalidValueTypeException (); } } + [DllImport("gconf-2")] + static extern ValueType gconf_value_get_list_type (IntPtr value); + + Type GetListType () + { + ValueType vt = gconf_value_get_list_type (Raw); + switch (vt) { + case ValueType.String: + return typeof (string); + case ValueType.Int: + return typeof (int); + case ValueType.Float: + return typeof (float); + case ValueType.Bool: + return typeof (bool); + case ValueType.List: + return typeof (GLib.SList); + default: + throw new InvalidValueTypeException (); + } + } + [DllImport("gconf-2")] static extern IntPtr gconf_value_new (ValueType type); @@ -173,10 +249,16 @@ namespace GConf ~Value () { - Dispose (); + Dispose (false); } public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) { if (managed && Raw != IntPtr.Zero) { diff --git a/glade/HandlerNotFoundExeception.cs b/glade/HandlerNotFoundExeception.cs index 8702cebb6..d9ff73632 100644 --- a/glade/HandlerNotFoundExeception.cs +++ b/glade/HandlerNotFoundExeception.cs @@ -14,7 +14,7 @@ namespace Glade { /// Exception thrown when signal autoconnection fails. /// [Serializable] - public class HandlerNotFoundException : Exception + public class HandlerNotFoundException : SystemException { string handler_name; string signal_name; @@ -23,6 +23,14 @@ namespace Glade { public HandlerNotFoundException (string handler_name, string signal_name, EventInfo evnt, Type delegate_type) + : this (handler_name, signal_name, evnt, delegate_type, null) + { + } + + public HandlerNotFoundException (string handler_name, string signal_name, + EventInfo evnt, Type delegate_type, Exception inner) + : base ("No handler " + handler_name + " found for signal " + signal_name, + inner) { this.handler_name = handler_name; this.signal_name = signal_name; @@ -39,13 +47,6 @@ namespace Glade { delegate_type = info.GetValue ("DelegateType", typeof (Type)) as Type; } - public override string Message - { - get { - return "No handler " + handler_name + " found for signal " + signal_name; - } - } - public string HandlerName { get { diff --git a/glib/ListBase.cs b/glib/ListBase.cs index 94176b9cc..6c62f2488 100644 --- a/glib/ListBase.cs +++ b/glib/ListBase.cs @@ -49,7 +49,7 @@ namespace GLib { ~ListBase () { - Dispose (); + Dispose (false); } public bool Managed { @@ -76,7 +76,8 @@ namespace GLib { } set { if (managed && list_ptr != IntPtr.Zero) - Dispose (); + FreeList (); + list_ptr = value; } } @@ -179,16 +180,27 @@ namespace GLib { // IDisposable public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) { if (!managed) return; + FreeList (); + } + + void FreeList () + { if (list_ptr != IntPtr.Zero) Free (list_ptr); list_ptr = IntPtr.Zero; length = -1; } - + // ICloneable abstract public object Clone (); }