2001-10-04 Mike Kestner <mkestner@speakeasy.net>

* glib/SimpleSignal.cs : Reworked to parallel SimpleEvent.

svn path=/trunk/gtk-sharp/; revision=1084
This commit is contained in:
Mike Kestner 2001-10-04 23:27:19 +00:00
parent 4c5e4f1d56
commit 26142a99ca
2 changed files with 70 additions and 31 deletions

View file

@ -1,3 +1,7 @@
2001-10-04 Mike Kestner <mkestner@speakeasy.net>
* glib/SimpleSignal.cs : Reworked to parallel SimpleEvent.
2001-10-04 Mike Kestner <mkestner@speakeasy.net> 2001-10-04 Mike Kestner <mkestner@speakeasy.net>
* gtk/Widget.cs : Implemented all the bool, string, and int props. * gtk/Widget.cs : Implemented all the bool, string, and int props.

View file

@ -7,6 +7,7 @@
namespace GLib { namespace GLib {
using System; using System;
using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using GLib; using GLib;
@ -19,7 +20,7 @@ namespace GLib {
/// specific data. /// specific data.
/// </remarks> /// </remarks>
public delegate void SimpleDelegate (IntPtr obj, String name); public delegate void SimpleDelegate (IntPtr obj, int key);
/// <summary> /// <summary>
/// SimpleSignal Class /// SimpleSignal Class
@ -31,47 +32,81 @@ namespace GLib {
public class SimpleSignal { public class SimpleSignal {
private static int _RefCount = 0; // A counter used to produce unique keys for instances.
private static int _NextKey = 0;
// Hashtable containing refs to all current instances.
private static Hashtable _Instances = new Hashtable ();
// locals to create and pin the shared delegate.
private static SimpleDelegate _Delegate; private static SimpleDelegate _Delegate;
private static GCHandle _GCHandle; private static GCHandle _GCHandle;
private static void SimpleCallback(IntPtr obj, String name) // Shared delegate that relays events to registered handlers.
private static void SimpleCallback(IntPtr obj, int inst_key)
{ {
Object o = Object.GetObject(obj); if (!_Instances.Contains (inst_key))
EventHandler eh = (EventHandler) o.Events[name]; throw new Exception ("Unexpected signal key");
if (eh != null)
{ SimpleSignal ss = (SimpleSignal) _Instances [inst_key];
eh(o, EventArgs.Empty); EventArgs args = new EventArgs ();
} ss._handler (ss._obj, args);
} }
public static SimpleDelegate Delegate // private instance members
{ private GLib.Object _obj;
get private EventHandler _handler;
{ private int _key;
if (_Delegate == null)
/// <summary>
/// SimpleSignal Constructor
/// </summary>
///
/// <remarks>
/// Registers a new event handler for a specified signal.
/// A connection to the raw object signal is made which
/// causes any events which occur to be relayed to the
/// event handler.
/// </remarks>
[DllImport ("gobject-1.3.dll", CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.Cdecl)]
static extern void g_signal_connect_data (
IntPtr obj, IntPtr name,
SimpleDelegate cb,
int key, IntPtr p, int flags);
public SimpleSignal (GLib.Object obj, IntPtr raw,
String name, EventHandler eh)
{ {
if (_Delegate == null) {
_Delegate = new SimpleDelegate(SimpleCallback); _Delegate = new SimpleDelegate(SimpleCallback);
/* FIXME: Can't do this until a layout attribute is defined for SimpleCallback /* FIXME: need layout attribute for
* apparently, since this throws an ArgumentException:Type does not have a * SimpleCallback to avoid an exception.
* layout attribute. * _GCHandle = GCHandle.Alloc (
* * _Delegate, GCHandleType.Pinned);
* _GCHandle = GCHandle.Alloc (_Delegate, GCHandleType.Pinned);
*/ */
} }
_RefCount++;
return _Delegate; _key = _NextKey++;
} _obj = obj;
_handler = eh;
_Instances [_key] = this;
g_signal_connect_data (
raw, Marshal.StringToHGlobalAnsi (name),
_Delegate, _key, new IntPtr (0), 0);
} }
public static void Unref() // Destructor needed to release references from the instance
// table and unpin the delegate if no refs remain.
~SimpleSignal ()
{ {
_RefCount--; _Instances.Remove (_key);
if (_RefCount < 1)
{ if (_Instances.Count == 0) {
_RefCount = 0; // FIXME: when pin works _GCHandle.Free();
_GCHandle.Free();
_Delegate = null; _Delegate = null;
} }
} }