From df41dcc17723a8aef38ae303fd2a7303419047f6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 5 Nov 2004 16:47:15 +0000 Subject: [PATCH] * parser/gapi2xml.pl (parseInitFunc, addPropElem): handle GtkContainer child properties * generator/Property.cs: * generator/ChildProperty.cs: make Property subclassable and add a "ChildProperty" subclass. * generator/Makefile.am (sources): add ChildProperty.cs * generator/ClassBase.cs: handle "childprop" nodes by creating ChildProperty objects. * glib/Value.cs (explicit operator EnumWrapper): use g_value_get_flags() rather than g_value_get_enum() when appropriate. * glib/glue/value.c (glibsharp_value_holds_flags): glue for that * gtk/gtk-api.raw: regen to pick up child properties * gtk/Gtk.metadata: * gtk/Container.custom: hide the auto-generated Gtk.Container.ChildGetProperty and implement a nicer one by hand. * gtk/glue/container.c (gtksharp_container_child_get_property): utility function to set up an appropriate GValue for us svn path=/trunk/gtk-sharp/; revision=35702 --- ChangeLog | 29 ++++++++++++++++ generator/ChildProperty.cs | 57 ++++++++++++++++++++++++++++++ generator/ClassBase.cs | 8 +++++ generator/Makefile.am | 1 + generator/Property.cs | 71 +++++++++++++++++++++++++++----------- glib/Value.cs | 8 +++-- glib/glue/value.c | 6 ++++ gtk/Container.custom | 10 ++++++ gtk/Gtk.metadata | 1 + gtk/glue/container.c | 15 ++++++++ gtk/gtk-api.raw | 32 +++++++++++++++++ parser/gapi2xml.pl | 18 +++++++--- 12 files changed, 229 insertions(+), 27 deletions(-) create mode 100644 generator/ChildProperty.cs diff --git a/ChangeLog b/ChangeLog index ccd458a39..d0cd61a55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2004-11-05 Dan Winship + + * parser/gapi2xml.pl (parseInitFunc, addPropElem): handle + GtkContainer child properties + + * generator/Property.cs: + * generator/ChildProperty.cs: make Property subclassable and add a + "ChildProperty" subclass. + + * generator/Makefile.am (sources): add ChildProperty.cs + + * generator/ClassBase.cs: handle "childprop" nodes by creating + ChildProperty objects. + + * glib/Value.cs (explicit operator EnumWrapper): use + g_value_get_flags() rather than g_value_get_enum() when + appropriate. + + * glib/glue/value.c (glibsharp_value_holds_flags): glue for that + + * gtk/gtk-api.raw: regen to pick up child properties + + * gtk/Gtk.metadata: + * gtk/Container.custom: hide the auto-generated + Gtk.Container.ChildGetProperty and implement a nicer one by hand. + + * gtk/glue/container.c (gtksharp_container_child_get_property): + utility function to set up an appropriate GValue for us + 2004-11-05 Tambet Ingo * generator/OpaqueGen.cs: Add optional "parent" attribute to Opaque diff --git a/generator/ChildProperty.cs b/generator/ChildProperty.cs new file mode 100644 index 000000000..07f9b60fc --- /dev/null +++ b/generator/ChildProperty.cs @@ -0,0 +1,57 @@ +// GtkSharp.Generation.ChildProperty.cs - GtkContainer child properties +// +// Copyright (c) 2004 Novell, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of version 2 of the GNU General Public +// License as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + + +namespace GtkSharp.Generation { + + using System; + using System.Collections; + using System.IO; + using System.Xml; + + public class ChildProperty : Property { + + public ChildProperty (XmlElement elem, ClassBase container_type) : base (elem, container_type) {} + + protected override string PropertyHeader (ref string indent, string modifiers, string cs_type, string name) { + return ""; + } + + protected override string GetterHeader (string modifiers, string cs_type, string name) { + return "public " + modifiers + cs_type + " Get" + name + " (Widget w)"; + } + + protected override string RawGetter (string cname) { + return "ChildGetProperty (w, " + cname + ")"; + } + + protected override string SetterHeader (string modifiers, string cs_type, string name) { + return "public " + modifiers + "void Set" + name + " (Widget w, " + cs_type + " value)"; + } + + protected override string RawSetter (string cname) { + return "ChildSetProperty(w, " + cname + ", val)"; + } + + protected override string PropertyFooter (string indent) { + return ""; + } + + } +} + diff --git a/generator/ClassBase.cs b/generator/ClassBase.cs index f5ffcce96..fa7f8be64 100644 --- a/generator/ClassBase.cs +++ b/generator/ClassBase.cs @@ -93,6 +93,13 @@ namespace GtkSharp.Generation { props.Add (name, new Property (member, this)); break; + case "childprop": + name = member.GetAttribute("name"); + while (props.ContainsKey(name)) + name += "mangled"; + props.Add (name, new ChildProperty (member, this)); + break; + case "signal": name = member.GetAttribute("name"); while (sigs.ContainsKey(name)) @@ -131,6 +138,7 @@ namespace GtkSharp.Generation { switch (name) { case "method": case "property": + case "childprop": case "signal": case "implements": case "constructor": diff --git a/generator/Makefile.am b/generator/Makefile.am index a41790b47..e37f06aa3 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -11,6 +11,7 @@ sources = \ BoxedGen.cs \ ByRefGen.cs \ CallbackGen.cs \ + ChildProperty.cs \ ClassBase.cs \ ClassGen.cs \ CodeGenerator.cs \ diff --git a/generator/Property.cs b/generator/Property.cs index aca11f8fb..3175fc60c 100644 --- a/generator/Property.cs +++ b/generator/Property.cs @@ -29,8 +29,8 @@ namespace GtkSharp.Generation { public class Property { - private XmlElement elem; - private ClassBase container_type; + protected XmlElement elem; + protected ClassBase container_type; public string Name { get { @@ -66,6 +66,34 @@ namespace GtkSharp.Generation { return true; } + protected virtual string PropertyHeader (ref string indent, string modifiers, string cs_type, string name) { + string header; + + header = indent + "public " + modifiers + cs_type + " " + name + " {\n"; + indent += "\t"; + return header; + } + + protected virtual string GetterHeader (string modifiers, string cs_type, string name) { + return "get"; + } + + protected virtual string RawGetter (string cname) { + return "GetProperty (" + cname + ")"; + } + + protected virtual string SetterHeader (string modifiers, string cs_type, string name) { + return "set"; + } + + protected virtual string RawSetter (string cname) { + return "SetProperty(" + cname + ", val)"; + } + + protected virtual string PropertyFooter (string indent) { + return indent.Substring (1) + "}\n"; + } + public void Generate (GenerationInfo gen_info) { SymbolTable table = SymbolTable.Table; @@ -141,23 +169,24 @@ namespace GtkSharp.Generation { sw.WriteLine(); - sw.WriteLine("\t\tpublic " + modifiers + cs_type + " " + name + " {"); + string indent = "\t\t"; + sw.Write(PropertyHeader (ref indent, modifiers, cs_type, name)); if (has_getter) { - sw.Write("\t\t\tget "); + sw.Write(indent + GetterHeader (modifiers, cs_type, name)); getter.GenerateBody(gen_info, "\t"); sw.WriteLine(); } else if (elem.HasAttribute("readable")) { - sw.WriteLine("\t\t\tget {"); - sw.WriteLine("\t\t\t\tGLib.Value val = GetProperty (" + cname + ");"); + sw.WriteLine(indent + GetterHeader (modifiers, cs_type, name) + " {"); + sw.WriteLine(indent + "\tGLib.Value val = " + RawGetter (cname) + ";"); if (table.IsObject (c_type)) { - sw.WriteLine("\t\t\t\tSystem.IntPtr raw_ret = (System.IntPtr) {0} val;", v_type); - sw.WriteLine("\t\t\t\t" + cs_type + " ret = " + table.FromNativeReturn(c_type, "raw_ret") + ";"); + sw.WriteLine(indent + "\tSystem.IntPtr raw_ret = (System.IntPtr) {0} val;", v_type); + sw.WriteLine(indent + "\t" + cs_type + " ret = " + table.FromNativeReturn(c_type, "raw_ret") + ";"); if (!table.IsBoxed (c_type) && !table.IsObject (c_type)) - sw.WriteLine("\t\t\t\tif (ret == null) ret = new " + cs_type + "(raw_ret);"); + sw.WriteLine(indent + "\tif (ret == null) ret = new " + cs_type + "(raw_ret);"); } else if (table.IsOpaque (c_type) || table.IsBoxed (c_type)) { - sw.WriteLine("\t\t\t\t" + cs_type + " ret = (" + cs_type + ") val;"); + sw.WriteLine(indent + "\t" + cs_type + " ret = (" + cs_type + ") val;"); } else { - sw.Write("\t\t\t\t" + cs_type + " ret = "); + sw.Write(indent + "\t" + cs_type + " ret = "); sw.Write ("(" + cs_type + ") "); if (v_type != "") { sw.Write(v_type + " "); @@ -165,18 +194,18 @@ namespace GtkSharp.Generation { sw.WriteLine("val;"); } - sw.WriteLine("\t\t\t\tval.Dispose ();"); - sw.WriteLine("\t\t\t\treturn ret;"); - sw.WriteLine("\t\t\t}"); + sw.WriteLine(indent + "\tval.Dispose ();"); + sw.WriteLine(indent + "\treturn ret;"); + sw.WriteLine(indent + "}"); } if (has_setter) { - sw.Write("\t\t\tset "); + sw.Write(indent + SetterHeader (modifiers, cs_type, name)); setter.GenerateBody(gen_info, "\t"); sw.WriteLine(); } else if (elem.HasAttribute("writeable") && !elem.HasAttribute("construct-only")) { - sw.WriteLine("\t\t\tset {"); - sw.Write("\t\t\t\tGLib.Value val = "); + sw.WriteLine(indent + SetterHeader (modifiers, cs_type, name) + " {"); + sw.Write(indent + "\tGLib.Value val = "); if (table.IsEnum(c_type)) { sw.WriteLine("new GLib.Value(this, " + cname + ", new GLib.EnumWrapper ((int) value, {0}));", table.IsEnumFlags (c_type) ? "true" : "false"); } else if (table.IsBoxed (c_type)) { @@ -190,12 +219,12 @@ namespace GtkSharp.Generation { } sw.WriteLine("value);"); } - sw.WriteLine("\t\t\t\tSetProperty(" + cname + ", val);"); - sw.WriteLine("\t\t\t\tval.Dispose ();"); - sw.WriteLine("\t\t\t}"); + sw.WriteLine(indent + "\t" + RawSetter (cname) + ";"); + sw.WriteLine(indent + "\tval.Dispose ();"); + sw.WriteLine(indent + "}"); } - sw.WriteLine("\t\t}"); + sw.Write(PropertyFooter (indent)); sw.WriteLine(); Statistics.PropCount++; diff --git a/glib/Value.cs b/glib/Value.cs index 5d526c32f..76a57b1db 100755 --- a/glib/Value.cs +++ b/glib/Value.cs @@ -290,11 +290,15 @@ namespace GLib { static extern int g_value_get_enum (ref Value val); [DllImport("libgobject-2.0-0.dll")] static extern uint g_value_get_flags (ref Value val); + [DllImport("glibsharpglue-2.0")] + static extern bool glibsharp_value_holds_flags (ref Value val); public static explicit operator EnumWrapper (Value val) { - // FIXME: handle flags - return new EnumWrapper (g_value_get_enum (ref val), false); + if (glibsharp_value_holds_flags (ref val)) + return new EnumWrapper ((int)g_value_get_flags (ref val), true); + else + return new EnumWrapper (g_value_get_enum (ref val), false); } [DllImport("glibsharpglue-2.0")] diff --git a/glib/glue/value.c b/glib/glue/value.c index f75f5c088..f9329d14c 100644 --- a/glib/glue/value.c +++ b/glib/glue/value.c @@ -25,6 +25,7 @@ void gtksharp_value_create_from_property (GValue *value, GObject *obj, const gchar* name); void gtksharp_value_create_from_type_and_property (GValue *value, GType gtype, const gchar* name); GType gtksharp_value_get_value_type (GValue *value); +gboolean glibsharp_value_holds_flags (GValue *value); /* */ void @@ -49,3 +50,8 @@ gtksharp_value_get_value_type (GValue *value) return G_VALUE_TYPE (value); } +gboolean +glibsharp_value_holds_flags (GValue *value) +{ + return G_VALUE_HOLDS_FLAGS (value); +} diff --git a/gtk/Container.custom b/gtk/Container.custom index bd4c766eb..fdbf9662d 100644 --- a/gtk/Container.custom +++ b/gtk/Container.custom @@ -19,6 +19,16 @@ // Boston, MA 02111-1307, USA. +[DllImport("gtksharpglue-2.0")] +static extern void gtksharp_container_child_get_property (IntPtr container, IntPtr child, string property, ref GLib.Value value); + +public GLib.Value ChildGetProperty (Gtk.Widget child, string property_name) { + GLib.Value value = new GLib.Value (); + + gtksharp_container_child_get_property (Handle, child.Handle, property_name, ref value); + return value; +} + [DllImport("libgtk-win32-2.0-0.dll")] static extern IntPtr gtk_container_get_children (IntPtr raw); diff --git a/gtk/Gtk.metadata b/gtk/Gtk.metadata index e31b2db09..bcdd82d34 100644 --- a/gtk/Gtk.metadata +++ b/gtk/Gtk.metadata @@ -127,6 +127,7 @@ 1 1 out + 1 1 1 1 diff --git a/gtk/glue/container.c b/gtk/glue/container.c index bc0fe304c..cbc820a76 100644 --- a/gtk/glue/container.c +++ b/gtk/glue/container.c @@ -64,6 +64,8 @@ gtksharp_container_base_child_type (GtkContainer *container) return slot; } +void gtksharp_container_override_child_type (GType gtype, gpointer cb); + void gtksharp_container_override_child_type (GType gtype, gpointer cb) { @@ -72,3 +74,16 @@ gtksharp_container_override_child_type (GType gtype, gpointer cb) klass = g_type_class_ref (gtype); ((GtkContainerClass *) klass)->child_type = cb; } + +void gtksharp_container_child_get_property (GtkContainer *container, GtkWidget *child, + const gchar* property, GValue *value); + +void +gtksharp_container_child_get_property (GtkContainer *container, GtkWidget *child, + const gchar* property, GValue *value) +{ + GParamSpec *spec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (container), property); + g_value_init (value, spec->value_type); + gtk_container_child_get_property (container, child, property, value); +} + diff --git a/gtk/gtk-api.raw b/gtk/gtk-api.raw index d994e4bcc..ae15a814e 100644 --- a/gtk/gtk-api.raw +++ b/gtk/gtk-api.raw @@ -2669,6 +2669,11 @@ + + + + + @@ -2908,6 +2913,7 @@ + @@ -5106,6 +5112,8 @@ + + @@ -6572,6 +6580,8 @@ + + @@ -6818,6 +6828,10 @@ + + + + @@ -7253,6 +7267,12 @@ + + + + + + @@ -7733,6 +7753,8 @@ + + @@ -9292,6 +9314,14 @@ + + + + + + + + @@ -10710,6 +10740,8 @@ + + diff --git a/parser/gapi2xml.pl b/parser/gapi2xml.pl index 8959080ca..146bf45e2 100755 --- a/parser/gapi2xml.pl +++ b/parser/gapi2xml.pl @@ -465,7 +465,7 @@ if ($ARGV[1]) { $scnt = keys(%sdefs); $fcnt = keys(%fdefs); $tcnt = keys(%types); print "structs: $scnt enums: $ecnt callbacks: $cbcnt\n"; print "funcs: $fcnt types: $tcnt classes: $classcnt\n"; -print "props: $propcnt signals: $sigcnt\n\n"; +print "props: $propcnt childprops: $childpropcnt signals: $sigcnt\n\n"; sub addFieldElems { @@ -776,7 +776,7 @@ sub addReturnElem sub addPropElem { - my ($spec, $node) = @_; + my ($spec, $node, $is_child) = @_; my ($name, $mode, $docs); $spec =~ /g_param_spec_(\w+)\s*\((.*)\s*\)\s*\)/; my $type = $1; @@ -788,6 +788,9 @@ sub addPropElem } else { $name =~ s/\s*\"//g; } + if ($is_child) { + $name = "child_$name"; + } $mode = $params[$#params]; @@ -807,7 +810,7 @@ sub addPropElem $type = StudlyCaps(lc($type)); } - $prop_elem = $doc->createElement('property'); + $prop_elem = $doc->createElement($is_child ? "childprop" : "property"); $node->appendChild($prop_elem); $prop_elem->setAttribute('name', StudlyCaps($name)); $prop_elem->setAttribute('cname', $name); @@ -952,8 +955,15 @@ sub parseInitFunc do { $prop .= $init_lines[++$linenum]; } until ($init_lines[$linenum] =~ /\)\s*;/); - addPropElem ($prop, $obj_el); + addPropElem ($prop, $obj_el, 0); $propcnt++; + } elsif ($line =~ /gtk_container_class_install_child_property/) { + my $prop = $line; + do { + $prop .= $init_lines[++$linenum]; + } until ($init_lines[$linenum] =~ /\)\s*;/); + addPropElem ($prop, $obj_el, 1); + $childpropcnt++; } elsif ($line =~ /\bg.*_signal_new/) { my $sig = $line; do {