ViewHelperを使ったPopUpについて考えてみる。

CairngormでViewHelperを使っているコンポーネントをPopupしたい場合どうするか、という話です。
ちょっと卵が先かニワトリが先か、ということで考えてしまったのでメモ。

Cairngormでは、ViewLocatorを使ってViewとロジックを分離します。
アプリケーションの見た目に関る部分はMXMLに記述して、動作に関る部分はViewHelperに記述することで
見た目と動作を別のものにするわけですね。
具体的にはMXMLの中でそのViewに該当するViewLocatorを宣言しておきます。
Hogeというコンポーネントに対するViewHelperがHogeViewHelperならこんな感じです。

 
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	xmlns:viewhelper="hoge.viewhelper.*" >
	<viewhelper:HogeViewHelper id="hogeViewHelper" />
 

そうするとHogeViewのインスタンスが生成された時に
HogeViewHelperのインスタンスが生成されて、
HogeViewHelperのviewフィールドにHogeViewのインスタンスへの参照が設定されます。
で、あわせてViewLocatorにMXMLで指定したHogeViewHelperのidをキーとして
(Cairngormのドキュメントで言うところのcanonical name)
HogeViewHelperのインスタンスが登録されます。
後はViewLocatorのインスタンスにgetViewHelper("hogeViewHelper")とすると
HogeViewHelperのインスタンスを返してくれます。

もう少しつっこんで書くと、
HogeViewHelperのスーパクラスであるViewHelperクラスには
initializedメソッドが定義されていて、
このメソッドの中で自身のviewとidを設定して、
対象となるViewに対してイベントリスナを設定しています。
イベントリスナはEvent.ADDEDとEvent.REMOVEDで
対象となるViewが表示対象となった時には
ViewLocatorに対して自身を登録して、
対象となるViewが表示対象外となった時には
ViewLocatorに対して自身をします。

つまり、ViewHelperの準備が完了するには以下のステップがあります。

  1. ViewHelperが設定されたViewのインスタンスが生成される。
  2. ViewHelperのインスタンスが生成される。
  3. ViewHelperがimplementsしているIMXMLObjectのinitializedメソッドが呼ばれる。
  4. initializedメソッドの中でViewHelperのidフィールドとviewフィールドが設定される。
  5. initializedメソッドの中でViewに対してイベントリスナが登録される。
  6. Viewが表示対象となる。(ApplicationでaddChildされるとか)
  7. イベントリスナに登録されたコールバックメソッドの中でViewHelperがViewLocatorに登録される。

これでようやくViewLocatorからViewHelperが取得できるようになるわけです。
反対にViewが表示対象外(ApplicationでremoveChildされるとか)すると
イベントリスナに登録されたコールバックメソッドの中でViewLocatorからViewHelperが削除されます。

はい、長々書きましたけど次に進みます。
FlexでPopUpを実現するには、PopUpManagerというクラスの3つのスタティックメソッドを使います。
シグネチャはこんな感じになってます。

 
public static function addPopUp(window:IFlexDisplayObject, parent:DisplayObject, modal:Boolean = false, childList:String = null):void
public static function createPopUp(parent:DisplayObject, className:Class, modal:Boolean = false, childList:String = null):IFlexDisplayObject
public static function removePopUp(popUp:IFlexDisplayObject):void
 

addPopUpかcreatePopUpでPopUpを表示して、removePopUpでPopUpを削除します。
addPopUpとcreatePopUpの違いは、
PopUpの対象をインスタンスで指定するか(addPopUp)
クラス名で指定するか(createPopUp)の違いです。

何も考えずApplicationの中でPopUpするなら、こんなコードを書くわけです。

 
var hogeView:HogeView = new HogeView();
PopUpManager.addPopUp(hogeView, this, true);
 

さて、ViewHelperを使うならどうしましょう。
しれっと考えるとViewHelperの中にpopUpとかいうメソッドを作って
それを呼びたいところですが、Viewのインスタンスが存在していないと
ViewHelperのインスタンスも存在していません。
ViewHelperがViewLocatorに登録されるのは
Viewが表示対象になった後なので、こんなコードもアウトです。

 
var hogeView:HogeView = new HogeView();
var hogeViewHelper:HogeViewHelper = HogeViewHelper(ViewLocator.getInstance().getViewHelper("hogeViewHelper"));
hogeViewHelper.popUp();
 

Viewが表示対象になるまではViewLocatorからViewHelperを取得できないので
PopUpしてからじゃないとViewHelperを使うことができない。ということです。
付け加えておくと、PopUpするためにはPopUp対象となる親コンポーネントを指定する必要があるので
親コンポーネントのViewHelperにViewを返すメソッドを定義しておいて、
子コンポーネントのViewHelperから親コンポーネントのViewHelperを取得して
親コンポーネントのViewHelperから親コンポーネントを取得してっていう
何やらスパゲッティな予感漂う実装になっちゃいますね。

はい、ということでこんな感じの実装はどうでしょう。
まず親コンポーネントのViewHelperにこんなメソッドを用意しておきます。

 
		public function createPopUp(className:Class, modal:Boolean = false, childList:String = null):IFlexDisplayObject {
			var parent:DisplayObject = ;
			return PopUpManager.createPopUp(parent, className, modal);
		}
 

で、PopUpする子コンポーネントのViewHelperにはこんなメソッドを。

 
		public function close():void {
			var window:IFlexDisplayObject = IFlexDisplayObject(this.view);
			PopUpManager.removePopUp(window);
		}
 

closeメソッドはこんな感じ親コンポーネントに実装することもできるでしょうけど

 
		public function close():void {
			var hogeViewHelper:HogeViewHelper = HogeViewHelper(ViewLocator.getInstance().getViewHelper("hogeViewHelper"));
			var window:IFlexDisplayObject = IFlexDisplayObject(hogeViewHelper.getView());
			PopUpManager.removePopUp(window);
		}
 

これだとHogeViewHelper側にViewを返すメソッド(getView())が必要になるので
ちょっといやな予感がしますね。
ちなみに親コンポーネントのViewHelperのcreatePopUpは、
addPopUpメソッドでもいける・・・と思います・・・試してませんけど^^;
PopUpManagerのremovePopUpメソッドが実行された時には、
REMOVEDなEventがdiapatchされますので、
ViewLocatorからHogeViewHelperの登録は削除されます。
つまり、後処理もちゃんとしてくれてるってことですね。

Category: Flex | Posted on: 2007/11/21 11:57 | Viewed: 3121

Comments

2010/07/16, 00:04 pluncled-online wrote:

Yes, correctly.

Add Comment

:

:
:

TrackBacks

このエントリにトラックバックはありません

TrackBack URL

http://www.azul.systems-noel.jp/trackback/item_76.html