diff --git a/ChangeLog b/ChangeLog index 3adbc0d58..3f7145857 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2002-07-16 Mike Kestner + + * generator/ClassBase.cs : make MarshalType virtual. + * generator/Parameters.cs : add Parameter class and Indexer. + * generator/Signal.cs : Now use Parameters. + (GetHandlerName): New abstraction of name handling. + (GenerateDecls): use GetHandlerName. + (GenComments): make private. + (GenHandler): New. Generate custom event handlers and args. + (Generate): use GenHandler. Pass args type to SignalHandler. + * generate/SignalHandler.cs : store args type. Generate handler + dependent args and use MulticastDelegate.DynamicInvoke. + * generate/StructGen.cs : override MarshalType. + * glib/SignalCallback.cs : store a MulticastDelegate and args type + * sample/*.cs : use new DeleteEventHandler + 2002-07-13 Rachel Hestilow * generator/Parameters.cs: Allow nulls if null_ok set. diff --git a/generator/ClassBase.cs b/generator/ClassBase.cs index 753e93041..11b4055b9 100644 --- a/generator/ClassBase.cs +++ b/generator/ClassBase.cs @@ -84,7 +84,7 @@ namespace GtkSharp.Generation { } } - public String MarshalType { + public virtual String MarshalType { get { return "IntPtr"; diff --git a/generator/Parameters.cs b/generator/Parameters.cs index d42904197..204e73615 100644 --- a/generator/Parameters.cs +++ b/generator/Parameters.cs @@ -10,6 +10,54 @@ namespace GtkSharp.Generation { using System.IO; using System.Xml; + public class Parameter { + + private XmlElement elem; + + public Parameter (XmlElement e) + { + elem = e; + } + + public string CSType { + get { + return SymbolTable.GetCSType( elem.GetAttribute("type")); + } + } + + public string Name { + get { + string name = elem.GetAttribute("name"); + switch (name) { + case "string": + return "str1ng"; + case "event": + return "evnt"; + case "object": + return "objekt"; + default: + break; + } + + return name; + } + } + + public string StudlyName { + get { + string name = elem.GetAttribute("name"); + string[] segs = name.Split('_'); + string studly = ""; + foreach (string s in segs) { + studly += (s.Substring(0,1).ToUpper() + s.Substring(1)); + } + return studly; + + } + } + + } + public class Parameters { private XmlElement elem; @@ -29,6 +77,17 @@ namespace GtkSharp.Generation { } } + public Parameter this [int idx] { + get { + int count = 0; + foreach (XmlNode node in elem.ChildNodes) { + if ((node is XmlElement) && (idx == count++)) + return new Parameter ((XmlElement) node); + } + return null; + } + } + public string ImportSig { get { return import_sig; diff --git a/generator/Signal.cs b/generator/Signal.cs index 654f5c402..50d87404c 100644 --- a/generator/Signal.cs +++ b/generator/Signal.cs @@ -16,12 +16,15 @@ namespace GtkSharp.Generation { private string marsh; private string name; private XmlElement elem; + private Parameters parms; private ClassBase container_type; public Signal (XmlElement elem, ClassBase container_type) { this.elem = elem; this.name = elem.GetAttribute ("name"); + if (elem["parameters"] != null) + parms = new Parameters (elem["parameters"]); this.container_type = container_type; } @@ -43,19 +46,27 @@ namespace GtkSharp.Generation { return false; } + if (parms != null && !parms.Validate ()) + return false; + return true; } - public void GenerateDecl (StreamWriter sw) - { + public void GenerateDecl (StreamWriter sw) + { + string argsname; + string handler = GetHandlerName (out argsname); + if (handler != "EventHandler") + handler = "GtkSharp." + handler; + GenComments (sw); if (elem.HasAttribute("new_flag") || (container_type != null && container_type.GetSignalRecursively (Name) != null)) sw.Write("new "); - sw.WriteLine ("\t\tevent EventHandler " + Name + ";"); + sw.WriteLine ("\t\tevent " + handler + " " + Name + ";"); } - public void GenComments (StreamWriter sw) + private void GenComments (StreamWriter sw) { sw.WriteLine(); sw.WriteLine("\t\t/// " + Name + " Event "); @@ -63,22 +74,95 @@ namespace GtkSharp.Generation { // FIXME: Generate some signal docs sw.WriteLine("\t\t/// "); } - + + private string GetHandlerName (out string argsname) + { + if (marsh == "voidObjectSignal") { + argsname = "EventArgs"; + return "EventHandler"; + } + + argsname = Name + "Args"; + return Name + "Handler"; + } + + private string GenHandler (out string argsname) + { + string handler = GetHandlerName (out argsname); + if (handler == "EventHandler") + return handler; + + char sep = Path.DirectorySeparatorChar; + string dir = ".." + sep + container_type.NS.ToLower() + sep + "generated"; + + if (!Directory.Exists (dir)) + Directory.CreateDirectory (dir); + + string filename = dir + sep + "GtkSharp." + handler + ".cs"; + + FileStream stream = new FileStream (filename, FileMode.Create, FileAccess.Write); + StreamWriter sw = new StreamWriter (stream); + + sw.WriteLine ("// Generated File. Do not modify."); + sw.WriteLine ("// 2001-2002 Mike Kestner"); + sw.WriteLine (); + sw.WriteLine ("namespace GtkSharp {"); + sw.WriteLine (); + sw.WriteLine ("\tusing System;"); + + sw.WriteLine (); + sw.WriteLine ("\t/// " + handler + " Delegate "); + sw.WriteLine ("\t/// "); + sw.WriteLine ("\t///\tDelegate signature for " + Name + " Event handlers"); + sw.WriteLine ("\t/// "); + sw.WriteLine (); + sw.WriteLine ("\tpublic delegate void " + handler + "(object o, " + argsname + " args);"); + sw.WriteLine (); + sw.WriteLine ("\t/// " + argsname + " Class "); + sw.WriteLine ("\t/// "); + sw.WriteLine ("\t///\tArguments for " + Name + " Event handlers"); + sw.WriteLine ("\t/// "); + sw.WriteLine (); + sw.WriteLine ("\tpublic class " + argsname + " : GtkSharp.SignalArgs {"); + if (parms != null) { + for (int i = 1; i < parms.Count; i++) { + sw.WriteLine ("\t\tpublic " + parms[i].CSType + " " + parms[i].StudlyName + "{"); + sw.WriteLine ("\t\t\tget {"); + sw.WriteLine ("\t\t\t\treturn (" + parms[i].CSType + ") Args[" + (i - 1) + "];"); + sw.WriteLine ("\t\t\t}"); + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + } + } + sw.WriteLine ("\t}"); + sw.WriteLine ("}"); + sw.Close (); + argsname = "GtkSharp." + argsname; + return "GtkSharp." + handler; + } + public void Generate (StreamWriter sw, ClassBase implementor, bool gen_docs) { string cname = "\"" + elem.GetAttribute("cname") + "\""; - marsh = "GtkSharp." + marsh; + string qual_marsh = "GtkSharp." + marsh; if (gen_docs) GenComments (sw); + + string argsname; + string handler = GenHandler (out argsname); + sw.Write("\t\tpublic "); if (elem.HasAttribute("new_flag") || (container_type != null && container_type.GetSignalRecursively (Name) != null) || (implementor != null && implementor.GetSignalRecursively (Name) != null)) sw.Write("new "); - sw.WriteLine("event EventHandler " + Name + " {"); + sw.WriteLine("event " + handler + " " + Name + " {"); sw.WriteLine("\t\t\tadd {"); sw.WriteLine("\t\t\t\tif (EventList[" + cname + "] == null)"); - sw.Write("\t\t\t\t\tSignals[" + cname + "] = new " + marsh); - sw.WriteLine("(this, Handle, " + cname + ", value);"); + sw.Write("\t\t\t\t\tSignals[" + cname + "] = new " + qual_marsh); + sw.Write("(this, Handle, " + cname + ", value, System.Type.GetType(\"" + argsname); + if (argsname != "EventArgs") + sw.Write("," + container_type.NS.ToLower() + "-sharp"); + sw.WriteLine("\"));"); sw.WriteLine("\t\t\t\tEventList.AddHandler(" + cname + ", value);"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tremove {"); diff --git a/generator/SignalHandler.cs b/generator/SignalHandler.cs index 26e24b1ab..cf9935ee5 100644 --- a/generator/SignalHandler.cs +++ b/generator/SignalHandler.cs @@ -14,6 +14,7 @@ namespace GtkSharp.Generation { public class SignalHandler { private static Hashtable handlers = new Hashtable (); + private string args_type; public static String GetName(XmlElement sig) { @@ -23,22 +24,23 @@ namespace GtkSharp.Generation { return ""; } - String retval = ret_elem.GetAttribute("type"); + string retval = ret_elem.GetAttribute("type"); if (retval == "") { Console.Write("Invalid return-type "); return ""; } - String s_ret = SymbolTable.GetCSType(retval); - String p_ret = SymbolTable.GetMarshalType(retval); + string s_ret = SymbolTable.GetCSType(retval); + string p_ret = SymbolTable.GetMarshalType(retval); if ((s_ret == "") || (p_ret == "")) { Console.Write("Funky type: " + retval); return ""; } - String key = retval; - String pinv = ""; - String name = SymbolTable.GetName(retval); + string key = retval; + string pinv = ""; + string name = SymbolTable.GetName(retval); + string argfields = ""; int pcnt = 0; ArrayList parms = new ArrayList(); @@ -53,8 +55,8 @@ namespace GtkSharp.Generation { if (!(parm is XmlElement) || parm.Name != "parameter") continue; XmlElement elem = (XmlElement) parm; - String type = elem.GetAttribute("type"); - String ptype = SymbolTable.GetMarshalType(type); + string type = elem.GetAttribute("type"); + string ptype = SymbolTable.GetMarshalType(type); if (ptype == "") { Console.Write("Funky type: " + type); return ""; @@ -99,8 +101,6 @@ namespace GtkSharp.Generation { String sname = name + "Signal"; String dname = name + "Delegate"; String cbname = name + "Callback"; - String hndlrname = name + "Handler"; - String argsname = name + "Args"; handlers[name] = sname; @@ -124,11 +124,6 @@ namespace GtkSharp.Generation { sw.Write("\tpublic delegate " + p_ret + " "); sw.WriteLine(dname + "(" + pinv + ", int key);"); sw.WriteLine(); - sw.WriteLine("\tpublic delegate void " + hndlrname + "(object o, " + argsname + " args);"); - sw.WriteLine(); - sw.WriteLine("\tpublic class " + argsname + " : EventArgs {"); - sw.WriteLine("\t}"); - sw.WriteLine(); sw.WriteLine("\tpublic class " + sname + " : SignalCallback {"); sw.WriteLine(); sw.WriteLine("\t\tprivate static " + dname + " _Delegate;"); @@ -140,37 +135,47 @@ namespace GtkSharp.Generation { sw.WriteLine("\t\t\t\tthrow new Exception(\"Unexpected signal key\");"); sw.WriteLine(); sw.WriteLine("\t\t\t" + sname + " inst = (" + sname + ") _Instances[key];"); - sw.WriteLine("\t\t\tSignalArgs args = new SignalArgs();"); - if (parms.Count > 1) { - sw.WriteLine("\t\t\targs.Args = new object[" + (parms.Count-1) + "];"); - } - for (int idx=1; idx < parms.Count; idx++) { - if (SymbolTable.IsObject((String)parms[idx])) { - sw.Write("\t\t\targs.Args[" + (idx-1) + "] "); - sw.WriteLine("= GLib.Object.GetObject(arg" + idx + ");"); - } else { - string ctype = (string) parms[idx]; - sw.WriteLine("\t\t\targs.Args[" + (idx-1) + "] = " + SymbolTable.FromNative (ctype, "arg" + idx) + ";"); - ClassBase wrapper = SymbolTable.GetClassGen (ctype); - if ((wrapper != null && !(wrapper is InterfaceGen)) || SymbolTable.IsManuallyWrapped (ctype) || SymbolTable.IsBoxed (ctype)) { - sw.WriteLine("\t\t\tif (args.Args[" + (idx-1) + "] == null)"); - sw.WriteLine("\t\t\t\targs.Args[{0}] = new {1}(arg{2});", idx-1, SymbolTable.GetCSType (ctype), idx); + if ((s_ret == "void") && (parms.Count == 1)) { + sw.WriteLine("\t\t\tEventHandler h = (EventHandler) inst._handler;"); + sw.WriteLine("\t\t\th (inst._obj, new EventArgs ());"); + sw.WriteLine("\t\t}"); + sw.WriteLine(); + } else { + sw.WriteLine("\t\t\tSignalArgs args = (SignalArgs) Activator.CreateInstance (inst._argstype);"); + if (parms.Count > 1) { + sw.WriteLine("\t\t\targs.Args = new object[" + (parms.Count-1) + "];"); + } + for (int idx=1; idx < parms.Count; idx++) { + if (SymbolTable.IsObject((String)parms[idx])) { + sw.Write("\t\t\targs.Args[" + (idx-1) + "] "); + sw.WriteLine("= GLib.Object.GetObject(arg" + idx + ");"); + } else { + string ctype = (string) parms[idx]; + sw.WriteLine("\t\t\targs.Args[" + (idx-1) + "] = " + SymbolTable.FromNative (ctype, "arg" + idx) + ";"); + ClassBase wrapper = SymbolTable.GetClassGen (ctype); + if ((wrapper != null && !(wrapper is InterfaceGen)) || SymbolTable.IsManuallyWrapped (ctype) || SymbolTable.IsBoxed (ctype)) { + sw.WriteLine("\t\t\tif (args.Args[" + (idx-1) + "] == null)"); + sw.WriteLine("\t\t\t\targs.Args[{0}] = new {1}(arg{2});", idx-1, SymbolTable.GetCSType (ctype), idx); + } } } + sw.WriteLine("\t\t\tobject[] argv = new object[2];"); + sw.WriteLine("\t\t\targv[0] = inst._obj;"); + sw.WriteLine("\t\t\targv[1] = args;"); + sw.WriteLine("\t\t\tinst._handler.DynamicInvoke(argv);"); + if (retval != "void") { + sw.WriteLine("\t\t\treturn (" + s_ret + ") args.RetVal;"); + } + sw.WriteLine("\t\t}"); + sw.WriteLine(); } - sw.WriteLine("\t\t\tinst._handler (inst._obj, args);"); - if (retval != "void") { - sw.WriteLine("\t\t\treturn (" + s_ret + ") args.RetVal;"); - } - sw.WriteLine("\t\t}"); - sw.WriteLine(); sw.Write("\t\t[DllImport(\"gobject-2.0\")]"); sw.Write("\t\tstatic extern void g_signal_connect_data("); sw.Write("IntPtr obj, String name, " + dname + " cb, int key, IntPtr p,"); sw.WriteLine(" int flags);"); sw.WriteLine(); sw.Write("\t\tpublic " + sname + "(GLib.Object obj, IntPtr raw, "); - sw.WriteLine("String name, EventHandler eh) : base(obj, eh)"); + sw.WriteLine("String name, MulticastDelegate eh, Type argstype) : base(obj, eh, argstype)"); sw.WriteLine("\t\t{"); sw.WriteLine("\t\t\tif (_Delegate == null) {"); sw.WriteLine("\t\t\t\t_Delegate = new " + dname + "(" + cbname + ");"); diff --git a/generator/StructGen.cs b/generator/StructGen.cs index b778fa2c3..c2bd8a707 100644 --- a/generator/StructGen.cs +++ b/generator/StructGen.cs @@ -14,7 +14,7 @@ namespace GtkSharp.Generation { public StructGen (XmlElement ns, XmlElement elem) : base (ns, elem) {} - public new string MarshalType { + public override string MarshalType { get { return QualifiedName; diff --git a/glib/SignalCallback.cs b/glib/SignalCallback.cs index 8dce633a2..f0f5ebf8d 100644 --- a/glib/SignalCallback.cs +++ b/glib/SignalCallback.cs @@ -28,8 +28,9 @@ namespace GtkSharp { // protected instance members protected GLib.Object _obj; - protected EventHandler _handler; + protected MulticastDelegate _handler; protected int _key; + protected Type _argstype; /// /// SignalCallback Constructor @@ -39,11 +40,12 @@ namespace GtkSharp { /// Initializes instance data. /// - public SignalCallback (GLib.Object obj, EventHandler eh) + public SignalCallback (GLib.Object obj, MulticastDelegate eh, Type argstype) { _key = _NextKey++; _obj = obj; _handler = eh; + _argstype = argstype; _Instances [_key] = this; } diff --git a/sample/ButtonApp.cs b/sample/ButtonApp.cs index 301c8e9b6..14a543c13 100755 --- a/sample/ButtonApp.cs +++ b/sample/ButtonApp.cs @@ -18,7 +18,7 @@ namespace GtkSamples { Application.Init (); Window win = new Window ("Button Tester"); win.DefaultSize = new Size (200, 150); - win.DeleteEvent += new EventHandler (Window_Delete); + win.DeleteEvent += new DeleteEventHandler (Window_Delete); Button btn = new Button ("Click Me"); btn.Clicked += new EventHandler (btn_click); win.Add (btn); @@ -32,11 +32,10 @@ namespace GtkSamples { Console.WriteLine ("Button Clicked"); } - static void Window_Delete (object obj, EventArgs args) + static void Window_Delete (object obj, DeleteEventArgs args) { - SignalArgs sa = (SignalArgs) args; Application.Quit (); - sa.RetVal = true; + args.RetVal = true; } } diff --git a/sample/HelloWorld.cs b/sample/HelloWorld.cs index 847039a6f..c4c946ee5 100755 --- a/sample/HelloWorld.cs +++ b/sample/HelloWorld.cs @@ -17,13 +17,13 @@ namespace GtkSamples { { Application.Init (); Gtk.Window win = new Gtk.Window ("Gtk# Hello World"); - win.DeleteEvent += new EventHandler (Window_Delete); + win.DeleteEvent += new DeleteEventHandler (Window_Delete); win.ShowAll (); Application.Run (); return 0; } - static void Window_Delete (object obj, EventArgs args) + static void Window_Delete (object obj, DeleteEventArgs args) { SignalArgs sa = (SignalArgs) args; Application.Quit (); diff --git a/sample/Menu.cs b/sample/Menu.cs index 731f3f127..fb0549e1e 100755 --- a/sample/Menu.cs +++ b/sample/Menu.cs @@ -17,7 +17,7 @@ namespace GtkSharp.Samples { { Application.Init(); Window win = new Window ("Menu Sample App"); - win.DeleteEvent += new EventHandler (delete_cb); + win.DeleteEvent += new DeleteEventHandler (delete_cb); win.DefaultSize = new Size(200, 150); VBox box = new VBox (false, 2); @@ -41,7 +41,7 @@ namespace GtkSharp.Samples { Application.Run (); } - static void delete_cb (object o, EventArgs args) + static void delete_cb (object o, DeleteEventArgs args) { SignalArgs sa = (SignalArgs) args; Application.Quit ();