Author: mkestner
Date: 2007-09-11 16:34:24 -0400 (Tue, 11 Sep 2007)
New Revision: 85658

Added:
   trunk/gtk-sharp/glib/GInterfaceAdapter.cs
   trunk/gtk-sharp/glib/GInterfaceAttribute.cs
Modified:
   trunk/gtk-sharp/ChangeLog
   trunk/gtk-sharp/generator/CallbackGen.cs
   trunk/gtk-sharp/generator/InterfaceGen.cs
   trunk/gtk-sharp/generator/ManagedCallString.cs
   trunk/gtk-sharp/generator/MethodBody.cs
   trunk/gtk-sharp/generator/Parameters.cs
   trunk/gtk-sharp/generator/ReturnValue.cs
   trunk/gtk-sharp/generator/VirtualMethod.cs
   trunk/gtk-sharp/glib/Makefile.am
   trunk/gtk-sharp/glib/Object.cs
   trunk/gtk-sharp/gtk/Gtk.metadata
Log:

2007-09-11  Mike Kestner  <[EMAIL PROTECTED]>

        * gtk/Gtk.metadata: virtual_method rules for GInterface generation.
        * generator/ReturnValue.cs (ToNative): new method for the virtual
        method generation.
        * generator/Parameters.cs (FromNative): null guarding.
        * generator/ManagedCallString.cs: rework for interface method
        generation including callback and error param support.
        * generator/CallbackGen.cs: Invoker support. new class that deals
        with persistence of native and wrapper delegates in native to managed
        callback method signatures.
        * generator/VirtualMethod.cs: support for generation of interface
        methods, and all the funky parameters that come with that.
        * generator/InterfaceGen.cs: Fill out the adapter implementation.
        * generator/MethodBody.cs: Initialize overload. Extend ThrowsException
        to support GError outside the last parameter slot.
        * glib/GInterfaceAttribute.cs: New attribute to mark interfaces and
        obtain adapter type.
        * glib/Object.cs (AddInterfaces): interface registration method.
        * glib/GInterfaceAdapter.cs: New abstract class for interface
        adapter generation.
        * glib/Makefile.am: add new files.


Modified: trunk/gtk-sharp/ChangeLog
===================================================================
--- trunk/gtk-sharp/ChangeLog   2007-09-11 20:13:14 UTC (rev 85657)
+++ trunk/gtk-sharp/ChangeLog   2007-09-11 20:34:24 UTC (rev 85658)
@@ -1,4 +1,27 @@
 2007-09-11  Mike Kestner  <[EMAIL PROTECTED]>
+
+       * gtk/Gtk.metadata: virtual_method rules for GInterface generation.
+       * generator/ReturnValue.cs (ToNative): new method for the virtual
+       method generation.
+       * generator/Parameters.cs (FromNative): null guarding.
+       * generator/ManagedCallString.cs: rework for interface method
+       generation including callback and error param support.
+       * generator/CallbackGen.cs: Invoker support. new class that deals
+       with persistence of native and wrapper delegates in native to managed
+       callback method signatures.
+       * generator/VirtualMethod.cs: support for generation of interface
+       methods, and all the funky parameters that come with that.
+       * generator/InterfaceGen.cs: Fill out the adapter implementation.
+       * generator/MethodBody.cs: Initialize overload. Extend ThrowsException
+       to support GError outside the last parameter slot.
+       * glib/GInterfaceAttribute.cs: New attribute to mark interfaces and
+       obtain adapter type.
+       * glib/Object.cs (AddInterfaces): interface registration method.
+       * glib/GInterfaceAdapter.cs: New abstract class for interface
+       adapter generation.
+       * glib/Makefile.am: add new files.
+
+2007-09-11  Mike Kestner  <[EMAIL PROTECTED]>
   
        * gtk/Object.custom (Destroy): add a null check to avoid 
        Gtk criticals.  The destroy case seems to be problematic with

Modified: trunk/gtk-sharp/generator/CallbackGen.cs
===================================================================
--- trunk/gtk-sharp/generator/CallbackGen.cs    2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/CallbackGen.cs    2007-09-11 20:34:24 UTC (rev 
85658)
@@ -60,6 +60,14 @@
                        return true;
                }
 
