// GLib.Signals.Simple.cs - GLib Simple Signal implementation // // Authors: Bob Smith <bob@thestuff.net> // Mike Kestner <mkestner@speakeasy.net> // // (c) 2001 Bob Smith & Mike Kestner namespace GLib { using System; using System.Collections; using System.Runtime.InteropServices; using GLib; /// <summary> /// SimpleDelegate Delegate /// </summary> /// /// <remarks> /// Used to connect to simple signals which contain no signal- /// specific data. /// </remarks> public delegate void SimpleDelegate (IntPtr obj, int key); /// <summary> /// SimpleSignal Class /// </summary> /// /// <remarks> /// Wraps a simple signal which contains no single-specific data. /// </remarks> public class SimpleSignal { // 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; // Shared delegate that relays events to registered handlers. private static void SimpleCallback(IntPtr obj, int inst_key) { 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); } // private instance members private GLib.Object _obj; private EventHandler _handler; private int _key; /// <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); /* 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); } // Destructor needed to release references from the instance // table and unpin the delegate if no refs remain. ~SimpleSignal () { _Instances.Remove (_key); if (_Instances.Count == 0) { // FIXME: when pin works _GCHandle.Free(); _Delegate = null; } } } }