#include <gtk/gtk.h>

G_BEGIN_DECLS

#define FOO_TYPE_BAR             (foo_bar_get_type ())
#define FOO_BAR(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOO_TYPE_BAR, FooBar))
#define FOO_BAR_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), FOO_TYPE_BAR, FooBarClass))
#define FOO_IS_BAR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOO_TYPE_BAR))
#define FOO_IS_BAR_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), FOO_TYPE_BAR))
#define FOO_BAR_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), FOO_TYPE_BAR, FooBarClass))

typedef struct _FooBarClass FooBarClass;
typedef struct _FooBar FooBar;

struct _FooBarClass
{
	GObjectClass parent_class;
};

struct _FooBar
{
	GObject parent_instance;
	gint construct;
};


enum
{
	PROP_0,

	PROP_CONSTRUCT
};

G_DEFINE_TYPE (FooBar, foo_bar, G_TYPE_OBJECT);

static void
foo_bar_init (FooBar *object)
{
	/* TODO: Add initialization code here */
}

static void
foo_bar_finalize (GObject *object)
{
	/* TODO: Add deinitalization code here */

	G_OBJECT_CLASS (foo_bar_parent_class)->finalize (object);
}

static void
foo_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
	g_return_if_fail (FOO_IS_BAR (object));

	switch (prop_id)
	{
	case PROP_CONSTRUCT:
		FOO_BAR (object)->construct = g_value_get_int (value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
foo_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
	g_return_if_fail (FOO_IS_BAR (object));

	switch (prop_id)
	{
	case PROP_CONSTRUCT:
		g_value_set_int (value, FOO_BAR (object)->construct);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static GObject *
foo_bar_constructor (GType                  type,
					 guint                  n_construct_properties,
					 GObjectConstructParam *construct_properties)
{
	GObject *object;
	
	object = G_OBJECT_CLASS (foo_bar_parent_class)->constructor (type,
																 n_construct_properties,
																 construct_properties);
	
	g_message ("foo_bar_constructor n_construct_properties=%d construct=%d", n_construct_properties, FOO_BAR (object)->construct);
	
	return object;
}
	
static void
foo_bar_constructed (GObject *object)
{
	if (G_OBJECT_CLASS (foo_bar_parent_class)->constructed)
		G_OBJECT_CLASS (foo_bar_parent_class)->constructed (object);
	
	g_message ("foo_bar_constructed construct=%d", FOO_BAR (object)->construct);
}

static void
foo_bar_class_init (FooBarClass *klass)
{
	GObjectClass* object_class = G_OBJECT_CLASS (klass);
	GObjectClass* parent_class = G_OBJECT_CLASS (klass);

	object_class->constructor = foo_bar_constructor;
	object_class->constructed = foo_bar_constructed;
	object_class->finalize = foo_bar_finalize;
	object_class->set_property = foo_bar_set_property;
	object_class->get_property = foo_bar_get_property;

	g_object_class_install_property (object_class,
	                                 PROP_CONSTRUCT,
	                                 g_param_spec_int ("construct",
													   "construct",
													   "a construct prop",
													   0, 999999, 0,
													   G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
}


/* gcc -o foobar foo-bar.c `pkg-config --cflags --libs gtk+-2.0` */

int
main (int argc, char **argv)
{
	GtkBuilder *builder;
	GtkObject *obj1, *builder_obj;
	
	gtk_init (&argc, &argv);

	g_message ("creating a new object with g_object_new ()");
	obj1 = g_object_new (FOO_TYPE_BAR, "construct", 4321, NULL);

	g_message ("creating a new object with gtk_builder_add_from_string ()");
	builder = gtk_builder_new ();
	gtk_builder_add_from_string (builder,
								 "<?xml version=\"1.0\"?>"
								 "<interface>"
								 "  <object class=\"FooBar\" id=\"areallyfoobar\">"
								 "    <property name=\"construct\">1234</property>"
								 "  </object>"
								 "</interface>", -1, NULL);

	return 0;
}

