株式会社antsのホームページへようこそ。

Flash JavaScript APIでオーサリングを効率化(その3)

0
Posted in Lab. By tanaka

JSFLネタ3回目は、前回作ったコマンドにダイアログボックスをつけてみようの巻です。ちょっと面倒くさいですが、これができるとアレをやったりコレをやったり夢がふくらみます。ダイアログボックスはXMLで用意する方法とSWFで用意する方法があります。まずはXMLの方から試していきましょう。


Flash JavaScript APIでオーサリングを効率化(その3)

JSFLネタ3回目は、前回作ったコマンドにダイアログボックスをつけてみようの巻です。ちょっと面倒くさいですが、これができるとアレをやったりコレをやったり夢がふくらみます。ダイアログボックスはXMLで用意する方法とSWFで用意する方法があります。まずはXMLの方から試していきましょう。

XULでダイアログボックスを作ろう

Flashは、XMLでユーザインターフェースを定義するXUL(XML-based User-interface Language)のサブセットをサポートしています。ヘルプ→FlashユーザーガイドにXML to UIという項目があるので、タグの一覧に目を通すとだいたい何ができるか想像つきますよ。これを見ながら、基準点の位置を選択できるようなダイアログボックスを組んでみます。ファイル名はdialog.xmlにしました。

<dialog.xml>

<?xml version="1.0" encoding="UTF-8"?>
<dialog id="regpoint_ui" title="基準点の変更" buttons="accept, cancel">
  <radiogroup id="align" groupbox = "true">
    <hbox>
      <radio label="左上" selected="true"/>
      <radio label="上" selected="false"/>
      <radio label="右上" selected="false"/>
    </hbox>
    <hbox>
      <radio label="左" selected="false"/>
      <radio label="中央" selected="false"/>
      <radio label="右" selected="false"/>
    </hbox>
    <hbox>
      <radio label="左下" selected="false"/>
      <radio label="下" selected="false"/>
      <radio label="右下" selected="false"/>
    </hbox>
  </radiogroup>
</dialog>

うーん、ラジオボタンだけで済んでしまってサンプルとしてはアレですが・・・。まあ組み方はだいたい分かりますよね。さて、このダイアログをどうやって表示するんでしょう?次のJSFLを見てください。

ダイアログを表示するサンプルJSFL

var path = fl.configURI + "Commands/dialog.xml";
var panel = fl.getDocumentDOM().xmlPanel(path);
if (panel.dismiss == "accept") {
  alert(panel.align + "が選択されました");
} else {
  alert("キャンセルされました");
}

こんな風にdocument.xmlPanel()メソッドに対してダイアログのXMLファイルを指定してあげると開くことができます。fl.configURIは、FlashのConfigulationディレクトリまでのパスを示すプロパティです。ここではdialog.xmlをJSFLと同じCommandsフォルダに入れてあるのでこのように指定にしましたが、別にJSFLと同じ場所に置く必要はありません。

■XULで作ったダイアログボックス
XULで作ったダイアログボックス

で、ダイアログの[OK]や[キャンセル]が押されると続きのJSFLが実行されるのですが、そのときxmlPanel()メソッドの戻り値としてダイアログボックス内の各値を保持したObjectオブジェクトが返ってきます。ダイアログに配置した各コントロールのidがプロパティ名になるのですが、それに加えてdismissというプロパティがあり、ユーザがOKしたのかキャンセルしたのか調べられます。OKのときは”accept”、キャンセルのときは”cancel”という値になります。

上のサンプルではOKのときに選択された値を表示しています。XULでラジオボタンのグループにalignというidを指定しているので、panel.alignで取得できるわけです。alignなんてぶつかりそうな名前は使うなというお叱りはごもっともですが、それはさておき取得できる値がlabelの値なんですよね。日本語を使っていたらそれをスクリプト処理することになるのでイヤな予感がしますね。

ちなみに今気づいたのですが、JSFLで日本語を扱いたいときはShift-JISで保存しないとダメみたいです。UTF-8で保存してたらアラートが文字化けしてしまいました。それに合わせてダイアログのほうもShift-JISにしてみたら、こっちはUTF-8じゃないと文字化けします・・・さらにイヤな予感。

やっぱりSWFでダイアログボックスを作ろう

肝心なダイアログ、ダサいです。こんなんじゃあ基準点を選ぶ気になれません。でもまあ今回の目的に合わないだけであって、悪いのはぼくです。XULは手っ取り早くインターフェースが作れて素晴らしいですよ!というわけで今回の目的に合ったインターフェースをSWFで作ってみましょう。

ダイアログであることはあまり気にせず、いつも作っているようにflaを組めばいいんです。うん、こんな感じ!基準点を選ぶと言ったらコレです。しかも従来の倍サイズにして押しやすくしてみましたよ。とりあえず基準点の位置を選べるようにスクリプトを仕込んで、[OK][キャンセル]ボタンは・・・面倒だからUIコンポーネントを置いときます。

■SWFで作ったダイアログボックス
XULで作ったダイアログボックス

