// GtkSharp.Generation.InterfaceGen.cs - The Interface Generatable. // // Author: Mike Kestner // // Copyright (c) 2001-2003 Mike Kestner // Copyright (c) 2004 Novell, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the 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 // General Public License for more details. // // You should have received a copy of the GNU 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. namespace GtkSharp.Generation { using System; using System.Collections; using System.IO; using System.Xml; public class InterfaceGen : ClassBase { ArrayList vms = new ArrayList (); ArrayList members = new ArrayList (); public InterfaceGen (XmlElement ns, XmlElement elem) : base (ns, elem) { foreach (XmlNode node in elem.ChildNodes) { switch (node.Name) { case "virtual_method": VirtualMethod vm = new VirtualMethod (node as XmlElement, this); vms.Add (vm); members.Add (vm); break; case "signal": members.Add ((node as XmlElement).GetAttribute ("cname").Replace ('-', '_')); break; default: if (!IsNodeNameHandled (node.Name)) Console.WriteLine ("Unexpected node " + node.Name + " in " + CName); break; } } } string IfaceName { get { return Name + "Iface"; } } void GenerateDelegates (StreamWriter sw) { if (vms.Count == 0) return; foreach (VirtualMethod vm in vms) { sw.WriteLine ("\t\t" + vm.NativeDelegate); } sw.WriteLine (); } void GenerateIfaceStruct (StreamWriter sw) { sw.WriteLine ("\t\t" + IfaceName + " iface;"); sw.WriteLine (); sw.WriteLine ("\t\tstruct " + IfaceName + " {"); sw.WriteLine ("\t\t\tpublic IntPtr gtype;"); sw.WriteLine ("\t\t\tpublic IntPtr itype;"); sw.WriteLine (); foreach (object member in members) { if (member is System.String) sw.WriteLine ("\t\t\tpublic IntPtr " + member + ";"); else if (member is VirtualMethod) { VirtualMethod vm = member as VirtualMethod; sw.WriteLine ("\t\t\tpublic " + vm.Name + "Delegate " + vm.CName + ";"); } } sw.WriteLine ("\t\t}"); sw.WriteLine (); } void GenerateCtor (StreamWriter sw) { sw.WriteLine ("\t\tprivate " + Name + "Adapter ()"); sw.WriteLine ("\t\t{"); foreach (VirtualMethod vm in vms) sw.WriteLine ("\t\t\tiface.{0} = new {1}Delegate ({1}Callback);", vm.CName, vm.Name); sw.WriteLine ("\t\t}"); sw.WriteLine (); } void GenerateAdapterProp (StreamWriter sw) { sw.WriteLine ("\t\tstatic " + Name + "Adapter singleton;"); sw.WriteLine (); sw.WriteLine ("\t\tinternal " + Name + "Adapter Adapter {"); sw.WriteLine ("\t\t\tget {"); sw.WriteLine ("\t\t\t\tif (singleton == null)"); sw.WriteLine ("\t\t\t\t\tsingleton = new " + Name + "Adapter ();"); sw.WriteLine ("\t\t\t\treturn singleton;"); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t}"); sw.WriteLine (); } void GenerateInitialize (StreamWriter sw) { sw.WriteLine ("\t\tpublic void Initialize (IntPtr ifaceptr, IntPtr data)"); sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t\t" + IfaceName + " iface = (" + IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));"); foreach (VirtualMethod vm in vms) sw.WriteLine ("\t\t\tiface." + vm.CName + " = this.iface." + vm.CName + ";"); sw.WriteLine ("\t\t\tMarshal.StructureToPtr (iface, ifaceptr, false);"); sw.WriteLine ("\t\t}"); } void GenerateCallbacks (StreamWriter sw) { foreach (VirtualMethod vm in vms) { sw.WriteLine (); vm.GenerateCallback (sw); } } void GenerateAdapter (GenerationInfo gen_info) { StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name + "Adapter"); sw.WriteLine ("namespace " + NS + " {"); sw.WriteLine (); sw.WriteLine ("\tusing System;"); sw.WriteLine ("\tusing System.Runtime.InteropServices;"); sw.WriteLine (); sw.WriteLine ("#region Autogenerated code"); sw.WriteLine ("\tinternal class " + Name + "Adapter : GLib.GInterfaceAdapter {"); sw.WriteLine (); GenerateDelegates (sw); GenerateIfaceStruct (sw); GenerateCtor (sw); GenerateAdapterProp (sw); GenerateInitialize (sw); GenerateCallbacks (sw); sw.WriteLine ("\t}"); sw.WriteLine ("#endregion"); sw.WriteLine ("}"); sw.Close (); gen_info.Writer = null; } void GenSignals (GenerationInfo gen_info) { if (sigs.Count == 0) return; StreamWriter sw = gen_info.Writer; sw.WriteLine (); sw.WriteLine ("\t\t// signals"); foreach (Signal sig in sigs.Values) { if (sig.Validate ()) { sig.GenerateDecl (sw); sig.GenEventHandler (gen_info); } else Console.WriteLine ("of interface " + QualifiedName); } } Hashtable GenVMDecls (StreamWriter sw) { if (vms.Count == 0) return new Hashtable (); sw.WriteLine (); sw.WriteLine ("\t\t// virtual methods"); Hashtable vm_decls = new Hashtable (); foreach (VirtualMethod vm in vms) { sw.WriteLine ("\t\t" + vm.Declaration); vm_decls [vm.Declaration] = vm; } return vm_decls; } void GenMethodDecls (StreamWriter sw, Hashtable vm_decls) { if (methods.Count == 0) return; bool need_comment = true; foreach (Method method in methods.Values) { //if (IgnoreMethod (method)) //continue; if (method.Validate ()) { if (!vm_decls.Contains (method.Declaration) && method.Name != "GetGType") { if (need_comment) { sw.WriteLine (); sw.WriteLine ("\t\t// non-virtual methods"); need_comment = false; } method.GenerateDecl (sw); } } else Console.WriteLine ("of interface " + QualifiedName); } } void GenerateInterface (GenerationInfo gen_info) { StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name); sw.WriteLine ("namespace " + NS + " {"); sw.WriteLine (); sw.WriteLine ("\tusing System;"); sw.WriteLine (); sw.WriteLine ("#region Autogenerated code"); sw.WriteLine ("\tpublic interface " + Name + " : GLib.GInterface {"); GenSignals (gen_info); GenMethodDecls (sw, GenVMDecls (sw)); AppendCustom (sw, gen_info.CustomDir); sw.WriteLine ("\t}"); sw.WriteLine ("#endregion"); sw.WriteLine ("}"); sw.Close (); gen_info.Writer = null; Statistics.IFaceCount++; } public void GenerateNotQuiteReadyYet (GenerationInfo gen_info) { ArrayList tmp = new ArrayList (); foreach (VirtualMethod vm in vms) { if (vm.Validate()) tmp.Add (vm); else { members.Remove (vm); Console.WriteLine ("of interface " + QualifiedName); } } vms = tmp; GenerateAdapter (gen_info); GenerateInterface (gen_info); } public override void Generate (GenerationInfo gen_info) { StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name); sw.WriteLine ("namespace " + NS + " {"); sw.WriteLine (); sw.WriteLine ("\tusing System;"); sw.WriteLine (); sw.WriteLine ("#region Autogenerated code"); sw.WriteLine ("\tpublic interface " + Name + " : GLib.IWrapper {"); sw.WriteLine (); foreach (Signal sig in sigs.Values) { if (sig.Validate ()) { sig.GenerateDecl (sw); sig.GenEventHandler (gen_info); } else Console.WriteLine ("of interface " + QualifiedName); } foreach (Method method in methods.Values) { if (IgnoreMethod (method)) continue; if (method.Validate ()) method.GenerateDecl (sw); else Console.WriteLine ("of interface " + QualifiedName); } AppendCustom (sw, gen_info.CustomDir); sw.WriteLine ("\t}"); sw.WriteLine ("#endregion"); sw.WriteLine ("}"); sw.Close (); gen_info.Writer = null; Statistics.IFaceCount++; } } }