XVCDによるダイアログボックスの実装

XVCDでダイアログボックスを実装して利用する手順を、簡単な例を示して説明します。

1. このチュートリアルの内容

このチュートリアルでは、XVCDでダイアログボックスを作成する方法と、そのダイアログボックスを利用してデータを追加・編集する方法を、例題を使い順を追って解説します。このチュートリアルを実践することで、XVCDによるボキャブラリコンポーネントにダイアログボックスを用いたデータ編集機能を追加できるようになります。

このチュートリアルを実践するために必要な知識や、開発環境の準備については、「XVCDで開発する環境の準備」をご覧ください。また、このチュートリアルを実践する前に、「XVCDによるボキャブラリコンポーネントの作成」を読み終えていることを想定しています。

このチュートリアル内のサンプルコードは、xfy Developer's Toolkit 配布パッケージ内のdoc/samples/developers/tutorial/xvcd_dialog_tutorialに収録されています。xfy Developer's Toolkitには、このチュートリアルのほかにも豊富なXVCDサンプルが用意されています。ぜひ、それらのサンプルもご覧ください。

なお、このチュートリアルでは、xfyユーザーエージェントとして、xfy Basic Editionに含まれるxfy Clientを使用します。チュートリアルを進めるときは、xfy Clientでブラウズバーを表示すると便利です。xfy Clientをインストールした直後は、ブラウズバーは表示されていません。ブラウズバーを表示するには、[表示 - ブラウズバー]を選択します。

2. XVCDでのダイアログボックス実装の概要

XVCDでダイアログボックスを実装する手順を追う前に、作業の全体像を把握しましょう。全体像を把握できるように、次の観点からダイアログボックスの実装について説明します。

2.1. XVCDで実装したダイアログボックスの基本的な仕組み

C++やJavaなどのほかの開発環境では、ダイアログボックスを利用するときに、一般的に次の実装作業が必要です。

  • ダイアログボックスにコントロールを配置する
  • 値を格納する変数をコントロールに割り当てる
  • ダイアログボックス上でのユーザーの操作に対応する処理を実装する
  • ダイアログボックスを開く
  • ダイアログボックスで設定された値を、コントロールに割り当てた変数から取得して利用する

こうして実装されたダイアログボックスは、開発環境で用意されているライブラリで制御されて動作します。

XVCDでダイアログボックスを利用するときの実装作業は、ほかの開発環境での作業とは少し異なります。XVCDでは、xfy Clientの編集画面にコントロールを配置したフォームを表示してXML文書を編集する場合に類似した仕組みで、ダイアログボックスの機能を実現します。XVCDのダイアログボックスは、コントロールを使ってXML文書フラグメントを編集し、その結果を元のXML文書フラグメントに反映すると考えればよいでしょう。

XVCDでダイアログボックスを利用するときの実装作業の項目は、おおよそ次のとおりです。

  • ダイアログボックスで設定する項目を内容に含むXML文書フラグメントを用意する
  • XML文書フラグメントの項目の値を設定するダイアログボックスを開く
  • XML文書フラグメントの項目の値をコントロールで設定するボキャブラリコンポーネントを実装する
  • ダイアログボックスで設定された値を、XML文書フラグメントから取得する

2.2. ダイアログボックスを利用するために実装するもの

XVCDでダイアログボックスを利用するためにXVCD開発者が実装するのは、次の2つです。

  • ダイアログボックスを利用するコマンド
  • ダイアログボックス用のボキャブラリコンポーネント

ここでは、それぞれに実装する内容を、簡単に説明します。

2.2.1. ダイアログボックスを利用するコマンド

ダイアログボックスを利用するコマンドは、次の処理を行います。

  • ダイアログボックスを開く
  • ダイアログボックスが閉じたあと、設定結果を取得して処理する

ダイアログボックスを開くには、 instruction:dialogインストラクションを使用します。instruction:dialogインストラクションはモーダルダイアログボックスを作成するコマンドインストラクションです。このコマンドインストラクションではモードレスダイアログボックスは作成できません。

ほかの開発環境では、ダイアログボックスを開くときに、その中のコントロールに対して値を設定します。XVCDでは、設定する項目を内容に含むXML文書フラグメントをinstruction:dialogインストラクションの内容に設定します。設定されたXML文書フラグメントにはダイアログボックス用のボキャブラリコンポーネントが適用されて、ダイアログボックスに表示されます。

