// WARNING: This file is in UTF8 format due to the use of ã // XML.custom // // Author: Ricardo Fernández Pascual // // Copyright (c) 2002 Ricardo Fernández Pascual // // Field binding code by Rachel Hestilow // Copyright (c) 2003 Rachel Hestilow // // This code is inserted after the automatically generated code. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the Lesser GNU General // Public License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this program; if not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // keep this around so it doesn't get GC'd static GladeSharp.XMLCustomWidgetHandlerWrapper callback_wrapper = null; [DllImport("libglade-2.0-0.dll")] static extern void glade_set_custom_handler (GladeSharp.XMLCustomWidgetHandlerNative handler, IntPtr user_data); public static Glade.XMLCustomWidgetHandler CustomHandler { set { callback_wrapper = new GladeSharp.XMLCustomWidgetHandlerWrapper (value); glade_set_custom_handler(callback_wrapper.NativeDelegate, IntPtr.Zero); } } [Obsolete ("Replaced by CustomHandler property.")] static public void SetCustomHandler (Glade.XMLCustomWidgetHandler handler) { CustomHandler = handler; } [DllImport("gladesharpglue-2")] static extern IntPtr gtksharp_glade_xml_get_filename (IntPtr raw); public string Filename { get { string ret; IntPtr ptr = gtksharp_glade_xml_get_filename (Handle); if (ptr == IntPtr.Zero) { // from resource ret = System.Reflection.Assembly.GetCallingAssembly ().Location; } else { ret = GLib.Marshaller.Utf8PtrToString (ptr); } return ret; } } public Gtk.Widget this [string name] { get { return GetWidget (name); } } [DllImport("libglade-2.0-0.dll")] static extern IntPtr glade_get_widget_name (IntPtr widget); static public string GetWidgetName (Gtk.Widget w) { string ret; IntPtr ptr = glade_get_widget_name (w.Handle); if (ptr == IntPtr.Zero) ret = ""; else ret = GLib.Marshaller.Utf8PtrToString (ptr); return ret; } [DllImport("libglade-2.0-0.dll")] 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, false) as Glade.XML; return ret; } /* a constructor that reads the XML from a Stream */ [DllImport("libglade-2.0-0.dll")] static extern IntPtr glade_xml_new_from_buffer(byte[] buffer, int size, IntPtr root, IntPtr domain); public XML (System.IO.Stream s, string root, string domain) : base (IntPtr.Zero) { if (GetType() != typeof (XML)) throw new InvalidOperationException ("Can't chain to this constructor from subclasses."); if (s == null) throw new ArgumentNullException ("s"); int size = (int) s.Length; byte[] buffer = new byte[size]; s.Read (buffer, 0, size); IntPtr nroot = GLib.Marshaller.StringToPtrGStrdup (root); IntPtr ndomain = GLib.Marshaller.StringToPtrGStrdup (domain); Raw = glade_xml_new_from_buffer(buffer, size, nroot, ndomain); GLib.Marshaller.Free (nroot); GLib.Marshaller.Free (ndomain); } public XML (string resource_name, string root) : this (System.Reflection.Assembly.GetEntryAssembly (), resource_name, root, null) { } public XML (System.Reflection.Assembly assembly, string resource_name, string root, string domain) : base (IntPtr.Zero) { if (GetType() != typeof (XML)) throw new InvalidOperationException ("Cannot chain to this constructor from subclasses."); 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 (); IntPtr nroot = GLib.Marshaller.StringToPtrGStrdup (root); IntPtr ndomain = GLib.Marshaller.StringToPtrGStrdup (domain); Raw = glade_xml_new_from_buffer(buffer, size, nroot, ndomain); GLib.Marshaller.Free (nroot); GLib.Marshaller.Free (ndomain); } /* signal autoconnection using reflection */ public void Autoconnect (object handler) { BindFields (handler); SignalConnector sc = new SignalConnector (this, handler); sc.Autoconnect (); } 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; } [GLib.CDeclCallback] delegate void RawXMLConnectFunc (IntPtr handler_name, IntPtr objekt, IntPtr signal_name, IntPtr signal_data, IntPtr connect_object, int after, IntPtr user_data); [DllImport("libglade-2.0-0.dll")] 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 (IntPtr native_handler_name, IntPtr objekt_ptr, IntPtr native_signal_name, IntPtr native_signal_data, IntPtr connect_object_ptr, int after, IntPtr user_data) { GLib.Object objekt = GLib.Object.GetObject (objekt_ptr, false); string handler_name = GLib.Marshaller.Utf8PtrToString (native_handler_name); string signal_name = GLib.Marshaller.Utf8PtrToString (native_signal_name); //string signal_data = GLib.Marshaller.Utf8PtrToString (native_signal_data); /* 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, false); /* 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) { string msg = ExplainError (ei.Name, delegate_type, handler_type, handler_name); throw new HandlerNotFoundException (msg, handler_name, signal_name, ei, delegate_type); } } } } static string GetSignature (System.Reflection.MethodInfo method) { if (method == null) return null; System.Reflection.ParameterInfo [] parameters = method.GetParameters (); System.Text.StringBuilder sb = new System.Text.StringBuilder (); sb.Append ('('); foreach (System.Reflection.ParameterInfo info in parameters) { sb.Append (info.ParameterType.ToString ()); sb.Append (','); } if (sb.Length != 0) sb.Length--; sb.Append (')'); return sb.ToString (); } static string GetSignature (Type delegate_type) { System.Reflection.MethodInfo method = delegate_type.GetMethod ("Invoke"); return GetSignature (method); } const System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance; static string GetSignature (Type klass, string method_name) { try { System.Reflection.MethodInfo method = klass.GetMethod (method_name, flags); return GetSignature (method); } catch { // May be more than one method with that name and none matches return null; } } static string ExplainError (string event_name, Type deleg, Type klass, string method) { if (deleg == null || klass == null || method == null) return null; System.Text.StringBuilder sb = new System.Text.StringBuilder (); string expected = GetSignature (deleg); string actual = GetSignature (klass, method); if (actual == null) return null; sb.AppendFormat ("The handler for the event {0} should take '{1}', " + "but the signature of the provided handler ('{2}') is '{3}'\n", event_name, expected, method, actual); return sb.ToString (); } 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), false); 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 | System.Reflection.BindingFlags.DeclaredOnly; if (target != null) flags |= System.Reflection.BindingFlags.Instance; else flags |= System.Reflection.BindingFlags.Static; do { System.Reflection.FieldInfo[] fields = type.GetFields (flags); if (fields == null) return; foreach (System.Reflection.FieldInfo field in fields) { object[] attrs = field.GetCustomAttributes (typeof (WidgetAttribute), false); if (attrs == null || attrs.Length == 0) continue; // The widget to field binding must be 1:1, so only check // the first attribute. WidgetAttribute attr = (WidgetAttribute) attrs[0]; Gtk.Widget widget; if (attr.Specified) widget = GetWidget (attr.Name); else widget = GetWidget (field.Name); if (widget != null) try { field.SetValue (target, widget, flags, null, null); } catch (Exception e) { Console.WriteLine ("Unable to set value for field " + field.Name); throw e; } } type = type.BaseType; } while (type != typeof(object) && type != null); } public void BindFields (object target) { BindFields (target, target.GetType ()); } public void BindFields (Type type) { BindFields (null, type); } public static Glade.XML FromStream (System.IO.Stream stream, string root, string domain) { return new Glade.XML (stream, root, domain); } public static Glade.XML FromAssembly ( System.Reflection.Assembly assembly, string resource_name, string root, string domain) { return new Glade.XML (assembly, resource_name, root, domain); } public static Glade.XML FromAssembly (string resource_name, string root, string domain) { return new Glade.XML ( System.Reflection.Assembly.GetCallingAssembly (), resource_name, root, domain); } [DllImport("libglade-2.0-0.dll")] static extern IntPtr glade_xml_get_widget_prefix(IntPtr raw, IntPtr name); public Gtk.Widget[] GetWidgetPrefix(string name) { IntPtr native = GLib.Marshaller.StringToPtrGStrdup (name); IntPtr raw_ret = glade_xml_get_widget_prefix(Handle, native); GLib.Marshaller.Free (native); if (raw_ret == IntPtr.Zero) return new Gtk.Widget [0]; GLib.List list = new GLib.List (raw_ret); Gtk.Widget[] result = new Gtk.Widget [list.Count]; int i = 0; foreach (Gtk.Widget w in list) result [i++] = w; return result; }