このダイアログの表示方法は後で説明するとして、SWF内に適当に置いた[OK]ボタンを押すとXULのときみたいにFlashが反応するんでしょうか?もちろんそんなことはありません。ボタンにそれ相応のスクリプトを割り当てて、明示的にFlashを操作する必要があります。そこで使うのがActionScriptのMMExecute()関数です。この関数は引数にストリングとして渡したJSFLを実行することができます。

例えば、ダイアログをキャンセルするにはJSFLでfl.xmlui.cancel()メソッドを実行すればよいので、SWFの[キャンセル]ボタンから直接実行するならこんな感じです。

ActionScriptからダイアログをキャンセルするサンプル

cancel_btn.onRelease = function():Void {
  MMExecute("fl.xmlui.cancel();");
};

[OK]ボタンを押したときは、ダイアログを閉じて特定のJSFLを実行したいですね。ダイアログを承認状態で閉じるにはJSFLでfl.xmlui.accept()メソッドを実行するのですが、この処理は実行するJSFL側に含めてしまえばオッケーです。JSFLにはfl.runScript()というメソッドがあって、指定したスクリプトファイルを実行できます。スクリプトファイル内の関数とパラメータも指定できるので、これを利用しましょう。例えば・・・

ActionScriptからJSFLを実行するサンプル

ok_btn.onRelease = function():Void {
  var jsfl:String = 'fl.configURI + "Commands/moveRegistrationPoint/command.jsfl"';
  var func:String = 'moveRegistrationPoint';
  var param:String = "LT";
  MMExecute('fl.runScript(' + jsfl + ',"' + func + '","' + param + '");');
};

といったようにスクリプトファイルcommand.jsfl内の関数moveRegistrationPoint()にパラメータ”LT”を渡して実行できるのです。もちろん実際はパラメータは固定じゃありませんよ。サンプルflaファイルをダウンロードできるようにしておきますので、実物はそちらを見てください。ってことでダイアログとして表示してみましょう。JSFLからつぎのように呼び出します。

<基準点を変更.jsfl>

var path = fl.configURI + "Commands/moveRegistrationPoint/dialog.xml";
var panel = fl.getDocumentDOM().xmlPanel(path);

実際にコマンドとしての処理を行うJSFLはcommand.jsflという別ファイルにするので、Flashの[コマンド]メニューから呼び出すJSFLはこれだけです。「基準点を変更.jsfl」とでも保存しておきましょう。あれ?ダイアログの呼び出し方がXMLのときと同じじゃん、と思うかも知れませんが、dialog.xmlの中身が違うんです。

<dialog.xml>

<?xml version="1.0" encoding="UTF-8"?>
<dialog id="regpoint_ui" title="基準点の変更">
  <flash id="regpoint_ui" width="240" height="120" src="dialog.swf" />
</dialog>

こうやってXULのコントロールの代わりにSWFを指定するようにしておくんですね。

ダイアログボックス付きのコマンドにしよう

ダイアログの作り方や値の取得方法がわかったところで、前回のコマンドを拡張して終わりにしましょう。SWFのダイアログから呼び出すcommand.jsflとして作りますよ。拡張後のスクリプトはこんな感じです。そんなには変わってませんけど。

SWFのダイアログから呼び出すcommand.jsfl

function moveRegistrationPoint(align) {
  fl.xmlui.accept();

  var doc = fl.getDocumentDOM();
  var items = doc.library.getSelectedItems();
  for (var i = 0; i < items.length; i++) {
    doc.library.editItem(items[i].name);
    doc.selectAll();
    var rect = doc.getSelectionRect();
    var w = rect.right - rect.left;
    var h = rect.bottom - rect.top;

    //基準点の位置を変更(水平)
    var l = -w / 2;
    if (align.indexOf("L") > -1) l = 0;
    else if (align.indexOf("R") > -1) l = -w;
    //基準点の位置を変更(垂直)
    var t = -h / 2;
    if (align.indexOf("T") > -1) t = 0;
    else if (align.indexOf("B") > -1) t = -h;

    doc.setSelectionBounds({left:l, top:t, right:l + w, bottom:t + h});
    doc.exitEditMode();
  }
}

SWFからは引数として”LT”, “T”, “RT”, “L”, “”, “R”, “LB”, “B”, “RB”のいずれかを渡すようにしていて、その値によって水平・垂直の基準点の位置を変更するようにしてます。中央にしかできなかった前回に比べ、だいぶ幸せになりました。ファイル構成は、Commandsフォルダ直下に「基準点を変更.jsfl」とmoveRegistrationPointフォルダを作り、このフォルダにdialog.xml、dialog.swf、command.jsflをまとめました。これらのファイルはフォルダにまとめた方がファイル名に悩まず済むし、余計なJSFLが[コマンド]メニューに表示されなくなりますよ。

■ファイル構成はこんな感じ
ファイル構成はこんな感じ

ということで3回に渡って書いてみたJSFLネタはこれにて終了です。みなさんもこれは便利というコマンドが出来たらどしどし配ってください。少なくともぼくにはください。あ、配布方法について書いてない。次回書いたほうがいいかな。

■今回のサンプルをダウンロード
sample.zip