2004-05-07 Mike Kestner <mkestner@ximian.com>

[Derived from a patch by Ben Maurer]
	* generator/Ctor.cs : generate code to detect subclassing and handle
	GType registration and native object creation properly.
	* generator/Parameters.cs : add PropertyName accessor for param attr.
	* generator/Property.cs : use a new GLib.Value ctor.
	* glib/ObjectManager.cs : redo hash access.
	* glib/Object.cs : CreateNativeObject method to invoke g_object_newv
	and some refactoring of RegisterGType and LookupGType.
	* glib/Value.cs : make gtype field an IntPtr.
	* glib/glue/object.c : glue for g_object_newv use.
	* glib/glue/value.c : new glue for value creation.
	* gtk/Dialog.custom : fix a ctor declaration for auto-reg.
	* gtk/Gtk.metadata : mark a couple property_name attrs as examples.
	* sample/Subclass.cs : use auto-GType-registration now.

svn path=/trunk/gtk-sharp/; revision=26916
This commit is contained in:
Mike Kestner 2004-05-07 13:42:59 +00:00
parent e301835e99
commit c9f1eadc11
12 changed files with 163 additions and 40 deletions

View file

@ -1,3 +1,20 @@
2004-05-07 Mike Kestner <mkestner@ximian.com>
[Derived from a patch by Ben Maurer]
* generator/Ctor.cs : generate code to detect subclassing and handle
GType registration and native object creation properly.
* generator/Parameters.cs : add PropertyName accessor for param attr.
* generator/Property.cs : use a new GLib.Value ctor.
* glib/ObjectManager.cs : redo hash access.
* glib/Object.cs : CreateNativeObject method to invoke g_object_newv
and some refactoring of RegisterGType and LookupGType.
* glib/Value.cs : make gtype field an IntPtr.
* glib/glue/object.c : glue for g_object_newv use.
* glib/glue/value.c : new glue for value creation.
* gtk/Dialog.custom : fix a ctor declaration for auto-reg.
* gtk/Gtk.metadata : mark a couple property_name attrs as examples.
* sample/Subclass.cs : use auto-GType-registration now.
2004-05-06 Mike Kestner <mkestner@ximian.com> 2004-05-06 Mike Kestner <mkestner@ximian.com>
* gdk/Gdk.metadata : some out and array magic for Property.Get. * gdk/Gdk.metadata : some out and array magic for Property.Get.

View file

