/*
 * test-ui.c: A test application to hammer the Bonobo UI api.
 *
 * NB. To run this program and test the xml IO code you
 * need to do something like ln -s /{prefix}/bonobo/doc/std-ui.xml ~/.gnome/ui
 *
 * Author:
 *	Michael Meeks (michael@helixcode.com)
 *
 * Copyright 2000 Ximian, Inc.
 */

#include "config.h"
#include <sys/time.h>
#include <gnome.h>
#include <bonobo.h>
#include <liboaf/liboaf.h>

#include <bonobo/bonobo-ui-xml.h>
#include <bonobo/bonobo-ui-util.h>
#include <bonobo/bonobo-win.h>

poptContext ctx;

#define NUM_WIN  1
#define NUM_FILL 10

static void
test_nodes_same (BonoboUINode *a,
		 BonoboUINode *b)
{
#if 0
	BonoboUINode *la, *lb;

	g_assert (bonobo_ui_node_same_attrs (a, b));

	la = bonobo_ui_node_children (a);
	lb = bonobo_ui_node_children (b);

	if (la || lb)
		test_nodes_same (la, lb);
#endif
}

static void
print_time (FILE *file, const char *msg,
	    struct timeval *t1, struct timeval *t2)
{
	long usecdiff = t2->tv_usec - t1->tv_usec;
	long usecdiv = 1000 * 1000;

	fprintf (file, "%s %d:%.6d\n", msg,
		 (int)((t2->tv_sec - t1->tv_sec) + (usecdiff / usecdiv)),
		 (int)(usecdiff % usecdiv));
}

static void
flush (void)
{
	while (gtk_events_pending ())
		gtk_main_iteration ();
	gdk_flush ();
}

static BonoboUIComponent *
fill_window (BonoboWindow *win, BonoboUINode *ui)
{
	BonoboUIContainer *container = bonobo_ui_container_new ();
	BonoboUIComponent *component = bonobo_ui_component_new ("Foo");

	bonobo_ui_container_set_win (container, win);
	bonobo_ui_component_set_container (
		component, BONOBO_OBJREF (container));
	
	if (ui)
		bonobo_ui_component_set_tree (
			component, "/", ui, NULL);

	return component;
}

static void
speed_tests (void)
{
	GtkWidget     *wins [NUM_WIN];
	int            i;
	struct timeval t1, t2;

#if 0
	{ /* GtkWindow */
		g_assert (!gettimeofday (&t1, NULL));
		{
			for (i = 0; i < NUM_WIN; i++) {
				wins [i] = gtk_window_new (GTK_WINDOW_TOPLEVEL);
				gtk_widget_show (wins [i]);
			}
			flush ();
		}
		g_assert (!gettimeofday (&t2, NULL));

		print_time (stderr, "Normal GtkWindow create ", &t1, &t2);

		g_assert (!gettimeofday (&t1, NULL));
		{
			for (i = 0; i < NUM_WIN; i++)
				gtk_widget_destroy (wins [i]);
		
			flush ();
		}
		g_assert (!gettimeofday (&t2, NULL));

		print_time (stderr, "Normal GtkWindow destroy ", &t1, &t2);
	}

	{ /* BonoboWindow */
		g_assert (!gettimeofday (&t1, NULL));
		{
			for (i = 0; i < NUM_WIN; i++) {
				wins [i] = bonobo_window_new ("foo", "baa");
				gtk_widget_show (wins [i]);
			}
			flush ();
		}
		g_assert (!gettimeofday (&t2, NULL));

		print_time (stderr, "plain BonoboWindow create ", &t1, &t2);

		g_assert (!gettimeofday (&t1, NULL));
		{
			for (i = 0; i < NUM_WIN; i++)
				gtk_widget_destroy (wins [i]);
		
			flush ();
		}
		g_assert (!gettimeofday (&t2, NULL));

		print_time (stderr, "plain BonoboWindow destroy ", &t1, &t2);
	}
#endif

	{ /* BonoboWindow + XML */
		BonoboUINode *ui;
		BonoboUIComponent *components [NUM_WIN];

		ui = bonobo_ui_util_new_ui (
			NULL, "std-ui.xml", ".", "foobar");

		if (!ui)
			g_warning ("XML Speed tests failed");
		else {


			g_assert (!gettimeofday (&t1, NULL));
			{
				for (i = 0; i < NUM_WIN; i++) {
					wins [i] = bonobo_window_new ("foo", "baa");
					components [i] = fill_window (BONOBO_WINDOW (wins [i]), ui);
					gtk_widget_show (wins [i]);
				}
				flush ();
			}
			g_assert (!gettimeofday (&t2, NULL));

			print_time (stderr, "plain BonoboWindow create ", &t1, &t2);

			g_assert (!gettimeofday (&t1, NULL));
			{
				for (i = 0; i < NUM_WIN; i++) {
					int i2;
					for (i2 = 0; i2 < NUM_FILL; i2++)
						bonobo_ui_component_set_tree (
							components [i], "/", ui, NULL);
					
					flush ();
				}
			}
			g_assert (!gettimeofday (&t2, NULL));

			print_time (stderr, "BonoboWindow XML thrash ", &t1, &t2);

			g_assert (!gettimeofday (&t1, NULL));
			{
				for (i = 0; i < NUM_WIN; i++)
					gtk_widget_destroy (wins [i]);
		
				flush ();
			}
			g_assert (!gettimeofday (&t2, NULL));

			print_time (stderr, "plain BonoboWindow destroy ", &t1, &t2);

			bonobo_ui_node_free (ui);
		}
	}
}

BonoboUIComponent *global_component;

static void
cb_do_quit (GtkWindow *window, gpointer dummy)
{
	gtk_main_quit ();
}

static void
cb_do_dump (GtkWindow *window, BonoboWindow *win)
{
	bonobo_window_dump (win, "on User input");
}

static void
cb_do_popup (GtkWindow *window, BonoboWindow *win)
{
	GtkWidget *menu;

	menu = gtk_menu_new ();

	bonobo_window_add_popup (win, GTK_MENU (menu), "/popups/MyStuff");

	gtk_widget_show (GTK_WIDGET (menu));
	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, 0);
}

static void
cb_do_hide_toolbar (GtkWindow *window, BonoboWindow *win)
{
	const char path [] = "/Toolbar";
	char *val;

	val = bonobo_ui_component_get_prop (global_component, path, "hidden", NULL);
	if (val && atoi (val))
		bonobo_ui_component_set_prop (global_component, path, "hidden", "0", NULL);
	else
		bonobo_ui_component_set_prop (global_component, path, "hidden", "1", NULL);
}

static void
cb_set_state (GtkEntry *state_entry, GtkEntry *path_entry)
{
	char *path, *state, *txt, *str;

	path = gtk_entry_get_text (path_entry);
	state = gtk_entry_get_text (state_entry);

	g_warning ("Set state on '%s' to '%s'", path, state);

	bonobo_ui_component_set_prop (
		global_component, path, "state", state, NULL);

	txt = bonobo_ui_component_get_prop (
		global_component, path, "state", NULL);

	g_warning ("Re-fetched state was '%s'", txt);

	str = g_strdup_printf ("The state is now '%s'", txt);
	bonobo_ui_component_set_status (global_component, str, NULL);
	g_free (str);

	g_free (txt);
}

static void
toggled_cb (BonoboUIComponent           *component,
	    const char                  *path,
	    Bonobo_UIComponent_EventType type,
	    const char                  *state,
	    gpointer                     user_data)
{
	fprintf (stderr, "toggled to '%s' type '%d' path '%s'\n",
		 state, type, path);
}

static void
disconnect_progress (GtkObject *progress, gpointer dummy)
{
	gtk_timeout_remove (GPOINTER_TO_UINT (dummy));
}

static gboolean
update_progress (GtkProgress *progress)
{
	float pos = gtk_progress_get_current_percentage (progress);

	if (pos < 0.95)
		gtk_progress_set_percentage (progress, pos + 0.05);
	else
		gtk_progress_set_percentage (progress, 0);

	return TRUE;
}

static void
slow_size_request (GtkWidget      *widget,
		   GtkRequisition *requisition,
		   gpointer        user_data)
{
/*	sleep (2);*/
}

static void
file_exit_cmd (BonoboUIComponent *uic,
	       gpointer           user_data,
	       const char        *verbname)
{
	exit (0);
}

static void
file_open_cmd (BonoboUIComponent *uic,
	       gpointer           user_data,
	       const char        *verbname)
{
	g_warning ("File Open");
}

BonoboUIVerb verbs [] = {
	BONOBO_UI_VERB ("FileExit", file_exit_cmd),
	BONOBO_UI_VERB ("FileOpen", file_open_cmd),

	BONOBO_UI_VERB_END
};

