2002-05-23 23:43:25 +00:00
// GtkSharp.Generation.Signal.cs - The Signal Generatable.
//
// Author: Mike Kestner <mkestner@speakeasy.net>
//
2004-06-25 16:35:15 +00:00
// Copyright (c) 2001-2003 Mike Kestner
2005-03-28 18:26:00 +00:00
// Copyright (c) 2003-2005 Novell, Inc.
2007-03-06 21:45:51 +00:00
// Copyright (c) 2007 Novell, Inc.
2004-06-25 16:35:15 +00:00
//
// 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.
2002-05-23 23:43:25 +00:00
namespace GtkSharp.Generation {
using System ;
using System.Collections ;
using System.IO ;
using System.Xml ;
public class Signal {
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
private string name ;
2002-05-23 23:43:25 +00:00
private XmlElement elem ;
2004-11-17 15:57:17 +00:00
private ReturnValue retval ;
2002-07-16 23:14:35 +00:00
private Parameters parms ;
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
private ClassBase container_type ;
2002-05-23 23:43:25 +00:00
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
public Signal ( XmlElement elem , ClassBase container_type )
2002-05-23 23:43:25 +00:00
{
this . elem = elem ;
2005-01-26 19:17:07 +00:00
name = elem . GetAttribute ( "name" ) ;
retval = new ReturnValue ( elem [ "return-type" ] ) ;
parms = new Parameters ( elem [ "parameters" ] ) ;
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
this . container_type = container_type ;
2002-05-23 23:43:25 +00:00
}
public string Name {
get {
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
return name ;
}
set {
name = value ;
2002-05-23 23:43:25 +00:00
}
}
public bool Validate ( )
{
2005-02-02 21:57:15 +00:00
if ( Name = = "" ) {
2005-06-30 17:09:39 +00:00
Console . Write ( "Nameless signal " ) ;
2002-05-23 23:43:25 +00:00
Statistics . ThrottledCount + + ;
return false ;
}
2005-06-30 17:09:39 +00:00
if ( ! parms . Validate ( ) | | ! retval . Validate ( ) ) {
Console . Write ( " in signal " + Name + " " ) ;
Statistics . ThrottledCount + + ;
2004-11-17 15:57:17 +00:00
return false ;
2005-06-30 17:09:39 +00:00
}
2004-11-17 15:57:17 +00:00
2002-05-23 23:43:25 +00:00
return true ;
}
2002-07-16 23:14:35 +00:00
public void GenerateDecl ( StreamWriter sw )
{
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
if ( elem . HasAttribute ( "new_flag" ) | | ( container_type ! = null & & container_type . GetSignalRecursively ( Name ) ! = null ) )
2002-06-21 Rachel Hestilow <hestilow@ximian.com>
* generator/ClassBase.cs: New base class for classes and interfaces.
* generator/InterfaceGen.cs: Inherit from ClassBase, generate declarations.
* generator/ObjectGen.cs: Move half of this into ClassBase.
* generator/Method.cs: Turn all applicable Get/Set functions into .NET
accessors. Remove redundant == overload and move into Equals, as
it was confusing "!= null".
* generator/Parameters.cs: Alter signature creation to accept "is_set"
option, add support for variable arguments. Add properties "Count",
"IsVarArgs", "VAType".
* generator/Ctor.cs: Fixup for changes in Parameters (indenting,
signature creation).
* generator/Signal.cs: Support generating declarations.
* generator/SymbolTable: Change GetObjectGen to GetClassGen.
* glib/IWrapper.cs: Move "Handle" declaration to here, so
both classes and interfaces can benefit from it.
* glib/Object.cs: Inherit from IWrapper.cs
* parser/Metadata.pm: Support attribute changes on constructors,
methods, signals, and paramater lists.
* parser/gapi2xml.pl: Parse init funcs for interfaces. Ignore "_"
functions here.
* parser/gapi_pp.pl: Remove boxed_type_register check, as it will
be caught in the init funcs.
* parser/Atk.metadata: Added.
* parser/Gtk.metadata: Add all needed signal/method collision
renames. Rename GtkEditable.Editable accessors to IsEditable,
as .NET does not like accessors with the same name as their
declaring type. Tag TreeStore constructor as varargs.
* samples/ButtonApp.cs: s/EmitAdd/Add.
* samples/Menu.cs: s/EmitAdd/Add, s/Activate/Activated.
svn path=/trunk/gtk-sharp/; revision=5394
2002-06-21 17:15:19 +00:00
sw . Write ( "new " ) ;
2002-07-13 Rachel Hestilow <hestilow@ximian.com>
* parser/Gnome.metadata, Gtk.metadata: More conflict
fixes.
* parser/build.pl: Fully qualify all lib names. (Gtk+ packages
are now LFS-compliant in Debian...)
* parser/gapi2xml.pl: Fix for whitespace in fields, defines,
and docs.
* generator/BoxedGen.cs: Remove extraneous CallByName definition,
add "override" keyword to FromNative.
(Generate): Generate methods after fields.
* generator/ClassBase.cs: Change CallByName, FromNative to virtual.
(.ctor): Ignore "hidden" nodes. Set container on signal.
(GenSignals, GenMethods): Add "implementor" argument for interface
use.
(Get(Method|Signal|Property)Recursively): Rework to correctly
recurse interfaces.
(Implements): Added.
* generator/Ctor.cs (Initialize): Move clash initialization completely
out of Generate, so we can check for collisions.
* generator/Method.cs (GenerateDeclCommon): Check for duplicates,
for "new" keyword.
(Generate): Add "implementor" argument.
* generator/ObjectGen.cs (Generate): Initialize ctor clashes on
this and all parents, before generating.
(Ctors, InitializeCtors): Added.
* generator/Signal.cs: Store the container_type, check for
collisions.
* generator/StructGen.cs: Add "override" keyword to overriden methods.
* gtk/FileSelection.custom (ActionArea): Add "new" keyword.
svn path=/trunk/gtk-sharp/; revision=5782
2002-07-13 20:31:23 +00:00
2003-10-06 20:12:09 +00:00
sw . WriteLine ( "\t\tevent " + EventHandlerQualifiedName + " " + Name + ";" ) ;
2002-07-16 23:14:35 +00:00
}
2005-02-02 21:57:15 +00:00
public string CName {
get {
return "\"" + elem . GetAttribute ( "cname" ) + "\"" ;
}
}
public string CallbackName {
get {
return Name + "SignalCallback" ;
}
}
private string CallbackSig {
get {
string result = "" ;
for ( int i = 0 ; i < parms . Count ; i + + ) {
if ( i > 0 )
result + = ", " ;
2007-04-28 16:42:10 +00:00
Parameter p = parms [ i ] ;
if ( p . PassAs ! = "" & & ! ( p . Generatable is StructBase ) )
result + = p . PassAs + " " ;
2007-08-13 14:29:06 +00:00
result + = ( p . MarshalType + " arg" + i ) ;
2005-02-02 21:57:15 +00:00
}
result + = ", IntPtr gch" ;
return result ;
}
}
public string DelegateName {
get {
return Name + "SignalDelegate" ;
}
}
2003-10-06 20:12:09 +00:00
private string EventArgsName {
get {
2005-02-02 21:57:15 +00:00
if ( IsEventHandler )
2003-10-06 20:12:09 +00:00
return "EventArgs" ;
else
return Name + "Args" ;
}
}
private string EventArgsQualifiedName {
get {
2005-02-02 21:57:15 +00:00
if ( IsEventHandler )
2003-10-06 20:12:09 +00:00
return "System.EventArgs" ;
else
2004-02-10 20:35:40 +00:00
return container_type . NS + "." + Name + "Args" ;
2003-10-06 20:12:09 +00:00
}
}
private string EventHandlerName {
get {
2005-02-02 21:57:15 +00:00
if ( IsEventHandler )
2003-10-06 20:12:09 +00:00
return "EventHandler" ;
2004-02-10 20:35:40 +00:00
else if ( SymbolTable . Table [ container_type . NS + Name + "Handler" ] ! = null )
return Name + "EventHandler" ;
else
2003-10-06 20:12:09 +00:00
return Name + "Handler" ;
}
}
private string EventHandlerQualifiedName {
get {
2005-02-02 21:57:15 +00:00
if ( IsEventHandler )
2003-10-06 20:12:09 +00:00
return "System.EventHandler" ;
else
2004-02-10 20:35:40 +00:00
return container_type . NS + "." + EventHandlerName ;
2003-10-06 20:12:09 +00:00
}
}
2007-03-06 21:45:51 +00:00
private bool HasOutParams {
get {
foreach ( Parameter p in parms ) {
if ( p . PassAs = = "out" )
return true ;
}
return false ;
}
}
2005-02-02 21:57:15 +00:00
public bool IsEventHandler {
get {
return retval . CSType = = "void" & & parms . Count = = 1 & & ( parms [ 0 ] . Generatable is ObjectGen | | parms [ 0 ] . Generatable is InterfaceGen ) ;
}
}
2003-12-09 05:01:22 +00:00
private bool IsVoid {
get {
2004-11-17 15:57:17 +00:00
return retval . CSType = = "void" ;
2003-12-09 05:01:22 +00:00
}
}
2004-01-14 18:05:50 +00:00
private string ReturnGType {
get {
2005-10-09 01:50:37 +00:00
IGeneratable igen = SymbolTable . Table [ retval . CType ] ;
2004-01-14 18:05:50 +00:00
if ( igen is ObjectGen )
return "GLib.GType.Object" ;
2005-01-28 20:24:14 +00:00
if ( igen is BoxedGen )
return retval . CSType + ".GType" ;
2005-10-09 01:50:37 +00:00
if ( igen is EnumGen )
return retval . CSType + "GType.GType" ;
2004-01-14 18:05:50 +00:00
2004-11-17 15:57:17 +00:00
switch ( retval . CSType ) {
2004-01-14 18:05:50 +00:00
case "bool" :
return "GLib.GType.Boolean" ;
case "string" :
return "GLib.GType.String" ;
case "int" :
return "GLib.GType.Int" ;
default :
2004-11-17 15:57:17 +00:00
throw new Exception ( retval . CSType ) ;
2004-01-14 18:05:50 +00:00
}
}
}
2005-02-02 21:57:15 +00:00
public void GenCallback ( StreamWriter sw )
{
SymbolTable table = SymbolTable . Table ;
2005-03-25 18:13:00 +00:00
sw . WriteLine ( "\t\t[GLib.CDeclCallback]" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\tdelegate " + retval . ToNativeType + " " + DelegateName + " (" + CallbackSig + ");" ) ;
sw . WriteLine ( ) ;
sw . WriteLine ( "\t\tstatic " + retval . ToNativeType + " " + CallbackName + " (" + CallbackSig + ")" ) ;
sw . WriteLine ( "\t\t{" ) ;
sw . WriteLine ( "\t\t\t{0} args = new {0} ();" , EventArgsQualifiedName ) ;
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\t\t\ttry {" ) ;
sw . WriteLine ( "\t\t\t\tGLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal;" ) ;
sw . WriteLine ( "\t\t\t\tif (sig == null)" ) ;
sw . WriteLine ( "\t\t\t\t\tthrow new Exception(\"Unknown signal GC handle received \" + gch);" ) ;
sw . WriteLine ( ) ;
2005-02-02 21:57:15 +00:00
if ( parms . Count > 1 )
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\t\t\t\targs.Args = new object[" + ( parms . Count - 1 ) + "];" ) ;
2005-02-02 21:57:15 +00:00
string finish = "" ;
for ( int idx = 1 ; idx < parms . Count ; idx + + ) {
Parameter p = parms [ idx ] ;
IGeneratable igen = p . Generatable ;
2005-06-30 17:09:39 +00:00
if ( p . PassAs ! = "out" ) {
if ( igen is ManualGen ) {
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\t\t\t\tif (arg{0} == IntPtr.Zero)" , idx ) ;
sw . WriteLine ( "\t\t\t\t\targs.Args[{0}] = null;" , idx - 1 ) ;
sw . WriteLine ( "\t\t\t\telse {" ) ;
sw . WriteLine ( "\t\t\t\t\targs.Args[" + ( idx - 1 ) + "] = " + p . FromNative ( "arg" + idx ) + ";" ) ;
sw . WriteLine ( "\t\t\t\t}" ) ;
2005-06-30 17:09:39 +00:00
} else
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\t\t\t\targs.Args[" + ( idx - 1 ) + "] = " + p . FromNative ( "arg" + idx ) + ";" ) ;
2005-06-30 17:09:39 +00:00
}
2007-04-28 16:42:10 +00:00
if ( igen is StructBase & & p . PassAs = = "ref" )
2007-04-20 15:38:47 +00:00
finish + = "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + ( idx - 1 ) + "], arg" + idx + ", false);\n" ;
else if ( p . PassAs ! = "" )
2007-03-06 20:10:15 +00:00
finish + = "\t\t\t\targ" + idx + " = " + igen . ToNativeReturn ( "((" + p . CSType + ")args.Args[" + ( idx - 1 ) + "])" ) + ";\n" ;
2005-02-02 21:57:15 +00:00
}
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\t\t\t\t{0} handler = ({0}) sig.Handler;" , EventHandlerQualifiedName ) ;
sw . WriteLine ( "\t\t\t\thandler (GLib.Object.GetObject (arg0), args);" ) ;
sw . WriteLine ( "\t\t\t} catch (Exception e) {" ) ;
sw . WriteLine ( "\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, false);" ) ;
sw . WriteLine ( "\t\t\t}" ) ;
2005-02-02 21:57:15 +00:00
2007-03-06 20:10:15 +00:00
if ( IsVoid & & finish . Length = = 0 ) {
sw . WriteLine ( "\t\t}\n" ) ;
return ;
2005-02-02 21:57:15 +00:00
}
2007-03-06 20:10:15 +00:00
sw . WriteLine ( "\n\t\t\ttry {" ) ;
sw . Write ( finish ) ;
if ( ! IsVoid ) {
if ( retval . CSType = = "bool" ) {
sw . WriteLine ( "\t\t\t\tif (args.RetVal == null)" ) ;
sw . WriteLine ( "\t\t\t\t\treturn false;" ) ;
}
sw . WriteLine ( "\t\t\t\treturn " + table . ToNativeReturn ( retval . CType , "((" + retval . CSType + ")args.RetVal)" ) + ";" ) ;
}
sw . WriteLine ( "\t\t\t} catch (Exception) {" ) ;
sw . WriteLine ( "\t\t\t\tException ex = new Exception (\"args.RetVal or 'out' property unset or set to incorrect type in " + EventHandlerQualifiedName + " callback\");" ) ;
sw . WriteLine ( "\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (ex, true);" ) ;
sw . WriteLine ( "\t\t\t\t// NOTREACHED: above call doesn't return." ) ;
sw . WriteLine ( "\t\t\t\tthrow ex;" ) ;
sw . WriteLine ( "\t\t\t}" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\t}" ) ;
sw . WriteLine ( ) ;
}
2004-12-21 18:46:42 +00:00
private bool NeedNew ( ClassBase implementor )
{
return elem . HasAttribute ( "new_flag" ) | |
( container_type ! = null & & container_type . GetSignalRecursively ( Name ) ! = null ) | |
( implementor ! = null & & implementor . GetSignalRecursively ( Name ) ! = null ) ;
}
2003-10-06 20:12:09 +00:00
public void GenEventHandler ( GenerationInfo gen_info )
2002-07-16 23:14:35 +00:00
{
2005-02-02 21:57:15 +00:00
if ( IsEventHandler )
2003-10-06 20:12:09 +00:00
return ;
2002-07-16 23:14:35 +00:00
2003-05-08 04:44:13 +00:00
string ns = container_type . NS ;
2002-07-16 23:14:35 +00:00
2004-02-10 20:35:40 +00:00
StreamWriter sw = gen_info . OpenStream ( EventHandlerName ) ;
2002-07-16 23:14:35 +00:00
2004-02-10 20:35:40 +00:00
sw . WriteLine ( "namespace " + ns + " {" ) ;
2002-07-16 23:14:35 +00:00
sw . WriteLine ( ) ;
sw . WriteLine ( "\tusing System;" ) ;
sw . WriteLine ( ) ;
2003-10-06 20:12:09 +00:00
sw . WriteLine ( "\tpublic delegate void " + EventHandlerName + "(object o, " + EventArgsName + " args);" ) ;
2002-07-16 23:14:35 +00:00
sw . WriteLine ( ) ;
2004-05-05 18:24:04 +00:00
sw . WriteLine ( "\tpublic class " + EventArgsName + " : GLib.SignalArgs {" ) ;
2005-01-26 19:17:07 +00:00
for ( int i = 1 ; i < parms . Count ; i + + ) {
sw . WriteLine ( "\t\tpublic " + parms [ i ] . CSType + " " + parms [ i ] . StudlyName + "{" ) ;
if ( parms [ i ] . PassAs ! = "out" ) {
sw . WriteLine ( "\t\t\tget {" ) ;
sw . WriteLine ( "\t\t\t\treturn (" + parms [ i ] . CSType + ") Args[" + ( i - 1 ) + "];" ) ;
sw . WriteLine ( "\t\t\t}" ) ;
2002-07-16 23:14:35 +00:00
}
2005-01-26 19:17:07 +00:00
if ( parms [ i ] . PassAs ! = "" ) {
sw . WriteLine ( "\t\t\tset {" ) ;
sw . WriteLine ( "\t\t\t\tArgs[" + ( i - 1 ) + "] = (" + parms [ i ] . CSType + ")value;" ) ;
sw . WriteLine ( "\t\t\t}" ) ;
}
sw . WriteLine ( "\t\t}" ) ;
sw . WriteLine ( ) ;
2002-07-16 23:14:35 +00:00
}
sw . WriteLine ( "\t}" ) ;
sw . WriteLine ( "}" ) ;
sw . Close ( ) ;
}
2003-12-10 22:56:49 +00:00
private void GenVirtualMethod ( StreamWriter sw , ClassBase implementor )
2003-12-09 05:01:22 +00:00
{
VMSignature vmsig = new VMSignature ( parms ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t[GLib.DefaultSignalHandler(Type=typeof(" + ( implementor ! = null ? implementor . QualifiedName : container_type . QualifiedName ) + "), ConnectionMethod=\"Override" + Name + "\")]" ) ;
2004-12-22 21:52:18 +00:00
sw . Write ( "\t\tprotected " ) ;
2004-12-21 18:46:42 +00:00
if ( NeedNew ( implementor ) )
2004-12-22 21:52:18 +00:00
sw . Write ( "new " ) ;
2004-12-21 18:46:42 +00:00
sw . WriteLine ( "virtual {0} {1} ({2})" , retval . CSType , "On" + Name , vmsig . ToString ( ) ) ;
2003-12-09 05:01:22 +00:00
sw . WriteLine ( "\t\t{" ) ;
2004-04-12 15:54:57 +00:00
if ( IsVoid )
sw . WriteLine ( "\t\t\tGLib.Value ret = GLib.Value.Empty;" ) ;
else
2004-01-14 18:05:50 +00:00
sw . WriteLine ( "\t\t\tGLib.Value ret = new GLib.Value (" + ReturnGType + ");" ) ;
2003-12-09 05:01:22 +00:00
2004-01-14 18:05:50 +00:00
sw . WriteLine ( "\t\t\tGLib.ValueArray inst_and_params = new GLib.ValueArray (" + parms . Count + ");" ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t\tGLib.Value[] vals = new GLib.Value [" + parms . Count + "];" ) ;
sw . WriteLine ( "\t\t\tvals [0] = new GLib.Value (this);" ) ;
2004-01-14 18:05:50 +00:00
sw . WriteLine ( "\t\t\tinst_and_params.Append (vals [0]);" ) ;
2003-12-09 05:01:22 +00:00
string cleanup = "" ;
for ( int i = 1 ; i < parms . Count ; i + + ) {
2005-06-30 17:09:39 +00:00
Parameter p = parms [ i ] ;
if ( p . PassAs ! = "" ) {
if ( SymbolTable . Table . IsBoxed ( p . CType ) ) {
if ( p . PassAs = = "ref" )
sw . WriteLine ( "\t\t\tvals [" + i + "] = new GLib.Value (" + p . Name + ");" ) ;
else
sw . WriteLine ( "\t\t\tvals [" + i + "] = new GLib.Value ((GLib.GType)typeof (" + p . CSType + "));" ) ;
cleanup + = "\t\t\t" + p . Name + " = (" + p . CSType + ") vals [" + i + "];\n" ;
} else {
if ( p . PassAs = = "ref" )
2005-07-19 15:27:08 +00:00
sw . WriteLine ( "\t\t\tIntPtr " + p . Name + "_ptr = GLib.Marshaller.StructureToPtrAlloc (" + p . Generatable . CallByName ( p . Name ) + ");" ) ;
2005-06-30 17:09:39 +00:00
else
2005-07-19 15:27:08 +00:00
sw . WriteLine ( "\t\t\tIntPtr " + p . Name + "_ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (" + p . MarshalType + ")));" ) ;
2005-06-30 17:09:39 +00:00
sw . WriteLine ( "\t\t\tvals [" + i + "] = new GLib.Value (" + p . Name + "_ptr);" ) ;
Automatic memory management for opaque types [#49565]
* glib/Opaque.cs (Owned): new property saying whether or not gtk#
owns the memory.
(Opaque): Set Owned to true in the void ctor and false in the
IntPtr one.
(GetOpaque): add a new overload that can also create opaques, a la
GLib.Object.GetObject.
(Ref, Unref, Free): empty virtual methods to be overridden by
subclasses.
(set_Raw): Unref() and possibly Free() the old value, Ref() the
new one.
(~Opaque, Dispose): set Raw to IntPtr.Zero (triggering Free/Unref
if needed)
* parser/gapi2xml.pl (addReturnElem): if the method is named Copy
and returns a pointer, set the "owned" attribute on the
return-type.
* */*-api.raw: Regen
* generator/HandleBase.cs (FromNative): Add new
FromNative/FromNativeReturn overloads that takes a "bool owned"
param. Implement the 1-arg FromNative and FromNativeReturn in
terms of that.
* generator/ObjectBase.cs (FromNative): Implement HandleBase's new
overload. Use the two-arg version of GLib.Object.GetObject when
"owned" is true.
* generator/OpaqueGen.cs (Generate): Pull out Ref, Unref, and
Free/Destroy/Dispose methods and handle them specially by
overriding Opaque.Ref, .Unref, and .Free appropriately. (If any
of the methods are marked deprecated, output a deprecated
do-nothing method as well, to save us from having to write all
those deprecated methods by hand.)
(FromNative): use GetOpaque, passing "owned".
* generator/ReturnValue.cs (FromNative): if the value is a
HandleBase, pass Owned to its FromNative().
* generator/Parameters.cs (Owned): new property (for use on out
params)
(FromNative): Call FromNative() on the generatable, handling Owned
in the case of HandleBase.
* generator/ManagedCallString.cs:
* generator/MethodBody.cs:
* generator/Signal.cs: use param.FromNative() rather than
param.Generatable.FromNative(), to get ownership right.
* */*.metadata: Mark opaque ref/unref/free methods deprecated
(except where we were hiding them before). Add "owned" attributes
to return values and out params as needed.
* pango/AttrIterator.custom (GetFont): work around a
memory-management oddity of the underlying method.
* pango/AttrFontDesc.cs (AttrFontDesc): copy the passed-in
FontDescriptor, since the attribute will assume ownership of it.
* gtk/TreeView.custom (GetPathAtPos): set the "owned" flag on the
returned TreePaths.
* gtk/TargetList.custom: Remove refcounting stuff, which is
now handled automatically
* gtk/NodeStore.cs (GetPath): clear the Owned flag on the created
TreePath so that the underlying structure doesn't get freed when
the function returns
* gtkhtml/HTMLStream.custom (Destroy): hide this and then
reimplement it by hand to keep OpaqueGen from using it in
Dispose(), since calling it after an HTMLStream.Close() will
result in a crash.
svn path=/trunk/gtk-sharp/; revision=47928
2005-08-02 18:45:21 +00:00
cleanup + = "\t\t\t" + p . Name + " = " + p . FromNative ( "(" + p . MarshalType + ") Marshal.PtrToStructure (" + p . Name + "_ptr, typeof (" + p . MarshalType + "))" ) + ";\n" ;
2005-06-30 17:09:39 +00:00
cleanup + = "\t\t\tMarshal.FreeHGlobal (" + p . Name + "_ptr);\n" ;
}
} else if ( p . IsLength & & parms [ i - 1 ] . IsString )
2005-12-12 14:46:19 +00:00
sw . WriteLine ( "\t\t\tvals [" + i + "] = new GLib.Value (System.Text.Encoding.UTF8.GetByteCount (" + parms [ i - 1 ] . Name + "));" ) ;
2003-12-09 05:01:22 +00:00
else
2005-06-30 17:09:39 +00:00
sw . WriteLine ( "\t\t\tvals [" + i + "] = new GLib.Value (" + p . Name + ");" ) ;
2003-12-09 05:01:22 +00:00
2004-01-14 18:05:50 +00:00
sw . WriteLine ( "\t\t\tinst_and_params.Append (vals [" + i + "]);" ) ;
2003-12-09 05:01:22 +00:00
}
2004-04-12 15:54:57 +00:00
sw . WriteLine ( "\t\t\tg_signal_chain_from_overridden (inst_and_params.ArrayPtr, ref ret);" ) ;
2003-12-09 05:01:22 +00:00
if ( cleanup ! = "" )
sw . WriteLine ( cleanup ) ;
2005-03-28 18:26:00 +00:00
sw . WriteLine ( "\t\t\tforeach (GLib.Value v in vals)" ) ;
sw . WriteLine ( "\t\t\t\tv.Dispose ();" ) ;
2006-02-03 15:55:22 +00:00
if ( ! IsVoid ) {
IGeneratable igen = SymbolTable . Table [ retval . CType ] ;
sw . WriteLine ( "\t\t\t" + retval . CSType + " result = (" + ( igen is EnumGen ? retval . CSType + ") (Enum" : retval . CSType ) + ") ret;" ) ;
sw . WriteLine ( "\t\t\tret.Dispose ();" ) ;
sw . WriteLine ( "\t\t\treturn result;" ) ;
}
2003-12-09 05:01:22 +00:00
sw . WriteLine ( "\t\t}\n" ) ;
}
2003-12-10 22:56:49 +00:00
private void GenDefaultHandlerDelegate ( StreamWriter sw , ClassBase implementor )
{
ManagedCallString call = new ManagedCallString ( parms ) ;
2005-03-25 18:13:00 +00:00
sw . WriteLine ( "\t\t[GLib.CDeclCallback]" ) ;
2007-08-13 14:29:06 +00:00
sw . WriteLine ( "\t\tdelegate " + retval . ToNativeType + " " + Name + "VMDelegate (" + parms . ImportSignature + ");\n" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\tstatic {0} {1};\n" , Name + "VMDelegate" , Name + "VMCallback" ) ;
2007-08-13 14:29:06 +00:00
sw . WriteLine ( "\t\tstatic " + retval . ToNativeType + " " + Name . ToLower ( ) + "_cb (" + parms . ImportSignature + ")" ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t{" ) ;
2007-03-06 21:45:51 +00:00
sw . WriteLine ( "\t\t\ttry {" ) ;
sw . WriteLine ( "\t\t\t\t{0} {1}_managed = GLib.Object.GetObject ({1}, false) as {0};" , implementor ! = null ? implementor . Name : container_type . Name , parms [ 0 ] . Name ) ;
sw . Write ( call . Setup ( "\t\t\t\t" ) ) ;
sw . Write ( "\t\t\t\t{0}" , IsVoid ? "" : retval . CSType = = retval . ToNativeType ? "return " : retval . CSType + " raw_ret = " ) ;
2005-08-09 17:33:46 +00:00
sw . WriteLine ( "{2}_managed.{0} ({1});" , "On" + Name , call . ToString ( ) , parms [ 0 ] . Name ) ;
2007-03-06 21:45:51 +00:00
sw . Write ( call . Finish ( "\t\t\t\t" ) ) ;
2005-01-28 20:24:14 +00:00
if ( ! IsVoid & & retval . CSType ! = retval . ToNativeType )
2007-03-06 21:45:51 +00:00
sw . WriteLine ( "\t\t\t\treturn {0};" , SymbolTable . Table . ToNativeReturn ( retval . CType , "raw_ret" ) ) ;
sw . WriteLine ( "\t\t\t} catch (Exception e) {" ) ;
bool fatal = HasOutParams | | ! IsVoid ;
sw . WriteLine ( "\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + ( fatal ? "true" : "false" ) + ");" ) ;
if ( fatal ) {
sw . WriteLine ( "\t\t\t\t// NOTREACHED: above call doesn't return" ) ;
sw . WriteLine ( "\t\t\t\tthrow e;" ) ;
}
sw . WriteLine ( "\t\t\t}" ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t}\n" ) ;
2004-06-11 22:41:01 +00:00
sw . WriteLine ( "\t\tprivate static void Override" + Name + " (GLib.GType gtype)" ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t{" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\t\tif (" + Name + "VMCallback == null)" ) ;
sw . WriteLine ( "\t\t\t\t" + Name + "VMCallback = new " + Name + "VMDelegate (" + Name . ToLower ( ) + "_cb);" ) ;
sw . WriteLine ( "\t\t\tOverrideVirtualMethod (gtype, " + CName + ", " + Name + "VMCallback);" ) ;
2003-12-10 22:56:49 +00:00
sw . WriteLine ( "\t\t}\n" ) ;
}
2003-10-05 00:20:17 +00:00
public void Generate ( GenerationInfo gen_info , ClassBase implementor )
2002-06-24 22:04:10 +00:00
{
2003-10-05 00:20:17 +00:00
StreamWriter sw = gen_info . Writer ;
2005-02-02 21:57:15 +00:00
if ( implementor = = null )
2003-10-06 20:12:09 +00:00
GenEventHandler ( gen_info ) ;
2002-06-24 22:04:10 +00:00
2005-02-02 21:57:15 +00:00
if ( ! IsEventHandler )
GenCallback ( sw ) ;
2003-12-10 22:56:49 +00:00
GenDefaultHandlerDelegate ( sw , implementor ) ;
GenVirtualMethod ( sw , implementor ) ;
2005-02-02 21:57:15 +00:00
string marsh = IsEventHandler ? "" : ", new " + DelegateName + "(" + CallbackName + ")" ;
2002-07-16 23:14:35 +00:00
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\t[GLib.Signal(" + CName + ")]" ) ;
2002-05-23 23:43:25 +00:00
sw . Write ( "\t\tpublic " ) ;
2004-12-21 18:46:42 +00:00
if ( NeedNew ( implementor ) )
2002-05-23 23:43:25 +00:00
sw . Write ( "new " ) ;
2003-10-06 20:12:09 +00:00
sw . WriteLine ( "event " + EventHandlerQualifiedName + " " + Name + " {" ) ;
2002-05-23 23:43:25 +00:00
sw . WriteLine ( "\t\t\tadd {" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (this, " + CName + marsh + ");" ) ;
sw . WriteLine ( "\t\t\t\tsig.AddDelegate (value);" ) ;
2002-05-23 23:43:25 +00:00
sw . WriteLine ( "\t\t\t}" ) ;
sw . WriteLine ( "\t\t\tremove {" ) ;
2005-02-02 21:57:15 +00:00
sw . WriteLine ( "\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (this, " + CName + marsh + ");" ) ;
sw . WriteLine ( "\t\t\t\tsig.RemoveDelegate (value);" ) ;
2002-05-23 23:43:25 +00:00
sw . WriteLine ( "\t\t\t}" ) ;
sw . WriteLine ( "\t\t}" ) ;
sw . WriteLine ( ) ;
Statistics . SignalCount + + ;
}
}
}