前へ 次へ 目次 文書セット ホーム


第 8 章

 

構造化コード生成および再使用可能な定義


はじめに

この章では、Sun WorkShop Visual の構造化コード生成機能を使用して、再使用可能なウィジェット階層を作成する方法を説明します。この機 能は、再使用可能なウィジェット階層を作成する上で、非常に便利です。これらの再使用可能階層は定義と 呼ばれ、ウィジェットパレット上に存在します。また、他のウィジェットと同様、階層に追加することもで きます。定義の詳細についても、本章で記述します。

構造化コード生成

Sun WorkShop Visual は、ユーザーの生成コードを構造化し、柔軟性を高め、簡単に再使用ができるようにする制御機能を備えて います。この項を読む前に、「基本モジュールの分析」 で説明されているデフォルト生成コードの構造を再度読み返し、理解しておくことをお勧めします。特にデ フォルトのコードでは、デザイン中の各シェルごとに別々の作成関数があることに注意してください。ウィ ジェットに名前が付けられていない場合、そのウィジェットは局所的に宣言されます。また、名前が付けら れている、あるいはウィジェットがアプリケーションシェルである場合は大域的に宣言されます。

構造化コード制御を使用すると、以下のことが実行できます。

コードを構造化するための Sun WorkShop Visual の制御機能は、コアリソースパネルの「コード生成」のページにあります。

関数構造体

構造化コード生成の最も簡単な例は、ウィジェットを関数構造体として指定するも のです。これにより、Sun WorkShop Visual はウィジェットとその子孫を作成する独立した関数を生成します。この関数は、格納ウィジェットの作成関 数によって呼び出されます。

ウィジェットを関数構造体として指定するには、コアリソースパネルの「コード生 成」ページを選択し、「構造」オプションメニューから「関数」を選択します。

 

    図 8-1 構造の例

図 8-1 に示されている階層は、わかりやすくするために多少単純化されていますが、次のコードを生成します。 1

Widget shell = (widget) NULL;
Widget form = (Widget) NULL;
Widget button_box = (Widget) NULL;
Widget b1 = (Widget) NULL;

/* これは button_box の作成関数です */

Widget create_button_box (Widget parent)
{
	Widget children[1];       /* マネージする子 */
	Arg al [64];                  /* 引数リスト */
	register int ac = 0;        /* 引数の個数 */
	Widget button_box = (Widget) NULL;
 
	button_box = XmCreateRowColumn ( parent,
		"button_box", al, ac );
	b1 =  XmCreatePushButton ( button_box, "b1", al, ac);
	children[ac++] = b1;
	XtManageChildren(children, ac);

/* ボタンボックスが作成され、マネージされずに返されます */

	return button_box;
}

/* シェルの作成関数がボタンボックス作成関数を呼び出します */

void create_shell (Widget parent)
{
	Widget children[1];       /* マネージする子 */
	Arg al[64];                  /* 引数リスト */
	register int ac = 0;       /* 引数の個数 */
 
	XtSetArg (al[ac], XmNallowShellResize, TRUE); ac++;
	shell = XmCreateDialogShell ( parent, "shell", al, ac );
	ac = 0;
	XtSetArg (al[ac], XmNautoUnmanage, FALSE); ac++;
	form = XmCreateForm ( shell, "form", al, ac );
	ac = 0;
	button_box = create_button_box ( form );

/* ボタンボックスのコンストレイント・リソースが親の作成関数内に設定されます */

	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
	XtSetValues ( button_box,al, ac );

/* ボタンボックスは、この時点でマネージされます */

	children[ac++] = button_box;
	XtManageChildren(children, ac);
}

ここで、モジュールは、階層全体を作成するための create_Shell() 、およびボタンボックスを作成するための create_button_box() という 2 個の関数を持っていることになります。

データ構造体

次のタイプのコード構造は、データ構造体です。これは、Sun WorkShop Visual がウィジェットとその子孫に対して独立した作成関数を生成する点で、関数構造体に似ています。ウィジェ ットがデータ構造体として指定された場合、Sun WorkShop Visual はウィジェットおよびその子孫を含む構造体に対して typedef を生成します。ウィジェットの作成によって、その型の構造体が作成、設定され、その構造体へのポインタ が返されます。削除関数 ( delete_ <ウィジェット名>) も生成されるため、割り当てられたメモリーを解放することができます。

ウィジェットをデータ構造体として指定するには、コアリソースパネルから「コー ド生成」ページを選択し、「構造」オプションメニューから「データ構造体」を選択します。

前に示した階層使用 (ただし、 button_box をデータ構造体として指定) すると、以下のコードが生成されます。

/* 最初に、データ構造体に対しての型宣言が生成されます */ 2

typedef struct button_box_s {
	Widget button_box;
	Widget b1;
} button_box_t, *button_box_p;
Widget shell = (Widget) NULL;
Widget form = (Widget) NULL;
button_box_p button_box = (button_box_p) 
NULL;

/* 作成関数によって button_box 構造体へのポインタが返されます */

