GWTの拡張(2) - ローディングパネル
GWT(Google Web Toolkit)はサーバ間通信を非同期で行う。
このため、入力したコード値に対応する名称をサーバから非同期で取得して画面に表示する際に、リクエスト処理中であることを表示するためにはアプリケーション側で制御する必要がある。
特に、こうした非同期処理を複数項目に対して適用したい場合には、複数の非同期通信が裏で行われることになるため、制御が難しくなる。
そこで、LoadingPanel
(ローディングパネル)を作成した。ブラウザの特定の位置に、ぐるぐる回るアニメーション画像を表示するパネルで、非同期でサーバ通信中であることを表すために利用する。
パネルの仕様
1つの画面で複数の非同期通信を行う場合を考慮して、非同期通信が行われている間はパネルを表示し続け、非同期通信が全て終わった時にパネルが消えるようにする。
クラス概要
処理概要
- 非同期通信処理時に
show()
を呼ぶ。 Panel
は、内部のカウンタが0ならパネルを表示する。[Loading...]状態となる。Panel
は、内部でカウンタを持っていて、カウントアップする。- 非同期通信処理終了時にhide()を呼ぶ。
Panel
は、カウントダウンする。カウントが0なら、パネルを消す。
hideAll()
は、カウントを0にし、パネルを消す。
このhideAll()
は、非同期通信処理中にメニューなどへ画面遷移した場合に、非同期通信処理をキャンセルし、パネルを消す場合に利用する。
import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; public class LoadingPanel extends Composite implements ResizeHandler { interface PanelPositionSetter { void setPosition(Element element); } private SimplePanel panel = new SimplePanel(); private PanelPositionSetter positionSetter; private int loadCount = 0; public LoadingPanel() { this(createWidget()); } public LoadingPanel(final Widget widget) { this(widget, createPositionSetter()); } LoadingPanel(final Widget widget, final PanelPositionSetter positionSetter) { initialize(widget, positionSetter); } @Override public void onResize(final ResizeEvent event) { positionSetter.setPosition(this.getElement()); } public void show() { setVisible(true); if (loadCount == 0) { DOM.setStyleAttribute(RootPanel.get().getElement(), "cursor", "progress"); RootPanel.get().add(this); panel.getElement().getStyle().setPosition(Position.ABSOLUTE); panel.getElement().getStyle().setZIndex(999999); positionSetter.setPosition(panel.getElement()); } loadCount++; } public void hide() { loadCount--; if (loadCount <= 0) { RootPanel.get().remove(this); DOM.setStyleAttribute(RootPanel.get().getElement(), "cursor", ""); } } public void hideAll() { loadCount = 0; hide(); } public void setPositionSetter(final PanelPositionSetter positionSetter) { this.positionSetter = positionSetter; } protected void initialize(final Widget widget, final PanelPositionSetter position) { initWidget(panel); panel.setWidget(widget); panel.getElement().setAttribute("name", "loadingPanel"); panel.getElement().setClassName("loadingPanel"); setVisible(false); this.positionSetter = position; } protected Widget createWidget() { return new Image("./loading.gif"); } protected PanelPositionSetter createPositionSetter() { // 右上に表示 return new PanelPositionSetter() { @Override public void setPosition(final Element element) { final int WINDOWS_IE_SCROLL_BAR_SIZE = 17; int top = DOM.getElementPropertyInt(RootPanel.getBodyElement(), "scrollTop"); int left = Window.getClientWidth() - element.getOffsetWidth() - WINDOWS_IE_SCROLL_BAR_SIZE - DOM.getElementPropertyInt(RootPanel.getBodyElement(), "scrollLeft"); element.getStyle().setTop(top, Unit.PX); element.getStyle().setLeft(left, Unit.PX); } }; } }
なお、このローディングパネルのアイディアは、以下の書籍の「第8章 ブログエディタアプリケーション」で紹介されているLoadingPanelを参考にした。
- 作者: ライアン・デュースバリー,Ryan Dewsbury,松田晃一,由谷哲夫
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2008/12/22
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 32回
- この商品を含むブログ (14件) を見る
[高橋 友樹]