/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * mate-panel-applet-frame-matecomponent.c: panel side container for applets
 *
 * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
 * Copyright (C) 2010 Vincent Untz <vuntz@gnome.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * 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.
 *
 * Authors:
 *	Mark McLoughlin <mark@skynet.ie>
 */

#include <config.h>

#include <string.h>

#include <libmatecomponentui.h>

#include <mate-panel-applet-frame.h>
#include <mate-panel-applets-manager.h>

#include "MATE_Panel.h"

#include "mate-panel-applet-frame-matecomponent.h"

G_DEFINE_TYPE (MatePanelAppletFrameMateComponent,
	       mate_panel_applet_frame_matecomponent,
	       PANEL_TYPE_APPLET_FRAME)

struct _MatePanelAppletFrameMateComponentPrivate
{
	MATE_Vertigo_MatePanelAppletShell  applet_shell;
	CORBA_Object                    control;
	MateComponent_PropertyBag              property_bag;
	MateComponentUIComponent              *ui_component;
};

#define PROPERTY_ORIENT      "mate-panel-applet-orient"
#define PROPERTY_SIZE        "mate-panel-applet-size"
#define PROPERTY_BACKGROUND  "mate-panel-applet-background"
#define PROPERTY_FLAGS       "mate-panel-applet-flags"
#define PROPERTY_SIZE_HINTS  "mate-panel-applet-size-hints"
#define PROPERTY_LOCKED_DOWN "mate-panel-applet-locked-down"

typedef enum {
       PANEL_SIZE_XX_SMALL = MATE_Vertigo_PANEL_XX_SMALL,
       PANEL_SIZE_X_SMALL  = MATE_Vertigo_PANEL_X_SMALL,
       PANEL_SIZE_SMALL    = MATE_Vertigo_PANEL_SMALL,
       PANEL_SIZE_MEDIUM   = MATE_Vertigo_PANEL_MEDIUM,
       PANEL_SIZE_LARGE    = MATE_Vertigo_PANEL_LARGE,
       PANEL_SIZE_X_LARGE  = MATE_Vertigo_PANEL_X_LARGE,
       PANEL_SIZE_XX_LARGE = MATE_Vertigo_PANEL_XX_LARGE
} PanelSize;

/* Keep in sync with mate-panel-applet.h. Uggh. */
typedef enum {
	APPLET_FLAGS_NONE   = 0,
	APPLET_EXPAND_MAJOR = 1 << 0,
	APPLET_EXPAND_MINOR = 1 << 1,
	APPLET_HAS_HANDLE   = 1 << 2
} MatePanelAppletFlags;

GQuark
mate_panel_applet_frame_matecomponent_error_quark (void)
{
        static GQuark ret = 0;

        if (ret == 0) {
                ret = g_quark_from_static_string ("mate_panel_applet_frame_matecomponent_error");
        }

        return ret;
}

static guint
get_mate_panel_applet_orient (PanelOrientation orientation)
{
	/* For some reason libmate-panel-applet and panel use a different logic for
	 * orientation, so we need to convert it. We should fix this. */
	switch (orientation) {
	case PANEL_ORIENTATION_TOP:
		return 1;
	case PANEL_ORIENTATION_BOTTOM:
		return 0;
	case PANEL_ORIENTATION_LEFT:
		return 3;
	case PANEL_ORIENTATION_RIGHT:
		return 2;
	default:
		g_assert_not_reached ();
		break;
	}
}

static void
mate_panel_applet_frame_matecomponent_update_flags (MatePanelAppletFrame *frame,
					const CORBA_any  *any)
{
	int      flags;
	gboolean major;
	gboolean minor;
	gboolean has_handle;

	flags = MATECOMPONENT_ARG_GET_SHORT (any);

	major = (flags & APPLET_EXPAND_MAJOR) != 0;
	minor = (flags & APPLET_EXPAND_MINOR) != 0;
	has_handle = (flags & APPLET_HAS_HANDLE) != 0;

	_mate_panel_applet_frame_update_flags (frame, major, minor, has_handle);
}

static void
mate_panel_applet_frame_matecomponent_update_size_hints (MatePanelAppletFrame *frame,
					     const CORBA_any  *any)
{
	CORBA_sequence_CORBA_long *seq;

	seq = any->_value;

	_mate_panel_applet_frame_update_size_hints (frame, seq->_buffer, seq->_length);
}

