Differences between revisions 13 and 14
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
= 新規プレゼンタの作成 = | 以下に移動しました。 |
Line 3: | Line 3: |
本来であればGWTPのEclipseプラグインを道入すれば、簡単にPresenter及びViewが作成されるはずだが、現在(2011/11/28)うまく動作していない。-->NameTokensを選択した後で、名称がnullのままだとNullPointerExceptionが発生してしまうのがその理由。指定すれば問題無い。 ここでは、手作業で新たなプレゼンタを作成してみる。 なお、前提として、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; } } }}} |
https://www.gwtcenter.com/gwtp-new-presenter |
以下に移動しました。