ActionScript 3.0で始めるオブジェクト指向スクリプティング

第41回Text Layout Frameworkへの外部XMLデータの読込みとユーザーインタラクション

前回の第40回Text Layout Frameworkでテキストコンテンツを表示するは、Text Layout Framework Markup形式のXMLデータを、フレームワークのクラスによりレイアウトして、ステージに表示した。今回は、まずXMLデータを外部ファイルから読込む。そのうえで、テキストの選択や編集など、ユーザーインタラクションを加えてみたい。

Text Layout Framework Markup形式のXMLデータを外部ファイルから読込む

XMLデータは、外部ファイルから読込めることが利点のひとつだ。つぎのようなText Layout Framework Markup形式のXMLデータを、外部ファイルtlf.xmlとしてFlashムービー(FLA)ファイルと同じ場所に保存しておく。これを読込んで、ステージに配置しよう。

<TextFlow xmlns='http://ns.adobe.com/textLayout/2008'>
  <p textAlign='center'>
    <span fontFamily='Impact' fontSize='18'>
    Using a TextFlow object to structure text data
    </span>
  </p>
  <p>
    <span>
    When you use the Text Layout Framework, text content is structured and stored in a TextFlow object.
    </span>
  </p>
</TextFlow>

外部XMLファイルの読込みは、第27回XMLデータを扱うですでに解説した。Text Layout Frameworkで扱うために、何かとくにしなければならないことはない。もっとも、フレームワークは、テキストの構造やフォーマット、そのレイアウトと表示などの役割を、それぞれのクラスが細かく分け合って担っていた第40回図3再掲⁠。そのため、慣れないうちは、処理の組立てに戸惑いやすい。そこで復習をかねてスクリプトを書いてみよう。

第40回図3 Text Layout Frameworkにおけるオブジェクトの関係(再掲)
第40回図3 Text Layout Frameworkにおけるオブジェクトの関係(再掲)

まず、読込んだText Layout Framework Markup形式のXMLデータからTextFlowインスタンスを生成する。つぎに、ContainerControllerインスタンスの参照をフローコンポーザーに渡したうえで、表示すればよかった。なお、TextFlowオブジェクトにはデフォルトのフォーマットを設定する。それには、第39回に学んだTextFlow.hostFormatプロパティを設定すればよい。つぎのスクリプト1が、そのフレームアクションだ。

スクリプト1 外部XMLデータをText Layout Frameworkで配置する
// フレームアクション
import flash.display.Sprite;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.formats.TextLayoutFormat;
var container:Sprite = new Sprite();
var markUp:XML;
var myFlow:TextFlow;
var controller:ContainerController = new ContainerController(container, 240, 100);
var composer:IFlowComposer;
var my_fmt:TextLayoutFormat = new TextLayoutFormat();
// 外部XMLファイルの読込み
var myLoader:URLLoader = new URLLoader();
var myRequest:URLRequest = new URLRequest("tlf.xml");
myLoader.addEventListener(Event.COMPLETE, xSetText);
myLoader.load(myRequest);
addChild(container);
// 読込み完了時の処理
function xSetText(eventObject:Event):void {
  markUp = XML(eventObject.target.data);
  myFlow = TextConverter.importToFlow(markUp, TextConverter.TEXT_LAYOUT_FORMAT);
  // デフォルトフォーマットの設定
  myFlow.hostFormat = my_fmt;
  my_fmt.fontFamily = "Helvetica";
  my_fmt.fontSize = 14;
  composer = myFlow.flowComposer;
  composer.addController(controller);
  composer.updateAllControllers();
}

[ムービープレビュー]を確かめると、本文には図1左図のようにTextFlow.hostFormatプロパティの設定が適用される。しかし、タイトルのエレメント(span)には属性としてフォーマットが指定されているため、その設定が優先する。デフォルトフォーマットには、Helveticaの14ポイントが指定してある。図1右図にはデフォルトフォーマットを定めない場合の表示を掲げたので、比べてほしい。

図1 エレメントに設定がなければデフォルトフォーマットになる
Helveticaの14ポイントをデフォルトに設定デフォルトフォーマットなし

Text Layout Frameworkにユーザーインタラクションを加える

つぎは、インタラクティブな操作だ。もっとも簡単なのは、テキストの選択だろう。[TLFテキスト]であれば、[プロパティ]インスペクタのテキストの種類で[選択可能]が選べる図2⁠。また、スクリプトなら、TLFTextField.selectableプロパティで設定が変えられる。

図2 [プロパティ]インスペクタで[TLFテキスト]のテキストの種類が選べる
図2 [プロパティ]インスペクタで[TLFテキスト]のテキストの種類が選べる

ところが、Text Layout FrameworkでTextFlowクラスなどをいくら探しても、このようなプロパティが見当たらない。ユーザーインタラクションは、別の新たなクラスが担うからだ。そのクラスのインスタンスは、TextFlow.interactionManagerプロパティに設定する。テキストが選択できるようにするには、SelectionManagerクラスのインスタンスを代入すればよい。

