Revision 7 as of 2011-11-28 05:07:41

Clear message
Locked History Actions

GWT/GWTP/NewPresenter

新規プレゼンタの作成

本来であればGWTPのEclipseプラグインを道入すれば、簡単にPresenter及びViewが作成されるはずだが、現在(2011/11/28)うまく動作していない。ここでは、手作業で新たなプレゼンタを作成してみる。

なお、前提として、Eclipseプラグインの「GWTP Project」でプロジェクトを作成する際に、「Generate gwtp-sample-basic」を選択してサンプルコードを生成済みであるとする。

基本的なステップ

ここでは、ごく基本的なステップで最低限の表示ができるまでを記述する。なお、パッケージ名の上位部分は省略している。

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 ....client.core;

import com.cm55.gwtp.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 ......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)」が正しいか。

  • ClientModuleのconfigure()内で正しくbindPresenter()の呼び出しが行われているか。

  • ClientGinjector内に正しくPresenter取得メソッドが定義されているか。

ルートパネルの変更

生の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が使用される。