diff --git a/ChangeLog b/ChangeLog index 465d2db01..0caeb6549 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-11-04 Mike Gorse + + * glib/PtrArray.cs, glib/glue/ptrarray.c, glib/Makefile.am, + glib/glue/Makefile.am, glib/gtype.cs, generator/SymbolTable.cs, + generator/ReturnValue.cs: Add PtrArray. + * glib/Marshaller.cs: Add PtrArrayToArray. + + * atk/Atk.metadata: Specify GetTarget return type. + + * atk/Object.custom, atk/glue/object.c: Support overriding + RefRelationSet. + 2008-11-03 Stephane Delcroix * gtk/Gtk.metadata: diff --git a/atk/Atk.metadata b/atk/Atk.metadata index 6c1914a37..afeffa703 100644 --- a/atk/Atk.metadata +++ b/atk/Atk.metadata @@ -26,5 +26,7 @@ true true 1 + true + AtkObject* 1 diff --git a/atk/Object.custom b/atk/Object.custom index b2fe92522..9e4a88fda 100644 --- a/atk/Object.custom +++ b/atk/Object.custom @@ -186,3 +186,44 @@ NotifyStateChange ((ulong)state, value); } + [DllImport("atksharpglue-2")] + static extern void atksharp_object_override_ref_relation_set (IntPtr type, RefRelationSetDelegate cb); + + [DllImport("atksharpglue-2")] + static extern IntPtr atksharp_object_base_ref_relation_set (IntPtr atk_obj); + + [GLib.CDeclCallback] + delegate IntPtr RefRelationSetDelegate (IntPtr raw); + + static RefRelationSetDelegate RefRelationSetCallback; + + static IntPtr RefRelationSet_cb (IntPtr raw) + { + try { + Atk.Object obj = GLib.Object.GetObject (raw, false) as Atk.Object; + Atk.RelationSet relation_set = obj.OnRefRelationSet (); + if (relation_set != null) + g_object_ref (relation_set.Handle); + return relation_set == null ? IntPtr.Zero : relation_set.Handle; + } catch (Exception e) { + GLib.ExceptionManager.RaiseUnhandledException (e, false); + } + + return IntPtr.Zero; + } + + + static void OverrideRefRelationSet (GLib.GType gtype) + { + if (RefRelationSetCallback == null) + RefRelationSetCallback = new RefRelationSetDelegate (RefRelationSet_cb); + atksharp_object_override_ref_relation_set (gtype.Val, RefRelationSetCallback); + } + + [GLib.DefaultSignalHandler (Type=typeof(Atk.Object), ConnectionMethod="OverrideRefRelationSet")] + protected virtual Atk.RelationSet OnRefRelationSet () + { + IntPtr raw = atksharp_object_base_ref_relation_set (Handle); + return GLib.Object.GetObject (raw, true) as RelationSet; + } + diff --git a/atk/glue/object.c b/atk/glue/object.c index 03002da1b..2e1fb8e08 100644 --- a/atk/glue/object.c +++ b/atk/glue/object.c @@ -32,6 +32,10 @@ AtkStateSet* atksharp_object_base_ref_state_set (AtkObject *base); void atksharp_object_override_get_index_in_parent (GType gtype, gpointer cb); +void atksharp_object_override_ref_relation_set (GType gtype, gpointer cb); + +AtkRelationSet* atksharp_object_base_ref_relation_set (AtkObject *base); + void atksharp_object_override_get_n_children (GType gtype, gpointer cb) { @@ -78,3 +82,22 @@ atksharp_object_override_get_index_in_parent (GType gtype, gpointer cb) ((AtkObjectClass *) klass)->get_index_in_parent = cb; } +void +atksharp_object_override_ref_relation_set (GType gtype, gpointer cb) +{ + AtkObjectClass *klass = g_type_class_peek (gtype); + if (!klass) + klass = g_type_class_ref (gtype); + ((AtkObjectClass *) klass)->ref_relation_set = cb; +} + +AtkRelationSet* +atksharp_object_base_ref_relation_set (AtkObject *atk_obj) +{ + AtkObjectClass *parent = g_type_class_peek (ATK_TYPE_OBJECT); + + if (parent->ref_relation_set) + return (*parent->ref_relation_set) (atk_obj); + return NULL; +} + diff --git a/generator/ReturnValue.cs b/generator/ReturnValue.cs index 88c36733a..4ace994d1 100644 --- a/generator/ReturnValue.cs +++ b/generator/ReturnValue.cs @@ -123,7 +123,10 @@ namespace GtkSharp.Generation { if (ElementType != String.Empty) { string args = (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false"); - return String.Format ("({0}[]) GLib.Marshaller.ListPtrToArray ({1}, typeof({2}), {3}, typeof({0}))", ElementType, var, IGen.QualifiedName, args); + if (IGen.QualifiedName == "GLib.PtrArray") + return String.Format ("({0}[]) GLib.Marshaller.PtrArrayToArray ({1}, {2}, typeof({0}))", ElementType, var, args); + else + return String.Format ("({0}[]) GLib.Marshaller.ListPtrToArray ({1}, typeof({2}), {3}, typeof({0}))", ElementType, var, IGen.QualifiedName, args); } else if (IGen is HandleBase) return ((HandleBase)IGen).FromNative (var, owned); else if (is_null_term) diff --git a/generator/SymbolTable.cs b/generator/SymbolTable.cs index cd36df191..e10b51f1d 100644 --- a/generator/SymbolTable.cs +++ b/generator/SymbolTable.cs @@ -116,6 +116,7 @@ namespace GtkSharp.Generation { AddType (new ManualGen ("GInitiallyUnowned", "GLib.InitiallyUnowned", "GLib.Object.GetObject ({0})")); AddType (new ManualGen ("GObject", "GLib.Object", "GLib.Object.GetObject ({0})")); AddType (new ManualGen ("GList", "GLib.List")); + AddType (new ManualGen ("GPtrArray", "GLib.PtrArray")); AddType (new ManualGen ("GSList", "GLib.SList")); AddType (new MarshalGen ("gunichar", "char", "uint", "GLib.Marshaller.CharToGUnichar ({0})", "GLib.Marshaller.GUnicharToChar ({0})")); AddType (new MarshalGen ("time_t", "System.DateTime", "IntPtr", "GLib.Marshaller.DateTimeTotime_t ({0})", "GLib.Marshaller.time_tToDateTime ({0})")); @@ -128,7 +129,6 @@ namespace GtkSharp.Generation { AddType (new SimpleGen ("GC", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GError", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GMemChunk", "IntPtr", "IntPtr.Zero")); - AddType (new SimpleGen ("GPtrArray", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GTimeVal", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GClosure", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GArray", "IntPtr", "IntPtr.Zero")); diff --git a/glib/GType.cs b/glib/GType.cs index 1c25a6cb7..8c2a5b88d 100755 --- a/glib/GType.cs +++ b/glib/GType.cs @@ -95,6 +95,7 @@ namespace GLib { Register (GType.String, typeof (string)); Register (GType.Pointer, typeof (IntPtr)); Register (GType.Object, typeof (GLib.Object)); + Register (GType.Pointer, typeof (IntPtr)); // One-way mapping gtypes[typeof (char)] = GType.UInt; diff --git a/glib/Makefile.am b/glib/Makefile.am index 077299909..2b3aa17e6 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -55,6 +55,7 @@ sources = \ ObjectManager.cs \ Opaque.cs \ PropertyAttribute.cs \ + PtrArray.cs \ Signal.cs \ SignalArgs.cs \ SignalAttribute.cs \ diff --git a/glib/Marshaller.cs b/glib/Marshaller.cs index e93938858..624b1805c 100644 --- a/glib/Marshaller.cs +++ b/glib/Marshaller.cs @@ -363,6 +363,15 @@ namespace GLib { return ListToArray (list, elem_type); } + public static Array PtrArrayToArray (IntPtr list_ptr, bool owned, bool elements_owned, Type elem_type) + { + GLib.PtrArray array = new GLib.PtrArray (list_ptr, elem_type, owned, elements_owned); + Array ret = Array.CreateInstance (elem_type, array.Count); + array.CopyTo (ret, 0); + array.Dispose (); + return ret; + } + public static Array ListToArray (ListBase list, System.Type type) { Array result = Array.CreateInstance (type, list.Count); diff --git a/glib/PtrArray.cs b/glib/PtrArray.cs new file mode 100644 index 000000000..df41dec29 --- /dev/null +++ b/glib/PtrArray.cs @@ -0,0 +1,275 @@ +// PtrArray.cs - PtrArray wrapper implementation +// +// Authors: Mike Gorse +// +// Copyright (c) 2008 Novell, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of version 2 of the Lesser GNU General +// Public License as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + + +namespace GLib { + + using System; + using System.Collections; + using System.Runtime.InteropServices; + + public class PtrArray : IDisposable, ICollection, ICloneable, IWrapper { + + private IntPtr handle = IntPtr.Zero; + private bool managed = false; + internal bool elements_owned = false; + protected System.Type element_type = null; + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_ptr_array_sized_new (uint n_preallocs); + + public PtrArray (uint n_preallocs, System.Type element_type, bool owned, bool elements_owned) + { + handle = g_ptr_array_sized_new (n_preallocs); + this.element_type = element_type; + managed = owned; + this.elements_owned = elements_owned; + } + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_ptr_array_new (); + + public PtrArray (System.Type element_type, bool owned, bool elements_owned) + { + handle = g_ptr_array_new (); + this.element_type = element_type; + managed = owned; + this.elements_owned = elements_owned; + } + + internal PtrArray (IntPtr raw, System.Type element_type, bool owned, bool elements_owned) + { + handle = raw; + this.element_type = element_type; + managed = owned; + this.elements_owned = elements_owned; + } + public PtrArray (IntPtr raw, System.Type element_type) : this (raw, element_type, false, false) {} + + public PtrArray (IntPtr raw) : this (raw, null) {} + + ~PtrArray () + { + Dispose (false); + } + + // IDisposable + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_ptr_array_free (IntPtr raw, bool free_seg); + + [DllImport ("libglib-2.0-0.dll")] + static extern void g_object_unref (IntPtr item); + + [DllImport ("libglib-2.0-0.dll")] + static extern void g_free (IntPtr item); + + void Dispose (bool disposing) + { + if (Handle == IntPtr.Zero) + return; + + if (elements_owned) { + int count = Count; + for (uint i = 0; i < count; i++) + if (typeof (GLib.Object).IsAssignableFrom (element_type)) + g_object_unref (NthData (i)); + else if (typeof (GLib.Opaque).IsAssignableFrom (element_type)) + GLib.Opaque.GetOpaque (NthData (i), element_type, true).Dispose (); + else + g_free (NthData (i)); + } + + if (managed) + g_ptr_array_free (Handle, true); + + handle = IntPtr.Zero; + } + + public IntPtr Handle { + get { + return handle; + } + } + + [DllImport("glibsharpglue-2")] + static extern IntPtr gtksharp_ptr_array_get_array (IntPtr raw); + + public IntPtr ArrayPtr { + get { + return gtksharp_ptr_array_get_array (Handle); + } + } + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_ptr_array_add (IntPtr raw, IntPtr val); + + public void Add (IntPtr val) + { + g_ptr_array_add (Handle, val); + } + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_ptr_array_remove (IntPtr raw, IntPtr data); + + public void Remove (IntPtr data) + { + g_ptr_array_remove (Handle, data); + } + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_ptr_array_remove_range (IntPtr raw, uint index, uint length); + + public void RemoveRange (IntPtr data, uint index, uint length) + { + g_ptr_array_remove_range (Handle, index, length); + } + + [DllImport("glibsharpglue-2")] + static extern int gtksharp_ptr_array_get_count (IntPtr raw); + + // ICollection + public int Count { + get { + return gtksharp_ptr_array_get_count (Handle); + } + } + + [DllImport("glibsharpglue-2")] + static extern IntPtr gtksharp_ptr_array_get_nth (IntPtr raw, uint idx); + + public object this [int index] { + get { + IntPtr data = NthData ((uint) index); + object ret = null; + ret = DataMarshal (data); + return ret; + } + } + + internal object DataMarshal (IntPtr data) + { + object ret = null; + if (element_type != null) { + if (element_type == typeof (string)) + ret = Marshaller.Utf8PtrToString (data); + else if (element_type == typeof (IntPtr)) + ret = data; + else if (element_type.IsSubclassOf (typeof (GLib.Object))) + ret = GLib.Object.GetObject (data, false); + else if (element_type.IsSubclassOf (typeof (GLib.Opaque))) + ret = GLib.Opaque.GetOpaque (data, element_type, elements_owned); + else if (element_type == typeof (int)) + ret = (int) data; + else if (element_type.IsValueType) + ret = Marshal.PtrToStructure (data, element_type); + else + ret = Activator.CreateInstance (element_type, new object[] {data}); + + } else if (Object.IsObject (data)) + ret = GLib.Object.GetObject (data, false); + + return ret; + } + + internal IntPtr NthData (uint index) + { + return gtksharp_ptr_array_get_nth (Handle, index);; + } + + // Synchronization could be tricky here. Hmm. + public bool IsSynchronized { + get { return false; } + } + + public object SyncRoot { + get { return null; } + } + + public void CopyTo (Array array, int index) + { + if (array == null) + throw new ArgumentNullException ("Array can't be null."); + + if (index < 0) + throw new ArgumentOutOfRangeException ("Index must be greater than 0."); + + if (index + Count < array.Length) + throw new ArgumentException ("Array not large enough to copy into starting at index."); + + for (int i = 0; i < Count; i++) + ((IList) array) [index + i] = this [i]; + } + + private class ListEnumerator : IEnumerator + { + private int current = -1; + private PtrArray vals; + + public ListEnumerator (PtrArray vals) + { + this.vals = vals; + } + + public object Current { + get { + if (current == -1) + return null; + return vals [current]; + } + } + + public bool MoveNext () + { + if (++current >= vals.Count) { + current = -1; + return false; + } + + return true; + } + + public void Reset () + { + current = -1; + } + } + + // IEnumerable + public IEnumerator GetEnumerator () + { + return new ListEnumerator (this); + } + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_ptr_array_copy (IntPtr raw); + + // ICloneable + public object Clone () + { + return new PtrArray (g_ptr_array_copy (Handle), element_type, false, false); + } + } +} diff --git a/glib/glue/Makefile.am b/glib/glue/Makefile.am index 3f34cc9e9..90f7390e0 100644 --- a/glib/glue/Makefile.am +++ b/glib/glue/Makefile.am @@ -7,6 +7,7 @@ libglibsharpglue_2_la_SOURCES = \ error.c \ list.c \ object.c \ + ptrarray.c \ signal.c \ slist.c \ type.c \ diff --git a/glib/glue/ptrarray.c b/glib/glue/ptrarray.c new file mode 100644 index 000000000..25e2b0bbd --- /dev/null +++ b/glib/glue/ptrarray.c @@ -0,0 +1,45 @@ +/* ptrarray.c : Glue to access GPtrArray fields + * + * Author: Mike Gorse + * + * Copyright (c) 2008 Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the Lesser GNU General + * Public License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void *gtksharp_ptr_array_get_array (GPtrArray *pa); +guint gtksharp_ptr_array_get_count (GPtrArray *pa); +void *gtksharp_ptr_array_get_nth (GPtrArray *pa, int index); + +void * +gtksharp_ptr_array_get_array (GPtrArray *pa) +{ + return pa->pdata; +} + +guint +gtksharp_ptr_array_get_count (GPtrArray *pa) +{ + return pa->len; +} + +void * +gtksharp_ptr_array_get_nth (GPtrArray *pa, int index) +{ + return g_ptr_array_index (pa, index); +} +