button_box_p create_button_box (Widget parent)
{
	Widget children[1];       /* マネージする子 */
	button_box_p button_box = (button_box_p)NULL;

/* 構造体にスペースが割り当てられ、フィールドが埋められます */

	button_box = (button_box_p) XtMalloc ( sizeof ( 
		button_box_t ) );
	button_box->button_box = XmCreateRowColumn ( parent, 
		"button_box", al, ac );
	button_box->b1 = XmCreatePushButton 
		( button_box->button_box, "b1", al, ac );
	children[ac++] = button_box->b1;
	XtManageChildren(children, ac);
	return button_box;
}

/* 割り当てられたメモリーを解放するための削除関数が提供されます */

void delete_button_box (button_box_p button_box)
{
	if ( ! button_box )
		return;
	XtFree ( ( char * )button_box );
}

/* 再度シェル作成関数がボタンボックス作成関数を呼び出します */

void create_shell (Widget parent)
{
	Widget children[1]; /* マネージする子 */
	Arg al[64]; /* 引数リスト */
	register int ac = 0; /* 引数の個数 */
	shell = XmCreateDialogShell ( parent, "shell", al, ac );
	form = XmCreateForm ( shell, "form", al, ac );
	button_box = create_button_box ( form );
	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); 
	ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM);
	ac++;

/* button_box ウィジェットは、構造体内部で参照されます */

	XtSetValues ( button_box->button_box,al, ac );
	ac = 0;
	children[ac++] = button_box->button_box;
	XtManageChildren(children, ac);
	ac = 0;
}

C++ クラス

C++ クラスの使用方法は、データ構造体の場合と非常によく似ています。
Sun WorkShop Visual は階層内の個々のウィジェットを C++ のクラスを使用して隠ぺいすることはしませんが、そのかわり階層の一部分を独自のクラスとして指定しま す。C++ のクラスとして指定されたウィジェットには対応したクラスが定義されます。そのウィジェットの名前の付 いた子孫ウィジェットは、クラスのメンバーとなり、ウィジェット作成およびウィジェット破壊のメソッド が供給されます。また、クラスにそれ自体がクラス (のポインタ) であるメンバーが含まれる場合には、これらのメンバーを作成および破壊するためのコンストラクタ、およ びデストラクタ・メソッドが生成されます。ウィジェットはクラスのインスタンス作成時に作成されるので はなく、ウィジェット作成関数が明示的に呼び出された場合に作成されることに注意してください。したが って、クラスのインスタンスを破壊することによって、ウィジェットが破壊されることはありません。

ウィジェットを C++ クラスとして指定するには、コアリソースパネルの「コード生成」ページを選択し、「構造」オプションメ ニューから「C++/Java クラス」を選択します。ウィジェットを C++ クラスとして指定し、C を生成する場合には、ウィジェットはデータ構造体として扱われるので、注意してください。

この節では C++ クラスについて説明します。Sun WorkShop Visual の Java クラスについての詳細は、第 10 章「Java 用のデザイン」を参照してください。

 

    図 8-2 C++ クラス構造の例

この例で生成されるコードを以下に示します。わかりやすくするために、簡略化し てあります。3

button_box および shell に対してクラスが宣言されます。

class button_box_c: public xd_XmRowColumn_c {
public:
	virtual void create (Widget parent, char *widget_name =
		NULL);
protected:
	Widget button_box;
	Widget b1;
	Widget b2;
};
 
typedef button_box_c *button_box_p;

shell クラスはコンストラクタとデスクトラクタ関数を持ちます。これは、クラス (またはデータ構造体) ヘのポインタであるメンバーを持っているためです。

class shell_c: public xd_XmDialog_c {
public:
	virtual void create (Widget parent, char *widget_name = NULL);
	shell_c();
	virtual ~shell_c();
protected:
	Widget shell;
	Widget form;
	Widget text;
	button_box_p button_box;
};
 
typedef shell_c *shell_p;
 
shell_p shell = (shell_p) NULL;

この時点で、作成関数はクラスのメソッドとなります。このメソッドは、本リリー スで提供される Sun WorkShop Visual の基底クラスにおいて公開宣言されます。

void button_box_c::create (Widget parent, char 
*widget_name)
{
	Widget children[2];      /* マネージする子 */
	Arg al[64];                  /* 引数リスト */
	register int ac = 0;       /* 引数の個数 */
 
	if ( !widget_name )
		widget_name = "button_box";
 
	button_box = XmCreateRowColumn ( parent, widget_name, 
		al, ac );

_xd_rootwidget は部分階層のルートにあるウィジェットを保存するクラスの限定公開メンバーです。これにより、基底クラ スはウィジェットを操作することができます。

	_xd_rootwidget = button_box;
	b1 = XmCreatePushButton ( button_box, "b1", al, ac );
	b2 = XmCreatePushButton ( button_box, "b2", al, ac );
	children[ac++] = b1;
	children[ac++] = b2;
	XtManageChildren(children, ac);
	ac = 0;
}

シェルの作成メソッドは、ボタンボックスの作成メソッドを呼び出します。