static void
mate_panel_applet_frame_matecomponent_init_properties (MatePanelAppletFrame *frame)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);
	CORBA_any *any;

	any = matecomponent_pbclient_get_value (matecomponent_frame->priv->property_bag,
					 PROPERTY_FLAGS,
					 MATECOMPONENT_ARG_SHORT,
					 NULL);
	if (any) {
		mate_panel_applet_frame_matecomponent_update_flags (frame, any);
		CORBA_free (any);
	}

	any = matecomponent_pbclient_get_value (matecomponent_frame->priv->property_bag,
					 PROPERTY_SIZE_HINTS,
					 TC_CORBA_sequence_CORBA_long,
					 NULL);
	if (any) {
		mate_panel_applet_frame_matecomponent_update_size_hints (frame, any);
		CORBA_free (any);
	}
}

static void
mate_panel_applet_frame_matecomponent_sync_menu_state (MatePanelAppletFrame *frame,
					   gboolean          movable,
					   gboolean          removable,
					   gboolean          lockable,
					   gboolean          locked,
					   gboolean          locked_down)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/LockAppletToPanel",
				      "state",
				      locked ? "1" : "0",
				      NULL);

	/* First sensitivity */
	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/LockAppletToPanel",
				      "sensitive",
				      lockable ? "1" : "0",
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/RemoveAppletFromPanel",
				      "sensitive",
				      (locked && !lockable) ? "0" : (removable ? "1" : "0"),
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/MoveApplet",
				      "sensitive",
				      locked ? "0" : (movable ? "1" : "0"),
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/LockAppletToPanel",
				      "hidden",
				      locked_down ? "1" : "0",
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/LockSeparator",
				      "hidden",
				      locked_down ? "1" : "0",
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/RemoveAppletFromPanel",
				      "hidden",
				      locked_down ? "1" : "0",
				      NULL);

	matecomponent_ui_component_set_prop (matecomponent_frame->priv->ui_component,
				      "/commands/MoveApplet",
				      "hidden",
				      locked_down ? "1" : "0",
				      NULL);
}

static void
mate_panel_applet_frame_matecomponent_popup_menu (MatePanelAppletFrame *frame,
				      guint             button,
				      guint32           timestamp)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);
	CORBA_Environment env;

	CORBA_exception_init (&env);

	MATE_Vertigo_MatePanelAppletShell_popup_menu (matecomponent_frame->priv->applet_shell,
						   button, timestamp, &env);
	if (MATECOMPONENT_EX (&env))
		g_warning ("Exception from popup_menu '%s'\n", env._id);

	CORBA_exception_free (&env);
}

static void
mate_panel_applet_frame_matecomponent_change_orientation (MatePanelAppletFrame *frame,
					      PanelOrientation  orientation)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);
	CORBA_unsigned_short orient = 0;

	switch (orientation) {
	case PANEL_ORIENTATION_TOP:
		orient = MATE_Vertigo_PANEL_ORIENT_DOWN;
		break;
	case PANEL_ORIENTATION_BOTTOM:
		orient = MATE_Vertigo_PANEL_ORIENT_UP;
		break;
	case PANEL_ORIENTATION_LEFT:
		orient = MATE_Vertigo_PANEL_ORIENT_RIGHT;
		break;
	case PANEL_ORIENTATION_RIGHT:
		orient = MATE_Vertigo_PANEL_ORIENT_LEFT;
		break;
	default:
		g_assert_not_reached ();
		break;
	}

	matecomponent_pbclient_set_short (matecomponent_frame->priv->property_bag,
				   PROPERTY_ORIENT,
				   orient,
				   NULL);

	gtk_widget_queue_resize (GTK_WIDGET (frame));
}