ユーザーの操作でダイアログボックスが閉じられると、ダイアログボックスでの設定結果を取得して処理します。ほかの開発環境では、ダイアログボックスのコントロールから設定結果を参照します。XVCDでは、ダイアログボックスで編集されたXML文書フラグメントから設定結果を参照します。このXML文書フラグメントは、instruction:dialogインストラクションで指定された変数に設定されます。ダイアログボックスを終了したあとのインストラクションでは、この変数からXML文書フラグメントを参照し、ダイアログボックスの設定結果を取得します。取得した設定結果は、xfy Clientで編集しているXML文書に挿入したり、XML文書の内容を変更したりするなど、必要な処理に使用します。

2.2.2. ダイアログボックス用のボキャブラリコンポーネント

ダイアログボックス用のボキャブラリコンポーネントは、次の役割を持つボキャブラリコンポーネントです。

  • instruction:dialogインストラクションの内容に記述されたXML文書フラグメントを元に、ダイアログボックスを構築する
  • ダイアログボックスの動作を制御する
  • ダイアログボックスで設定された値を、XML文書フラグメントに反映する

ほかの開発環境では、コントロールをウィンドウへ配置してダイアログボックスを構築します。XVCDでは、xfy Clientの編集画面を作成する場合と同じ方法でダイアログボックスを構築します。「コントロール記述リファレンス」にあるユーザーインターフェイスコントロールを使用して、ほかの開発環境と同じようなダイアログボックスを構築できます。

ダイアログボックス用のボキャブラリコンポーネントには、通常のボキャブラリコンポーネントとは異なり、ダイアログボックスを閉じるためのボタンを配置して、ダイアログボックスを閉じる処理を実装する必要があります。

2.3. XVCDでダイアログボックスを利用する流れ

XVCDでダイアログボックスを利用する流れは、大きく3つのステップに分けられます。このチュートリアルでは、処理の流れに沿って、以下のステップごとに手順を解説します。

  1. ダイアログボックスの表示
    instruction:dialogインストラクションでダイアログボックスを開くまでの処理を実装します。この処理は、ダイアログボックスを利用するコマンドの前半部分に該当します。
  2. ダイアログボックスの制御
    ダイアログボックス用のボキャブラリコンポーネントを実装します。
  3. ダイアログボックスでの設定結果の反映
    ダイアログボックスが閉じられたあとのインストラクションで、変数からXML文書フラグメントを参照して設定結果を反映する処理を実装します。この処理は、ダイアログボックスを利用するコマンドの後半部分に該当します。

次の章から、実例を使ってXVCDでダイアログボックスを利用する方法を説明します。

3. ダイアログボックスを利用するボキャブラリコンポーネントの用意

XVCDでダイアログボックスを用いてデータを追加・編集する手順を解説する前に、ダイアログボックスを利用するボキャブラリコンポーネントを作成します。今回は、住所録を表示するボキャブラリコンポーネントを作成します。

3.1. XML文書の定義

まず、XML文書ファイルを用意します。 ここでは、次のような住所録を表すXML文書を作成します。まだXVCDファイルは作成していませんが、あらかじめこのXML文書に関連付けるXVCDファイルを指定しておきましょう。 これから作成するXVCDのファイル名は、AddressBook.xvcdとします。

<?xml version="1.0" encoding="UTF-8"?>

<?com.xfy vocabulary-connection href="AddressBook.xvcd" ?>
<ab:addressbook xmlns:ab="http://xmlns.example.com/developer/tutorial/addressbook">
    <ab:entry>
        <ab:person>George Adams</ab:person>
        <ab:address>Rochester, NY USA</ab:address>
    </ab:entry>
</ab:addressbook>

XML文書は AddressBook.xml というファイル名で適切なフォルダに保存します。

3.2. XVCDによるボキャブラリコンポーネントの作成

次に、XVCDで住所録を表示するボキャブラリコンポーネントを作成します。