void shell_c::create (Widget parent, char 
*widget_name)
{
	Widget children[2];      /* マネージする子 */
	Arg al[64];                  /* 引数リスト */
	register int ac = 0;       /* 引数の個数 */
 
	if ( !widget_name )
		widget_name = "shell";
	XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
	shell = XmCreateDialogShell ( parent, widget_name, al, 
		ac );
	ac = 0;
	_xd_rootwidget = shell;
	XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
	form = XmCreateForm ( shell, "form", al, ac );
	ac = 0;
	text = XmCreateText ( form, "text", al, ac );

ボタンボックスクラスは、コンストラクタ・メソッドでインスタンス生成されるた め、この時点ではウィジェットのみが作成される必要があります。

	button_box->create ( form, "button_box" );
 
	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); 
	ac++;
	XtSetArg(al[ac], XmNtopWidget,
		button_box->xd_rootwidget( )); ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); 
	ac++;
	XtSetValues ( text,al, ac );
	ac = 0;
 
	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); 
	ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); 
	ac++;
	XtSetValues ( button_box->xd_rootwidget(),al, ac );
	ac = 0;
	children[ac++] = text;
	children[ac++] = button_box->xd_rootwidget();
	XtManageChildren(children, ac);
	ac = 0;
}
shell_c::shell_c()
{

子クラスのインスタンスを生成します。

	button_box = new button_box_c;
}
shell_c::~shell_c()
{

子クラスを解放します。

	delete button_box;
}

ウィジェットが C++ クラスに指定され、C コードが生成される場合、ウィジェットはデータ構造体と同様に扱われます。

デフォルトでは、生成クラスは Sun WorkShop Visual の基底クラスの 1 つから派生しますが、「C++ アクセス」オプションメニューの下のフィールドに基底クラスを指定して、変更することもできます。本リ リースで供給される Sun WorkShop Visual 基底クラスは、生成コードを正確に実行するための最小限のサポートを提供しています。これらのクラスを 変更および拡張すると、ご使用の GUI 開発手法に適した再使用可能なメソッドを作成することができます。

子孫ウィジェットは名前が付けられている場合、あるいはそれ自体がデータ構造で あったり C++ クラスである場合は、クラスの限定公開メンバーとして現れます。したがって、C++ クラスウィジェットそのもの、およびクラスメンバーとして呼び出す必要のある子孫に名前を付けることは 重要です。デフォルトのアクセス制御の変更は、「C++ アクセス」オプションメニューから必要なレベル (公開、限定公開、または非公開) を選択することにより実行できます。

C++ クラスウィジェットに対して、名前の付けられていないウィジェットを使用した場合でも、即座にエラーが 生じることはありません。しかし、Sun WorkShop Visual が名前の付けられていないウィジェットに対して自動的に割り当てる数は、階層の編集時に変更される可能 性があるため、名前の付けられていないウィジェットを使用することはお勧めできません。

コールバック・メソッド

コールバック関数を呼び出す X ツールキット関数は、以下の形式のコールバック関数をとります。

void my_callback (Widget, XtPointer, XtPointer)

通常のメンバー関数はコールバック関数には適していません。これは C++ コンパイラが、オブジェクトに対してインスタンスデータを検索する最初の引数 ( this ポインタ) を X メンバー関数に余分に渡してしまうためです。コールバック関数として通常のメンバー関数を使用すると、 メンバー関数はウィジェットポインタをインスタンスデータポインタとして解釈するため、意図したとおり には動作しません。

Sun WorkShop Visual は、この問題を回避するために一般によく使用される技術を使用しています。静的メンバー関数 ( this ポインタを予定していない) が宣言され、コールバック関数として使用されます。

static void my_callback (Widget, Xtpointer call_data, XtPointer client_data)

インスタンスへポインタを引き渡すためには、クライアントデータ (client_data) 引数が使用されます。静的メンバー関数は、単にインスタンスポインタを使用して通常の非静的メンバー関 数を呼び出し、そのウィジェットと引数 (call_data) を渡します。非静的メンバー関数は、以下の形式をとります。

virtual void my_callback (Widget, XtPointer call_data)

Sun WorkShop Visual は、両方の関数宣言、静的コールバック関数に対する全コード、およびユーザーの書いた標準メンバー関数 に対するスタブを生成します。この関数は仮想として宣言されているため、動作を変更するために派生クラ スにおいて書き換えることができます。この手法については、ダグラス A ヤング著、磯谷正孝訳の『オブジェクト指向プログラミングと C++: OSF/Motif 版』 (Douglas Young 『 Object-Oriented Programming with C++ and OSF/Motif 』) に詳しく記述されています。

コールバック・メソッドの編集

コールバック・メソッドを追加する場合は、まだそのメソッドが宣言されていなけ ればその宣言も追加されます。「コールバック」ダイアログ内の「メソッド」ボタンを押すと、現在選択し ているウィジェットを包含するクラスで宣言されているメソッドが表示されます。

Sun WorkShop Visual はデフォルトで、メソッドを純粋仮想ではなく、公開アクセスを持つものとして宣言します。これらの属性 を変更したい場合は、「メソッド宣言」ダイアログを使用して変更してください。詳細は、「メソッド宣言」を参照してください。

メソッド宣言

コールバックをメソッドとして追加する場合は、効率的に処理するために、Sun WorkShop Visual はメソッドの宣言をそのウィジェットの包含するクラスに追加します。包含するクラスであるウィジェット を選択し、「ウィジェット」メニューから「メソッド宣言」を選択することにより、メソッド宣言の表示、 追加および削除を行うことができます。メソッド宣言ダイアログを図 8-3 に示します。

 

    図 8-3 メソッド宣言ダイアログ

「構造の色」で説明するように「表示」メニューの「構造の色」を使用し、メソッドを追加し たウィジェットに最も近い上位クラスを選択します。このウィジェットが C++ クラスとして定義されている場合は、これは当然同じウィジェットとなります。

メソッドのアクセス制御

デフォルトでは、Sun WorkShop Visual の追加するメソッドのアクセスは「公開」です。「メソッド宣言」ダイアログにある「アクセス」オプショ ンメニューを使用すると、個々のコールバック・メソッドに対してのアクセスを、「公開」、「非公開」、 「限定公開」の中からを選択できます。

純粋仮想メソッド

「純粋仮想」トグルを設定して、非静的メンバー関数を純粋仮想関数として宣言す ることができます。たとえば、このトグルをメニューバークラスのコールバック・メソッド OnNew() に設定した場合、Sun WorkShop Visual はメソッドを以下のように宣言します。

class menubar_c:  public xd_XmMenubar_c {
...
public:
...
	virtual void OnNew( Widget, Xtpointer) = 0;
};

この関数は純粋仮想関数であるため、 menubar_c は抽象クラスとなり、
menubar_c::OnNew() の実装を行う必要はありません。 menubar_c のインスタンスを作成することはできませんが、他のクラスの基底クラスとして使用することが可能となり ます。

デフォルトでは、Sun WorkShop Visual の追加するメソッドは純粋仮想ではありません。

コールバック・メソッドの削除

コールバック・メソッドをウィジェットから削除するということは、単にそのメソ ッド (ウィジェットへのコール) の使用を止めるということを意味します。Sun WorkShop Visual でコールバック・メソッドを追加すると、メソッドの宣言が自動的に追加されます。メソッドの宣言も一緒 に削除したい場合は、包含するクラスであるウィジェットのメソッド宣言リストから宣言を削除する必要が あります。詳細な手順および Sun WorkShop Visual を使用して追加された宣言の詳細は、 「メソッド宣言」を参照してください。

構造体の変更とメソッドの無効化

上記のように、追加されたコールバック・メソッドは包含するクラスで宣言されま す。このウィジェット (包含するクラス) の構造体を変更した結果ウィジェットがクラスでなくなると、メソッドは無効になります。このような場合 、Sun WorkShop Visual は図 8-4 に示すような 「無効化されたメソッド」 ダイアログを表示します。

このダイアログはモード付きなので、デザインで作業を続けるにはダイアログを閉 じなければなりません。このダイアログが表示されるのは、メソッド宣言が無効になるようにウィジェット の構造体を変更したときだけです。

 

    図 8-4 「無効化されたメソッド」 ダイアログ

左側のウィジェットリストには、構造体を変更することでメソッドが無効化される すべてのウィジェットが表示されます。ウィジェットを選択すると、無効化されたメソッドが右側に表示さ れます。選択した各メソッドについて、現在宣言されているクラスと、メソッドを宣言できる新しいクラス がこのダイアログに表示されます。「提示されたクラス」 は常に最上位に最も近い上位クラスです。適当なクラスが他に存在しない場合は、このダイアログはメソッ ドが関数になることを警告します。

「宣言」 を押すと、選択したメソッドの宣言が 「提示されたクラス」 に変わります。「すべてを宣言」 を押すと、無効化された各メソッドがそれぞれの 「提示されたクラス」 に変わります。

メソッドプレリュード

「コードプレリュード」ダイアログを使用して、C++ クラスにデータや関数メンバーを追加することができます。「公開メソッド」、「限定公開メソッド」また は「非公開メソッド」を選択し、テキスト領域 (直接編集している場合はコード) に宣言を入力します。基本モジュールおよび外部宣言ファイルの両方のクラス宣言に C++ コードプレリュードが生成されます。

派生クラスの作成

クラスに関数を追加する場合、Sun WorkShop Visual によって生成されたクラスから派生した新しいクラスを書くことをお勧めします。派生クラスと生成された 基底クラス間の論理的な違いを使用して、メンバーを追加して仮想関数を実装することができます。

デフォルトでは、Sun WorkShop Visual はルートウィジェットの変数名をもとに C++ クラス名を決定します。したがって、ウィジェット menubar のクラスは menubar_c となります。

class menubar_c: public xd_XmMenuBar_c {
...
};

Sun WorkShop Visual はクラスのインスタンスを作成するコードを生成する場合に、同じ名前を使用します。

menubar = new menubar_c;

Sun WorkShop Visual がクラスをある名前で生成し、別の名前でインスタンスを作成するようにデフォルト動作を変更することが できます。

menubar = new mymenubar_c;

デフォルト動作の変更を行うには、コアリソースパネルの「コード生成」ページに ある「インスタンス名」を使用します。

基底クラスの変更

デフォルトでは、Sun WorkShop Visual はルートウィジェットの型に適した基底クラスから生成クラスを派生させます。たとえば、ウィジェット階 層のルートにメニューバーを持つクラスは、 xd_XmMenuBar_c から派生しています。基底クラスの名前は、コアリソースパネルで変更することができます。

Sun WorkShop Visual 製品には、基底クラスの実装例が含まれています。これらをそのまま、あるいは修正を加えて使用して、特 定のアプリケーションの分野に適した機能を追加することができます。

実装例の基底クラスを構築するためのメークファイルも含まれています。Sun WorkShop Visual は基底クラスについて以下の 2 点を仮定します。

    1. Widget 型のデータメンバー _xd_rootwidget が存在する

    2. 付属関数 xd_rootwidget( ) があり、値 _xd_rootwidget を取り出して返す

これらの仮定は、クラス xd_base_c 中で使用されています。このクラスには他のいくつかの基本的な制約も存在します。

class xd_base_c
{
public:
	xd_base_c() {_xd_rootwidget=NULL;}
	Widget xd_rootwidget() const {return _xd_rootwidget;}
protected:
	Widget _xd_rootwidget;
private:
	void operator=(xd_base_c&); // 代入なし
	xd_base_c(xd_base_c&);      // デフォルトのコピーなし
};

Sun WorkShop Visual は、使用される基底クラスについてその他の制約は行いません。つまり言い換えると、基底クラスのセット は、それらが xd-base_c (または別の基底クラスで Sun WorkShop Visual の仮定を満たすもの) から派生したものであれば使用可能です。

基底クラスのコンストラクタに対して、クラス名と一緒に実際の引数を渡すことも 可能です。引数が供給される場合 (基底クラス文字列が '()' を含んでいる場合)、そのクラスはコンストラクタを持つように強制され、引数文字列は基底クラスに渡さ れます。たとえば、ウィジェット menubar に対して「基底クラス」文字列を mymenubar_c ("Hello World") に設定すると、Sun WorkShop Visual は以下のように生成を行います。

class menubar_c : public mymenubar_c { 
public: 	
	menubar_c(); 	
	...     
};
...
menubar_c::menubar_c () : mymenubar ( "Hello World" ) 
{     
}
...
menubar = new menubar_c;

子のみを生成するウィジェット

子のみ生成構造体オプションを選択すると、あるウィジェット (子のみを生成するウィジェット) を別の構造体を保持するための構造体として指定することができます。 子のみを生成するウィジェットは、階層内のそれらの子孫に対してのコンテキストを提供しますが、子のみ を生成するウィジェット自身に対してのコードは生成しません。以下に示す例を考察してみましょう。

 

    図 8-5 子のみ生成構造体の使用例

図 8-5 に示すデザインからコードを生成する場合、Sun WorkShop Visual はメニュー構造に対してのみコードを作成します。この機能を使用すると、アプリケーションプログラムで 制御可能なデザインの一部分だけを生成することができます。

Microsoft Windows モードでの子のみ生成構造体

Microsoft Windows モードでは、シェルの子は C++ クラスにはできません。Microsoft Windows モードでシェルの子だけを C++ で生成するには、シェルの下に「ダミーの」コンテナウィジェット (ローカラムやフォーム) を追加して、そのコンテナウィジェット以下を C++ クラスにします。この方法は、Microsoft Windows モードで定義を作りたい場合にも役立ちます。これは、ウィジェットの集まりを定義するにはルートウィジ ェットが構造化されていなければならないからです。

構造化コード生成と UIL

何らかの構造を含むデザインに対して UIL を生成する場合の手順は、基本的には C および C++ の場合と同じです。独立した階層が UIL ファイルに生成され、それぞれの作成関数がコードファイルに生成されます。作成関数は UIL 階層から適切なウィジェットを取り出し、適切にデータ構造フィールドへの記入を行います。

宣言範囲の変更

ウィジェットは通常、何らかの方法で構造化されていない場合、あるいは名前が付 けられていない場合には、閉じた作成関数内で局所的に宣言されます。ウィジェットが構造化されているか 、名前が付けられている場合には、それらはそれが含まれる構造体 (存在する場合) 内で、あるいは大域的変数として宣言されます。このデフォルト動作は、コアリソースパネルにあるウィジ ェットの記憶クラスを設定することにより、変更できます。記憶クラスを「局所」に設定すると、本来は大 域的として宣言される、または構造体内で宣言されるはずのウィジェットが作成関数に対して局所的に宣言 されます。記憶クラスを「大域」に設定すると、名前の付いていないウィジェットまたは構造の中の名前の 付いた要素が大域的に宣言されます。「大域」設定は、ウィジェット型リソースおよび 「到達不能ウィジェット」で説明されているリンクに対して特に有効です。「静的」オプショ ンは「大域」に似ていますが、宣言はモジュールに対して静的です。

名前の付いていないウィジェットを強制的にデータ構造にすることはできません。 名前のないデータ構造ウィジェットの子は、データ構造の作成関数に対して局所的に作成され、管理されま す。

到達不能ウィジェット

ブリテンボード用の XmNdefaultButton のようなウィジェット型のリソースと一緒に、あるいはリンクと一緒に構造化コード生成を使用する場合、 範囲外のウィジェットを参照するデザインを指定してしまうことがあります。これらは、到達不能ウィジェ ットとみなされます。Sun WorkShop Visual は、このような事例の検出を行い、コード生成時に警告を発します。また、「子のみ生成」構造体を使用し た場合や階層を実行時に動的に作成した場合、到達不能ウィジェットが予想外の障害を発生させる可能性も あります。

 

    図 8-6 到達不能ウィジェットのある階層