static void
mate_panel_applet_frame_matecomponent_change_size (MatePanelAppletFrame *frame,
				       guint             size)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);

	/* Normalise the size to the constants defined in the IDL. */
	size = size <= PANEL_SIZE_XX_SMALL ? PANEL_SIZE_XX_SMALL :
	       size <= PANEL_SIZE_X_SMALL  ? PANEL_SIZE_X_SMALL  :
	       size <= PANEL_SIZE_SMALL    ? PANEL_SIZE_SMALL    :
	       size <= PANEL_SIZE_MEDIUM   ? PANEL_SIZE_MEDIUM   :
	       size <= PANEL_SIZE_LARGE    ? PANEL_SIZE_LARGE    :
	       size <= PANEL_SIZE_X_LARGE  ? PANEL_SIZE_X_LARGE  : PANEL_SIZE_XX_LARGE;

	matecomponent_pbclient_set_short (matecomponent_frame->priv->property_bag,
				   PROPERTY_SIZE,
				   size,
				   NULL);
}

static void
mate_panel_applet_frame_matecomponent_change_background (MatePanelAppletFrame    *frame,
					     PanelBackgroundType  type)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (frame);
	char *bg_str;

	bg_str = _mate_panel_applet_frame_get_background_string (
			frame, PANEL_WIDGET (GTK_WIDGET (frame)->parent), type);

	if (bg_str != NULL) {
		matecomponent_pbclient_set_string (matecomponent_frame->priv->property_bag,
					    PROPERTY_BACKGROUND,
					    bg_str, NULL);

		g_free (bg_str);
	}
}

static void
mate_panel_applet_frame_matecomponent_applet_broken (MateCORBAConnection  *cnx,
					 MatePanelAppletFrame *frame)
{
	_mate_panel_applet_frame_applet_broken (frame);
}

static void
popup_handle_remove (MateComponentUIComponent *uic,
		     MatePanelAppletFrame  *frame,
		     const gchar       *verbname)
{
	_mate_panel_applet_frame_applet_remove (frame);
}

static void
popup_handle_move (MateComponentUIComponent *uic,
		   MatePanelAppletFrame  *frame,
		   const gchar       *verbname)
{
	_mate_panel_applet_frame_applet_move (frame);
}

static void
listener_popup_handle_lock (MateComponentUIComponent            *uic,
			    const char                   *path,
			    MateComponent_UIComponent_EventType  type,
			    const char                   *state,
			    gpointer                      data)
{
	MatePanelAppletFrame *frame;
	gboolean          locked;

	g_assert (!strcmp (path, "LockAppletToPanel"));

	if (type != MateComponent_UIComponent_STATE_CHANGED)
		return;

	if (!state)
		return;

	frame = (MatePanelAppletFrame *) data;
	locked = (strcmp (state, "1") == 0);

	_mate_panel_applet_frame_applet_lock (frame, locked);

	mate_panel_applet_frame_sync_menu_state (frame);
}

static MateComponentUIVerb popup_verbs [] = {
        MATECOMPONENT_UI_UNSAFE_VERB ("RemoveAppletFromPanel", popup_handle_remove),
        MATECOMPONENT_UI_UNSAFE_VERB ("MoveApplet",            popup_handle_move),

        MATECOMPONENT_UI_VERB_END
};


static void
mate_panel_applet_frame_matecomponent_finalize (GObject *object)
{
	MatePanelAppletFrameMateComponent *frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (object);

	if (frame->priv->control) {
		/* do this before unref'ing every matecomponent stuff since it looks
		 * like we can receive some events when unref'ing them */
		MateCORBA_small_unlisten_for_broken (frame->priv->control,
						 G_CALLBACK (mate_panel_applet_frame_matecomponent_applet_broken));
		matecomponent_object_release_unref (frame->priv->control, NULL);
		frame->priv->control = CORBA_OBJECT_NIL;
	}

	if (frame->priv->property_bag)
		matecomponent_object_release_unref (
			frame->priv->property_bag, NULL);

	if (frame->priv->applet_shell)
		matecomponent_object_release_unref (
			frame->priv->applet_shell, NULL);

	if (frame->priv->ui_component)
		matecomponent_object_unref (
			MATECOMPONENT_OBJECT (frame->priv->ui_component));

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

static void
mate_panel_applet_frame_matecomponent_init (MatePanelAppletFrameMateComponent *frame)
{
	GtkWidget *container;

	frame->priv = G_TYPE_INSTANCE_GET_PRIVATE (frame,
						   PANEL_TYPE_APPLET_FRAME_MATECOMPONENT,
						   MatePanelAppletFrameMateComponentPrivate);

	frame->priv->applet_shell = CORBA_OBJECT_NIL;
	frame->priv->control      = CORBA_OBJECT_NIL;
	frame->priv->property_bag = CORBA_OBJECT_NIL;
	frame->priv->ui_component = NULL;
}

static void
mate_panel_applet_frame_matecomponent_class_init (MatePanelAppletFrameMateComponentClass *class)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS (class);
	MatePanelAppletFrameClass *frame_class = MATE_PANEL_APPLET_FRAME_CLASS (class);

	gobject_class->finalize = mate_panel_applet_frame_matecomponent_finalize;

	frame_class->init_properties = mate_panel_applet_frame_matecomponent_init_properties;
	frame_class->sync_menu_state = mate_panel_applet_frame_matecomponent_sync_menu_state;
	frame_class->popup_menu = mate_panel_applet_frame_matecomponent_popup_menu;
	frame_class->change_orientation = mate_panel_applet_frame_matecomponent_change_orientation;
	frame_class->change_size = mate_panel_applet_frame_matecomponent_change_size;
	frame_class->change_background = mate_panel_applet_frame_matecomponent_change_background;

	g_type_class_add_private (class, sizeof (MatePanelAppletFrameMateComponentPrivate));
}

