2002-09-13 Ricardo Fernndez Pascual <ric@users.sourceforge.net>
* glade/HandlerNotFoundExeception.cs: Added. * glade/Makefile.in * glade/XML.custom: Support for autoconnecting signals using reflection. * glib/SignalAttribute.cs: Added. * generator/Signal.cs: Mark events generated from glib signals with the "Signal" attribute. * sample/GladeTest.cs * sample/Makefile.in * sample/test.glade: Test of signal autoconnection. svn path=/trunk/gtk-sharp/; revision=7430
This commit is contained in:
parent
6b6bb616b2
commit
f1011f687e
9 changed files with 405 additions and 2 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2002-09-13 Ricardo Fern<72>ndez Pascual <ric@users.sourceforge.net>
|
||||||
|
|
||||||
|
* glade/HandlerNotFoundExeception.cs: Added.
|
||||||
|
* glade/Makefile.in
|
||||||
|
* glade/XML.custom: Support for autoconnecting signals using
|
||||||
|
reflection.
|
||||||
|
* glib/SignalAttribute.cs: Added.
|
||||||
|
* generator/Signal.cs: Mark events generated from glib signals
|
||||||
|
with the "Signal" attribute.
|
||||||
|
* sample/GladeTest.cs
|
||||||
|
* sample/Makefile.in
|
||||||
|
* sample/test.glade: Test of signal autoconnection.
|
||||||
|
|
||||||
2002-09-12 Rachel Hestilow <hestilow@ximian.com>
|
2002-09-12 Rachel Hestilow <hestilow@ximian.com>
|
||||||
|
|
||||||
* sources/Gtk.metadata: Set null_ok on the callback argument
|
* sources/Gtk.metadata: Set null_ok on the callback argument
|
||||||
|
|
|
@ -152,6 +152,7 @@ namespace GtkSharp.Generation {
|
||||||
string argsname;
|
string argsname;
|
||||||
string handler = GenHandler (out argsname);
|
string handler = GenHandler (out argsname);
|
||||||
|
|
||||||
|
sw.WriteLine("\t\t[GLib.Signal("+ cname + ")]");
|
||||||
sw.Write("\t\tpublic ");
|
sw.Write("\t\tpublic ");
|
||||||
if (elem.HasAttribute("new_flag") || (container_type != null && container_type.GetSignalRecursively (Name) != null) || (implementor != null && implementor.GetSignalRecursively (Name) != null))
|
if (elem.HasAttribute("new_flag") || (container_type != null && container_type.GetSignalRecursively (Name) != null) || (implementor != null && implementor.GetSignalRecursively (Name) != null))
|
||||||
sw.Write("new ");
|
sw.Write("new ");
|
||||||
|
|
88
glade/HandlerNotFoundExeception.cs
Normal file
88
glade/HandlerNotFoundExeception.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// HandlerNotFoundException.cs
|
||||||
|
//
|
||||||
|
// Author: Ricardo Fern<72>ndez Pascual <ric@users.sourceforge.net>
|
||||||
|
//
|
||||||
|
// (c) 2002 Ricardo Fern<72>ndez Pascual
|
||||||
|
|
||||||
|
namespace Glade {
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exception thrown when signal autoconnection fails.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class HandlerNotFoundException : Exception
|
||||||
|
{
|
||||||
|
string handler_name;
|
||||||
|
string signal_name;
|
||||||
|
EventInfo evnt;
|
||||||
|
Type delegate_type;
|
||||||
|
|
||||||
|
public HandlerNotFoundException (string handler_name, string signal_name,
|
||||||
|
EventInfo evnt, Type delegate_type)
|
||||||
|
{
|
||||||
|
this.handler_name = handler_name;
|
||||||
|
this.signal_name = signal_name;
|
||||||
|
this.evnt = evnt;
|
||||||
|
this.delegate_type = delegate_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HandlerNotFoundException (SerializationInfo info, StreamingContext context)
|
||||||
|
: base (info, context)
|
||||||
|
{
|
||||||
|
handler_name = info.GetString ("HandlerName");
|
||||||
|
signal_name = info.GetString ("SignalName");
|
||||||
|
evnt = info.GetValue ("Event", typeof (EventInfo)) as EventInfo;
|
||||||
|
delegate_type = info.GetValue ("DelegateType", typeof (Type)) as Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return "No handler " + handler_name + " found for signal " + signal_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string HandlerName
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return handler_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SignalName
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return signal_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventInfo Event
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return evnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type DelegateType
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return delegate_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetObjectData (SerializationInfo info, StreamingContext context)
|
||||||
|
{
|
||||||
|
base.GetObjectData (info, context);
|
||||||
|
info.AddValue ("HandlerName", handler_name);
|
||||||
|
info.AddValue ("SignalName", signal_name);
|
||||||
|
info.AddValue ("Event", evnt);
|
||||||
|
info.AddValue ("DelegateType", delegate_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ windows:
|
||||||
|
|
||||||
linux: glade-sharp.dll
|
linux: glade-sharp.dll
|
||||||
|
|
||||||
glade-sharp.dll: generated/*.cs
|
glade-sharp.dll: *.cs generated/*.cs
|
||||||
$(MCS) --unsafe --target library -r System.Drawing -L ../glib -L ../pango -L ../atk -L ../gdk -L ../gtk -r glib-sharp.dll -r pango-sharp.dll -r atk-sharp.dll -r gdk-sharp.dll -r gtk-sharp.dll -o glade-sharp.dll --recurse '*.cs'
|
$(MCS) --unsafe --target library -r System.Drawing -L ../glib -L ../pango -L ../atk -L ../gdk -L ../gtk -r glib-sharp.dll -r pango-sharp.dll -r atk-sharp.dll -r gdk-sharp.dll -r gtk-sharp.dll -o glade-sharp.dll --recurse '*.cs'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
149
glade/XML.custom
149
glade/XML.custom
|
@ -45,4 +45,153 @@
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* signal autoconnection using reflection */
|
||||||
|
|
||||||
|
/// <summary>Automatically connect signals</summary>
|
||||||
|
/// <remarks>Connects the signals defined in the glade file with handler methods
|
||||||
|
/// provided by the given object.</remarks>
|
||||||
|
public void Autoconnect (object handler)
|
||||||
|
{
|
||||||
|
SignalConnector sc = new SignalConnector (this, handler);
|
||||||
|
sc.Autoconnect ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Automatically connect signals</summary>
|
||||||
|
/// <remarks>Connects the signals defined in the glade file with static handler
|
||||||
|
/// methods provided by the given type.</remarks>
|
||||||
|
public void Autoconnect (Type handler_class)
|
||||||
|
{
|
||||||
|
SignalConnector sc = new SignalConnector (this, handler_class);
|
||||||
|
sc.Autoconnect ();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SignalConnector
|
||||||
|
{
|
||||||
|
/* the Glade.XML object whose signals we want to connect */
|
||||||
|
XML gxml;
|
||||||
|
|
||||||
|
/* the object to look for handlers */
|
||||||
|
object handler_object;
|
||||||
|
|
||||||
|
/* the type to look for handlers if no object has been specified */
|
||||||
|
Type handler_type;
|
||||||
|
|
||||||
|
public SignalConnector (XML gxml, object handler)
|
||||||
|
{
|
||||||
|
this.gxml = gxml;
|
||||||
|
this.handler_object = handler;
|
||||||
|
this.handler_type = handler.GetType ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignalConnector (XML gxml, Type type)
|
||||||
|
{
|
||||||
|
this.gxml = gxml;
|
||||||
|
this.handler_object = null;
|
||||||
|
this.handler_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate void RawXMLConnectFunc (string handler_name, IntPtr objekt,
|
||||||
|
string signal_name, string signal_data,
|
||||||
|
IntPtr connect_object, int after, IntPtr user_data);
|
||||||
|
|
||||||
|
[DllImport("glade-2.0")]
|
||||||
|
static extern void glade_xml_signal_autoconnect_full (IntPtr raw, RawXMLConnectFunc func,
|
||||||
|
IntPtr user_data);
|
||||||
|
|
||||||
|
public void Autoconnect () {
|
||||||
|
RawXMLConnectFunc cf = new RawXMLConnectFunc (ConnectFunc);
|
||||||
|
glade_xml_signal_autoconnect_full (gxml.Handle, cf, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectFunc (string handler_name, IntPtr objekt_ptr,
|
||||||
|
string signal_name, string signal_data,
|
||||||
|
IntPtr connect_object_ptr, int after, IntPtr user_data) {
|
||||||
|
|
||||||
|
GLib.Object objekt = GLib.Object.GetObject (objekt_ptr);
|
||||||
|
|
||||||
|
/* if an connect_object_ptr is provided, use that as handler */
|
||||||
|
object connect_object =
|
||||||
|
connect_object_ptr == IntPtr.Zero
|
||||||
|
? handler_object
|
||||||
|
: GLib.Object.GetObject (connect_object_ptr);
|
||||||
|
|
||||||
|
/* search for the event to connect */
|
||||||
|
System.Reflection.MemberInfo[] evnts = objekt.GetType ().
|
||||||
|
FindMembers (System.Reflection.MemberTypes.Event,
|
||||||
|
System.Reflection.BindingFlags.Instance
|
||||||
|
| System.Reflection.BindingFlags.Static
|
||||||
|
| System.Reflection.BindingFlags.Public
|
||||||
|
| System.Reflection.BindingFlags.NonPublic,
|
||||||
|
signalFilter, signal_name);
|
||||||
|
foreach (System.Reflection.EventInfo ei in evnts)
|
||||||
|
{
|
||||||
|
bool connected = false;
|
||||||
|
System.Reflection.MethodInfo add = ei.GetAddMethod ();
|
||||||
|
System.Reflection.ParameterInfo[] addpi = add.GetParameters ();
|
||||||
|
if (addpi.Length == 1)
|
||||||
|
{ /* this should be always true, unless there's something broken */
|
||||||
|
Type delegate_type = addpi[0].ParameterType;
|
||||||
|
|
||||||
|
/* look for an instance method */
|
||||||
|
if (connect_object != null) try
|
||||||
|
{
|
||||||
|
Delegate d = Delegate.CreateDelegate
|
||||||
|
(delegate_type, connect_object, handler_name);
|
||||||
|
add.Invoke (objekt, new object[] { d } );
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
/* ignore if there is not such instance method */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for a static method if no instance method has been found */
|
||||||
|
if (!connected && handler_type != null) try
|
||||||
|
{
|
||||||
|
Delegate d = Delegate.CreateDelegate
|
||||||
|
(delegate_type, handler_type, handler_name);
|
||||||
|
add.Invoke (objekt, new object[] { d } );
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
/* ignore if there is not such static method */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
throw new HandlerNotFoundException (handler_name, signal_name, ei, delegate_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Reflection.MemberFilter signalFilter = new System.Reflection.MemberFilter (SignalFilter);
|
||||||
|
|
||||||
|
/* matches events to GLib signal names */
|
||||||
|
static bool SignalFilter (System.Reflection.MemberInfo m, object filterCriteria)
|
||||||
|
{
|
||||||
|
string signame = (filterCriteria as string);
|
||||||
|
object[] attrs = m.GetCustomAttributes (typeof (GLib.SignalAttribute), true);
|
||||||
|
if (attrs.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (GLib.SignalAttribute a in attrs)
|
||||||
|
{
|
||||||
|
if (signame == a.CName)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this tries to match the names when no attibutes are present.
|
||||||
|
It is only a fallback. */
|
||||||
|
signame = signame.ToLower ().Replace ("_", "");
|
||||||
|
string evname = m.Name.ToLower ();
|
||||||
|
return signame == evname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
41
glib/SignalAttribute.cs
Normal file
41
glib/SignalAttribute.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// SignalAttribute.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Ricardo Fern<72>ndez Pascual <ric@users.sourceforge.net>
|
||||||
|
//
|
||||||
|
// (C) Ricardo Fern<72>ndez Pascual <ric@users.sourceforge.net>
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace GLib {
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks events genrated from glib signals
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// This attribute indentifies events generated from glib signals
|
||||||
|
/// and allows obtaining its original name.
|
||||||
|
/// </remarks>
|
||||||
|
[Serializable]
|
||||||
|
public class SignalAttribute : Attribute
|
||||||
|
{
|
||||||
|
private string cname;
|
||||||
|
|
||||||
|
public SignalAttribute (string cname)
|
||||||
|
{
|
||||||
|
this.cname = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SignalAttribute () {}
|
||||||
|
|
||||||
|
public string CName
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
sample/GladeTest.cs
Normal file
50
sample/GladeTest.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// GladeViewer.cs - Tests for LibGlade in C#
|
||||||
|
//
|
||||||
|
// Author: Ricardo Fern<72>ndez Pascual <ric@users.sourceforge.net>
|
||||||
|
//
|
||||||
|
// (c) 2002 Ricardo Fern<72>ndez Pascual
|
||||||
|
|
||||||
|
namespace GladeSamples {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Gtk;
|
||||||
|
using Gnome;
|
||||||
|
using Glade;
|
||||||
|
using GtkSharp;
|
||||||
|
|
||||||
|
public class GladeTest : Program
|
||||||
|
{
|
||||||
|
public static void Main (string[] args)
|
||||||
|
{
|
||||||
|
new GladeTest (args).Run ();
|
||||||
|
}
|
||||||
|
public GladeTest (string[] args, params object[] props)
|
||||||
|
: base ("GladeTest", "0.1", Modules.UI, args, props)
|
||||||
|
{
|
||||||
|
Glade.XML gxml = new Glade.XML ("test.glade", "main_window", null);
|
||||||
|
gxml.Autoconnect (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnWindowDeleteEvent (object o, DeleteEventArgs args)
|
||||||
|
{
|
||||||
|
Quit ();
|
||||||
|
args.RetVal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnButton1Clicked (Object b, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine ("Button 1 clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnButton2Clicked (Object b, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine ("Button 2 clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnButton2Entered (Object b, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine ("Button 2 entered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ MCS=mcs
|
||||||
|
|
||||||
@ENABLE_GLADE_TRUE@ GLADE_PATH=-L ../glade
|
@ENABLE_GLADE_TRUE@ GLADE_PATH=-L ../glade
|
||||||
@ENABLE_GLADE_TRUE@ GLADE_ASSEMBLY=-r glade-sharp.dll
|
@ENABLE_GLADE_TRUE@ GLADE_ASSEMBLY=-r glade-sharp.dll
|
||||||
@ENABLE_GLADE_TRUE@ GLADE_TARGETS=glade-viewer.exe
|
@ENABLE_GLADE_TRUE@ GLADE_TARGETS=glade-viewer.exe glade-test.exe
|
||||||
|
|
||||||
local_paths=-L ../glib -L ../pango -L ../atk -L ../gdk -L ../gtk $(GNOME_PATH) $(GLADE_PATH)
|
local_paths=-L ../glib -L ../pango -L ../atk -L ../gdk -L ../gtk $(GNOME_PATH) $(GLADE_PATH)
|
||||||
all_assemblies=-r glib-sharp.dll -r pango-sharp.dll -r atk-sharp.dll -r gdk-sharp.dll -r gtk-sharp.dll $(GNOME_ASSEMBLY) $(GLADE_ASSEMBLY) -r System.Drawing
|
all_assemblies=-r glib-sharp.dll -r pango-sharp.dll -r atk-sharp.dll -r gdk-sharp.dll -r gtk-sharp.dll $(GNOME_ASSEMBLY) $(GLADE_ASSEMBLY) -r System.Drawing
|
||||||
|
@ -50,6 +50,9 @@ treeviewdemo.exe: TreeViewDemo.cs
|
||||||
glade-viewer.exe: GladeViewer.cs
|
glade-viewer.exe: GladeViewer.cs
|
||||||
$(MCS) --unsafe -o glade-viewer.exe $(local_paths) $(all_assemblies) GladeViewer.cs
|
$(MCS) --unsafe -o glade-viewer.exe $(local_paths) $(all_assemblies) GladeViewer.cs
|
||||||
|
|
||||||
|
glade-test.exe: GladeTest.cs
|
||||||
|
$(MCS) --unsafe -o glade-test.exe $(local_paths) $(all_assemblies) GladeTest.cs
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.exe
|
rm -f *.exe
|
||||||
|
|
||||||
|
|
58
sample/test.glade
Normal file
58
sample/test.glade
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||||
|
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
||||||
|
|
||||||
|
<glade-interface>
|
||||||
|
|
||||||
|
<widget class="GtkWindow" id="main_window">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="title" translatable="yes">Glade# test</property>
|
||||||
|
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||||
|
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||||
|
<property name="modal">False</property>
|
||||||
|
<property name="resizable">True</property>
|
||||||
|
<property name="destroy_with_parent">False</property>
|
||||||
|
<signal name="delete_event" handler="OnWindowDeleteEvent" last_modification_time="Tue, 03 Sep 2002 14:47:57 GMT"/>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="homogeneous">False</property>
|
||||||
|
<property name="spacing">0</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="button1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Click here</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||||
|
<signal name="clicked" handler="OnButton1Clicked" last_modification_time="Tue, 13 Aug 2002 15:24:35 GMT"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="padding">0</property>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="button2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Don't click here</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||||
|
<signal name="clicked" handler="OnButton2Clicked" last_modification_time="Tue, 13 Aug 2002 15:24:35 GMT"/>
|
||||||
|
<signal name="enter" handler="OnButton2Entered" last_modification_time="Wed, 04 Sep 2002 14:04:40 GMT"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="padding">0</property>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
|
||||||
|
</glade-interface>
|
Loading…
Add table
Reference in a new issue