Flex4 sparkコンポーネントのTextAreaでENTERの改行をキャンセルするには
Flex4.1でもってAIRでの話です。
mxコンポーネントのTextAreaでは改行をキャンセルするやりようがあるのですが、SparkではText Layout Frameworkが使われるようになって様変わりしてしまいました。
結論から先に書いとくと、改行のキャンセルできます。ただし、ControlやAltキーとの組み合わせなどの場合は多少工夫が必要です。
一応話の前提として、下はmxコンポーネントでのやり方を書かれておられるブログ記事へのリンクです。
http://nnekuro983.blogspot.com/2010/12/flextextarea.html
sparkのTextAreaは文字の実体部分がRichEditableTextになっていますが、multilineというプロパティがtrueになっています。
ソースコードの中を追っかけていくと、これがtrueになっていると、困ったことに改行をとれないんですね。
なんでかというと、例えば文中にhtmlタグを埋め込んだりとか、wysiwigみたいなことしたりとか、他にも色々とリッチな事が出来るようになってる関係であえて?握りつぶしてるみたいです。
このへん、詳細は省きますが、一つ一つのパラグラフをオブジェクトとして扱えるというのが今回のうり?らしいので・・。
で、それの関係上、内部的にはFlexEvent.ENTERを発行せず、splitParagraphというのを呼んで、段落を2 つのエレメントに分割という処理を行っています。
なので、mxコンポーネントのように、TEXT_INPUTで待ち受けて改行処理を無効化でません。
ではどうするのか?
一番手っ取り早いのはsparkのTextAreaを使うのをやめて、mxコンポーネントのTextAreaを使うことです。しかし、今回はspark用に作っていただいたskinを当てなければ行けないという事情がありこれは却下しました。
TextArea,RichEditableText等、片っ端から継承したカスタムクラスを作成して該当部分をオーバーライドするという方法もあります。しかし、これもSkinも含めると影響範囲が大きすぎてコストに見合わないので却下しました。
で、フレームワークのソースコードを追っかけたり、デバッグしたり、海外のフォーラムをあさったりして*1うんうん唸っていたのですが、発見しました。
TextOperationEvent.CHANGINGで、引っかける、です。
この、TextOperationEventを待ち受けるとeventにはoperationというFlowOperation型のインスタンスが渡ってきます。
これが、色々リッチなオペレーション処理を実行するオブジェクトの実体というわけです。
で、前述の段落分割にはそれを受け持つ、SplitOperationというFlowOperationのサブクラスがいて、分割処理を行います。
注意すべきは、SplitOperationは、TextOperationEvent.CHANGEではとれないという事です。
ちなみにCHANGINGは編集操作が発生する前に送出で、CHANGEは編集操作完了後に送出です。
というわけで、サンプルコードです。
//........................ <fx:Script> <![CDATA[ //イベントリスナー登録 protected function textArea_creationCompleteHandler(event:FlexEvent):void{ textArea.addEventListener(TextOperationEvent.CHANGING,onChangingHandler); } //SplitParagraphOperationが来たときのみキャンセル private function onChangingHandler(event:TextOperationEvent):void { if(event.operation is SplitParagraphOperation){ event.preventDefault(); } } ]]> </fx:Script> <s:TextArea id="textArea" width="100" creationComplete="textArea_creationCompleteHandler(event)" height="60" /> //........................................
なお、実際にはただ改行をキャンセルするのではなく、Alt+EnterやCtrl+Enterといった他のキーと組み合わせた場合のみキャンセルという処理でした。その場合、上で書いたようにもう一工夫必要です。
なぜ工夫が必要かというと、TextOperationEvent.CHANGINGはKeyboadEvent.KEY_DOWNより先に発行されるからです。
なので、問答無用にキャンセルではなく、CHANGINGの段階でとりあえず何か保持しておいて、KEY_DOWN又はKEY_UPでキーコードをみて判定という形になります。
しかし、これってもしかしてバグなんですかね?
*1:観測範囲では残念ながら情報皆無でした