static MATE_Vertigo_MatePanelAppletShell
mate_panel_applet_frame_get_applet_shell (MateComponent_Control control)
{
	CORBA_Environment              env;
	MATE_Vertigo_MatePanelAppletShell retval;

	CORBA_exception_init (&env);

	retval = MateComponent_Unknown_queryInterface (control,
						"IDL:MATE/Vertigo/MatePanelAppletShell:1.0",
						&env);
	if (MATECOMPONENT_EX (&env)) {
		g_warning ("Unable to obtain AppletShell interface from control\n");

		retval = CORBA_OBJECT_NIL;
	}

	CORBA_exception_free (&env);

	return retval;
}

static const char* mate_panel_applet_frame_get_orient_string(MatePanelAppletFrame* frame, MatePanelAppletFrameActivating* frame_act)
{
	PanelOrientation orientation;
	const char* retval = NULL;

	orientation = mate_panel_applet_frame_activating_get_orientation(frame_act);

	switch (orientation)
	{
		case PANEL_ORIENTATION_TOP:
			retval = "down";
			break;
		case PANEL_ORIENTATION_BOTTOM:
			retval = "up";
			break;
		case PANEL_ORIENTATION_LEFT:
			retval = "right";
			break;
		case PANEL_ORIENTATION_RIGHT:
			retval = "left";
			break;
		default:
			g_assert_not_reached();
			break;
	}

	return retval;
}

static const char* mate_panel_applet_frame_get_size_string (MatePanelAppletFrame* frame, MatePanelAppletFrameActivating* frame_act)
{
	const char* retval = NULL;
	guint32 size;

	size = mate_panel_applet_frame_activating_get_size(frame_act);

	if (size <= PANEL_SIZE_XX_SMALL)
	{
		retval = "xx-small";
	}
	else if (size <= PANEL_SIZE_X_SMALL)
	{
		retval = "x-small";
	}
	else if (size <= PANEL_SIZE_SMALL)
	{
		retval = "small";
	}
	else if (size <= PANEL_SIZE_MEDIUM)
	{
		retval = "medium";
	}
	else if (size <= PANEL_SIZE_LARGE)
	{
		retval = "large";
	}
	else if (size <= PANEL_SIZE_X_LARGE)
	{
		retval = "x-large";
	}
	else
	{
		retval = "xx-large";
	}

	return retval;
}

static char *
mate_panel_applet_frame_construct_item (MatePanelAppletFrame           *frame,
				   MatePanelAppletFrameActivating *frame_act)
{
	char *retval;
	char *conf_path = NULL;
	char *bg_str = NULL;
	gboolean locked_down;

	conf_path = mate_panel_applet_frame_activating_get_conf_path (frame_act);
	//FIXME vuntz
#if 0
	bg_str = _mate_panel_applet_frame_get_background_string (
				frame, panel, panel->background.type);
#endif

	if (bg_str == NULL)
		bg_str = g_strdup ("");

	locked_down = mate_panel_applet_frame_activating_get_locked_down (frame_act);

	retval = g_strdup_printf (
			"prefs_key=%s;"
			"background=%s;orient=%s;size=%s;locked_down=%s",
			conf_path, bg_str,
			mate_panel_applet_frame_get_orient_string (frame, frame_act),
			mate_panel_applet_frame_get_size_string (frame, frame_act),
			locked_down ? "true" : "false");

	g_free (conf_path);
	g_free (bg_str);

	return retval;
}

