mirror of
https://github.com/Ryujinx/GtkSharp.git
synced 2024-12-26 21:15:36 +00:00
3821938764
* generator/CallbackGen.cs: the new generated wrappers have: -(optional) Field of the same type returned by the callback. -A call to RemoveIfNotAlive at the beginning. It returns true, return the dummy field. -Added an object to the ctor signature and pass it to the base class. * generator/Ctor.cs: added a Params property. * generator/Method.cs: set Static property in Parameters if the method is static. * generator/Parameters.cs: added Static property. The call creation of the delegate wrapper (if applicable) uses the new signature. Pass a null as object is the method is static. * generator/StructBase.cs: set Static for the parameters of the ctors. * glib/DelegateWrapper.cs: the ctor takes an object (the one creating the wrapper or null) and creates a weak reference to it. Store it in a static Hashtable (this way the wrapper itself is not garbage collected). (RemoveIfNotAlive): called from the native delegate callbacks. If the target of the weak reference has been garbage collected, removes itself from the hashtable to let the GC dispose this instance and returns true. * gdk/Pixbuf.custom: * gtk/Clipboard.custom: * gtk/GtkSharp.GtkClipboardClearFuncNative.cs: * gtk/GtkSharp.GtkClipboardGetFuncNative.cs: * glade/XML.custom: changed delegate wrappers to match the new signature. svn path=/trunk/gtk-sharp/; revision=13237
292 lines
9.2 KiB
Plaintext
292 lines
9.2 KiB
Plaintext
// WARNING: This file is in UTF8 format due to the use of ã
|
|
// XML.custom
|
|
//
|
|
// Author: Ricardo Fernández Pascual <ric@users.sourceforge.net>
|
|
//
|
|
// (c) 2002 Ricardo Fernández Pascual
|
|
//
|
|
// Field binding code by Rachel Hestilow <hestilow@ximian.com>
|
|
// (c) 2003 Rachel Hestilow
|
|
//
|
|
// This code is inserted after the automatically generated code.
|
|
|
|
// keep this around so it doesn't get GC'd
|
|
static GladeSharp.XMLCustomWidgetHandlerWrapper callback_wrapper = null;
|
|
|
|
[DllImport("glade-2.0")]
|
|
static extern void glade_set_custom_handler (GladeSharp.XMLCustomWidgetHandlerNative handler, IntPtr user_data);
|
|
|
|
static public void SetCustomHandler (Glade.XMLCustomWidgetHandler handler)
|
|
{
|
|
callback_wrapper = new GladeSharp.XMLCustomWidgetHandlerWrapper (handler, null);
|
|
glade_set_custom_handler (callback_wrapper.NativeDelegate, IntPtr.Zero);
|
|
}
|
|
|
|
[DllImport("gtksharpglue")]
|
|
static extern string gtksharp_glade_xml_get_filename (IntPtr raw);
|
|
|
|
/// <summary>Filename Property</summary>
|
|
/// <remarks>Gets the filename used to create this GladeXML object
|
|
/// </remarks>
|
|
public string Filename {
|
|
get {
|
|
string ret = gtksharp_glade_xml_get_filename (Handle);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/// <summary>Indexer of widgets</summary>
|
|
/// <remarks>Acts like GetWidget</remarks>
|
|
public Gtk.Widget this [string name] {
|
|
get {
|
|
return GetWidget (name);
|
|
}
|
|
}
|
|
|
|
[DllImport("glade-2.0")]
|
|
static extern string glade_get_widget_name (IntPtr widget);
|
|
|
|
static public string GetWidgetName (Gtk.Widget w) {
|
|
string ret = glade_get_widget_name (w.Handle);
|
|
return ret;
|
|
}
|
|
|
|
[DllImport("glade-2.0")]
|
|
static extern IntPtr glade_get_widget_tree (IntPtr widget);
|
|
|
|
static public Glade.XML GetWidgetTree (Gtk.Widget w) {
|
|
IntPtr ret_raw = glade_get_widget_tree (w.Handle);
|
|
Glade.XML ret = GLib.Object.GetObject (ret_raw) as Glade.XML;
|
|
return ret;
|
|
}
|
|
|
|
/* a constructor that reads the XML from a Stream */
|
|
|
|
[DllImport("glade-2.0")]
|
|
static extern IntPtr glade_xml_new_from_buffer(byte[] buffer, int size, string root, string domain);
|
|
|
|
/// <summary>Creates a Glade.XML object from a Stream</summary>
|
|
/// <remarks>Reads the contents of the stream and parses it. It must be in
|
|
/// correct Glade format</remarks>
|
|
public XML (System.IO.Stream s, string root, string domain)
|
|
{
|
|
if (s == null)
|
|
throw new ArgumentNullException ("s");
|
|
|
|
int size = (int) s.Length;
|
|
byte[] buffer = new byte[size];
|
|
s.Read (buffer, 0, size);
|
|
Raw = glade_xml_new_from_buffer(buffer, size, root, domain);
|
|
}
|
|
|
|
/// <summary>Creates a Glade.XML object from a resource</summary>
|
|
/// <remarks>Reads the contents of the resource in the
|
|
/// given assembly and parses it. If the assembly is null,
|
|
/// the current assembly will be used. It must be in
|
|
/// correct Glade format</remarks>
|
|
public XML (System.Reflection.Assembly assembly, string resource_name, string root, string domain)
|
|
{
|
|
if (assembly == null)
|
|
assembly = System.Reflection.Assembly.GetCallingAssembly ();
|
|
|
|
System.IO.Stream s = assembly.GetManifestResourceStream (resource_name);
|
|
if (s == null)
|
|
throw new ArgumentException ("Cannot get resource file '" + resource_name + "'",
|
|
"resource_name");
|
|
|
|
int size = (int) s.Length;
|
|
byte[] buffer = new byte[size];
|
|
s.Read (buffer, 0, size);
|
|
s.Close ();
|
|
Raw = glade_xml_new_from_buffer(buffer, size, root, domain);
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
BindFields (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)
|
|
{
|
|
BindFields (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;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BindFields (object target, Type type)
|
|
{
|
|
System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic;
|
|
if (target != null)
|
|
flags |= System.Reflection.BindingFlags.Instance;
|
|
else
|
|
flags |= System.Reflection.BindingFlags.Static;
|
|
|
|
System.Reflection.FieldInfo[] fields = type.GetFields (flags);
|
|
if (fields == null)
|
|
return;
|
|
|
|
foreach (System.Reflection.FieldInfo field in fields)
|
|
{
|
|
object[] attrs = field.GetCustomAttributes (typeof (WidgetAttribute), true);
|
|
if (attrs == null || attrs.Length == 0)
|
|
continue;
|
|
// The widget to field binding must be 1:1, so only check
|
|
// the first attribute.
|
|
WidgetAttribute widget = (WidgetAttribute) attrs[0];
|
|
if (widget.Specified) field.SetValue (target, GetWidget (widget.Name), flags, null, null);
|
|
else field.SetValue (target, GetWidget (field.Name), flags, null, null);
|
|
}
|
|
}
|
|
|
|
public void BindFields (object target)
|
|
{
|
|
BindFields (target, target.GetType ());
|
|
}
|
|
|
|
public void BindFields (Type type)
|
|
{
|
|
BindFields (null, type);
|
|
}
|
|
|