<?xml version="1.0" encoding="UTF-8"?>
<xvcd:xvcd
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xvcd="http://xmlns.xfy.com/xvcd"
    xmlns:instruction="http://xmlns.xfy.com/instruction"
    xmlns:ctrl="http://xmlns.xfy.com/controls"
    xmlns:event="http://xmlns.xfy.com/event"
    xmlns:ui="http://xmlns.xfy.com/ui"
    xmlns:command="http://xmlns.xfy.com/command"
    xmlns:ab="http://xmlns.example.com/developer/tutorial/addressbook"
    version="1.0">
    
    <!-- 住所録のボキャブラリコンポーネント定義 -->
    <xvcd:vocabulary name="AddressBook" match="ab:addressbook" call-template="Root" />

    <xvcd:template name="Root">
        <html>
            <body>
                <h2>Address Book</h2>
                <table border="1">
                    <tr>
                        <th>Name</th>
                        <th>Address</th>
                    </tr>
                    <xvcd:for-each select="ab:entry">
                        <tr>
                            <td><xvcd:text-of select="ab:person" /></td>
                            <td><xvcd:text-of select="ab:address" /></td>
                        </tr>
                    </xvcd:for-each>
                </table>
            </body>
        </html>
    </xvcd:template>
</xvcd:xvcd>

作成したXVCDは、AddressBook.xvcdというファイル名で保存します。AddressBook.xvcdは、AddressBook.xmlと同じフォルダに保存します。

4. ダイアログボックスを利用するコマンドの実装

用意したボキャブラリコンポーネントに、ダイアログボックスを利用するコマンドを実装します。このチュートリアルでは、次の2つの実装の例を示します。

4.1. ダイアログボックスで作成したXML文書フラグメントの追加

まず、ダイアログボックスで作成したXML文書フラグメントをXML文書へ追加する方法を、例を示して解説します。ここでは、ダイアログボックスを使用して住所エントリーを追加するコマンドの作成を、例にして説明します。作成するコマンドの名前は、AddEntryとします。AddEntryコマンドでは、追加する住所エントリーを instruction:dialogインストラクションで表示したダイアログボックスで編集し、住所録の末尾へ追加します。

4.1.1. ダイアログボックスの表示

まず、AddEntryコマンドのinstruction:dialogインストラクションを使用してダイアログボックスを開く部分を実装します。

AddressBook.xvcdをテキストエディタで開き、 xvcd:xvcd要素の内容にAddEntryコマンドを追加します。強調文字で表記した個所が、追加する内容です。

<xvcd:xvcd ...>
    : 
    : ボキャブラリコンポーネントの定義は省略
    :

    <!-- 住所エントリーを追加するコマンド -->
    <xvcd:command name="AddEntry">

        <!-- ダイアログボックスを表示するインストラクション -->
        <instruction:dialog return-to="result">
            <!-- ダイアログボックスで表示・編集するXMLボキャブラリ -->
            <ab:edit-dialog>
                <ab:entry>
                    <ab:person />
                    <ab:address />
                </ab:entry>
            </ab:edit-dialog>
        </instruction:dialog>

    </xvcd:command>

    : 
    : テンプレートは省略
    :
</xvcd:xvcd>

instruction:dialogインストラクションの内容には、ダイアログボックスで表示・編集するXML文書フラグメントを記述します。この例では、ab:edit-dialog要素とその内容が表示・編集するXML文書フラグメントです。ダイアログボックスでは元の文書とは別のボキャブラリコンポーネントで表示・編集するため、独自のXMLボキャブラリを使用します。この例では、元の文書で使用しないab:edit-dialog要素を頂点要素として、独自のXMLボキャブラリを定義しています。

instruction:dialogインストラクションのreturn-to属性には、ダイアログボックスで設定された結果を格納する変数の名前を設定します。この変数について、詳しくは「ダイアログボックスの設定結果の利用」で解説します。

作成したAddEntryコマンドは、メニューから実行することにします。ここでは、メインメニューに「Entry」というメニューを作成し、そのサブメニューにメニュー項目「add」を作成します。ここにAddEntryコマンドを割り付けます。AddEntryコマンドはダイアログボックスを使用して住所エントリーを追加します。選択するとダイアログボックスが表示されるメニューには「...」を表示して、ダイアログボックスが表示されるコマンドであることをユーザーに示すことが望まれます。メニューに「...」を表示するには、ui:menu-item要素のopen-dialog属性の値にtrueを設定します。これを「add」メニューを表すui:menu-item要素に設定すると、メニューが表示されたときに「add...」と表示されます。

このメニューの実装を、AddressBook.xvcdxvcd:vocabulary要素の内容に追加します。強調文字で表記した個所が、追加・変更した個所です。

<xvcd:xvcd ...>

    <!-- 住所録のボキャブラリコンポーネント定義 -->
    <xvcd:vocabulary name="AddressBook" match="ab:addressbook" call-template="Root">
        <ui:ui version="1.0">
            <ui:main-menu>
                <ui:menu label="Entry">
                    <ui:menu-item label="add" command="AddEntry" open-dialog="true" />
                </ui:menu>
            </ui:main-menu>
        </ui:ui>
    </xvcd:vocabulary>

    : 
    : テンプレート、コマンドは省略
    :
</xvcd:xvcd>

これで、AddEntryコマンドの前半部分のダイアログボックスを開くところまで実装しました。ただし、ダイアログボックスを開いただけでは、ダイアログボックスでXML文書フラグメントを編集できません。ダイアログボックスでXML文書フラグメントを編集するには、ダイアログボックス内で使用するボキャブラリコンポーネントを追加する必要があります。次はその手順を解説します。

4.1.2. ダイアログボックス用のボキャブラリコンポーネント

「ダイアログボックスの表示」で作成したコマンドを実行すると、ダイアログボックスが表示されます。ただし、その内容にはアイコンが表示されます。このアイコンは、適用できるボキャブラリコンポーネントがないときに使用される汎用ボキャブラリコンポーネントの、Iconコンポーネントで表示されたものです。

Iconコンポーネントで表示されたダイアログボックス
Iconコンポーネントで表示されたダイアログボックス

ダイアログボックスの内容を表示して編集できるようにするには、ダイアログボックスの内容を記述したXMLボキャブラリ用のボキャブラリコンポーネントを追加する必要があります。 ここでは、AddressBook.xvcdにダイアログボックス用のボキャブラリコンポーネントを追加します。

AddressBook.xvcdをテキストエディタで開き、 xvcd:xvcd要素の内容にダイアログボックス用のボキャブラリコンポーネントを追加します。強調文字で表記した個所が、追加する内容です。

<xvcd:xvcd ...>

   :
   : 元の文書のボキャブラリコンポーネントは省略。
   :

    <!-- ダイアログボックス用のボキャブラリコンポーネントの定義 -->
    <xvcd:vocabulary name="EditDialog" match="ab:edit-dialog" call-template="EditDialogRoot" />

    <!-- OKでダイアログボックスを閉じるコマンド -->
    <xvcd:command name="Ok">
        <!-- closed-by属性を設定する -->
        <xvcd:set-attribute name="closed-by" value="ok" select="/ab:edit-dialog" />

        <!-- ダイアログボックスを閉じるコマンドをpostする -->
        <instruction:post name="command:dialog-close" />
    </xvcd:command>

    <!-- キャンセルでダイアログボックスを閉じるコマンド -->
    <xvcd:command name="Cancel">
        <!-- ダイアログボックスを閉じるコマンドをpostする -->
        <instruction:post name="command:dialog-close" />
    </xvcd:command>

    <!-- ダイアログボックスの内容を作成するテンプレート -->
    <xvcd:template name="EditDialogRoot">
        <html>
            <head>
                <title>Entry</title>
            </head>
            <body>
                <table>
                    <tr>
                        <td>Name:</td>
                        <td>
                            <ctrl:input style="width: 24em" ref="ab:entry/ab:person" maxlength="32" />
                        </td>
                    </tr>
                    <tr>
                        <td>Address:</td>
                        <td>
                            <ctrl:input style="width: 24em" ref="ab:entry/ab:address" maxlength="64" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" style="text-align: right;">
                            <!-- OK ボタン -->
                            <ctrl:trigger command="Ok">
                                <ctrl:label>OK</ctrl:label>
                            </ctrl:trigger>
                            <xvcd:text> </xvcd:text>
                            <!-- キャンセルボタン -->
                            <ctrl:trigger command="Cancel">
                                <ctrl:label>Cancel</ctrl:label>
                            </ctrl:trigger>
                        </td>
                    </tr>
                </table>
            </body>
        </html>
    </xvcd:template>
</xvcd:xvcd>

Name」と「Address」で使用している ctrl:input要素は、テキストフィールドを作成する要素です。

ダイアログボックス用のボキャブラリコンポーネントでは、画面上に[OK]や[キャンセル]などのボタンを配置します。 ctrl:trigger要素はボタンを作成する要素です。ctrl:trigger要素で作成されたボタンは、クリックされたときにcommand属性で指定したコマンドを実行します。この例では、[OK]がクリックされると、Okコマンドが実行されます。また、[キャンセル]がクリックされるとCancelコマンドが実行されます。

