X-Designer 再現 ウィジェットセットの拡張例

X-Designer 再現 ウィジェットセットの拡張例


以下の例は X-Designer 再現機能のソースに対するのものです。この例はウィジェットのクラス (ここでは Motif XmList ウィジェットクラス) 用のコンバータを登録する方法を示したものです。XmList ウィジェットでのクリックが、そのリスト内の要素の特定インスタンスの選択に変換される様子を示しています。これは、 X-Designer 再現機能が XmList ウィジェットに対して実際に使用する機能です。この機能の使用例を以下のスクリプトに示します。

    in my_shell
	push my_list_widget(`this line',1)

このスクリプトが再現されると、ウィジェット内の適切な (x,y) 座標でクリックがシミュレートされます。

この例を実習すると、以下の 3 点が可能になります。

この例のソースファイルは、Makefile とともに $ XDROOT/src/examples/replay/cvtXm ディレクトリに用意されています。$ XDROOT は、 X-Designer のインストールディレクトリです。

このディレクトリの内容は、以下のとおりです。

サポートファイルは、共有オブジェクトが X-Designer 再現機構と通信するための枠組みを提供します。これらのファイルを変更する必要はありません。

この例では、XmList コンバータを含む motif2.c およびこれらのコンバータを登録するためのコードを組み込んでいる register.c をについて学習します。

この例では、 X-Designer 再現のウィジェットセットを拡張する方法を 3 段階で説明します。

  1. イベント (x y) から名前/属性対への変換: xdsXYToNameProc

  2. 一対の名前/属性からイベント (x y) への変換: xdsNameToXYProc

  3. コンバータの登録: xdsRegisterContextHandler

関連する 3 つのルーチンは以下のとおりです。

  1. xdsListXyToName() - (x,y) 位置を取得し、一対の名前/属性を返します。

  2. xdsListNameToXy() - 一対の名前/属性を取得し、(x,y) 位置を返します。

  3. xdsRegister() - ウィジェットおよび関連するコンバータを X-Designer 再現に登録します。

ウィジェットおよび関連するコンバータを X-Designer 再現に登録します。重要なことは、コンバータコードの構造およびコンバータの登録方法であり、XmList コンバータの実装方法ではありません。

xdsListXyToName()

この関数は motif2.c にあり、(x,y) 座標を名前/属性対に変換します。ここでは、xdsXyToNameProc インタフェース定義の構造体を説明しています。この関数は X-Designer 再現が記録モードのときに使用されます。

int
xdsListXyToName( widget, x, y, namep, attrp)
  Widget widget;
  int x, y;
  char ** namep;
  char ** attrp;
{
  extern Boolean XmStringCompare();
  extern char *  xdsCvtXmStringToString();
  extern Boolean xdsCvtSetListError();
  extern int     xdsCvtListFailure();
  extern Boolean xdsCvtGetXmListEntries();
  extern int XmListYToPos();
  static char name[255];
  static char count[20];
  int pos;

  int len = 0;
  int n;
  int instance = 1;
  XmString * list = (XmString*)0;
  XmString   item;
  /* 要素を取得する */
  if (!xdsGetXmListEntries( widget,&list, &len)) {
    return xdsListFailure();
  }
  /* XmListYToPos() を使用してリスト要素を取得する */
  pos = XmListYToPos( widget, (Position)y);
  if (pos < 0 || pos > len) {
    xdsCvtSetListError(LIST_OUT_OF_BOUNDS);
    return xdsCvtListFailure();
  }
  item = list[--pos];
  for (n = 0; n < pos; n++) {
    if (XmStringCompare( item, list[n]) == True)
      instance++;
  }
  /* 記述を作成する */
  (void) sprintf ( count, "%d", instance);
  (void) strcpy  ( name, xdsXmStringToString(item));

  *namep  = name;
  *attrp  = count;
  return 1;
}

xdsListNameToXy()

この関数は motif2.c にあり、(x,y) 座標を名前/属性対に変換します。ここでは、xdsXyToNameProc インタフェース定義の構造体を説明しています。この関数は X-Designer 再現が記録モードのときに使用されます。

int
xdsListNameToXy( widget, name, attr, xp, yp)
  Widget widget;
  char * name;
  char * attr;
  int  * xp;
  int * yp;
{
  extern char * xdsCvtXmStringToString();
  extern Boolean xdsCvtSetListError();
  extern int    xdsCvtListFailure();
  extern int    xdsCvtSetListItem();
  extern Boolean xdsCvtGetXmListEntries();
  Position x, y;
  Dimension w, h;
  int pos;
  int len = 0;
  int n;
  char * s;
  int instance = 1;

  XmString * list = (XmString*)0;
  XmString   item;
  if ((instance = atoi(attr)) == 0) {
    xdsCvtSetListError(LIST_BAD_INSTANCE);
    return xdsCvtListFailure();
  }
  instance--;
  if (!xdsCvtGetXmListEntries( widget, &list, &len)) {
    xdsCvtSetListError(LIST_EMPTY_LIST);
    return xdsCvtListFailure();
  }
  for ( n = 0; n < len; n++) {
    s = xdsCvtXmStringToString(list[n]);
    if (strcmp( name, s) != 0)
      continue;
    if (instance--)
      continue;
    break;
  }
  if (n == len) {
    xdsCvtSetListError(LIST_ELEMENT_NOT_FOUND);
    return xdsCvtListFailure();
  }
  (void) xdsCvtSetListItem( widget, n+1);
  if (!XmListPosToBounds( widget, n+1, &x, &y, &w, &h)) {
    xdsCvtSetListError(LIST_OUT_OF_BOUNDS);

    return xdsCvtListFailure();
  }
  *xp = x + (w/2);
  *yp = y + (h/2);
  return 1;
}

xdsRegister()

この関数は、register.c と呼ばれています。motif2.c の 2 つのコンバータおよび XmScrollBar、XmScale、XmDrawingArea の各ウィジェット用のコンバータを登録します。

void
RegisterWidgets()
{
  extern Boolean xdsRegister();
  extern int xdsListNameToXy();
  extern int xdsListXyToName();
  extern int xdsScrollBarNameToXy();
  extern int xdsScrollBarXyToName();
  extern int xdsScaleNameToXy();
  extern int xdsScaleXyToName();
  extern int xdsDaNameToXy();
  extern int xdsDaXyToName();
  (void) xdsRegister( "XmList", xdsListNameToXy, xdsListXyToName);
  (void) xdsRegister( "XmScrollBar", xdsScrollBarNameToXy, xdsScrollBarXyToName);
  (void) xdsRegister( "XmScale", xdsScaleNameToXy, xdsScaleXyToName);
  (void) xdsRegister( "XmDrawingArea", xdsDaNameToXy, xdsDaXyToName);
}
void RegisterThisListWidget(

  Widget w;
{
  xdsRegisterContextHandler(w, xdsListNameToXy, xdsListXyToName);
}

この関数は xdsSetup.h に定義されています。ここでは、xdsRegisterContextHandler インタフェース定義の構造体を説明しています。

Boolean
xdsRegister( classname, name2xy, xy2name)
  char * classname;
  int_f  name2xy;
  int_f  xy2name;
{
  bool_f bf = xdsGetRegisterFunction();
  if (!bf)
    return False;
  return (*bf)( classname, name2xy, xy2name);
}

例の構築

提供されている Makefile は、共有オブジェクトを構築するよう構成されています。多数のオペレーティングシステムがサポートされています。これらのシステムをリストするには、次のように入力します。

% make

共有オブジェクトは、Makefile の OBJECT 行を次のように変更するだけで構築することができます。

    OBJECT = cvt<classname>

クラス名には、ウィジェットクラスの接頭辞を指定します。この例では、ウィジェットクラスは XmList なので、次のように Xm 接頭辞を入力します。

    OBJECT=cvtXm

共有オブジェクトを構築するには、make <システム名> と入力します。たとえば、Solaris マシンの場合は、make solaris と入力します。これで、libcvtXm.so という共有オブジェクトが構築されます。

共有オブジェクトが構築されたら、そのオブジェクトを $ XDROOT/lib/xds というディレクトリにコピーまたはリンクします。これで、 X-Designer 再現が必要に応じてこのオブジェクトを読み込むことができます。

カスタムウィジェット用のコンバータの追加

前述の例は、ウィジェットクラスに関するものです。カスタマイズ可能なウィジェット (すなわち、Motif XmDrawingArea などのウィジェットの特定のインスタンス) の場合は、変換ルーチンを登録するための機能が X-Designer とともに提供されています。この機能を使用すると、 X-Designer 再現機能がウィジェットのインスタンス (Motif であるかどうかに関わらず) の中で行なったユーザーアクションアを記録および再現できるように、 X-Designer 再現機能の動作をカスタマイズすることができます。

コンバータ登録コードは、以下のとおりです。

int_f _xdsRegisterFunction = (int_f)0;
Boolean
xdsRegisterContextHandler( widget, name2xy, xy2name)
  Widget widget;
  int_f  name2xy;
  int_f  xy2name;
{
  if (!_xdsRegisterFunction)
    return False;
  return (*_xdsRegisterFunction)( widget, name2xy, xy2name, 
True);
}


注 - _xdsRegisterFunction 関数のポインタ変数は 0 に設定されています。これは、アプリケーションが X-Designer 再現機能を使用しないで実行される場合は、ルーチンは常にリターンし、アプリケーションでは何も行わないことを意味します。アプリケーションを X-Designer 再現機能とともに実行する場合は、変数は Register ハンドラを指すよう設定されるので、このルーチンが呼び出されます。

コンバータを登録するルーチンについては、以下で説明します。

コンバータの登録

名前

    xdsRegisterContextHandler  -   コンバータの登録に使用する関数のインタフェース

定義

    Boolean xdsRegisterContextHandler(
      Widget widget,
      xdsNameToXYProc name2xy,
      xdsXYToNameProc xy2name)
    Boolean xdsRemoveContextHandler( Widget widget)

入力内容

機能説明

このルーチンは、ウィジェットにおけるイベントの独自解釈を登録するためのものです。以下の例に示すように、ウィジェットをコード内に作成した後は、いつでも xdsRegisterContextHandler を呼び出すことができます。

  button1 = XmCreatePushButton ( shell1, "button1", al, ac );
  xdsRegisterContextHandler(shell1, func1, func2)

X-Designer 再現は、再現時は func1 ルーチンを呼び出し、記録時は func2 ルーチンを呼び出します。

この機能は、ソースファイル (client.c) として、またはコンパイル済みライブラリモジュール (libxdsclient.a) として使用することができます。ソースファイルの場合はアプリケーションとともにコンパイルし、ライブラリモジュールの場合はアプリケーションと再リンクします。

この機能はアプリケーション自体には影響せず、アプリケーション内に残しても悪影響はありません。

まとめ

X-Designer 再現ウィジェットセットを拡張するには、以下の作業を行います。

ウィジェットクラスの場合は、以下の作業を行います。

個々のウィジェットには、以下の作業を行います。

提供されている examples ディレクトリの内容を参考にして、コンバータの記述、登録、構築を行なってください。

関連項目: