はじめに
この文章では、XBL の応用である、XULウィジェットへのアクセスを可能にする簡単な XPCOMインターフェースについて述べます。 XBLのこのインターフェースを定義するという特徴は、自動補完を行う C++ オブジェクトへの XPConnectを介したインターフェースを定義するのに使用されます。 一度通常の XULテキストフィールドをこのインターフェースに結び付ければ、通常の JavaScript を用いて、オブジェクトの自動補完機能を呼び出すようになります。 この相互作用の基本的なモデルは次のとおりです:
XPCOMオブジェクトへ結び付ける
ウィジェットは、自動補完の検索を行う自動補完エンジンである XPCOMオブジェクトを保持します。
<binding name="autocomplete" extends="xul:box"> <content> <xul:textfield class="addressingWidget"/> <xul:menupopup/> </content> <interface> <property name="autoCompleteSession"> ![CDATA[ Components.classes['component://netscape/messenger/autoc...&type=addrbook']. getService(Components.interfaces.nsIAutoCompleteSession); ]] </property>
ですので、autoCompleteSession というウィジェットに propetry を定義しました。 この property の初期値は評価されて xp-connectオブジェクトへ入ります。 これで、.autoCompleteSession を呼ぶと xp-connectオブジェクトを返します。
XPCOMインターフェースを公開する
ウィジェットでサポートしたい XPCOM オブジェクトのインターフェースを手動で公開するには、あまりきれいでないトリックをひとつ行う必要があります。 幸運なことに、このデモンストレーションでは我々はインターフェースにメソッドをひとつだけ持っています =). わたしのやることは具体的には、メソッド呼び出しを XPCOMオブジェクトへ中継する XBLウィジェットにメソッドの属性を定義することで全てです。
<method name="autoComplete"> <argument name="aSearchString"/> <argument name="resultListener"/> <body> ![CDATA[ return this.autoCompleteSession.autoComplete(null, anonymousContent[0], aSearchString, this.autoCompleteListener); ]] </body> </method>
メソッドの本体がそのまま自動補完のセッションを得て、その上で自動補完メソッドを呼び出しているのが分かるでしょう。
ウィジェットのインターフェースを実装する
次にやるべきことは、自動補完のセッションを渡せるようにウィジェットのインターフェースを実装することです。 自動補完セッションがウィジェットに検索結果付きでコールバックしてほしいところです。 XPCOMオブジェクトのときに行ったのと同じようなトリックを行うことができます。
<property name="autoCompleteListener"> ![CDATA[ ({ onAutoCompleteResult: function(aItem, aOriginalString, aMatch) { if ( aItem ) { anonymousContent[0].value = aMatch; } } }) ]]
autoCompleteListener の値を処理する JS がオブジェクトを生成する(そして式をわたしが行ったようなペアの集合につつむ)限りは、その autoCompleteListener の値はわたしのインターフェースを実装したオブジェクトになります。 ここで、.autoCompleteListener の結果を auto complete listener を必要とするメソッド(たとえばわたしの自動補完セッションオブジェクトのような)へ渡すことができます。
イベントハンドラを作る
最後の部分は簡単なところです。 自動補完検索を開始するハンドラが欲しいところです。 このハンドラは、そのまま XPCOMオブジェクトに渡される、我々の公開したウィジェット上の自動補完メソッドを呼んで、nsIAutoCompleteListener の実装に渡します。
<handlers> <handler type="keypress" keycode="vk_return" value="autoComplete(anonymousContent[0].value, this.autoCompleteListener);"/> </handlers>