[OK]と[キャンセル]が配置されたダイアログボックスでは、[OK]がクリックされたときだけ、以降のコマンドの処理を実行します。ダイアログボックスが閉じたあとでは、[OK]がクリックされたかそうでないかを知ることはできません。そのため、[OK]がクリックされてダイアログボックスが閉じたことが判別できるように、XMLボキャブラリの頂点要素に属性を設定します。

このAddEntryコマンドの例では、[OK]がクリックされたときだけ、住所エントリーを追加します。そのため、[OK]がクリックされたときに、ab:edit-dialog要素のclosed-by属性の値に"ok"を設定しています。

OkコマンドとCancelコマンドでは、コマンドの最後でダイアログボックスを閉じるために、 command:dialog-closeコマンド instruction:postインストラクションで呼び出しています。

ダイアログボックスを閉じる操作

command:dialog-closeコマンドのほか、次のユーザーによる操作でダイアログボックスは閉じられます。

  • ウィンドウコントロールのクローズボックスがクリックされた
  • ウィンドウコントロールのメニューで、ダイアログボックスを閉じるコマンドが選択された
    Windowsの場合は、タイトルバー上で右クリックして表示されるメニューで[閉じる]が選択された場合です。
  • ダイアログボックスを閉じるショートカットキーを押された
    Windowsの場合は、Alt+F4キーが押された場合です。

4.1.3. ダイアログボックスの設定結果の利用

ダイアログボックスでユーザーが設定した結果は、ダイアログボックス上で編集されたXML文書フラグメントとして表されます。ここでは、ダイアログボックスで編集された住所エントリーを住所録の末尾に追加する処理を、AddEntryコマンドに実装します。

ダイアログボックスでの設定結果は、instruction:dialogインストラクションのreturn-to属性に記述した名前の変数に格納されます。ダイアログボックスを閉じるときに、ダイアログボックスに表示されたXML文書フラグメントの編集結果と、終了したときの状態を表す instruction:dialog-result要素からなるXML文書フラグメントが変数に格納されます。設定結果を参照するときには、この変数を参照します。設定結果が格納された変数を利用できるスコープは、 instruction:variableインストラクションで定義された変数のスコープと同じです。

この住所録の例では、instruction:dialogインストラクションのreturn-to属性に設定された変数resultに、次のような内容のXML文書フラグメントが設定されます。

<ab:edit-dialog closed-by="ok">
    <ab:entry>
       <ab:person>Betty Jackson</ab:person>
       <ab:address>Denver, Colorado USA</ab:address>
    </ab:entry>
</ab:edit-dialog>
<instruction:dialog-result is-closed-with-command="true" />

instruction:dialog-result要素のis-closed-with-command属性は、ダイアログボックスを command:dialog-closeコマンドで閉じた場合にtrueが設定されます。ダイアログボックスのクローズボックスやキー操作で強制的に終了された場合は、falseが設定されます。

では、住所エントリーを住所録の末尾に追加しましょう。住所エントリーを住所録の末尾に追加する処理は、「ダイアログボックスの表示」で作成したAddEntryコマンドのinstruction:dialogインストラクションの後ろに追加します。強調文字で表記した個所が、追加した個所です。

<xvcd:xvcd ...>
    : 
    : ボキャブラリコンポーネントの定義は省略
    :

    <!-- 住所エントリーを追加するコマンド -->
    <xvcd:command name="AddEntry">

        <!-- ダイアログボックスを表示するインストラクション -->
        <instruction:dialog return-to="result">
            <!-- ダイアログボックスで表示・編集するXMLボキャブラリ -->
            <ab:edit-dialog>
                <ab:entry>
                    <ab:person />
                    <ab:address />
                </ab:entry>
            </ab:edit-dialog>
        </instruction:dialog>

        <!-- ダイアログボックスで編集された結果を反映します。 -->
        <instruction:if test="'ok'=$result/ab:edit-dialog/@closed-by">
            <!--
               ダイアログボックスで編集された住所エントリーを元の文書の末尾に追加します。
               xvcd:insertインストラクションの内容はVCによる変換が行われます。
            -->
            <xvcd:insert ref="/ab:addressbook" position="last-child">
                <xvcd:copy-of select="$result//ab:entry" />
            </xvcd:insert>
        </instruction:if>
    </xvcd:command>

    : 
    : テンプレートは省略
    :