図 8-6 に到達不能ウィジェットを示します。 b1 はフォームの作成関数からアクセス可能でデフォルトボタン引数として使用可能でなければなりません。し かし、 b1 button_box 関数に対して局所的であるため、フォームの作成関数のスコープには入っていません。Sun WorkShop Visual は、この状況を検出すると、以下の警告をコード生成時に表示します。

 

    図 8-7 到達不能ウィジェットエラー

コードは生成されますが、予想通りにはコンパイル、あるいは実行しない場合があ ります。この場合の最も簡単な解決方法は、記憶クラスオプションを使用して適切なウィジェットを強制的 に大域的と指定することです。

定義

ウィジェットの階層が構造 (C++ クラスまたは C 構造体) としてカプセル化された場合、それを定義に変化させることにより、他のデザインで再使用することができ ます。定義とは Sun WorkShop Visual のウィジェットパレットに追加して、再使用できるウィジェット階層です。パレットから定義を選択するこ とにより、デザインに定義のインスタンスが作成されます。このインスタンスをさらに修飾し、再び定義に することも可能です。

前提条件

ウィジェット階層は、以下の場合に定義となることができます。

    1. ルートウィジェットがデフォルトではない変数名を持っている

    2. ルートウィジェットが C++ クラスまたは構造体として指定されている

    3. ルートウィジェットが別の定義の一部ではない

    4. ウィジェット階層が定義を含んでいない

    5. ウィジェット階層が大域的または静的ウィジェットを含んでいない

定義の指定

定義を指定する場合、対象となるウィジェットを含むデザインファイルが保存され 、かつ、対象となるウィジェットに定義として印が付けられている必要があります。ウィジェットに定義と しての印をつけるためには、「ウィジェット」メニューにある「定義」を使用します。定義を作成すると、 その中のウィジェットは凍結され、ウィジェットのリソースパネルは使用不可能となるため、ウィジェット の追加やウィジェット名の変更を行うことはできません。一時的に定義の指定を解除して、定義を構成する ウィジェットを編集することはできます。ただし、定義を使用するデザインとの矛盾を避けるため、この操 作は慎重に行なってください。詳細は、「定義の変更」を参照してください。

他のデザインにおいて定義を使用可能にするためには、Sun WorkShop Visual はその定義に対しての外部参照を必要とします。これは、「定義を編集」ダイアログで編集できる「定義」 ファイルにより提供されます。

定義の短縮操作

パレットメニューにある「定義する」ボタンを使用すると、簡単に新しい定義を追 加することができます。このボタンは、現在選択されているウィジェットを定義として指定し、そのデザイ ンを保存してパレットに定義を追加します。定義に対してのヘッダーファイル名は、コード生成ダイアログ にある型宣言ファイル名から取り込まれます。アイコンは使用されません。

定義ファイル

Sun WorkShop Visual は、定義ファイルを読み出して、その内容をパレットに表示します。定義ファイル名は、 definisionFileName リソースの設定により指定されます。デフォルト値は $HOME/.xddefinitionsrc です。

複数のプロジェクトで作業を進める必要があり、それぞれのプロジェクトが異なる 定義のセットを使用する場合、リソースを設定して定義ファイルを変更することができます。以下に例を示 します。

visu.definitionsFileName:/home/project6/xddefs

このリソースの値は環境変数を含むことができます。以下に例を示します。

visu.definitionsFileName:$PROJECT_ROOT/xddefs

新しい設定に変更する場合は、Sun WorkShop Visual を終了して再起動します。

定義ファイルの編集

定義ファイルの変更は、「パレット」メニューにある「定義を編集」ボタンを使用 して行います。このボタンは、図 8-8 に示すダイアログを表示します。

 

    図 8-8 パレットへの定義の追加

このダイアログを使用して、新しい定義の追加、削除あるいは既存の定義を編集す ることができます。定義を追加する場合には、以下を入力します。

  • 定義
    定義名
  • ウィジェット名
    定義のルートウィジェットの変数名
  • 保存ファイル
    保存されているデザインファイルの名前 ( .xd )

また、以下の指定を行うことができます。

  • アイコンリソース
    定義に対してピックスマップ・ファイルを割り当てるために使用されるリソース名。詳細は、「アイコンファイルの指定」を参照してください。
  • アイコンファイル
    アイコンリソースを使用しても見つからない場合にウィジェットパレットとして使用される、ビットマップ または xpm ピックスマップを含んでいるファイル。
  • インクルードファイル
    対応する構造体またはクラスを宣言するヘッダーファイルの名前。定義のインスタンスが使用されると、こ のファイルが生成コードに自動的に インクルードされます。そのため、コンパイラがファイルを見つけることができるかどうかを確認する必要 があります。定義から生成された外部宣言ファイルと同じ名前を指定してください。
  • リソースファイル
    定義の値を含んでいるリソースファイルの名前。定義のインスタンスが使用されると、このファイルは生成 リソースファイルにインクルードされます。定義に対して外部ファイルが生成された場合に、指定された名 前に対応します。
  • ファミリ
    この定義が属するファミリ、すなわちグループ。これは、ウィジェットパレット上に定義を表示する場合に 限って関係があります。定義はまとめられてファミリとなります。ファミリは常に 1 つ表示されています。表示されるファミリを変更するには、ウィジェットパレットの定義の上にあるオプシ ョンメニューからファミリを選択します。デフォルトでは、定義は「Default」のファミリに割り当てられ ています。ファミリには、任意の名前を指定することができます。また、同じファミリにまとめる定義の数 には、制限はありません。
  • ヘルプ
    ユーザーにヘルプを提供するために使用されるドキュメントとマーカーの組み合わせ。「定義のオンラインヘルプ」を参照してください。
  • MFC オフセット
    このフィールドは、Sun WorkShop Visual が Microsoft Windows モードである場合にのみ表示されます。Microsoft Windows アプリケーションでは、個々のコントロールを識別するために固有の番号が指定されます。Sun WorkShop Visual は、コントロールごとに固有の番号を生成するため、通常は問題ありません。ただし、すでに多数のコント ロールを持っているインスタンスにウィジェットを追加する場合には、番号が重なってしまう場合もありま す。MFC オフセットは、インスタンスに追加されるコントロールの ID に加算されます。MFC オフセットの数を増やすことで、コントロールの ID と定義内にあるコントロールとの衝突を避けることができます。

