Spark 勉強会 #2に行けなくて一人スパークしてみようと、昨日エントリーした「ProxyなAdapter」ですが、もう少し便利にしたいなぁということで細々改善してみました。あと、Proxyを継承して動的(dynamic)にしている関係で、指がヌルい僕にとってはFlashDevelopの補完ができずに、まだまだ指ダレしてしまう。なわけで、補完の聞く静的なAdapterをどうにかしようと。静的だといろいろ効率よさそうですし。
なわけで、現状のソースはこれです
以下、変わったところについて。
FAdapter リスナの停止・再開
前のものは、リスナの停止・再開を abort()、resume()で行うようにしていました。それに加えて以下の書き方でも通るようにしました。
var adapter:FAdapter = new FAdapter(stage);
adapter.click = function( e:MouseEvent ):void
{
trace( "test1", e.type )
};
//停止 adapter.abort("click") と同じ
adapter.click = false;
//再開 adapter.resume("click") と同じ
adapter.click = true;
FAdapter 一度きり受ける
一回のみイベントを受けたい場合(onCompleteとか)がよくあると思うのですが、そんなときはこれ。一度イベントが送出されると自動で removeListener されます。
adapter.complete = function( e:Event ):void
{
trace( e.type );
};
FAdapter.oneTime( adapter.complete );
このメソッドは FAdapter の static メソッドです。
FAdapter イベントのフィルタ
条件付きでイベントを受けたいときもあるだろうということで、そんなときはこれ。filterで指定した関数が true を返すときだけイベントが送出されます。
var flg:Boolean = false;
function filter( e:MouseEvent ):Boolean
{
return flg;
}
FAdapter.filter( adapter.click, filter );
このメソッドも FAdapter の static メソッドです。このメソッドには第3引数があって、以下のように書くと、filter関数が false を返すと removeListener されます。
var count:int=0;
adapter.mouseDown = function( e:MouseEvent ):void
{
count++;
trace( count );
};
function filter( e:MouseEvent ):Boolean
{
return (count
FAdapter.oneTime(),FAdapter.filter()で条件設定をしたリスナは、以下のようにして条件解除できます。
FAdapter.clearFilter( adapter.mouseDown );
静的なアダプタ
続いて静的なアダプタについてです。静的なアダプタは、FAbstractFixAdapter クラス を継承することで実現しています。このクラスは、FAdapter を内部に持ち処理を委譲しています。また、抽象クラスのつもりなので、このクラス自体は使いません。実際使う場合のサンプルは、adapters 内を見てください。
FMouseAdapter クラスを例に簡単に説明してみます。
リスナの登録や削除は、FAdapterと若干異なります。異なるというか方法が限定的です。
var adapter:FMouseAdapter = new FMouseAdapter( stage );
function handler( e:MouseEvent ):void
{
trace(e);
}
//登録
adapter.click = handler;
//停止
adapter.click = false; // or adapter.abort("click");
//再開
adapter.click = true; // or adapter.resume("click");
//削除
adapter.click = null;
//usecaptureなどを設定して登録
adapter.click = adapter.makeListenerInfo( handler, false, 1000, false );
//全削除
adapter.removeAll();
//付け替え
adapter.dispatcher = new AnyDispatcherClass();
一応、FAdapter.oneTime(), FAdapter.filter() を適用することもできます。
FAdapterにないメソッドとして、bind() があります。これは、targetに該当するメソッドがあれば一括でリスナ登録をするものです。
※バインドのルールとかいじれるようにしたいけど、今はないです。なのでバインドとは呼べないのでは
package
{
import flash.display.Sprite;
import flash.events.Event;
import snapfit.events.adapters.FInteractiveAdapter;
import snapfit.events.FAdapter;
public class MySprite extends Sprite
{
private var adapter:FInteractiveAdapter;
public function MySprite()
{
super();
adapter = new FInteractiveAdapter(this);
//登録
adapter.bind(this);
FAdapter.oneTime( adapter.addedToStage );
FAdapter.oneTime( adapter.removedFromStage );
}
public function addedToStage( e:Event ):void
{
trace( e );
}
public function removedFromStage( e:Event ):void
{
adapter.removeAll();
trace( e );
}
public function enterFrame( e:Event ):void
{
trace( e );
}
}
}
この bind() には問題があって、handler関数のスコープ(private等)によっては見えないので登録ができないんです。まぁやっかいでして。今のところ名前空間をあててなんとなくやる感じにしています。
package
{
import flash.display.Sprite;
import flash.events.Event;
import snapfit.events.adapters.FInteractiveAdapter;
import snapfit.events.FAdapter;
//bind用の名前空間
import snapfit.events.ns_fadapter;
public class MySprite extends Sprite
{
private var adapter:FInteractiveAdapter;
public function MySprite()
{
super();
adapter = new FInteractiveAdapter(this);
adapter.bind(this);
}
ns_fadapter function enterFrame( e:Event ):void
{
trace( e );
}
}
}
名前空間をあてるにせよ付け焼き刃的対処なので、何かいい方法ないかなぁとか思うのですが。
まとめみたいな
課題やデバッグはあれですが何となく使えそうなかたちになってきたかなぁと思ってます。課題は、先の bind の件と一つのイベントタイプにリスナが一つしか登録できないところでしょうか。後のものは大抵1対1だろうからいいのかなぁとは思ってますが、何かいい方法があれば改善しようと。Dictionary使えばなんとかなりそうですが。一応、暫定ですが SparkProject にコミットしておきました。
ブラウザ:
https://www.libspark.org/browser/as3/snapfit/trunk/src/snapfit/events
SVN:
https://www.libspark.org/svn/as3/snapfit/trunk/src
一人スパーク完了。ということで。