mirror of
				https://github.com/Ryujinx/GtkSharp.git
				synced 2025-10-29 08:47:11 +00:00 
			
		
		
		
	* glade/XML.custom: Store the callback wrapper so it doesn't get GC'd. svn path=/trunk/gtk-sharp/; revision=44040
		
			
				
	
	
		
			371 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			12 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>
 | |
| //
 | |
| // Copyright (c) 2002 Ricardo Fernández Pascual
 | |
| //
 | |
| // Field binding code by Rachel Hestilow <hestilow@ximian.com>
 | |
| // 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) 
 | |
| 						{
 | |
| 							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 attr = (WidgetAttribute) attrs[0];
 | |
| 				Gtk.Widget widget;
 | |
| 				if (attr.Specified) 
 | |
| 					widget = GetWidget (attr.Name);
 | |
| 				else 
 | |
| 					widget = GetWidget (field.Name);
 | |
| 
 | |
| 				if (widget != null)
 | |
| 					field.SetValue (target, widget, flags, null, 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;
 | |
| 		}
 |