</xvcd:xvcd>

この住所録の例では、ダイアログボックスの設定結果を表すXML文書フラグメントは、変数resultに格納されます。この変数resultに格納されたXML文書フラグメントを参照すると、ダイアログボックスでユーザーが設定した結果を利用できます。

ユーザーがダイアログボックスで設定した結果を利用するのは、ダイアログボックスで[OK]がクリックされたときだけです。従って、ダイアログボックスが閉じたあと、[OK]がクリックされたかそうでないかを調べる必要があります。「ダイアログボックス用のボキャブラリコンポーネント」で作成したダイアログボックス用のボキャブラリコンポーネントでは、[OK]がクリックされたかそうでないかを表す情報を、設定結果を表すXML文書フラグメントに設定します。この例の場合、[OK]がクリックされたときは、XML文書フラグメントの頂点要素であるab:edit-dialog要素のclosed-by属性の値に"ok"が設定されます。そのため、この属性の値を調べると、ダイアログボックスが[OK]で閉じられたかそうでないかを判断できます。

実際にダイアログボックスで[OK]がクリックされかそうでないかを判断しているのは、instruction:dialogインストラクションの次にある instruction:ifインストラクションです。このインストラクションでは、変数resultに格納されたXML文書フラグメントを調べて、ab:edit-dialog要素のclosed-by属性の値に"ok"が設定されていれば、[OK]でダイアログボックスが閉じられたと判断しています。

[OK]がクリックされたときは、ダイアログボックスでユーザーが設定した結果を利用します。この住所録の例では、ユーザーが編集した住所エントリーを表すXML文書フラグメントを、住所録の末尾に追加します。住所エントリーを住所録に追加するには、 xvcd:insertインストラクションを使用します。xvcd:insertインストラクションの内容はボキャブラリコネクション(以下、VCと表記します)によって変換されます。今回は、VCによる変換を利用し、住所エントリーを xvcd:copy-of要素でコピーしています。

以上で、住所録に住所エントリーを追加するコマンドAddEnteryの実装は完了です。

実際にxfy Clientで表示しましょう。AddressBook.xmlをxfy Clientで開いてください。 メインメニューに[Entry]が追加されています。

メニューが追加された
メニューが追加された

[Entry - Add]を実行しましょう。ダイアログボックスが表示されます。

ダイアログボックスが表示された
ダイアログボックスが表示された

ダイアログボックスで[Name]に「Betty Jackson」、[Address]に「Denver, Colorado USA」を入力して[OK]をクリックしましょう。最終行に住所エントリーが1行追加され、「Betty Jackson」/「Denver, Colorado USA」と表示されます。

住所エントリーが追加された
住所エントリーが追加された

4.2. ダイアログボックスを使用した文書中のXMLフラグメントの編集

次に、文書中のXML文書フラグメントをダイアログボックスで編集し、その結果を文書に反映する方法を解説します。文書中のXML文書フラグメントをダイアログボックスで編集する場合は、次の処理中に文書中のXML文書フラグメントを参照する必要があります。

  • ダイアログボックスを開く処理
  • ダイアログボックスでの設定結果を利用する処理

ここでは、既存の住所エントリーの内容を編集するコマンドを例にして説明します。作成するコマンドの名前は、EditEntryとします。ダイアログボックスのボキャブラリコンポーネントには、「ダイアログボックス用のボキャブラリコンポーネント」で作成したボキャブラリコンポーネントを、そのまま利用します。

4.2.1. ダイアログボックスの表示

「ダイアログボックスで作成したXML文書フラグメントの追加」では、ダイアログボックスで新規の住所エントリーを利用しました。今度は、ダイアログボックスで文書中の住所エントリーをコピーしたものを利用します。 instruction:dialogインストラクションの内容はVCによって変換されます。そこで、VCによる変換を利用して、文書中の住所エントリーをコピーします。

今回は文書中でキャレットがある住所エントリーを xvcd:copy-of要素でコピーします。キャレットがある住所エントリーは、 xvcd:caret-node関数で参照します。

AddressBook.xvcdをテキストエディタで開き、 xvcd:xvcd要素以下にEditEntryコマンドを追加します。強調文字で表記した個所が、追加する内容です。

