GWT Widgetを拡張する
GWTのWidgetは階層に基づいたクラス設計がなされている為、簡単に拡張できる。
例) input要素に追加されたplaceholder属性をプロパティとして利用することのできるTextBoxを作る
元々GWTのTextBoxクラス(com.google.gwt.user.client.ui.TextBox)はinput要素のピアとして提供されている。 このクラスにplaceholderプロパテイを追加するように実装してみよう。
既存のTextBoxを拡張する
placeholderプロパティを追加したTextBox5というクラスを実装してみよう。
public class TextBox5 extends TextBox { public String getPlaceHolder() { return DOM.getElementProperty(this.getElement(), "placeholder"); } public void setPlaceHolder(String placeholder) { DOM.setElementProperty(this.getElement(), "placeholder", placeholder); } }
簡単だ。実装のポイントはDOM.get/setElementPropertyメソッド。このメソッドでピアの要素(input要素)の属性を取得/設定することができるので、HTMLの仕様が変わっても、プラットホームによって違っても対応が可能だ。
この例の場合、placeholder属性の読み書きを行っている。
モジュール化する
順序が逆になったがGWTで使用するクラスはなんらかのモジュールに属している必要がある。本来、ある程度まとまった実装(Widget全部とか)をモジュール化するのだろうが、今回は一つのクラスだけが属しているモジュールとして、Kazz.gwt.xmlを作成する。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.2.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.2.0/distro-source/core/src/gwt-module.dtd"> <module rename-to="kazz"> <inherits name="com.google.gwt.user.User" /> <inherits name="com.google.gwt.i18n.I18N"/> <inherits name="com.google.gwt.resources.Resources" /> <source path="client" /> </module>
基本的には必要な他のモジュールをinheritするだけで良いと思う。
他のモジュールで参照する
他のモジュールで参照する場合、Javaクラスのクラスパスとは別にモジュールをinheritする必要がある。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.2.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.2.0/distro-source/core/src/gwt-module.dtd"> <module rename-to="addressbook"> <inherits name="org.kazz.gwt.Kazz" /> <!-- 使用するモジュールをInherit --> <source path="client" /> <entry-point class="net.kazzz.client.AddressBook" /> </module>
UiBinderからTextBox5を利用する
上記方法で実装、モジュール化したWidgetはGWTアプリケーションからは勿論のこと、UiBinderから使うこともできる。
これはGWTDesignerで拙作の住所録UIをUiBinderで作成している所だが、入力に使用しているTextBoxはTextBox5クラスを使用しているのが分かる。実際にplaceholderプロパティを設定しているのも分かるだろう。まだコンポーネントパレットに登録していないのでXML側ではネームスペースも含めて手動で追加する必要がある。
- AddressBookUi.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:j="urn:import:org.kazz.gwt.client.widget" <== TextBox5を使用するために追加したネームスペース > <g:HTMLPanel styleName="{style.AddressInfo}"> <g:Grid ui:field="pnlAddressInfo"> <g:row> <g:customCell><g:Label ui:field="lblFullName" text="氏名"/></g:customCell> <g:customCell><j:TextBox5 ui:field="txtFullName" visibleLength="20" placeHolder="例) 山田太郎" /></g:customCell> </g:row> <g:row> <g:customCell><g:Label ui:field="lblAddress" text="住所"/></g:customCell> <g:customCell><j:TextBox5 ui:field="txtAddress" visibleLength="50" placeHolder="例) 東京都千代田区外神田"/></g:customCell> </g:row> <g:row> <g:customCell><g:Label ui:field="lblEmail" text="e-mail"/></g:customCell> <g:customCell><j:TextBox5 ui:field="txtEmail" visibleLength="25" placeHolder="例) mail@example.com"/></g:customCell> </g:row> : : </ui:UiBinder>
ここで素晴らしいのは拡張したクラスに合わせて追加したクラス(TextBox5)のためのXML名前空間もきちんと補完されることだ。
前回のエントリで解説したように、UiBinderで定期したクラスはui:fieldで指定したフィールド名で参照することができる。
- AddressBookUi.java
@UiField Label lblFullName; @UiField TextBox5 txtFullName; @UiField Label lblAddress; @UiField TextBox5 txtAddress; @UiField Label lblEmail; @UiField TextBox5 txtEmail;