GWTPプレゼンタの作成
以下の記述は少々古い。後に書き直す予定。
手作業で新たなプレゼンタを作成してみる。
なお、前提として、Eclipseプラグインの「GWTP Project」でプロジェクトを作成する際に、「Generate gwtp-sample-basic」を選択してサンプルコードを生成済みであるとする。
基本的なステップ
ここでは、ごく基本的なステップで最低限の表示ができるまでを記述する。なお、パッケージ名の上位部分は省略している。
- NameTokensへの追加
- Presenterの作成
- Viewの作成
- ClientModuleへの追加
- Injectorへの追加
NameTokensへの追加
client.place.NameTokensクラスにPlaceの名称を登録する。Placeというのは、いわばGWTP内でページ切り替えを行う場合の「ページ」にあたる。
GWTでは、基本的に使用するhtmlページはただ一つだけで、その中で仮想的なページ切り替えを行うが、それをPlaceと称している。
public class NameTokens {
public static final String main = "main";
public static final String response = "response";
public static final String something = "something";
...
他のPlaceにならってgetSomething()などのメソッドを付加する必要は無い。
Presenterの作成
Presenterは、MVCを改良したMVPモデルのPにあたる。簡単に言えばコントローラの役割である。
Presenterの名称は慣習的にPresenterで終了しなければならない。
SomethingPresenter.java
package com.example.myproject.client.core;
import com.example.myproject.client.place.*;
import com.google.gwt.event.shared.*;
import com.google.inject.*;
import com.gwtplatform.dispatch.shared.*;
import com.gwtplatform.mvp.client.*;
import com.gwtplatform.mvp.client.annotations.*;
import com.gwtplatform.mvp.client.proxy.*;
public class SomethingPresenter extends
Presenter<SomethingPresenter.MyView, SomethingPresenter.MyProxy> {
@ProxyStandard
@NameToken(NameTokens.something)
public interface MyProxy extends ProxyPlace<SomethingPresenter> {}
public interface MyView extends View {}
@Inject
public SomethingPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, final DispatchAsync dispatcher, final PlaceManager placeManager) {
super(eventBus, view, proxy);
}
@Override
protected void revealInParent() {
RevealRootContentEvent.fire(this, this);
}
}
特にMyProxyにつけられている@NameTokenは重要。この引数を間違えると動作しない。
Viewの作成
ViewはGUI部分になる。これにはSomethingPresenter.MyViewを実装させる。
package com.example.myproject.client.core;
import com.google.gwt.user.client.ui.*;
import com.google.inject.*;
import com.gwtplatform.mvp.client.*;
public class SomethingView extends ViewImpl implements SomethingPresenter.MyView {
private static String html = "<div id=\"something\"></div>\n";
private final HTMLPanel panel = new HTMLPanel(html);
@Inject
public SomethingView() {
Button someButton = new Button("do something");
panel.add(someButton, "something");
}
@Override
public Widget asWidget() {
return panel;
}
}
ちなみにHTMLパネルではなく、LayoutPanelなどを使えば普通にGWT DesignerでGUI構築が可能。
ただし、その場合、Presenter側のrevealInParentメソッドによって、ルートとなるパネルがRootPanel相当(?)かRootLayoutPanel相当(?)のいずれかになるかが決まるのでそれを考慮しなければならない(後述)。
ClientModuleへの追加
client.gin.ClientModuleのconfigure()メソッドに以下を追加して、GINがこれらを扱えるようにする。
bindPresenter(SomethingPresenter.class, SomethingPresenter.MyView.class,
SomethingView.class, SomethingPresenter.MyProxy.class);
Injectorへの追加
client.gin.ClientGinjectorに以下を追加し、SomethingPresenterを注入できるようにする。
Provider<SomethingPresenter>getSomethingPresenter();
動作確認
DevelopModeでメインページを表示した後、URLの最後に#somethingをつける。つまり、
http://127.0.0.1:8888/gwtp.html?gwt.codesvr=127.0.0.1:9997#something
といったURLになる。これで「do something」ボタンが表示されれば成功である。
他の方法としては、MainPagePresenterの
// Then, we transmit it to the ResponsePresenter, which will do the server call
placeManager.revealPlace(new PlaceRequest(NameTokens.response).with(
ResponsePresenter.textToServerParam, textToServer));
の部分を
placeManager.revealPlace(new PlaceRequest(NameTokens.something));
に変更する。この場合、デフォルトプレースのSendボタンをクリックすると画面が切り替わる。
うまくいかない場合のチェック事項
新規作成したPresenter/Viewに全く画面遷移しない場合がある。この場合、エラーらしいものは表示されず、常にデフォルトプレースの表示になってしまうので何が悪いのかわかりにくい。次をチェックしてみること。
- 新規Presenter内に定義したProxyのアノテーション。上記例の場合は「@NameToken(NameTokens.something)」が正しいか。
- NameTokens内に定義したトークン文字列に同じものが無いか。
- ClientModuleのconfigure()内で正しくbindPresenter()の呼び出しが行われているか。
- ClientGinjector内に正しくPresenter取得メソッドが定義されているか。
- 新規Presenterを追加した後に、Development Modeを再起動したか(クライアント側だけの問題であるが、再起動しないと動作しない)。
ルートパネルの変更
生のGWTではRootPanel.get()あるいはRootLayoutPanel.get()のどちらを呼び出すかによって、いずれのルートパネルにするかを決定していたが、
※後者の場合は、ブラウザ画面サイズ変更が伝播される。
GWTPの場合には、これをPresenterのrevealInParentメソッドで行う模様。つまり、
@Override
protected void revealInParent() {
RevealRootContentEvent.fire(this, this);
}
とすると、ViewのルートパネルとしてRootPanelが、
@Override
protected void revealInParent() {
RevealRootLayoutContentEvent.fire(this, this);
}
とするとRootLayoutPanelが使用される。
例えば、RootLayoutPanelにしておいて、SomethingViewをGWT Designerを使ってGUI構築することができる
(RootPanelでもできるがサイズ指定が必要)。
package com.example.myproject.client.core;
import com.google.gwt.user.client.ui.*;
import com.google.inject.*;
import com.gwtplatform.mvp.client.*;
import com.google.gwt.dom.client.Style.Unit;
public class SomethingView extends ViewImpl implements SomethingPresenter.MyView {
private final LayoutPanel panel = new LayoutPanel();
@Inject
public SomethingView() {
DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Unit.EM);
panel.add(dockLayoutPanel);
HorizontalPanel horizontalPanel = new HorizontalPanel();
horizontalPanel.setSpacing(5);
dockLayoutPanel.addNorth(horizontalPanel, 7.7);
Button btnNewButton = new Button("New button");
horizontalPanel.add(btnNewButton);
Button btnNewButton_1 = new Button("New button");
horizontalPanel.add(btnNewButton_1);
Button btnNewButton_2 = new Button("New button");
dockLayoutPanel.add(btnNewButton_2);
}
@Override
public Widget asWidget() {
return panel;
}
}
ディスカッション
コメント一覧
まだ、コメントがありません