@ -23,6 +23,7 @@ namespace GtkSharp.Generation {
private string clashName = null; private string clashName = null;
private ClassBase container_type; private ClassBase container_type;
private bool force_static; private bool force_static;
private bool needs_chaining = false;
public bool Preferred { public bool Preferred {
get { return preferred; } get { return preferred; }
@ -47,6 +48,8 @@ namespace GtkSharp.Generation {
parms = new Parameters (parms_elem, container_type.NS); parms = new Parameters (parms_elem, container_type.NS);
if (elem.HasAttribute ("preferred")) if (elem.HasAttribute ("preferred"))
preferred = true; preferred = true;
if (container_type is ObjectGen)
needs_chaining = true;
} }
public bool Validate () public bool Validate ()
@ -102,6 +105,8 @@ namespace GtkSharp.Generation {
else else
safety = ""; safety = "";
SymbolTable table = SymbolTable.Table;
sw.WriteLine("\t\t[DllImport(\"" + libname + "\")]"); sw.WriteLine("\t\t[DllImport(\"" + libname + "\")]");
sw.WriteLine("\t\tstatic extern " + safety + "IntPtr " + cname + "(" + isig.ToString () + ");"); sw.WriteLine("\t\tstatic extern " + safety + "IntPtr " + cname + "(" + isig.ToString () + ");");
sw.WriteLine(); sw.WriteLine();
@ -133,9 +138,60 @@ namespace GtkSharp.Generation {
sw.Write ("new {0} (", name); sw.Write ("new {0} (", name);
sw.WriteLine (cname + "(" + body.GetCallString (false) + "));"); sw.WriteLine (cname + "(" + body.GetCallString (false) + "));");
} else { } else {
sw.WriteLine("\t\tpublic " + safety + name + "(" + sig.ToString() + ") : base (IntPtr.Zero)"); sw.WriteLine("\t\tpublic {0}{1} ({2}) {3}", safety, name, sig.ToString(), needs_chaining ? ": base (IntPtr.Zero)" : "");
sw.WriteLine("\t\t{"); sw.WriteLine("\t\t{");
if (needs_chaining) {
sw.WriteLine ("\t\t\tif (GetType () != typeof (" + name + ")) {");
if (Params == null || Params.Count == 0) {
sw.WriteLine ("\t\t\t\tCreateNativeObject (new string [0], new GLib.Value[0]);");
sw.WriteLine ("\t\t\t\treturn;");
} else {
ArrayList names = new ArrayList ();
ArrayList values = new ArrayList ();
for (int i = 0; i < Params.Count; i++) {
Parameter p = Params[i];
if (container_type.GetPropertyRecursively (p.StudlyName) != null) {
names.Add (p.Name);
values.Add (p.Name);
} else if (p.PropertyName != String.Empty) {
names.Add (p.PropertyName);
values.Add (p.Name);
}
}
if (names.Count == Params.Count) {
sw.WriteLine ("\t\t\t\tArrayList vals = new ArrayList();");
sw.WriteLine ("\t\t\t\tArrayList names = new ArrayList();");
for (int i = 0; i < names.Count; i++) {
Parameter p = Params [i];
string indent = "\t\t\t\t";
if (p.NullOk && p.Generatable is ObjectGen) {
sw.WriteLine (indent + "if (" + p.Name + " != null) {");
indent += "\t";
}
sw.WriteLine (indent + "names.Add (\"" + names [i] + "\");");
sw.Write (indent + "vals.Add (");
if (table.IsEnum (p.CType))
sw.WriteLine ("new GLib.Value (this, \"" + names[i] + "\", new GLib.EnumWrapper ((int)" + values[i] + ", " + (table.IsEnumFlags (p.CType) ? "true" : "false") + ")));");
else
sw.WriteLine ("new GLib.Value (" + values[i] + "));");
if (p.NullOk && p.Generatable is ObjectGen)
sw.WriteLine ("\t\t\t\t}");
}
sw.WriteLine ("\t\t\t\tCreateNativeObject ((string[])names.ToArray (typeof (string)), (GLib.Value[])vals.ToArray (typeof (GLib.Value)));");
sw.WriteLine ("\t\t\t\treturn;");
} else
sw.WriteLine ("\t\t\t\tthrow new InvalidOperationException (\"Can't override this constructor.\");");
}
sw.WriteLine ("\t\t\t}");
}
body.Initialize(gen_info, false, false, ""); body.Initialize(gen_info, false, false, "");
sw.WriteLine("\t\t\t{0} = {1}({2});", container_type.AssignToName, cname, body.GetCallString (false)); sw.WriteLine("\t\t\t{0} = {1}({2});", container_type.AssignToName, cname, body.GetCallString (false));
body.HandleException (sw, ""); body.HandleException (sw, "");

View file

@ -145,6 +145,12 @@ namespace GtkSharp.Generation {
} }
} }
public string PropertyName {
get {
return elem.GetAttribute("property_name");
}
}
public string PassAs { public string PassAs {
get { get {
if (elem.HasAttribute ("pass_as")) if (elem.HasAttribute ("pass_as"))
@ -195,7 +201,6 @@ namespace GtkSharp.Generation {
} }
} }
} }
public class Parameters { public class Parameters {

View file

@ -162,7 +162,7 @@ namespace GtkSharp.Generation {
sw.WriteLine("\t\t\tset {"); sw.WriteLine("\t\t\tset {");
sw.Write("\t\t\t\tGLib.Value val = "); sw.Write("\t\t\t\tGLib.Value val = ");
if (table.IsEnum(c_type)) { if (table.IsEnum(c_type)) {
sw.WriteLine("new GLib.Value(Handle, " + cname + ", new GLib.EnumWrapper ((int) value, {0}));", table.IsEnumFlags (c_type) ? "true" : "false"); 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)) { } else if (table.IsBoxed (c_type)) {
sw.WriteLine("(GLib.Value) value;"); sw.WriteLine("(GLib.Value) value;");
} else if (table.IsOpaque (c_type)) { } else if (table.IsOpaque (c_type)) {

View file

@ -127,15 +127,9 @@ namespace GLib {
public static GType RegisterGType (System.Type t) public static GType RegisterGType (System.Type t)
{ {
System.Type parent = t.BaseType; GType parent_gtype = LookupGType (t.BaseType);
PropertyInfo pi = parent.GetProperty ("GType", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); string name = t.FullName.Replace(".", "_");
if (pi == null) { GtkSharp.ObjectManager.RegisterType (name, t.FullName, t.Assembly.GetName().Name);
Console.WriteLine ("null PropertyInfo");
return GType.Invalid;
}
GType parent_gtype = (GType) pi.GetValue (null, null);
string name = t.Namespace.Replace(".", "_") + t.Name;
GtkSharp.ObjectManager.RegisterType (name, t.Namespace + t.Name, t.Assembly.GetName().Name);
GType gtype = new GType (gtksharp_register_type (name, parent_gtype.Val)); GType gtype = new GType (gtksharp_register_type (name, parent_gtype.Val));
ConnectDefaultHandlers (gtype, t); ConnectDefaultHandlers (gtype, t);
g_types[t] = gtype; g_types[t] = gtype;
@ -144,9 +138,15 @@ namespace GLib {
static Hashtable g_types = new Hashtable (); static Hashtable g_types = new Hashtable ();
public static GType GetGType (System.Type t)
public GType LookupGType ()
{ {
if (g_types.ContainsKey (t)) return LookupGType (GetType ());
}
private static GType LookupGType (System.Type t)
{
if (g_types.Contains (t))
return (GType) g_types [t]; return (GType) g_types [t];
PropertyInfo pi = t.GetProperty ("GType", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); PropertyInfo pi = t.GetProperty ("GType", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
@ -169,6 +169,14 @@ namespace GLib {
Raw = g_object_new (gtype.Val, IntPtr.Zero); Raw = g_object_new (gtype.Val, IntPtr.Zero);
} }
[DllImport("glibsharpglue")]
static extern IntPtr gtksharp_object_newv (IntPtr gtype, int n_params, string[] names, GLib.Value[] vals);
protected void CreateNativeObject (string[] names, GLib.Value[] vals)
{
Raw = gtksharp_object_newv (LookupGType ().Val, names.Length, names, vals);
}
protected virtual IntPtr Raw { protected virtual IntPtr Raw {
get { get {
return _obj; return _obj;

View file

@ -45,12 +45,12 @@ namespace GtkSharp {
public static void RegisterType (string native_name, string managed_name, string assembly) public static void RegisterType (string native_name, string managed_name, string assembly)
{ {
types.Add(native_name, managed_name + "," + assembly); RegisterType (native_name, managed_name + "," + assembly);
} }
public static void RegisterType (string native_name, string mangled) public static void RegisterType (string native_name, string mangled)
{ {
types.Add(native_name, mangled); types [native_name] = mangled;
} }
static string GetExpected (string cname) static string GetExpected (string cname)

View file

@ -15,7 +15,7 @@ namespace GLib {
[StructLayout (LayoutKind.Sequential)] [StructLayout (LayoutKind.Sequential)]
public struct Value : IDisposable { public struct Value : IDisposable {
GType type; IntPtr type;
long pad_1; long pad_1;
long pad_2; long pad_2;
@ -30,6 +30,9 @@ namespace GLib {
[DllImport("glibsharpglue")] [DllImport("glibsharpglue")]
static extern IntPtr gtksharp_value_create_from_property(ref GLib.Value val, IntPtr obj, string name); static extern IntPtr gtksharp_value_create_from_property(ref GLib.Value val, IntPtr obj, string name);
[DllImport("glibsharpglue")]
static extern IntPtr gtksharp_value_create_from_type_and_property(ref GLib.Value val, IntPtr gtype, string name);
public void Dispose () public void Dispose ()
{ {
g_value_unset (ref this); g_value_unset (ref this);
@ -42,14 +45,14 @@ namespace GLib {
public Value (GLib.GType gtype) public Value (GLib.GType gtype)
{ {
type = GType.Invalid; type = IntPtr.Zero;
pad_1 = pad_2 = 0; pad_1 = pad_2 = 0;
g_value_init (ref this, gtype.Val); g_value_init (ref this, gtype.Val);
} }
public Value (GLib.Object obj, string prop_name) public Value (GLib.Object obj, string prop_name)
{ {
type = GType.Invalid; type = IntPtr.Zero;
pad_1 = pad_2 = 0; pad_1 = pad_2 = 0;
gtksharp_value_create_from_property (ref this, obj.Handle, prop_name); gtksharp_value_create_from_property (ref this, obj.Handle, prop_name);
} }
@ -81,7 +84,7 @@ namespace GLib {
public Value (IntPtr obj, string prop_name, Opaque val) public Value (IntPtr obj, string prop_name, Opaque val)
{ {
type = GType.Invalid; type = IntPtr.Zero;
pad_1 = pad_2 = 0; pad_1 = pad_2 = 0;
gtksharp_value_create_from_property (ref this, obj, prop_name); gtksharp_value_create_from_property (ref this, obj, prop_name);
g_value_set_boxed (ref this, val.Handle); g_value_set_boxed (ref this, val.Handle);
@ -155,11 +158,11 @@ namespace GLib {
[DllImport("libgobject-2.0-0.dll")] [DllImport("libgobject-2.0-0.dll")]
static extern void g_value_set_char (ref Value val, char data); static extern void g_value_set_char (ref Value val, char data);
public Value (IntPtr obj, string prop_name, EnumWrapper wrap) public Value (GLib.Object obj, string prop_name, EnumWrapper wrap)
{ {
type = GType.Invalid; type = IntPtr.Zero;
pad_1 = pad_2 = 0; pad_1 = pad_2 = 0;
gtksharp_value_create_from_property (ref this, obj, prop_name); gtksharp_value_create_from_type_and_property (ref this, obj.LookupGType ().Val, prop_name);
if (wrap.flags) if (wrap.flags)
g_value_set_flags (ref this, (uint) (int) wrap); g_value_set_flags (ref this, (uint) (int) wrap);
else else
@ -168,7 +171,7 @@ namespace GLib {
public Value (object obj) public Value (object obj)
{ {
type = GType.Invalid; type = IntPtr.Zero;
pad_1 = pad_2 = 0; pad_1 = pad_2 = 0;
GType gtype = TypeConverter.LookupType (obj.GetType ()); GType gtype = TypeConverter.LookupType (obj.GetType ());

View file

@ -9,6 +9,7 @@
/* Forward declarations */ /* Forward declarations */
int gtksharp_object_get_ref_count (GObject *obj); int gtksharp_object_get_ref_count (GObject *obj);
GObject *gtksharp_object_newv (GType type, gint cnt, gchar **names, GValue *vals);
/* */ /* */
int int
@ -16,3 +17,25 @@ gtksharp_object_get_ref_count (GObject *obj)
{ {
return obj->ref_count; return obj->ref_count;
} }
GObject *
gtksharp_object_newv (GType type, gint cnt, gchar **names, GValue *vals)
{
int i;
GParameter *parms = NULL;
GObject *result;
if (cnt > 0)
parms = g_new0 (GParameter, cnt);
for (i = 0; i < cnt; i++) {
parms[i].name = names[i];
parms[i].value = vals[i];
}
result = g_object_newv (type, cnt, parms);
g_free (parms);
return result;
}

View file

@ -9,6 +9,7 @@
/* Forward declarations */ /* Forward declarations */
void gtksharp_value_create_from_property (GValue *value, GObject *obj, const gchar* name); 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); GType gtksharp_value_get_value_type (GValue *value);
gpointer glibsharp_value_get_boxed (GValue *value); gpointer glibsharp_value_get_boxed (GValue *value);
void glibsharp_value_set_boxed (GValue *value, gpointer boxed); void glibsharp_value_set_boxed (GValue *value, gpointer boxed);
@ -21,6 +22,13 @@ gtksharp_value_create_from_property (GValue *value, GObject *obj, const gchar* n
g_value_init (value, spec->value_type); g_value_init (value, spec->value_type);
} }
void
gtksharp_value_create_from_type_and_property (GValue *value, GType gtype, const gchar* name)
{
GParamSpec *spec = g_object_class_find_property (g_type_class_ref (gtype), name);
g_value_init (value, spec->value_type);
}
GType GType
gtksharp_value_get_value_type (GValue *value) gtksharp_value_get_value_type (GValue *value)
{ {

View file

@ -14,8 +14,22 @@
static extern IntPtr gtk_dialog_new_with_buttons (string title, IntPtr i, int flags, IntPtr dummy); static extern IntPtr gtk_dialog_new_with_buttons (string title, IntPtr i, int flags, IntPtr dummy);
public Dialog (string title, Gtk.Window parent, Gtk.DialogFlags flags) : base(IntPtr.Zero) public Dialog (string title, Gtk.Window parent, Gtk.DialogFlags flags) : base(IntPtr.Zero)
{ {
if (GetType() != typeof (Dialog)) if (GetType() != typeof (Dialog)) {
throw new InvalidOperationException ("Can't chain to this constructor from subclasses."); GLib.Value[] vals = new GLib.Value [1];
string[] names = new string [1];
names [0] = "title";
vals [0] = new GLib.Value (title);
CreateNativeObject (names, vals);
TransientFor = parent;
if ((flags & DialogFlags.Modal) > 0)
Modal = true;
if ((flags & DialogFlags.DestroyWithParent) > 0)
DestroyWithParent = true;
if ((flags & DialogFlags.NoSeparator) > 0)
HasSeparator = false;
return;
}
Raw = gtk_dialog_new_with_buttons (title, parent.Handle, (int) flags, IntPtr.Zero); Raw = gtk_dialog_new_with_buttons (title, parent.Handle, (int) flags, IntPtr.Zero);
} }

View file

@ -67,6 +67,7 @@
<attr path="/api/namespace/object[@cname='GtkBox']/method[@name='PackEndDefaults']" name="name">PackEnd</attr> <attr path="/api/namespace/object[@cname='GtkBox']/method[@name='PackEndDefaults']" name="name">PackEnd</attr>
<attr path="/api/namespace/object[@cname='GtkBox']/method[@name='PackStartDefaults']" name="name">PackStart</attr> <attr path="/api/namespace/object[@cname='GtkBox']/method[@name='PackStartDefaults']" name="name">PackStart</attr>
<attr path="/api/namespace/object[@cname='GtkButton']/constructor[@cname='gtk_button_new_from_stock']" name="preferred">1</attr> <attr path="/api/namespace/object[@cname='GtkButton']/constructor[@cname='gtk_button_new_from_stock']" name="preferred">1</attr>
<attr path="/api/namespace/object[@cname='GtkButton']/constructor[@cname='gtk_button_new_from_stock']/*/*[@name='stock_id']" name="property_name">label</attr>
<attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Clicked']" name="name">Click</attr> <attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Clicked']" name="name">Click</attr>
<attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Pressed']" name="name">Press</attr> <attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Pressed']" name="name">Press</attr>
<attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Released']" name="name">Release</attr> <attr path="/api/namespace/object[@cname='GtkButton']/method[@name='Released']" name="name">Release</attr>
@ -116,6 +117,7 @@
<attr path="/api/namespace/object[@cname='GtkItem']/signal[@name='Select']" name="name">Selected</attr> <attr path="/api/namespace/object[@cname='GtkItem']/signal[@name='Select']" name="name">Selected</attr>
<attr path="/api/namespace/object[@cname='GtkItem']/signal[@name='Toggle']" name="name">Toggled</attr> <attr path="/api/namespace/object[@cname='GtkItem']/signal[@name='Toggle']" name="name">Toggled</attr>
<attr path="/api/namespace/object[@cname='GtkLabel']/constructor[@cname='gtk_label_new_with_mnemonic']" name="preferred">1</attr> <attr path="/api/namespace/object[@cname='GtkLabel']/constructor[@cname='gtk_label_new_with_mnemonic']" name="preferred">1</attr>
<attr path="/api/namespace/object[@cname='GtkLabel']/constructor[@cname='gtk_label_new_with_mnemonic']/*/*[@name='str']" name="property_name">label</attr>
<attr path="/api/namespace/object[@cname='GtkLayout']/constructor[@cname='gtk_layout_new']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr> <attr path="/api/namespace/object[@cname='GtkLayout']/constructor[@cname='gtk_layout_new']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr>
<attr path="/api/namespace/object[@cname='GtkLayout']/method[@name='SetHadjustment']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr> <attr path="/api/namespace/object[@cname='GtkLayout']/method[@name='SetHadjustment']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr>
<attr path="/api/namespace/object[@cname='GtkLayout']/method[@name='SetVadjustment']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr> <attr path="/api/namespace/object[@cname='GtkLayout']/method[@name='SetVadjustment']/*/*[@type='GtkAdjustment*']" name="null_ok">1</attr>

View file

@ -31,20 +31,7 @@ namespace GtkSamples {
public class MyButton : Gtk.Button { public class MyButton : Gtk.Button {
static GLib.GType gtype = GLib.GType.Invalid; public MyButton () : base ("I'm a subclassed button") {}
public MyButton () : base (GType)
{
Label = "I'm a subclassed button";
}
public static new GLib.GType GType {
get {
if (gtype == GLib.GType.Invalid)
gtype = RegisterGType (typeof (MyButton));
return gtype;
}
}
protected override void OnClicked () protected override void OnClicked ()
{ {