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接口。

其工作流程如下:

  • 用户选择了菜单中如“insert...”项,打算运行一个组件;
  • 包容器Container通过GOAD找到希望的组件Component;
  • 组件工厂被启动(如果尚未启动的话),生成一个组件的实例Embeddable;
  • 包容器把这个组件加到自己内部的组件列表中,同时生成一个客户区ClientSite;
  • 在ClientSite和Embeddable之间建立联系;
  • 此时并没有显示出来,如果要显示出来,首先要得到一个ClientSite;
  • 为这个ClientSite生成一个视图区ViewFrame用以画组件的视图;
  • ViewFrame有两个GTK控件wrapper和socket专门用来显示组件的视图;
  • 将视图区放到包容器中并显示;
  • 为Embeddable生成一个视图View;
  • ViewFrame给这个视图View一个窗口,这时组件的视图就显示出来了;
  • 通过鼠标器双击视图,包容器要求组件激活自己(进入编辑模式);
  • 组件告诉包容器自己已经激活,如果不是原地激活,包容器需要将文档中相关的区域变灰;
  • 组件可以请求改变外观大小;
  • 组件可以请求与包容器的菜单合并;
  • 编辑完毕时,符合文档的内容被更新;
  • 符合文档的内容可以被保存或打印。

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

Container和Containee的关系如下图:

Bonobo简介_第1张图片

图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的组件程序。

你可能感兴趣的:(Bonobo简介)