GtkSharp/glib/ListBase.cs
Rachel Hestilow c8d090f62f 2002-08-31 Rachel Hestilow <hestilow@ximian.com>
Proper GList, GSList support. Read-only for now.

	* glue/list.c: Added.
	* glue/Makefile.am: Add list.c
	* glue/type.c: Add function gtksharp_is_object.

	* glib/ListBase.cs, List.cs: Added.
	* glib/SList.cs: Inherit from ListBase.
	* glib/Object.cs: Add static method "IsObject".

	* generator/Method.cs: Pass on element_type to constructor
	if specified.
	* generator/SymbolTable.cs: Move GList to manual types.

	* sample/GladeViewer.cs: Remove list hacks.

	* sources/Gnome.metadata: Specify element types for
	CanvasPathDef.Split and IconList.GetSelection. Rename
	CanvasPathDef *to methods to properly capitalized *To.
	* sources/Gtk.metadata: Hide Widget.ListAccelClosures until
	GClosure is handled properly.
	* sources/Pango.metadata: Added.

	* sample/test/TestToolbar.cs: Compile with recent delegate changes.

svn path=/trunk/gtk-sharp/; revision=7166
2002-09-01 04:46:38 +00:00

177 lines
3.3 KiB
C#

// SList.cs - GSList class wrapper implementation
//
// Authors: Mike Kestner <mkestner@speakeasy.net>
//
// (c) 2002 Mike Kestner
namespace GLib {
using System;
using System.Collections;
using System.Runtime.InteropServices;
/// <summary>
/// ListBase Class
/// </summary>
///
/// <remarks>
/// Base class for GList and GSList.
/// </remarks>
internal abstract class ListBase : IDisposable, ICollection, GLib.IWrapper, ICloneable {
private IntPtr list_ptr = IntPtr.Zero;
private int length = -1;
private bool managed = false;
private Type element_type = null;
abstract internal IntPtr GetData (IntPtr current);
abstract internal IntPtr Next (IntPtr current);
abstract internal int Length (IntPtr list);
abstract internal void Free (IntPtr list);
protected ListBase (IntPtr list, Type element_type)
{
list_ptr = list;
this.element_type = element_type;
}
protected ListBase (IntPtr list)
{
list_ptr = list;
}
~ListBase ()
{
Console.WriteLine ("entering dispose");
Dispose ();
Console.WriteLine ("leaving dispose");
}
public bool Managed {
set { managed = value; }
}
/// <summary>
/// Handle Property
/// </summary>
///
/// <remarks>
/// A raw list reference for marshaling situations.
/// </remarks>
public IntPtr Handle {
get {
return list_ptr;
}
}
internal IntPtr Raw {
get {
return list_ptr;
}
set {
if (managed && list_ptr != IntPtr.Zero)
Dispose ();
list_ptr = value;
}
}
// ICollection
public int Count {
get {
if (length == -1)
length = Length (list_ptr);
return length;
}
}
// 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)
{
object[] orig = new object[Count];
int i = 0;
foreach (object o in this)
orig[i] = o;
orig.CopyTo (array, index);
}
private class ListEnumerator : IEnumerator
{
private IntPtr current = IntPtr.Zero;
private ListBase list;
public ListEnumerator (ListBase list)
{
this.list = list;
}
public object Current {
get {
IntPtr data = list.GetData (current);
object ret = null;
if (list.element_type != null)
{
if (list.element_type == typeof (string))
ret = Marshal.PtrToStringAnsi (data);
else if (list.element_type == typeof (int))
ret = (int) data;
else if (list.element_type.IsValueType)
ret = Marshal.PtrToStructure (data, list.element_type);
else
ret = Activator.CreateInstance (list.element_type, new object[] {data});
}
else if (Object.IsObject (data))
ret = GLib.Object.GetObject (data);
return ret;
}
}
public bool MoveNext ()
{
if (current == IntPtr.Zero)
current = list.list_ptr;
else
current = list.Next (current);
return (current != IntPtr.Zero);
}
public void Reset ()
{
current = IntPtr.Zero;
}
}
// IEnumerable
public IEnumerator GetEnumerator ()
{
return new ListEnumerator (this);
}
// IDisposable
public void Dispose ()
{
if (!managed)
return;
if (list_ptr != IntPtr.Zero)
Free (list_ptr);
list_ptr = IntPtr.Zero;
length = -1;
}
// ICloneable
abstract public object Clone ();
}
}