<xvcd:xvcd ...>

    :
    : テンプレート、ボキャブラリコンポーネントの定義は省略。
    :

    <!-- 住所エントリーを編集するコマンド -->
    <xvcd:command name="EditEntry">

        <!-- ダイアログボックスを表示するインストラクション -->
        <instruction:dialog return-to="result">
            <ab:edit-dialog>
                <!-- キャレットがある住所エントリーをコピー -->
                <xvcd:copy-of select="xvcd:caret-node()/ancestor-or-self::ab:entry[1]" />
            </ab:edit-dialog>
        </instruction:dialog>

    </xvcd:command>

    :
    : ダイアログボックス用のボキャブラリコンポーネントは省略。
    :
</xvcd:xvcd>

次に、EditEntryコマンドをメインメニューから実行できるようにします。 強調文字で表記した個所が、追加した個所です。

<xvcd:xvcd ...>
    <!-- 住所録のボキャブラリコンポーネント定義 -->
    <xvcd:vocabulary name="AddressBook" match="ab:addressbook" call-template="Root">

        <ui:ui version="1.0">
            <ui:main-menu>
                <ui:menu label="Entry">
                    <ui:menu-item label="add" command="AddEntry" open-dialog="true" />
                    <ui:menu-item label="edit" command="EditEntry" open-dialog="true" />
                </ui:menu>
            </ui:main-menu>
        </ui:ui>

    </xvcd:vocabulary>

    :
    : コマンド、テンプレート、ダイアログボックス用のボキャブラリコンポーネントは省略。
    :
</xvcd:xvcd>

ここでは、メインメニューの「Entry」メニューの「edit」でEditEntryコマンドを実行します。

4.2.2. ダイアログボックスの設定結果の利用

「ダイアログボックスで作成したXML文書フラグメントの追加」ではダイアログボックスで編集された住所エントリーを文書の末尾に追加しました。今回はキャレットがある住所エントリーを、ダイアログボックスで編集された住所エントリーと差し替えます。

まず、 xvcd:insertインストラクションでキャレットがある住所エントリーの前に、ダイアログボックスで編集された住所エントリーを挿入します。次に xvcd:deleteインストラクションでキャレットがある住所エントリーを削除します。キャレットがある住所エントリーはxvcd:caret-node関数からたどります。そのためxvcd:insertインストラクションでは、キャレットが移動しないようにcaret-move属性でnoneを指定します。

「ダイアログボックスの表示」で作成したEditEntryコマンドのinstruction:dialogインストラクションの後ろに処理を追加します。強調文字で表記した個所が、追加した個所です。

<xvcd:xvcd ...>

    :
    : テンプレート、ボキャブラリコンポーネントの定義は省略。
    :

    <!-- 住所エントリーを編集するコマンド -->
    <xvcd:command name="EditEntry">

        <!-- ダイアログボックスを表示するインストラクション -->
        <instruction:dialog return-to="result">
            <ab:edit-dialog>
                <!-- キャレットがある住所エントリーをコピー -->
                <xvcd:copy-of select="xvcd:caret-node()/ancestor-or-self::ab:entry[1]" />
            </ab:edit-dialog>
        </instruction:dialog>

        <!-- ダイアログボックスで編集された結果の反映 -->
        <instruction:if test="'ok'=$result/ab:edit-dialog/@closed-by">

            <!-- キャレットがある住所エントリーの前に、
                 ダイアログボックスで編集された住所エントリーを挿入 -->
            <xvcd:insert ref="xvcd:caret-node()/ancestor-or-self::ab:entry[1]"
                position="before" caret-move="none">
                <xvcd:copy-of select="$result//ab:entry" />
            </xvcd:insert>

            <!-- キャレットがある住所エントリーを削除 -->
            <xvcd:delete select="xvcd:caret-node()/ancestor-or-self::ab:entry[1]" />

        </instruction:if>
    </xvcd:command>

    :
    : ダイアログボックス用のボキャブラリコンポーネントは省略。
    :
</xvcd:xvcd>

以上で、既存の住所エントリーの内容を編集するコマンドEditEnteryの実装は完了です。

実際にxfy Clientで表示しましょう。AddressBook.xmlをxfy Clientで開いてください。メインメニューに[Entry - Edit]が追加されています。

メニューが追加された
メニューが追加された

[Entry - Edit]を実行しましょう。ダイアログボックスが表示されます。

