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

* HACKING : Little bit of cleanup.
	* gdk/SimpleEvent.cs : Redesigned a bit. Docs.  Replaced refcounting
	mechanism with an instance hash and added ctor/dtor.  This class
	now completely encapsulates the signal attachment and forwarding
	mechanism for GdkEvent based signals.  It attaches to the raw signal,
	maintains a ref to the associated event handler, and uses the static
	callback to activate the event handler on signal receipt.
	* sample/makefile : killed one last CSC explicit reference.

svn path=/trunk/gtk-sharp/; revision=1076
This commit is contained in:
Mike Kestner 2001-10-04 19:12:55 +00:00
parent bda62ac3b7
commit bb326f46c9
4 changed files with 112 additions and 45 deletions

View File

@ -1,3 +1,14 @@
2001-10-04 Mike Kestner <mkestner@speakeasy.net>
* HACKING : Little bit of cleanup.
* gdk/SimpleEvent.cs : Redesigned a bit. Docs. Replaced refcounting
mechanism with an instance hash and added ctor/dtor. This class
now completely encapsulates the signal attachment and forwarding
mechanism for GdkEvent based signals. It attaches to the raw signal,
maintains a ref to the associated event handler, and uses the static
callback to activate the event handler on signal receipt.
* sample/makefile : killed one last CSC explicit reference.
2001-10-02 Mike Kestner <mkestner@speakeasy.net> 2001-10-02 Mike Kestner <mkestner@speakeasy.net>
* glib/Value.cs : Tried adding CallingConvention.Cdecl to all the * glib/Value.cs : Tried adding CallingConvention.Cdecl to all the

24
HACKING
View File

@ -1,19 +1,15 @@
Please please please hack on gtk-sharp. Before beginning work on something, please post your intentions to the
mailing list (gtk-sharp-list@ximian.com). Duplication of effort just gets
Okay, now for the details. folks cranky in general.
Prior to checking anything into CVS, please send a patch to the mailing list Prior to checking anything into CVS, please send a patch to the mailing list
(gtk-sharp-list@ximian.com) for approval. Any patches should be submitted in for approval. Any patches should be submitted in diff -u format. Also, it is
diff -u format. Also, it is assumed that the submitter has verified that the assumed that the submitter has verified that the patch does not break the
patch does not break the build, and hopefully that it doesn't break runtime. build, and hopefully that it doesn't break runtime.
Second, patches without Documentation comments will be seriously frowned upon, Patches without Documentation comments will be seriously frowned upon,
if not outright rejected. All classes, methods, properties, events, etc... if not outright rejected. All classes, methods, properties, events, etc...
that are non-private should be documented with XML comment tags. At a minimum, that are non-private should be documented with XML comment tags. At a minimum,
the summary and remarks tags, plus returns and params, if applicable. the summary and remarks tags, plus returns and params, if applicable. Doing
this as we go is the only feasible way to make sure that our docs won't end
Third, Make a ChangeLog entry. Get credit for your hard work, and let me know up sucking bigtime.
who I need to get cranky with at a glance, instead of having to do cvs history
reports. :-)
Fourth, please please please hack on gtk-sharp.

View File

@ -6,6 +6,7 @@
namespace Gdk { namespace Gdk {
using System; using System;
using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using GLib; using GLib;
using Gdk; using Gdk;
@ -29,42 +30,103 @@ namespace Gdk {
} }
} }
public delegate bool SimpleEventDelegate(IntPtr obj, IntPtr e, String name); /// <summary>
/// SimpleEventDelegate Delegate
/// </summary>
///
/// <remarks>
/// Callback used to connect to GdkEvent based signals.
/// </remarks>
public delegate bool SimpleEventDelegate(IntPtr obj, IntPtr e,
int key);
/// <summary>
/// SimpleEvent Class
/// </summary>
///
/// <remarks>
/// Connects to a specified signal on a raw object and relays
/// events to an EventHandle when they occur.
/// </remarks>
public class SimpleEvent { public class SimpleEvent {
private static bool SimpleEventCallback (IntPtr obj, IntPtr e, String name) // A Counter used to produce unique keys for instances.
{ private static int _NextKey = 0;
GLib.Object o = GLib.Object.GetObject (obj);
EventHandler eh = (EventHandler) o.Events [name]; // A hash table containing refs to all current instances.
if (eh != null) private static Hashtable _Instances = new Hashtable ();
{
EventArgs args = new SimpleEventArgs (new Gdk.Event(e)); // locals to create and pin the shared delegate.
eh(o, args);
}
return true; //FIXME: How do we manage the return value?
}
private static int _RefCount;
private static SimpleEventDelegate _Delegate; private static SimpleEventDelegate _Delegate;
private static GCHandle _GCHandle; private static GCHandle _GCHandle;
public static SimpleEventDelegate Delegate
// Shared delegate that relays events to registered handlers
private static bool SimpleEventCallback (IntPtr obj, IntPtr e,
int inst_key)
{ {
get if (!_Instances.Contains (inst_key))
{ throw new Exception ("Unexpected event key");
if (_Delegate == null)
{ SimpleEvent se = (SimpleEvent) _Instances [inst_key];
_Delegate = new SimpleEventDelegate(SimpleEventCallback); EventArgs args = new SimpleEventArgs (
_GCHandle = GCHandle.Alloc (_Delegate, GCHandleType.Pinned); new Gdk.Event (e));
} se._handler (se._obj, args);
_RefCount++; return true; //FIXME: How do we manage the return value?
return _Delegate;
}
} }
public static void Unref()
// private instance members
private GLib.Object _obj;
private EventHandler _handler;
private int _key;
/// <summary>
/// SimpleEvent 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, SimpleEventDelegate eh,
int key, IntPtr p, int flags);
public SimpleEvent (GLib.Object obj, IntPtr raw,
String name, EventHandler eh)
{ {
_RefCount--; if (_Delegate == null) {
if (_RefCount < 1) _Delegate = new SimpleEventDelegate (
{ SimpleEventCallback);
_RefCount = 0; _GCHandle = GCHandle.Alloc (
_Delegate, GCHandleType.Pinned);
}
_key = _NextKey++;
_Instances [_key] = this;
_obj = obj;
_handler = eh;
g_signal_connect_data (
raw, Marshal.StringToHGlobalAnsi (name),
_Delegate, _key, new IntPtr (0), 0);
}
// Destructor is needed to release references from the instance
// table and unpin the delegate if no refs remain.
~SimpleEvent ()
{
// FIXME: Disconnect the signal
_Instances.Remove (_key);
if (_Instances.Count == 0) {
_GCHandle.Free(); _GCHandle.Free();
_Delegate = null; _Delegate = null;
} }

View File

@ -1,5 +1,3 @@
CSC=/cygdrive/c/winnt/microsoft.net/framework/v1.0.2914/csc.exe
all: all:
@echo "You must use 'make windows' or 'make unix'." @echo "You must use 'make windows' or 'make unix'."
@echo "'make unix' is broken for now." @echo "'make unix' is broken for now."