static void
mate_panel_applet_frame_event_listener (MateComponentListener    *listener,
				   const char        *event,
				   const CORBA_any   *any,
				   CORBA_Environment *ev,
				   MatePanelAppletFrame  *frame)
{
	if (!strcmp (event, "MateComponent/Property:change:" PROPERTY_FLAGS))
		mate_panel_applet_frame_matecomponent_update_flags (frame, any);

	else if (!strcmp (event, "MateComponent/Property:change:" PROPERTY_SIZE_HINTS))
		mate_panel_applet_frame_matecomponent_update_size_hints (frame, any);
}

static void
mate_panel_applet_frame_matecomponent_activated (CORBA_Object  object,
				     const char   *error_reason,
				     gpointer      data)
{
	MatePanelAppletFrameActivating *frame_act;
	MatePanelAppletFrameMateComponent *matecomponent_frame;
	MatePanelAppletFrame   *frame;
	GtkWidget          *widget;
	MateComponentControlFrame *control_frame;
	MateComponent_Control      control;
	MateComponent_ItemContainer container;
	CORBA_Environment   corba_ev;
	AppletInfo         *info;
	char               *error;
	char               *item_name;
	GError             *gerror = NULL;

	widget = NULL;
	matecomponent_frame = MATE_PANEL_APPLET_FRAME_MATECOMPONENT (data);
	frame = MATE_PANEL_APPLET_FRAME (data);
	frame_act = g_object_get_data (G_OBJECT (frame), "mate-panel-applet-frame-activating");
	g_object_set_data (G_OBJECT (frame), "mate-panel-applet-frame-activating", NULL);

	/* according to the source of matecomponent control == NULL && no
	   exception can happen, so handle it */
	if (error_reason != NULL || object == CORBA_OBJECT_NIL) {
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, error_reason);
		goto error_out;
	}

	CORBA_exception_init (&corba_ev);

	item_name = mate_panel_applet_frame_construct_item (frame,
						       frame_act);

	matecomponent_frame->priv->control = CORBA_OBJECT_NIL;
	container = MateComponent_Unknown_queryInterface (object,
						   "IDL:MateComponent/ItemContainer:1.0",
						   &corba_ev);
	if (!MATECOMPONENT_EX (&corba_ev) && container != CORBA_OBJECT_NIL) {
		MateComponent_Unknown containee;

		containee = MateComponent_ItemContainer_getObjectByName (container,
								  item_name,
								  TRUE,
								  &corba_ev);
		matecomponent_object_release_unref (container, NULL);

		if (!MATECOMPONENT_EX (&corba_ev) && containee != CORBA_OBJECT_NIL) {
			matecomponent_frame->priv->control =
				MateComponent_Unknown_queryInterface (containee,
							       "IDL:MateComponent/Control:1.0",
							       &corba_ev);

			matecomponent_object_release_unref (containee, NULL);
		}
	}
	g_free (item_name);

	if (matecomponent_frame->priv->control == CORBA_OBJECT_NIL) {
		error = matecomponent_exception_get_text (&corba_ev);
		gerror = g_error_new (mate_panel_applet_frame_matecomponent_error_quark (), 0, "failed to get MateComponent/Control interface:\n", error);
		CORBA_exception_free (&corba_ev);
		matecomponent_object_release_unref (object, NULL);
		g_free (error);
		goto error_out;
	}

	widget = matecomponent_widget_new_control_from_objref (matecomponent_frame->priv->control,
							CORBA_OBJECT_NIL);

	CORBA_exception_free (&corba_ev);
	matecomponent_object_release_unref (object, NULL);

	if (!widget) {
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, "no widget created");
		goto error_out;
	}

	control_frame = matecomponent_widget_get_control_frame (MATECOMPONENT_WIDGET (widget));
	if (control_frame == NULL) {
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, "cannot get control frame");
		goto error_out;
	}

	matecomponent_frame->priv->property_bag =
		matecomponent_control_frame_get_control_property_bag (control_frame,
							       &corba_ev);
	if (matecomponent_frame->priv->property_bag == NULL || MATECOMPONENT_EX (&corba_ev)) {
		error = matecomponent_exception_get_text (&corba_ev);
		CORBA_exception_free (&corba_ev);
		gerror = g_error_new (mate_panel_applet_frame_matecomponent_error_quark (), 0, "cannot get property bag frame:\n%s", error);
		g_free (error);
		goto error_out;
	}

	matecomponent_event_source_client_add_listener (matecomponent_frame->priv->property_bag,
						 (MateComponentListenerCallbackFn) mate_panel_applet_frame_event_listener,
						 "MateComponent/Property:change:mate-panel-applet",
						 NULL,
						 frame);

	matecomponent_frame->priv->ui_component =
		matecomponent_control_frame_get_popup_component (control_frame,
							  &corba_ev);
	if (matecomponent_frame->priv->ui_component == NULL || MATECOMPONENT_EX (&corba_ev)) {
		error = matecomponent_exception_get_text (&corba_ev);
		CORBA_exception_free (&corba_ev);
		gerror = g_error_new (mate_panel_applet_frame_matecomponent_error_quark (), 0, "cannot get popup component:\n%s", error);
		g_free (error);
		goto error_out;
	}

	matecomponent_ui_util_set_ui (matecomponent_frame->priv->ui_component, DATADIR,
			       "MATE_Panel_Popup.xml", "panel", NULL);

	matecomponent_ui_component_add_listener (matecomponent_frame->priv->ui_component,
					  "LockAppletToPanel",
					  listener_popup_handle_lock,
					  frame);

	matecomponent_ui_component_add_verb_list_with_data (
		matecomponent_frame->priv->ui_component, popup_verbs, frame);

	control = matecomponent_control_frame_get_control (control_frame);
	if (!control) {
		CORBA_exception_free (&corba_ev);
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, "cannot get control");
		goto error_out;
	}

	matecomponent_frame->priv->applet_shell = mate_panel_applet_frame_get_applet_shell (control);
	if (matecomponent_frame->priv->applet_shell == CORBA_OBJECT_NIL) {
		CORBA_exception_free (&corba_ev);
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, "cannot get applet shell");
		goto error_out;
	}

	CORBA_exception_free (&corba_ev);

	MateCORBA_small_listen_for_broken (object,
				       G_CALLBACK (mate_panel_applet_frame_matecomponent_applet_broken),
				       frame);

	gtk_container_add (GTK_CONTAINER (frame), widget);

	goto out;