ダイアログボックスが表示された
ダイアログボックスが表示された

ダイアログボックスで[Name]を「Betty Jackson」に、[Address]を「Denver, Colorado USA」に、それぞれ変更して、[OK]をクリックしましょう。住所エントリーが変更され、「Betty Jackson」/「Denver, Colorado USA」と表示されます。

住所エントリーが変更された
住所エントリーが変更された

5. ダイアログボックスの洗練

XVCDで作成するダイアログボックスの見た目や挙動を、利用しているシステムで表示されるダイアログボックスに近づける方法を紹介します。

5.1. 基本デザインの設定

配色やフォントなどの基本デザインを次の表のように設定すると、利用しているシステムで表示されるダイアログボックスに見た目が近くなります。

背景色 ThreeDFace
テキスト色 WindowText
フォントサイズ 12px
フォント名 sans-serif

また、ダイアログボックスの内容にXHTMLを使用すると、html要素のデフォルトのスタイルではスクロールバー分の領域が右側に追加されます。これを回避するために、CSSのoverflowプロパティに値visibleを指定して、スクロールバーが表示されないようにします。

この設定を住所録のXVCDに反映しましょう。AddressBook.xvcdをテキストエディタで開き、ダイアログボックスのテンプレートへstyle要素を追加します。強調文字で表記した個所が、追加した個所です。

<xvcd:xvcd ...>
    :
    : 住所録のボキャブラリコンポーネント、ボキャブラリコンポーネントの定義、コマンドは省略。
    :

    <xvcd:template name="EditDialogRoot">
        <html>
            <head>
                <title>Entry</title>
                <style type="text/css" xml:space="preserve">
                html {
                    overflow: visible;
                }
                body {
                    background-color: ThreeDFace;
                    color: WindowText;
                    font-size: 12px;
                    font-family: sans-serif;
                }
                </style>
            </head>
            <body>
            :
            : body要素以下のテンプレートは省略
            :
            </body>
        </html>
    </xvcd:template>
</xvcd:xvcd>

この設定を反映していないダイアログボックスと、設定を反映したダイアログボックスを比べてみましょう。まず、設定を反映していないダイアログボックスは、次の図のように表示されます。

使用前
スタイル使用前

一方、設定を反映したダイアログボックスは、次の図のように表示されます。

使用後
スタイル使用後

5.2. デフォルトボタン処理やEscキー処理への対応

実際のダイアログボックスではEnterキーを押すとデフォルトボタンの処理を実行します。またEscキーを押すとキャンセルに相当する処理を行います。xfyプラットフォームではこれらの処理は行いません。これらの処理を実現するには、ダイアログボックスのボキャブラリコンポーネントでEnterキーやEscキーのキーイベントを受け取り、目的の処理を実行する必要があります。

キーイベントを受け取って処理する例は、「ユーザーの操作に対応したボキャブラリコンポーネントの作成」をご覧ください。キーイベントは、イベントが発生した要素で xvcd:action要素を使用して受け取らなかった場合は、上の階層の要素へバブリングします。従って、ダイアログボックス全体でEnterキーとEscキーのキーイベントを受け取る場合は、内容を表示する最上位の要素へxvcd:action要素を記述します。XHTMLの場合はbody要素にxvcd:action要素を記述します。

以下はAddressBook.xvcdにデフォルトボタンの処理とEscキーの処理を追加した例です。強調文字で表記した個所が、追加した個所です。

<xvcd:xvcd ...>
    :
    : 住所録のボキャブラリコンポーネント、ボキャブラリコンポーネントの定義、コマンドは省略。
    :

    <xvcd:template name="EditDialogRoot">
        <html>
            <head>
                <title>Entry</title>
            </head>
            <body>
                <!-- デフォルトボタンのキーイベントのハンドリング -->
                <xvcd:action event="event:key-pressed[@stroke='ENTER']">
                    <!-- OKボタンをデフォルトとした場合です。Okコマンドを実行します。 -->
                    <instruction:call name="Ok" />
                </xvcd:action>

                <!-- Escキーイベントのハンドリング -->
                <xvcd:action event="event:key-pressed[@stroke='ESCAPE']">
                    <!-- Cancelコマンドを実行します。 -->
                    <instruction:call name="Cancel" />
                </xvcd:action>

                :
                : 以下の内容は省略
                :
            </body>
        </html>
    </xvcd:template>
</xvcd:xvcd>