上一页 下一页

Bonobo

Bonobo简介

Bonobo是一个组件系统,它是GNOME实现可重用软件组件的基石。组件是指这样一种软件,它们提供了定义完善的接口,被设计来与其它的组件协同工作。在Bonobo体系中,CORBA是将组件们联系在一起的通信层。使用CORBA做底层的另外好处是,组件及使用组件的软件可以用任何语言编写而不影响它们的交互。 Bonobo的诞生主要出于一下三个方面的原因:

Bonobo实现了一下功能:

Bonobo的目的是为Unix平台提供一套组件编写和符合文档的标准环境。GNOME只是其中的一个实现。与GTK+下对象命名习惯(如“GtkWindow”)不同,Bonobo对象使用CORBA repository ID的方式命名。如实现了Bonobo GNOME:ClientSite接口的对象可能的一个名字是“IDL:GNOME/ClientSite:1.0”。

Bonobo的组件分两大类:container和containee(又称为embeddable或components)。为了使得二者可以交互,Bonobo为它们定义了完备的接口IDL描述。从而实现实现Bonobo组件的核心就是是实现container/containee的标准接口。(其实container不一定是个component,但为简单起见,我们也这样称呼它。)

一个包容器必须实现接口:GNOME::ClientSite 和 GNOME::ViewFrame。如果要支持原地激活还要实现GNOME::UIHandler接口。一个组件则至少要实现接口:GNOME::Embeddable 和 GNOME::View接口。

其工作流程如下:

一个组件Embeddable只有一个ClientSite,每个显示View都需要一个ViewFrame。

Container和Containee的关系如下图:

图1:Container和Containee的关系

所有的Bonobo接口都是从GNOME::Unknown集成出来的。

module GNOME {
	interface Unknown {
		void ref ();

		void unref ();
		
		Object query_interface (in string repoid);
	};
};

好在GNOME已经替我们实现了这个接口,即GnomeObject:

typedef struct {
	POA_GNOME_Unknown servant_placeholder;
	gpointer gnome_object;
} GnomeObjectServant;

typedef struct _GnomeObjectPrivate GnomeObjectPrivate;

typedef struct {
	GtkObject base;

	CORBA_Object          corba_objref;
	gpointer              servant;
	GnomeObjectPrivate   *priv;
} GnomeObject;

typedef struct {
	GtkObjectClass parent_class;

	/*
	 * signals.  
	 */
	void  (*query_interface) (GnomeObject *object, 
                                  const char *repo_id, 
                                  CORBA_Object *retval);
	void  (*system_exception)(GnomeObject *object, 
                                  CORBA_Object cobject, 
                                  CORBA_Environment *ev);
	void  (*object_gone)     (GnomeObject *object, 
                                  CORBA_Object cobject, 
                                  CORBA_Environment *ev);
} GnomeObjectClass;

typedef struct {
	int   ref_count;
	GList *objs;
} GnomeAggregateObject;

struct _GnomeObjectPrivate {
	GnomeAggregateObject *ao;
	int destroy_id;
};

void
gnome_object_ref (GnomeObject *object)
{
	g_return_if_fail (object != NULL);
	g_return_if_fail (GNOME_IS_OBJECT (object));
	g_return_if_fail (object->priv->ao->ref_count != 0);

	object->priv->ao->ref_count++;
}

void
gnome_object_unref (GnomeObject *object)
{
	g_return_if_fail (object != NULL);
	g_return_if_fail (GNOME_IS_OBJECT (object));
	g_return_if_fail (object->priv->ao->ref_count > 0);

	object->priv->ao->ref_count--;

	if (object->priv->ao->ref_count == 0){
		GnomeAggregateObject *ao = object->priv->ao;
		GList *l;
		
		for (l = ao->objs; l; l = l->next){
			GnomeObject *o = l->data;
			
			gtk_signal_disconnect (GTK_OBJECT (o), o->priv->destroy_id);
			gtk_object_destroy (l->data);
		}

		g_list_free (ao->objs);
		g_free (ao);
	}
}

static void
impl_GNOME_Unknown_ref (PortableServer_Servant servant, CORBA_Environment *ev)
{
	GnomeObject *object;

	object = gnome_object_from_servant (servant);          
        /* baaad !! we MUST call gnome_object_ref() */
	object->priv->ao->ref_count++;
}

static void
impl_GNOME_Unknown_unref (PortableServer_Servant servant, CORBA_Environment *ev)
{
	GnomeObject *object;

	object = gnome_object_from_servant (servant);

	gnome_object_unref (object);
}
 

所有Bonobo的接口都从GNOME::Unkown继承。类似地,GNOME替我们缺省实现了所有要求的接口,它们都是从GnomeObject继承。而我们甚至不需要懂CORBA和Bonobo就可以编写GNOME的组件程序。

上一页 下一页