作成時に設定されない属性は、後で設定することができます。たとえば、定義のテ ストおよびデバッグは、定義のアイコンをデザインする前に実行できます。

「仮設定」を使用して、現在選択されているウィジェットのダイアログ上にあるフ ィールドのいくつかを自動的に設定することができます。

ベースディレクトリ

定義が相対ファイル名 (/ で始まらない名前) で指定されている場合、Sun WorkShop Visual はファイル名の前にベースディレクトリを追加します。ベースディレクトリが指定されていない場合は、定 義デザインファイルを含んでいるディレクトリが使用されます。

ベースディレクトリを指定するには、「定義を編集」ダイアログを表示して「ベー スディレクトリ」をクリックし、新しいディレクトリを選択して「了解」をクリックします。すると、新し いベースディレクトリが定義ファイルに保存され、Sun WorkShop Visual の現在のセッションに即座に適用されます。現在のデザインが既存の定義のインスタンスを含んでいる場合 、ベースディレクトリを変更することはできません。

定義の変更

定義内にあるウィジェットは凍結されています。したがって、ウィジェットの追加 または削除、名前の変更、配置エディタでのコンストレイントの設定、リソースのリセットは、行うことが できません。定義を変更するためには、一時的に定義を解除する必要があります。定義を変更する必要があ る場合には、以下に示す手順に従って操作を実行してください。

    1. 定義を含んでいる保存ファイルを開きます。

    2. 定義のルートウィジェットを選択します。

    3. ウィジェットメニューをプルダウンし、「定義」トグルをオフにします。

    トグルをオフにすると、定義にあるウィジェットの凍結が解除されるため、必要に 応じた変更、修正を行うことができます。

    4. 編集が終了したら、ルートウィジェットを選択し、「定義」トグルを再度オンにします。

    5. コードファイルと外部宣言ファイルを再生成します。

    6. デザインを保存します。

定義の変更による影響

定義を変更すると、その定義を使用するすべてのデザインファイルに影響がありま す。定義を使用するデザインを開くたびに、Sun WorkShop Visual は定義を含むファイルを開き、これら両方のファイルからの情報を組み合わせます。定義が変更されると、 Sun WorkShop Visual は、変更前の定義を使用していたデザインが新しい定義を受け入れるように試みます。

受け入れられない変更がある場合には、Sun WorkShop Visual はエラーメッセージを表示し、デザインの不適合部分を一時的に Sun WorkShop Visual のクリップボード・ファイルに保存します。以下の方法のいずれかで、不適合を解決します。

  • クリップボード・ファイルをユーザーのデザインにペーストし、その内容と新しい 定義を手動で解決する
  • クリップボード・ファイルの内容をすべて破棄する
  • 変更を保存することなく Sun WorkShop Visual を終了する、あるいはデザインと互換性がある定義に戻す

不適合の確率を最小限にするには、次のことを守ってください。

  • 定義内のウィジェット名を変更しない
  • 定義内のウィジェットの置き換えは、同名のサブクラスウィジェットのみで行う
    たとえば、ラベル「foo」とプッシュボタン「foo」を置き換えても、通常は不適合は発生しません。

インスタンス

定義のインスタンスは、パレットの適切なボタンをクリックするだけで作成できま す。インスタンスはカラー背景で表示されます。

定義とインスタンスは、それぞれに個別のデザインとして作成されなければなりま せん。Sun WorkShop Visual 内では定義とインスタンスは同一のデザインの中に存在していますが、それぞれに対するコードが個別のコ ードでなければ、コンパイルは行われません。

定義ファミリ

定義はそのファミリごとに、ウィジェットパレット上でまとめられます。ウィジェ ットパレットで定義の上にあるオプションメニューを使用すると、現在表示されているファミリを変更する ことができます。定義のファミリを指定する方法の詳細は、「定義ファイルの編集」を参照してください。

インスタンスの変更と拡張

定義のインスタンス作成は、構造 (C 構造体または C++ クラス) のインスタンス作成に対応しています。変更が生成されるコードに反映される場合に限り、インスタンスを 作成した後で変更を行うことができます。たとえば、ウィジェットがアクセス可能である (例: C++ の場合、ウィジェットに名前があり、適切なアクセスモードを持っている) 場合にのみ、ウィジェットにリソースを設定したり、あるいはウィジェットに子を追加することが可能です 。ウィジェットの除去、あるいはその名前の変更を行うことはできません。ただし、ルートウィジェットは 例外です。インスタンスのルートウィジェットは常に (メンバー関数 xd_rootwidget() を介して) アクセス可能であるため、常に変更することができます。

    注 - アクセス権のないウィジェットは、配置エディタ上で移動およびコンストレイント の設定を行うことはできません。