TextFlowオブジェクト.interactionManager = new SelectionManager();

前掲スクリプト1にこのステートメントを加え、SelectionManagerクラスをimport宣言したのが、つぎのスクリプト2だ。これで、配置したテキストが選択できる図3⁠。

スクリプト2 Text Layout Frameworkでテキストを選択できるようにする
// フレームアクション
import flash.display.Sprite;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.edit.SelectionManager;
var container:Sprite = new Sprite();
var markUp:XML;
var myFlow:TextFlow;
var controller:ContainerController = new ContainerController(container, 240, 100);
var composer:IFlowComposer;
var my_fmt:TextLayoutFormat = new TextLayoutFormat();
var myLoader:URLLoader = new URLLoader();
var myRequest:URLRequest = new URLRequest("tlf.xml");
myLoader.addEventListener(Event.COMPLETE, xSetText);
myLoader.load(myRequest);
addChild(container);
function xSetText(eventObject:Event):void {
  markUp = XML(eventObject.target.data);
  myFlow = TextConverter.importToFlow(markUp, TextConverter.TEXT_LAYOUT_FORMAT);
  myFlow.hostFormat = my_fmt;
  myFlow.interactionManager = new SelectionManager();
  my_fmt.fontFamily = "Helvetica";
  my_fmt.fontSize = 14;
  composer = myFlow.flowComposer;
  composer.addController(controller);
  composer.updateAllControllers();
}
図3 配置したテキストが選択できる
図3 配置したテキストが選択できる

TextFlow.interactionManagerプロパティには、EditManagerクラスのインスタンスを設定することもできる[1]⁠。すると、テキストをただ選ぶだけでなく、書替えられるようになる図4⁠。

// import flashx.textLayout.edit.SelectionManager;
import flashx.textLayout.edit.EditManager;   // 変更
function xSetText(eventObject:Event):void {
  // ...[中略]...
  // myFlow.interactionManager = new SelectionManager();
  myFlow.interactionManager = new EditManager();   // 変更
  // ...[中略]...
}
図4 TextFlow.interactionManagerプロパティにEditManagerインスタンスを設定するとテキストが編集できる
図4 TextFlow.interactionManagerプロパティにEditManagerインスタンスを設定するとテキストが編集できる
テキストを選択(左⁠⁠、テキストを書替え(右)
テキストを選択テキストを書替え

さらに、EditManagerクラスのコンストラクタメソッドには、UndoManagerオブジェクトが引数として渡せる。そのEditManagerインスタンスをTextFlow.interactionManagerプロパティに設定すると、編集の取消しややり直しができるようになる。前掲スクリプト2を修正して、テキストの編集と取消しまで可能にしたのがつぎのスクリプト3だ。

スクリプト3 Text Layout Frameworkでテキストを編集および取消しできるようにする
// フレームアクション
import flash.display.Sprite;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.edit.EditManager;
import flashx.undo.UndoManager;
var container:Sprite = new Sprite();
var markUp:XML;
var myFlow:TextFlow;
var controller:ContainerController = new ContainerController(container, 240, 100);
var composer:IFlowComposer;
var my_fmt:TextLayoutFormat = new TextLayoutFormat();
var myLoader:URLLoader = new URLLoader();
var myRequest:URLRequest = new URLRequest("tlf.xml");
myLoader.addEventListener(Event.COMPLETE, xSetText);
myLoader.load(myRequest);
addChild(container);
function xSetText(eventObject:Event):void {
  markUp = XML(eventObject.target.data);
  myFlow = TextConverter.importToFlow(markUp, TextConverter.TEXT_LAYOUT_FORMAT);
  myFlow.hostFormat = my_fmt;
  myFlow.interactionManager = new EditManager(new UndoManager());
  my_fmt.fontFamily = "Helvetica";
  my_fmt.fontSize = 14;
  composer = myFlow.flowComposer;
  composer.addController(controller);
  composer.updateAllControllers();
}

編集の取消しは[Ctrl](Windows)/[command](Mac)+[z]、やり直しが[Ctrl](Windows)/[command](Mac)+[y]のショートカットキーで行える[2]⁠。[ムービープレビュー]で試すときは、[制御]メニューで[キーボードショートカットを無効]にすることを忘れないでほしい。

第39回より3回にわたって、新しいテキストエンジンとText Layout Frameworkの基本について解説した[3]⁠。次回からは、また3次元空間のお題に戻る。つぎの第42回は、3次元空間の座標を扱うクラスVector3Dの説明に入ろう。

図5 クラスSelectionManagerはインターフェイスISelectionManagerを実装する
図5 クラスSelectionManagerはインターフェイスISelectionManagerを実装する

今回解説した次のサンプルファイルがダウンロードできます。

おすすめ記事

記事・ニュース一覧