error_out:
	if (widget)
		g_object_unref (widget);
	if (!gerror)
		gerror = g_error_new_literal (mate_panel_applet_frame_matecomponent_error_quark (), 0, "unknown error");

out:
	_mate_panel_applet_frame_activated (frame, frame_act, gerror);
}

gboolean
mate_panel_applet_frame_matecomponent_load (const gchar                 *iid,
			        MatePanelAppletFrameActivating  *frame_act)
{
	MatePanelAppletFrameMateComponent *matecomponent_frame;
	MatePanelAppletFrame       *frame;
	CORBA_Environment       ev;

	g_return_val_if_fail (iid != NULL, FALSE);
	g_return_val_if_fail (frame_act != NULL, FALSE);

	if (!mate_panel_applets_manager_factory_activate (iid))
		return FALSE;

	matecomponent_frame = g_object_new (PANEL_TYPE_APPLET_FRAME_MATECOMPONENT, NULL);
	frame = MATE_PANEL_APPLET_FRAME (matecomponent_frame);
	_mate_panel_applet_frame_set_iid (frame, iid);

	g_object_set_data (G_OBJECT (frame), "mate-panel-applet-frame-activating", frame_act);

	CORBA_exception_init (&ev);

	matecomponent_activation_activate_from_id_async ((gchar *) iid, 0,
						  (MateComponentActivationCallback) mate_panel_applet_frame_matecomponent_activated,
						  frame, &ev);

	CORBA_exception_free (&ev);

	return TRUE;
}