派生構造の作成

定義から派生した新しい構造を作成すると役に立つ場合が多くあります。派生構造 を作成するには、コアリソースダイアログのコード生成ページにある「構造」オプションを設定します。派 生構造は、定義と同じ値にのみ設定することができます。つまり、C 構造体から C++ クラスを派生させることはできません。

定義のコールバック・メソッドの書き換え

インスタンス内の、定義から継承されたメソッドは書き換えることができます。そ の場合は、インスタンスは定義とは異なる動作を行います。

インスタンスを含むコードのコンパイル

定義のインスタンスを含むデザインから生成されたコードをコンパイルするには、 定義コードともリンクする必要があります。これを行うには次の 2 つの方法があります。

    1. 定義コードを含むライブラリとリンクする

    2. 定義コードとインスタンスコードをコンパイルする

各方法については以下で説明します。

ライブラリの使用

定義コードを含むライブラリをインスタンスコードとリンクさせるには、まず定義 のコードをライブラリにコンパイルします。通常、UNIX または C や C++ では、次の方法でコンパイルします。

make <definitioncode>.o
ar r <definitionlib>.a <definitioncode>.o

次に、以下が可能になるように、インスタンスを含むコードのメークファイルを編 集する必要があります。

    1. コンパイラが定義を含むヘッダーファイルを検出できる
    Sun WorkShop Visual は、このヘッダーファイルをインスタンスに対して生成されたコードに自動的に インクルードします。

    2. リンカーが定義コードを含むライブラリを検出できる
    ライブラリのフルパス名を 「EXTRALIBS」 に追加します。

定義とインスタンスのコンパイル

定義のインスタンスをコンパイルするもう 1 つの方法として、定義、定義のインスタンス、対応するメークファイルを同じディレクトリに生成する方法 があります。Sun WorkShop Visual では、定義とインスタンスの両方が同じアプリケーションにコンパイルされるようにメークファイルを構成 することができます。以下に、その手順を示します。

    1. インスタンスを含むデザインを開きます。

    2. 「メインプログラム」 を生成することを確認します。

    3. 「メークファイル・オプション」 ダイアログの 「新規メークファイル」 と 「メークファイル・テンプレート」 トグルをオンにします。

    4. 必要なすべてのファイルを生成します。

    5. 定義デザインを開きます。

    6. 「メインプログラム」 生成トグルをオフにします。

    7. 「メークファイル・オプション」 ダイアログの 「新規メークファイル」 トグルをオフにして、「メークファイル・テンプレート」 トグルはオンのままにしておきます。

    8. 「コードオプション」 ダイアログで、「リンク」 を「生成しない」 (リンク関数は生成済みなので、2 回目の生成ではエラーになる) に設定します。

    9. コード、外部宣言ファイル、メークファイル (必要であればリソースも) を生成します。

    10. コマンドプロンプトに 「 make 」 と入力します。

    以上で、インスタンスを含むアプリケーションが 1 つ完成します。

定義およびリソースファイル

定義の構成要素であるウィジェットに対するリソース値は、プログラム中に書き込 むか、またはリソースファイル内に指定することができます。

インスタンスと定義リソースファイル

定義に対してリソースファイルを指定すると、Sun WorkShop Visual は定義のインスタンスを持つデザインのリソースファイル内にそのファイルをインクルードします。リソー スファイルを読み出す Xlib メカニズムが、この指令を解釈して使用し、定義に対してのリソースファイルを検索します。

定義のオンラインヘルプ

定義についての情報を記録して、他の開発者にその内容を伝えるために、定義に対 してのオンラインヘルプをつけることができます。 <Tab> と矢印キーを使用して、定義のアイコンやボタンに移動し、 <osfHelp> (通常は <F1> ) を押すと、オンラインヘルプが Sun WorkShop Visual インターフェース内で呼び出されます。

ヘルプファイルは Sun WorkShop Visual ヘルプディレクトリのサブディレクトリに保存されています。

ヘルプディレクトリは helpDir リソースにより決定します。デフォルトでは、 $VISUROOT/lib/locale/${ LANG }/help となっています。

VISUROOT は、Sun WorkShop Visual のインストールディレクトリです。 LANG は使用するロケールで、デフォルトでは「 C 」です。

テキストのヘルプドキュメント

テキストのヘルプドキュメントは HTML 形式です。ファイルの名前は、ドキュメント名とマーカー名を連結して形成されています。この連結処理は visu.userHelpCatString リソースで行われます。デフォルトではこのリソースは「.」に設定されています。ファイルには 「 .html 」 接尾辞が付けられます。Sun WorkShop Visual は Sun WorkShop Visual.helpDir リソースで指定した検索パスに従いファイルを捜します。


1. コメント行は生成されません。

2. コメント行は生成されません。

3. コメント行は生成されません。


前へ 次へ 目次 文書セット ホーム

サン・マイクロシステムズ株式会社
Copyright information. All rights reserved.