+               public string InvokerName {
+                       get {
+                               if (!valid)
+                                       return String.Empty;
+                               return NS + "Sharp." + Name + "Invoker";
+                       }
+               }
+
                public override string MarshalType {
                        get {
                                if (valid)
@@ -86,6 +94,72 @@
                        sw.WriteLine (indent + "}");
                }
 
+               string CastFromInt (string type)
+               {
+                       return type != "int" ? "(" + type + ") " : "";
+               }
+
+               string InvokeString {
+                       get {
+                               if (parms.Count == 0)
+                                       return String.Empty;
+
+                               string[] result = new string [parms.Count];
+                               for (int i = 0; i < parms.Count; i++) {
+                                       Parameter p = parms [i];
+                                       IGeneratable igen = p.Generatable;
+
+                                       if (i > 0 && parms [i - 1].IsString && 
p.IsLength) {
+                                               string string_name = parms [i - 
1].Name;
+                                               result[i] = igen.CallByName 
(CastFromInt (p.CSType) + "System.Text.Encoding.UTF8.GetByteCount (" +  
string_name + ")");
+                                               continue;
+                                       }
+
+                                       p.CallName = p.Name;
+                                       result [i] = p.CallString;
+                                       if (p.IsUserData)
+                                               result [i] = "IntPtr.Zero"; 
+                               }
+
+                               return String.Join (", ", result);
+                       }
+               }
+
+               MethodBody body;
+
+               void GenInvoker (GenerationInfo gen_info, StreamWriter sw)
+               {
+                       sw.WriteLine ("\tinternal class " + Name + "Invoker {");
+                       sw.WriteLine ();
+                       sw.WriteLine ("\t\t" + Name + "Native native_cb;");
+                       sw.WriteLine ();
+                       sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + 
Name + "Native native_cb)");
+                       sw.WriteLine ("\t\t{");
+                       sw.WriteLine ("\t\t\tthis.native_cb = native_cb;");
+                       sw.WriteLine ("\t\t}");
+                       sw.WriteLine ();
+                       sw.WriteLine ("\t\tinternal " + QualifiedName + " 
Handler {");
+                       sw.WriteLine ("\t\t\tget {");
+                       sw.WriteLine ("\t\t\t\treturn new " + QualifiedName + 
"(InvokeNative);");
+                       sw.WriteLine ("\t\t\t}");
+                       sw.WriteLine ("\t\t}");
+                       sw.WriteLine ();
+                       sw.WriteLine ("\t\t" + retval.CSType + " InvokeNative 
(" + sig + ")");
+                       sw.WriteLine ("\t\t{");
+                       body.Initialize (gen_info);
+                       string call = "native_cb (" + InvokeString + ")";
+                       if (retval.IsVoid)
+                               sw.WriteLine ("\t\t\t" + call + ";");
+                       else
+                               sw.WriteLine ("\t\t\t" + retval.CSType + " 
result = " + retval.FromNative (call) + ";");
+                       body.Finish (sw, String.Empty);
+                       if (!retval.IsVoid)
+                               sw.WriteLine ("\t\t\treturn result;");
+                       sw.WriteLine ("\t\t}");
+                       sw.WriteLine ("\t}");
+                       sw.WriteLine ();
+               }
+
                public string GenWrapper (GenerationInfo gen_info)
                {
                        string wrapper = Name + "Native";
@@ -94,8 +168,11 @@
                        if (!Validate ())
                                return String.Empty;
 
-                       StreamWriter sw = gen_info.OpenStream (qualname);
+                       body = new MethodBody (parms);
 
+                       StreamWriter save_sw = gen_info.Writer;
+                       StreamWriter sw = gen_info.Writer = gen_info.OpenStream 
(qualname);
+
                        sw.WriteLine ("namespace " + NS + "Sharp {");
                        sw.WriteLine ();
                        sw.WriteLine ("\tusing System;");
@@ -105,6 +182,7 @@
                        sw.WriteLine ("\t[GLib.CDeclCallback]");
                        sw.WriteLine ("\tinternal delegate " + 
retval.MarshalType + " " + wrapper + "(" + parms.ImportSignature + ");");
                        sw.WriteLine ();
+                       GenInvoker (gen_info, sw);
                        sw.WriteLine ("\tinternal class " + Name + "Wrapper {");
                        sw.WriteLine ();
                        sw.WriteLine ("\t\tpublic " + retval.MarshalType + " 
NativeCallback (" + parms.ImportSignature + ")");
@@ -214,6 +292,7 @@
                        sw.WriteLine ("#endregion");
                        sw.WriteLine ("}");
                        sw.Close ();
+                       gen_info.Writer = save_sw;
                        return NS + "Sharp." + Name + "Wrapper";
                }
                

Modified: trunk/gtk-sharp/generator/InterfaceGen.cs
===================================================================
--- trunk/gtk-sharp/generator/InterfaceGen.cs   2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/InterfaceGen.cs   2007-09-11 20:34:24 UTC (rev 
85658)
@@ -81,14 +81,15 @@
                                return;
 
                        foreach (VirtualMethod vm in vms) {
-                               sw.WriteLine ("\t\t" + vm.NativeDelegate);
+                               if (vm.IsValid)
+                                       sw.WriteLine ("\t\t" + 
vm.NativeDelegate);
                        }
                        sw.WriteLine ();
                }
 
                void GenerateIfaceStruct (StreamWriter sw)
                {
-                       sw.WriteLine ("\t\t" + IfaceName + " iface;");
+                       sw.WriteLine ("\t\tstatic " + IfaceName + " iface;");
                        sw.WriteLine ();
                        sw.WriteLine ("\t\tstruct " + IfaceName + " {");
                        sw.WriteLine ("\t\t\tpublic IntPtr gtype;");
@@ -100,7 +101,11 @@
                                        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 + ";");
+                                       bool has_method = methods [vm.Name] != 
null;
+                                       if (!has_method)
+                                               Console.WriteLine ("Interface " 
+ QualifiedName + " virtual method " + vm.Name + " has no matching method to 
invoke.");
+                                       string type = has_method && vm.IsValid 
? vm.Name + "Delegate" : "IntPtr";
+                                       sw.WriteLine ("\t\t\tpublic " + type + 
" " + vm.CName + ";");
                                }
                        }
 
@@ -108,49 +113,64 @@
                        sw.WriteLine ();
                }
 
-               void GenerateCtor (StreamWriter sw)
+               void GenerateStaticCtor (StreamWriter sw)
                {
-                       sw.WriteLine ("\t\tprivate " + Name + "Adapter ()");
+                       sw.WriteLine ("\t\tstatic " + 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);
+                       foreach (VirtualMethod vm in vms) {
+                               bool has_method = methods [vm.Name] != null;
+                               if (has_method && vm.IsValid)
+                                       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\tstatic void Initialize (IntPtr 
ifaceptr, IntPtr data)");
                        sw.WriteLine ("\t\t{");
-                       sw.WriteLine ("\t\t\t" + IfaceName + " iface = (" + 
IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));");
+                       sw.WriteLine ("\t\t\t" + IfaceName + " native_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\tnative_iface." + vm.CName 
+ " = iface." + vm.CName + ";");
+                       sw.WriteLine ("\t\t\tMarshal.StructureToPtr 
(native_iface, ifaceptr, false);");
+                       sw.WriteLine ("\t\t\tGCHandle gch = (GCHandle) data;");
+                       sw.WriteLine ("\t\t\tgch.Free ();");
                        sw.WriteLine ("\t\t}");
+                       sw.WriteLine ();
                }
 
                void GenerateCallbacks (StreamWriter sw)
                {
                        foreach (VirtualMethod vm in vms) {
+                               if (methods [vm.Name] == null)
+                                       continue;
                                sw.WriteLine ();
                                vm.GenerateCallback (sw);
                        }
                }
 
+               void GenerateCtor (StreamWriter sw)
+               {
+                       sw.WriteLine ("\t\tpublic " + Name + "Adapter ()");
+                       sw.WriteLine ("\t\t{");
+                       sw.WriteLine ("\t\t\tInitHandler = new 
GLib.GInterfaceInitHandler (Initialize);");
+                       sw.WriteLine ("\t\t}");
+                       sw.WriteLine ();
+               }
+
+               void GenerateGType (StreamWriter sw)
+               {
+                       Method m = GetMethod ("GetType");
+                       m.GenerateImport (sw);
+                       sw.WriteLine ("\t\tpublic override GLib.GType GType {");
+                       sw.WriteLine ("\t\t\tget {");
+                       sw.WriteLine ("\t\t\t\treturn new GLib.GType (" + 
m.CName +  " ());");
+                       sw.WriteLine ("\t\t\t}");
+                       sw.WriteLine ("\t\t}");
+                       sw.WriteLine ();
+               }
+
                void GenerateAdapter (GenerationInfo gen_info)
                {
                        StreamWriter sw = gen_info.Writer = gen_info.OpenStream 
(Name + "Adapter");
@@ -166,10 +186,11 @@
 
                        GenerateDelegates (sw);
                        GenerateIfaceStruct (sw);
+                       GenerateStaticCtor (sw);
+                       GenerateCallbacks (sw);
+                       GenerateInitialize (sw);
                        GenerateCtor (sw);
-                       GenerateAdapterProp (sw);
-                       GenerateInitialize (sw);
-                       GenerateCallbacks (sw);
+                       GenerateGType (sw);
 
                        sw.WriteLine ("\t}");
                        sw.WriteLine ("#endregion");
@@ -253,11 +274,12 @@
                        Statistics.IFaceCount++;
                }
 
+#if false
                public void GenerateNotQuiteReadyYet (GenerationInfo gen_info)
                {
                        ArrayList tmp = new ArrayList ();
                        foreach (VirtualMethod vm in vms) {
-                               if (vm.Validate())
+                               if (vm.IsValid)
                                        tmp.Add (vm);
                                else {
                                        members.Remove (vm);
@@ -268,9 +290,11 @@
                        GenerateAdapter (gen_info);
                        GenerateInterface (gen_info);
                }
+#endif
 
                public override void Generate (GenerationInfo gen_info)
                {
+                       GenerateAdapter (gen_info);
                        StreamWriter sw = gen_info.Writer = gen_info.OpenStream 
(Name);
 
                        sw.WriteLine ("namespace " + NS + " {");
@@ -278,6 +302,7 @@
                        sw.WriteLine ("\tusing System;");
                        sw.WriteLine ();
                        sw.WriteLine ("#region Autogenerated code");
+                       sw.WriteLine ("\t[GLib.GInterface (typeof (" + Name + 
"Adapter))]");
                        sw.WriteLine ("\tpublic interface " + Name + " : 
GLib.IWrapper {");
                        sw.WriteLine ();
                        

Modified: trunk/gtk-sharp/generator/ManagedCallString.cs
===================================================================
--- trunk/gtk-sharp/generator/ManagedCallString.cs      2007-09-11 20:13:14 UTC 
(rev 85657)
+++ trunk/gtk-sharp/generator/ManagedCallString.cs      2007-09-11 20:34:24 UTC 
(rev 85658)
@@ -29,19 +29,27 @@
                
                ArrayList parms = new ArrayList ();
                ArrayList special = new ArrayList ();
+               bool has_error;
 
                public ManagedCallString (Parameters parms)
                {
                        for (int i = 1; i < parms.Count; i ++) {
                                Parameter p = parms [i];
-                               if (p.IsLength && parms [i-1].IsString)
+                               if (p.IsLength && parms [i-1].IsString) 
                                        continue;
+                               else if (p.Scope == "notified")
+                                       i += 2;
+                                       
+                               else if (p is ErrorParameter) {
+                                       has_error = true;
+                                       continue;
+                               }
                                this.parms.Add (p);
 
-                               IGeneratable igen = p.Generatable;
-                               if ((igen is StructGen || p.PassAs != "") &&
-                                   (p.Name != p.FromNative (p.Name)))
+                               if (p.PassAs != String.Empty && (p.Name != 
p.FromNative (p.Name)))
                                        this.special.Add (true);
+                               else if (p.Generatable is CallbackGen)
+                                       this.special.Add (true);
                                else
                                        this.special.Add (false);
                        }
@@ -51,6 +59,9 @@
                {
                        string ret = "";
 
+                       if (has_error)
+                               ret = indent + "error = IntPtr.Zero;\n";
+
                        for (int i = 0; i < parms.Count; i ++) {
                                if ((bool)special[i] == false)
                                        continue;
@@ -58,10 +69,14 @@
                                Parameter p = parms [i] as Parameter;
                                IGeneratable igen = p.Generatable;
 
-                               ret += indent + igen.QualifiedName + " my" + 
p.Name;
-                               if (igen is StructGen || p.PassAs == "ref")
-                                       ret += " = " + p.FromNative (p.Name);
-                               ret += ";\n";
+                               if (igen is CallbackGen) {
+                                       ret += indent + String.Format ("{0} 
{1}_invoker = new {0} ({1});\n", (igen as CallbackGen).InvokerName, p.Name);
+                               } else {
+                                       ret += indent + igen.QualifiedName + " 
my" + p.Name;
+                                       if (p.PassAs == "ref")
+                                               ret += " = " + p.FromNative 
(p.Name);
+                                       ret += ";\n";
+                               }
                        }
 
                        return ret;
@@ -77,7 +92,10 @@
                        for (int i = 0; i < parms.Count; i ++) {
                                Parameter p = parms [i] as Parameter;
                                result [i] = p.PassAs == "" ? "" : p.PassAs + " 
";
-                               result [i] += ((bool)special[i]) ? "my" + 
p.Name : p.FromNative (p.Name);
+                               if (p.Generatable is CallbackGen)
+                                       result [i] += p.Name + 
"_invoker.Handler";
+                               else
+                                       result [i] += ((bool)special[i]) ? "my" 
+ p.Name : p.FromNative (p.Name);
                        }
 
                        return String.Join (", ", result);
@@ -94,7 +112,9 @@
                                Parameter p = parms [i] as Parameter;
                                IGeneratable igen = p.Generatable;
 
-                               if (igen is StructBase)
+                               if (igen is CallbackGen)
+                                       continue;
+                               else if (igen is StructBase || igen is ByRefGen)
                                        ret += indent + String.Format ("if ({0} 
!= IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (my{0}, 
{0}, false);\n", p.Name);
                                else
                                        ret += indent + p.Name + " = " + 
igen.ToNativeReturn ("my" + p.Name) + ";\n";

Modified: trunk/gtk-sharp/generator/MethodBody.cs
===================================================================
--- trunk/gtk-sharp/generator/MethodBody.cs     2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/MethodBody.cs     2007-09-11 20:34:24 UTC (rev 
85658)
@@ -75,6 +75,11 @@
                        return String.Join (", ", result);
                }
 
+               public void Initialize (GenerationInfo gen_info)
+               {
+                       Initialize (gen_info, false, false, String.Empty);
+               }
+
                public void Initialize (GenerationInfo gen_info, bool is_get, 
bool is_set, string indent)
                {
                        if (parameters.Count == 0)
@@ -124,7 +129,6 @@
                                                sw.WriteLine (indent + 
"\t\t\t{0} {1}_wrapper = new {0} ({1});", wrapper, name);
                                                break;
                                        }
-                                               
                                }
                        }
 
@@ -158,10 +162,17 @@
                
                public bool ThrowsException {
                        get {
-                               if (parameters.Count < 1)
-                                       return false;
+                               int idx = parameters.Count - 1;
 
-                               return parameters [parameters.Count - 1].CType 
== "GError**";
+                               while (idx >= 0) {
+                                       if (parameters [idx].IsUserData)
+                                               idx--;
+                                       else if (parameters [idx].CType == 
"GError**")
+                                               return true;
+                                       else
+                                               break;
+                               }
+                               return false;
                        }
                }
        }

Modified: trunk/gtk-sharp/generator/Parameters.cs
===================================================================
--- trunk/gtk-sharp/generator/Parameters.cs     2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/Parameters.cs     2007-09-11 20:34:24 UTC (rev 
85658)
@@ -285,7 +285,9 @@
 
                public string FromNative (string var)
                {
-                       if (Generatable is HandleBase)
+                       if (Generatable == null)
+                               return String.Empty;
+                       else if (Generatable is HandleBase)
                                return ((HandleBase)Generatable).FromNative 
(var, Owned);
                        else
                                return Generatable.FromNative (var);

Modified: trunk/gtk-sharp/generator/ReturnValue.cs
===================================================================
--- trunk/gtk-sharp/generator/ReturnValue.cs    2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/ReturnValue.cs    2007-09-11 20:34:24 UTC (rev 
85658)
@@ -137,6 +137,22 @@
                                return IGen.FromNativeReturn (var);
                }
                        
+               public string ToNative (string var)
+               {
+                       if (IGen == null)
+                               return String.Empty;
+
+                       if (ElementType.Length > 0) {
+                               string args = ", typeof (" + ElementType + "), 
" + (Owned ? "true" : "false") + ", " + (ElementsOwned ? "true" : "false");
+                               var = "new " + IGen.QualifiedName + "(" + var + 
args + ")";
+                       }
+
+                       if (IGen is IManualMarshaler)
+                               return (IGen as IManualMarshaler).AllocNative 
(var);
+                       else
+                               return IGen.ToNativeReturn (var);
+               }
+
                public bool Validate ()
                {
                        if (MarshalType == "" || CSType == "") {

Modified: trunk/gtk-sharp/generator/VirtualMethod.cs
===================================================================
--- trunk/gtk-sharp/generator/VirtualMethod.cs  2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/generator/VirtualMethod.cs  2007-09-11 20:34:24 UTC (rev 
85658)
@@ -53,6 +53,24 @@
                        }
                }
 
+               bool IsGetter {
+                       get {
+                               return (Name.StartsWith ("Get") || 
Name.StartsWith ("Has")) && ((!retval.IsVoid && parms.Count == 1) || 
(retval.IsVoid && parms.Count == 2 && parms [1].PassAs == "out"));
+                       }
+               }
+       
+               bool IsSetter {
+                       get {
+                               if (!Name.StartsWith ("Set") || !retval.IsVoid)
+                                       return false;
+
+                               if (parms.Count == 2 || (parms.Count == 4 && 
parms [1].Scope == "notified"))
+                                       return true;
+                               else
+                                       return false;
+                       }
+               }
+ 
                public string MarshalReturnType {
                        get {
                                return SymbolTable.Table.GetToNativeReturnType 
(elem["return-type"].GetAttribute("type"));
@@ -73,39 +91,64 @@
 
                public void GenerateCallback (StreamWriter sw)
                {
+                       if (!Validate ())
+                               return;
+
                        ManagedCallString call = new ManagedCallString (parms);
                        string type = parms [0].CSType;
                        string name = parms [0].Name;
                        string call_string = "__obj." + Name + " (" + call + 
")";
+                       if (IsGetter)
+                               call_string = "__obj." + (Name.StartsWith 
("Get") ? Name.Substring (3) : Name);
+                       else if (IsSetter)
+                               call_string = "__obj." + Name.Substring (3) + " 
= " + call;
                        sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + 
Name + "Callback (" + parms.ImportSignature + ")");
                        sw.WriteLine ("\t\t{");
                        sw.WriteLine ("\t\t\t" + type + " __obj = 
GLib.Object.GetObject (" + name + ", false) as " + type + ";");
                        sw.Write (call.Setup ("\t\t\t"));
-                       if (retval.CSType == "void")
-                               sw.WriteLine ("\t\t\t" + call_string + ";");
-                       else {
-                               sw.WriteLine ("\t\t\treturn " + 
SymbolTable.Table.ToNativeReturn (retval.CType, call_string) + ";");
-                       }
+                       if (retval.IsVoid) { 
+                               if (IsGetter) {
+                                       Parameter p = parms [1];
+                                       string out_name = p.Name;
+                                       if (p.MarshalType != p.CSType)
+                                               out_name = "my" + out_name;
+                                       sw.WriteLine ("\t\t\t" + out_name + " = 
" + call_string + ";");
+                               } else
+                                       sw.WriteLine ("\t\t\t" + call_string + 
";");
+                       } else
+                               sw.WriteLine ("\t\t\t" + retval.ToNativeType + 
" result = " + retval.ToNative (call_string) + ";");
                        sw.Write (call.Finish ("\t\t\t"));
+                       if (!retval.IsVoid)
+                               sw.WriteLine ("\t\t\treturn result;");
                        sw.WriteLine ("\t\t}");
                }
 
-               public bool Validate ()
+               enum ValidState {
+                       Unvalidated,
+                       Invalid,
+                       Valid
+               }
+
+               ValidState vstate = ValidState.Unvalidated;
+
+               public bool IsValid {
+                       get { 
+                               if (vstate == ValidState.Unvalidated)
+                                       return Validate ();
+                               else
+                                       return vstate == ValidState.Valid; 
+                       }
+               }
+
+               bool Validate ()
                {
                        if (!parms.Validate () || !retval.Validate ()) {
                                Console.Write ("in virtual method " + Name + " 
");
+                               vstate = ValidState.Invalid;
                                return false;
                        }
 
-                       for (int i = 0; i < parms.Count; i++) {
-                               Parameter p = parms [i];
-                               if (p.Generatable is CallbackGen) {
-                                       Console.Write("Callback: " + p.CSType + 
" in virtual method " + Name + " ");
-                                       Statistics.ThrottledCount++;
-                                       return false;
-                               }
-                       }
-
+                       vstate = ValidState.Valid;
                        return true;
                }
        }

Added: trunk/gtk-sharp/glib/GInterfaceAdapter.cs
===================================================================
--- trunk/gtk-sharp/glib/GInterfaceAdapter.cs   2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/glib/GInterfaceAdapter.cs   2007-09-11 20:34:24 UTC (rev 
85658)
@@ -0,0 +1,67 @@
+// GInterfaceAdapter.cs
+//
+// Author:   Mike Kestner  <[EMAIL PROTECTED]>
+//
+// Copyright (c) 2007 Novell, Inc.
+//
+// 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.
+
+
+namespace GLib {
+
+       using System;
+       using System.Runtime.InteropServices;
+
+       public delegate void GInterfaceInitHandler (IntPtr iface_ptr, IntPtr 
data);
+
+       internal delegate void GInterfaceFinalizeHandler (IntPtr iface_ptr, 
IntPtr data);
+
+       internal struct GInterfaceInfo {
+               internal GInterfaceInitHandler InitHandler;
+               internal GInterfaceFinalizeHandler FinalizeHandler;
+               internal IntPtr Data;
+       }
+
+       public abstract class GInterfaceAdapter {
+
+               GInterfaceInfo info;
+
+               protected GInterfaceAdapter ()
+               {
+                       info.FinalizeHandler = new GInterfaceFinalizeHandler 
(Finalize);
+                       info.Data = (IntPtr) GCHandle.Alloc (this);
+               }
+
+               protected GInterfaceInitHandler InitHandler {
+                       set {
+                               info.InitHandler = value;
+                       }
+               }
+
+               public abstract GType GType { get; }
+
+               internal GInterfaceInfo Info {
+                       get {
+                               return info;
+                       }
+               }
+
+               void Finalize (IntPtr iface_ptr, IntPtr data)
+               {
+                       GCHandle gch = (GCHandle) data;
+                       gch.Free ();
+               }
+       }
+}

Added: trunk/gtk-sharp/glib/GInterfaceAttribute.cs
===================================================================
--- trunk/gtk-sharp/glib/GInterfaceAttribute.cs 2007-09-11 20:13:14 UTC (rev 
85657)
+++ trunk/gtk-sharp/glib/GInterfaceAttribute.cs 2007-09-11 20:34:24 UTC (rev 
85658)
@@ -0,0 +1,42 @@
+// GInterfaceAttribute.cs
+//
+// Copyright (c) 2007 Novell, Inc.
+//
+// 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.
+
+
+namespace GLib {
+
+       using System;
+
+       [AttributeUsage (AttributeTargets.Interface)]
+       public sealed class GInterfaceAttribute : Attribute {
+               Type adapter_type;
+
+               public GInterfaceAttribute (Type adapter_type)
+               {
+                       this.adapter_type = adapter_type;
+               }
+
+               public Type AdapterType {
+                       get {
+                               return adapter_type;
+                       }
+                       set {
+                               adapter_type = value;
+                       }
+               }
+       }
+}

Modified: trunk/gtk-sharp/glib/Makefile.am
===================================================================
--- trunk/gtk-sharp/glib/Makefile.am    2007-09-11 20:13:14 UTC (rev 85657)
+++ trunk/gtk-sharp/glib/Makefile.am    2007-09-11 20:34:24 UTC (rev 85658)
@@ -28,6 +28,8 @@
        ExceptionManager.cs                     \
        FileUtils.cs                            \
        GException.cs                           \
+       GInterfaceAdapter.cs                    \
+       GInterfaceAttribute.cs                  \
        GString.cs                              \
        GType.cs                                \
        GTypeAttribute.cs                       \

Modified: trunk/gtk-sharp/glib/Object.cs
===================================================================
--- trunk/gtk-sharp/glib/Object.cs      2007-09-11 20:13:14 UTC (rev 85657)
+++ trunk/gtk-sharp/glib/Object.cs      2007-09-11 20:34:24 UTC (rev 85658)
@@ -183,6 +183,24 @@
                        }
                }
 
+               [DllImport("libgobject-2.0-0.dll")]
+               static extern void g_type_add_interface_static (IntPtr gtype, 
IntPtr iface_type, ref GInterfaceInfo info);
+
+               static void AddInterfaces (GType gtype, Type t)
+               {
+                       foreach (Type iface in t.GetInterfaces ()) {
+                               if (!iface.IsDefined (typeof 
(GInterfaceAttribute), true) || iface.IsAssignableFrom (t.BaseType))
+                                       continue;
+
+                               GInterfaceAttribute attr = 
iface.GetCustomAttributes (typeof (GInterfaceAttribute), false) [0] as 
GInterfaceAttribute;
+                               GInterfaceAdapter adapter = 
Activator.CreateInstance (attr.AdapterType, null) as GInterfaceAdapter;
+                               
+                               GInterfaceInfo info = adapter.Info;
+                               g_type_add_interface_static (gtype.Val, 
adapter.GType.Val, ref info);
+                               Console.WriteLine (adapter);
+                       }
+               }
+
                [DllImport("glibsharpglue-2")]
                static extern IntPtr gtksharp_register_type (IntPtr name, 
IntPtr parent_type);
 
@@ -221,6 +239,7 @@
                        GLib.GType.Register (gtype, t);
                        ConnectDefaultHandlers (gtype, t);
                        InvokeClassInitializers (gtype, t);
+                       AddInterfaces (gtype, t);
                        g_types[t] = gtype;
                        return gtype;
                }

Modified: trunk/gtk-sharp/gtk/Gtk.metadata
===================================================================
--- trunk/gtk-sharp/gtk/Gtk.metadata    2007-09-11 20:13:14 UTC (rev 85657)
+++ trunk/gtk-sharp/gtk/Gtk.metadata    2007-09-11 20:34:24 UTC (rev 85658)
@@ -128,6 +128,10 @@
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'DeleteText']" name="name">TextDeleted</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'InsertText']/*/[EMAIL PROTECTED]'position']" 
name="pass_as">ref</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'InsertText']" name="name">TextInserted</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'DoDeleteText']" name="name">DeleteText</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'DoInsertText']" name="name">InsertText</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'do_insert_text']/*/[EMAIL PROTECTED]'position']" 
name="pass_as">ref</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkEditable']/[EMAIL 
PROTECTED]'SetSelectionBounds']" name="name">SelectRegion</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'Action']" name="new_flag">1</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'GetCurrentFolder']/return-type" name="type">gfilename*</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'GetFilename']/return-type" name="type">gfilename*</attr>
@@ -146,17 +150,30 @@
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'gtk_file_chooser_list_shortcut_folder_uris']/return-type" 
name="element_type">gchar*</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'gtk_file_chooser_list_shortcut_folder_uris']/return-type" 
name="elements_owned">true</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'gtk_file_chooser_list_shortcut_folder_uris']/return-type" 
name="owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'GetPaths']" name="name">GetFilenames</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'get_paths']/return-type" name="element_type">gfilename*</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'get_paths']/return-type" name="elements_owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'get_paths']/return-type" name="owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'ListFilters']" name="name">GetFilters</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_filters']/return-type" name="element_type">gchar*</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_filters']/return-type" name="elements_owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_filters']/return-type" name="owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'ListShortcutFolders']" name="name">GetShortcutFolders</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_shortcut_folders']/return-type" 
name="element_type">gchar*</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_shortcut_folders']/return-type" 
name="elements_owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkFileChooser']/[EMAIL 
PROTECTED]'list_shortcut_folders']/return-type" name="owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkRecentChooser']/[EMAIL 
PROTECTED]'GetRecentManager']" name="hidden">1</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'Foreach']/*/[EMAIL PROTECTED]'func']" name="scope">call</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIterFirst']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIterFirst']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'Get']" name="hidden">1</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIterFromString']/*/[EMAIL PROTECTED]'iter']" 
name="pass_as">out</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIter']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetPath']/return-type" name="owned">true</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetValue']/*/[EMAIL PROTECTED]'value']" name="pass_as">ref</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterChildren']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterNext']/*/[EMAIL PROTECTED]'iter']" name="pass_as">ref</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterNthChild']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterParent']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIterFromString']/*/[EMAIL PROTECTED]'iter']" 
name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetIter']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetPath']/return-type" name="owned">true</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'GetValue']/*/[EMAIL PROTECTED]'value']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterChildren']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterNext']/*/[EMAIL PROTECTED]'iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterNthChild']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'IterParent']/*/[EMAIL PROTECTED]'iter']" name="pass_as">out</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'RowChanged']" name="name">EmitRowChanged</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'RowDeleted']" name="name">EmitRowDeleted</attr>
   <attr path="/api/namespace/[EMAIL PROTECTED]'GtkTreeModel']/[EMAIL 
PROTECTED]'RowHasChildToggled']" name="name">EmitRowHasChildToggled</attr>

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to