From 26142a99ca6e5646257271be1a02e2afbe3070a8 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Thu, 4 Oct 2001 23:27:19 +0000 Subject: [PATCH] 2001-10-04 Mike Kestner * glib/SimpleSignal.cs : Reworked to parallel SimpleEvent. svn path=/trunk/gtk-sharp/; revision=1084 --- ChangeLog | 4 ++ glib/SimpleSignal.cs | 97 ++++++++++++++++++++++++++++++-------------- 2 files changed, 70 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index c36ff9a65..3ea9d025e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2001-10-04 Mike Kestner + + * glib/SimpleSignal.cs : Reworked to parallel SimpleEvent. + 2001-10-04 Mike Kestner * gtk/Widget.cs : Implemented all the bool, string, and int props. diff --git a/glib/SimpleSignal.cs b/glib/SimpleSignal.cs index 4d8dbc375..d4083ca68 100644 --- a/glib/SimpleSignal.cs +++ b/glib/SimpleSignal.cs @@ -7,6 +7,7 @@ namespace GLib { using System; + using System.Collections; using System.Runtime.InteropServices; using GLib; @@ -19,7 +20,7 @@ namespace GLib { /// specific data. /// - public delegate void SimpleDelegate (IntPtr obj, String name); + public delegate void SimpleDelegate (IntPtr obj, int key); /// /// SimpleSignal Class @@ -31,47 +32,81 @@ namespace GLib { 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 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); - EventHandler eh = (EventHandler) o.Events[name]; - if (eh != null) - { - eh(o, EventArgs.Empty); - } + if (!_Instances.Contains (inst_key)) + throw new Exception ("Unexpected signal key"); + + SimpleSignal ss = (SimpleSignal) _Instances [inst_key]; + EventArgs args = new EventArgs (); + ss._handler (ss._obj, args); } - public static SimpleDelegate Delegate - { - get - { - if (_Delegate == null) - { - _Delegate = new SimpleDelegate(SimpleCallback); + // private instance members + private GLib.Object _obj; + private EventHandler _handler; + private int _key; -/* FIXME: Can't do this until a layout attribute is defined for SimpleCallback - * apparently, since this throws an ArgumentException:Type does not have a - * layout attribute. - * - * _GCHandle = GCHandle.Alloc (_Delegate, GCHandleType.Pinned); - */ - } - _RefCount++; - return _Delegate; + /// + /// SimpleSignal Constructor + /// + /// + /// + /// 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. + /// + + [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); + + /* FIXME: need layout attribute for + * SimpleCallback to avoid an exception. + * _GCHandle = GCHandle.Alloc ( + * _Delegate, GCHandleType.Pinned); + */ } + + _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--; - if (_RefCount < 1) - { - _RefCount = 0; - _GCHandle.Free(); + _Instances.Remove (_key); + + if (_Instances.Count == 0) { + // FIXME: when pin works _GCHandle.Free(); _Delegate = null; } }