int
main (int argc, char **argv)
{
	BonoboWindow *win;
	CORBA_ORB  orb;
	BonoboUIComponent *componenta;
	BonoboUIComponent *componentb;
	BonoboUIComponent *componentc;
	BonoboUIContainer *container;
	Bonobo_UIContainer corba_container;
	CORBA_Environment  ev;
	char *txt, *fname;

	char simplea [] =
		"<menu>\n"
		"	<submenu name=\"File\" _label=\"_Gå\">\n"
		"		<menuitem name=\"open\" pos=\"bottom\" _label=\"_Open\" verb=\"FileOpen\"pixtype=\"stock\" pixname=\"Open\" _tip=\"Wibble\"/>\n"
		"		<control name=\"MyControl\"/>\n"
		"		<control name=\"ThisIsEmpty\"/>\n"
		"		<menuitem name=\"close\" noplace=\"1\" verb=\"FileExit\" _label=\"_CloseA\" _tip=\"hi\""
		"		pixtype=\"stock\" pixname=\"Close\" accel=\"*Control*q\"/>\n"
		"	</submenu>\n"
		"</menu>";
	char simpleb [] =
		"<submenu name=\"File\" _label=\"_File\">\n"
		"	<menuitem name=\"open\" _label=\"_OpenB\" pixtype=\"stock\" pixname=\"Open\" _tip=\"Open you fool\"/>\n"
		"       <separator/>\n"
		"       <menuitem name=\"toggle\" type=\"toggle\" id=\"MyFoo\" _label=\"_ToggleMe\" _tip=\"a\" accel=\"*Control*t\"/>\n"
		"       <placeholder name=\"Nice\" delimit=\"top\"/>\n"
		"	<menuitem name=\"close\" noplace=\"1\" verb=\"FileExit\" _label=\"_CloseB\" _tip=\"hi\""
		"        pixtype=\"stock\" pixname=\"Close\" accel=\"*Control*q\"/>\n"
		"</submenu>\n";
	char simplec [] =
		"<submenu name=\"File\" _label=\"_FileC\" _tip=\"what!\">\n"
		"    <placeholder name=\"Nice\" delimit=\"top\" hidden=\"1\">\n"
		"	<menuitem name=\"fooa\" _label=\"_FooA\" type=\"radio\" group=\"foogroup\" _tip=\"Radio1\"/>\n"
		"	<menuitem name=\"foob\" _label=\"_FooB\" type=\"radio\" group=\"foogroup\" _tip=\"kippers\"/>\n"
		"	<menuitem name=\"wibble\" verb=\"ThisForcesAnError\" _label=\"_Baa\""
		"        pixtype=\"stock\" pixname=\"Open\" sensitive=\"0\" _tip=\"fish\"/>\n"
		"       <separator/>\n"
		"    </placeholder>\n"
		"</submenu>\n";
	char simpled [] =
		"<menuitem name=\"save\" _label=\"_SaveD\" pixtype=\"stock\" pixname=\"Save\" _tip=\"tip1\"/>\n";
	char simplee [] =
		"<menuitem name=\"fish\" _label=\"_Inplace\" pixtype=\"stock\" pixname=\"Save\" _tip=\"tip2\"/>\n";
	char toola [] =
		"<dockitem name=\"Toolbar\" homogeneous=\"0\" vlook=\"icon\">\n"
		"	<toolitem type=\"toggle\" name=\"foo2\" id=\"MyFoo\"pixtype=\"stock\" pixname=\"Save\""
		"        _label=\"TogSave\" _tip=\"My tooltip\" priority=\"1\"/>\n"
		"	<separator/>\n"
		"	<toolitem name=\"baa\" pixtype=\"stock\" pixname=\"Open\" _label=\"baa\" _tip=\"My 2nd tooltip\" verb=\"testme\"/>\n"
		"	<control name=\"AControl\" _tip=\"a tip on a control\" hidden=\"0\" vdisplay=\"button\"\n"
		"	pixtype=\"stock\" pixname=\"Attach\"/>\n"
		"</dockitem>";
	char toolb [] =
		"<dockitem name=\"Toolbar\" look=\"icon\" relief=\"none\">\n"
		"	<toolitem name=\"foo1\" _label=\"Insensitive\" sensitive=\"0\" hidden=\"0\" priority=\"1\"/>\n"
		"	<toolitem type=\"toggle\" name=\"foo5\" id=\"MyFoo\" pixtype=\"stock\" pixname=\"Close\""
		"	 _label=\"TogSame\" _tip=\"My tooltip\"/>\n"
		"</dockitem>";
	char statusa [] =
		"<item name=\"main\">Kippers</item>\n";
	char statusb [] =
		"<status>\n"
		"	<item name=\"main\"/>\n"
		"	<control name=\"Progress\"/>\n"
		"</status>";
	BonoboUINode *accel;

	free (malloc (8));

	gnome_init_with_popt_table ("container", VERSION,
				    argc, argv, oaf_popt_options, 0, &ctx);

	textdomain (PACKAGE);

	orb = oaf_init (argc, argv);

	if (bonobo_init (orb, NULL, NULL) == FALSE)
		g_error (_("Could not initialize Bonobo!\n"));

	bonobo_activate ();

	{ /* Test encode / decode str */
		char *a, *b, *c;
		int   i;
		gboolean err;

		a = g_malloc (256);
		for (i = 0; i < 256; i++) {
			if (i == 255)
				*(a + i) = '\0';
			else
				*(a + i) = i + 1;
		}

		b = bonobo_ui_util_encode_str (a);
		c = bonobo_ui_util_decode_str (a, &err); /* sanity check */
		g_free (c);

		c = bonobo_ui_util_decode_str (b, &err);
		g_assert (err == FALSE);
		if (strcmp (a, c)) {
			g_warning ("Strings differ lengths %d should be %d",
				   strlen (c), strlen (a));

			for (i = 0; i < 256; i++) {
				if (a [i] != b [i])
					printf ("a [%d] (=%d) != b [%d] (=%d)\n",
						i, a [i], i, b [i]);
			}
		} /* else
		     printf ("String encode / decode worked\n"); */

		g_free (c);
		g_free (b);
		g_free (a);

		b = bonobo_ui_util_encode_str ("Hello World");
		c = bonobo_ui_util_decode_str (b, &err);
		g_assert (err == FALSE);

/*		printf ("Encode to '%s' and back to '%s'\n", b, c); */

		g_free (c);
		g_free (b);
	}

	{
		BonoboUINode *n = bonobo_ui_node_from_string (toola);
		test_nodes_same (n, n);
		bonobo_ui_node_free (n);
	}

	speed_tests ();

	win = BONOBO_WINDOW (bonobo_window_new ("Win", "My Test Application"));
	container = bonobo_ui_container_new ();
	bonobo_ui_container_set_win (container, win);
	
	bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (win),
					  "/test-ui/UIConfig/kvps");

	corba_container = BONOBO_OBJREF (container);

	{
		GtkWidget *box = gtk_vbox_new (FALSE, 0);
		GtkWidget *button;
		GtkWidget *path_entry, *state_entry;

		button = gtk_button_new_with_label ("Press me to test!");
		gtk_signal_connect (GTK_OBJECT (button), "clicked",
				    (GtkSignalFunc) cb_do_quit, NULL);
		gtk_widget_show (GTK_WIDGET (button));
		gtk_box_pack_start_defaults (GTK_BOX (box), button);

		button = gtk_button_new_with_label ("Dump Xml tree");
		gtk_signal_connect (GTK_OBJECT (button), "clicked",
				    (GtkSignalFunc) cb_do_dump, win);
		gtk_widget_show (GTK_WIDGET (button));
		gtk_box_pack_start_defaults (GTK_BOX (box), button);

		button = gtk_button_new_with_label ("Popup");
		gtk_signal_connect (GTK_OBJECT (button), "clicked",
				    (GtkSignalFunc) cb_do_popup, win);
		gtk_widget_show (GTK_WIDGET (button));
		gtk_box_pack_start_defaults (GTK_BOX (box), button);

		button = gtk_button_new_with_label ("Hide toolbar");
		gtk_signal_connect (GTK_OBJECT (button), "clicked",
				    (GtkSignalFunc) cb_do_hide_toolbar, win);
		gtk_widget_show (GTK_WIDGET (button));
		gtk_box_pack_start_defaults (GTK_BOX (box), button);

		path_entry = gtk_entry_new ();
		gtk_entry_set_text (GTK_ENTRY (path_entry), "/menu/File/toggle");
		gtk_widget_show (GTK_WIDGET (path_entry));
		gtk_box_pack_start_defaults (GTK_BOX (box), path_entry);

		state_entry = gtk_entry_new ();
		gtk_entry_set_text (GTK_ENTRY (state_entry), "1");
		gtk_signal_connect (GTK_OBJECT (state_entry), "changed",
				    (GtkSignalFunc) cb_set_state, path_entry);
		gtk_widget_show (GTK_WIDGET (state_entry));
		gtk_box_pack_start_defaults (GTK_BOX (box), state_entry);

		gtk_widget_show (GTK_WIDGET (box));
		bonobo_window_set_contents (win, box);
	}

	gtk_signal_connect (GTK_OBJECT (win), "size_request", 
			    slow_size_request, NULL);

	componenta = bonobo_ui_component_new ("A");
	bonobo_object_unref (BONOBO_OBJECT (componenta));

	componenta = bonobo_ui_component_new ("A");
	componentb = bonobo_ui_component_new ("B");
	componentc = bonobo_ui_component_new ("C");

	bonobo_ui_component_add_verb_list_with_data (
		componenta, verbs, GUINT_TO_POINTER (12));

	bonobo_ui_component_remove_verb (componenta, "FileExit");
	bonobo_ui_component_remove_verb_by_data (componenta, GUINT_TO_POINTER (12));

	bonobo_ui_component_set_container (componenta, corba_container);
	bonobo_ui_component_set_container (componentb, corba_container);
	bonobo_ui_component_set_container (componentc, corba_container);

	global_component = componenta;

	CORBA_exception_init (&ev);

	fname = bonobo_ui_util_get_ui_fname (NULL, "std-ui.xml");
	if (fname && g_file_exists (fname)) {
		fprintf (stderr, "\n\n--- Add std-ui.xml ---\n\n\n");
		bonobo_ui_util_set_ui (componenta, NULL, "std-ui.xml",
				       "gnomecal");
		bonobo_ui_component_thaw (componenta, NULL);

/*		bonobo_ui_component_set_prop (
			componenta, "/menu/Preferences",
			"pixname", "/demo/a.xpm", NULL);*/

		/* NB. bad, bad practice */
		gtk_widget_show_all (GTK_WIDGET (win));

		gtk_main ();
	} else {
		g_warning ("Can't find ~/.gnome/ui/std-ui.xml, perhaps "
			   " you need to symlink bonobo/doc/std-ui.xml there");
		gtk_widget_show (GTK_WIDGET (win));
	}
	g_free (fname);

	bonobo_ui_component_freeze (componenta, NULL);

	fprintf (stderr, "\n\n--- Remove A ---\n\n\n");
	bonobo_ui_component_rm (componenta, "/", &ev);

	bonobo_ui_component_set_translate (componentb, "/status", statusa, &ev);

	bonobo_ui_component_set_translate (componenta, "/", simplea, &ev);

	bonobo_ui_component_set_translate (componentb, "/",
				 "<popups> <popup name=\"MyStuff\"/> </popups>", &ev);
	bonobo_ui_component_set_translate (componenta, "/popups/MyStuff", simpleb, &ev);

	bonobo_ui_component_set_translate (componentb, "/",   toola, &ev);

	{
		GtkWidget *widget = gtk_button_new_with_label ("My Label");
		BonoboControl *control = bonobo_control_new (widget);
		
		gtk_widget_show (widget);
		bonobo_ui_component_object_set (componenta,
						"/menu/File/MyControl",
						BONOBO_OBJREF (control),
						NULL);
	}

	{
		GtkWidget *widget = gtk_entry_new ();
		BonoboControl *control = bonobo_control_new (widget);
		
		gtk_entry_set_text (GTK_ENTRY (widget), "Example text");
		gtk_widget_show (widget);
		bonobo_ui_component_object_set (componenta,
						"/Toolbar/AControl",
						BONOBO_OBJREF (control),
						NULL);
	}

	bonobo_ui_component_add_listener (componentb, "MyFoo", toggled_cb, NULL);

	bonobo_ui_component_set_translate (componentb, "/",     statusb, &ev);

	/* Duplicate set */
	bonobo_ui_component_set_translate (componenta, "/", simplea, &ev);

	bonobo_ui_component_add_verb_list_with_data (
		componenta, verbs, GUINT_TO_POINTER (15));

	bonobo_ui_component_thaw (componenta, NULL);

	bonobo_ui_component_set_status (componenta, "WhatA1", &ev);
	bonobo_ui_component_set_status (componentb, "WhatB2", &ev);
	bonobo_ui_component_set_status (componenta, "WhatA3", &ev);
	bonobo_ui_component_rm (componenta, "/status", &ev);
	bonobo_ui_component_set_status (componentb, "WhatB4", &ev);
	bonobo_ui_component_set_status (componenta, "WhatA5", &ev);
	bonobo_ui_component_set_status (componenta, "WhatA6", &ev);
	bonobo_ui_component_set_status (componentb, "WhatB7", &ev);
	bonobo_ui_component_set_status (componentb, "", &ev);

	{
		char *txt = bonobo_ui_component_get (componenta, "/status/main", TRUE, NULL);
		if (!txt || strcmp (txt, "<?xml version=\"1.0\"?>\n<item name=\"main\">576861744136</item>\n")) {
			g_warning ("Broken merging code '%s'", txt);
			g_assert_not_reached ();
		}
	}

	gtk_main ();

	bonobo_ui_component_freeze (componenta, NULL);

	accel = bonobo_ui_util_build_accel (GDK_A, GDK_CONTROL_MASK, "KeyWibbleVerb");
	bonobo_ui_component_set_tree (componenta, "/keybindings", accel, &ev);
	bonobo_ui_node_free (accel);

	bonobo_ui_component_set_translate (componentb, "/menu", simpleb, &ev);
	bonobo_ui_component_set_translate (componenta, "/",     toolb, &ev);

	bonobo_ui_component_set_prop (componenta, "/menu/File", "label",
				      "_Gå", NULL);

	/* A 'transparent' node merge */
	txt = bonobo_ui_component_get_prop (componenta, "/Toolbar", "look", NULL);
	printf ("Before merge look '%s'\n", txt);
	bonobo_ui_component_set_translate (componenta, "/", "<dockitem name=\"Toolbar\"/>", &ev);
	g_free (txt);
	txt = bonobo_ui_component_get_prop (componenta, "/Toolbar", "look", NULL);
	printf ("After merge look '%s'\n", txt);
	if (txt == NULL || strcmp (txt, "icon"))
		g_warning ("Serious transparency regression");
	g_free (txt);

	bonobo_ui_component_set_translate (componenta, "/menu/File/Nice", simplee, &ev);

	{
		GtkWidget *widget = gtk_progress_bar_new ();
		BonoboControl *control = bonobo_control_new (widget);
		guint id;

		gtk_progress_bar_update (GTK_PROGRESS_BAR (widget), 0.5);
		gtk_widget_show (widget);
		bonobo_ui_component_object_set (componenta, "/status/Progress",
						BONOBO_OBJREF (control),
						NULL);

		id = gtk_timeout_add (100, (GSourceFunc) update_progress, widget);
		gtk_signal_connect (GTK_OBJECT (widget), "destroy",
				    disconnect_progress, GUINT_TO_POINTER (id));
	}

	bonobo_ui_component_set_status (componenta, "This is a very long status message "
					"that should cause the window to be resized if "
					"there is in fact a bug in it", NULL);

	bonobo_ui_component_thaw (componenta, NULL);
	gtk_main ();
	bonobo_ui_component_freeze (componenta, NULL);

	bonobo_ui_component_set_translate (componentc, "/commands",
				 "<cmd name=\"MyFoo\" sensitive=\"0\"/>", &ev);
	bonobo_ui_component_set_translate (componentc, "/menu", simplec, &ev);
	
	bonobo_ui_component_set_translate (componentc, "/menu/File", simpled, &ev);

	bonobo_ui_component_thaw (componenta, NULL);
	gtk_main ();
	bonobo_ui_component_freeze (componenta, NULL);

	fprintf (stderr, "\n\n--- Remove 2 ---\n\n\n");
	bonobo_ui_component_rm (componentb, "/", &ev);
	bonobo_ui_component_set_prop (componentc, "/menu/File/save",
				      "label", "SaveC", NULL);

	bonobo_ui_component_thaw (componenta, NULL);
	gtk_main ();
	bonobo_ui_component_freeze (componenta, NULL);

	fprintf (stderr, "\n\n--- Remove 3 ---\n\n\n");
	bonobo_ui_component_rm (componentc, "/", &ev);

	bonobo_ui_component_thaw (componenta, NULL);
	gtk_main ();
	bonobo_ui_component_freeze (componenta, NULL);

	fprintf (stderr, "\n\n--- Remove 1 ---\n\n\n");
	bonobo_ui_component_rm (componenta, "/", &ev);

	bonobo_ui_component_thaw (componenta, NULL);
	gtk_main ();

	bonobo_object_unref (BONOBO_OBJECT (componenta));
	bonobo_object_unref (BONOBO_OBJECT (componentb));
	bonobo_object_unref (BONOBO_OBJECT (componentc));

	bonobo_object_unref (BONOBO_OBJECT (container));
	gtk_widget_destroy (GTK_WIDGET (win));

	CORBA_exception_free (&ev);

	if (ctx)
		poptFreeContext (ctx);

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1