TextFlowで選択位置の取得

TextFlowを使うと文章表示での表現力が飛躍的に高まるんだけど、TextField/TLFTextFieldとあまりに違いすぎて戸惑いやすい。

TextFlowで選択位置の取得 – wonderfl build flash online

最近、このあたりの作業で丸一日以上時間をかけてしまった。別に難しそうなことは一切してないはずなのに、どこにどのプロパティ、メソッドが収められているのかさっぱりわからず、時間ばかりが過ぎてく焦りを味わった。少なくとも同じところで詰まりたくは無いので、要素を抜き出しメモ。

[sourcecode language=”as3″]
package
{

import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.compose.StandardFlowComposer;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.container.ScrollPolicy;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.events.SelectionEvent;
import flashx.textLayout.formats.JustificationRule;
import flashx.textLayout.formats.TextAlign;
/**
* …
* @author umhr
*/
[SWF(width = 465, height = 465, backgroundColor = 0xF3F3F3, frameRate = 30)]
public class Canvas extends Sprite
{

private var _textFlow:TextFlow = new TextFlow();
private var _textField:TextField = new TextField();
public function Canvas()
{
init();
}
private function init():void
{
if (stage) onInit();
else addEventListener(Event.ADDED_TO_STAGE, onInit);
}

private function onInit(event:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, onInit);
// entry point

var source:String = "";
source += "行く川のながれは絶えずして、しかも本の水にあらず。よどみに浮ぶうたかたは、かつ消えかつ結びて久しくとゞまることなし。";
source += "世の中にある人とすみかと、またかくの如し。玉しきの都の中にむねをならべいらかをあらそへる、たかきいやしき人のすまひは、";
source += "代々を經て盡きせぬものなれど、これをまことかと尋ぬれば、昔ありし家はまれなり。或はこぞ破れ(やけイ)てことしは造り、あるは大家ほろびて小家となる。";
source += "住む人もこれにおなじ。所もかはらず、人も多かれど、いにしへ見し人は、二三十人が中に、わづかにひとりふたりなり。あしたに死し、ゆふべに生るゝならひ、";
source += "たゞ水の泡にぞ似たりける。知らず、生れ死ぬる人、いづかたより來りて、いづかたへか去る。又知らず、かりのやどり、誰が爲に心を惱まし、";
source += "何によりてか目をよろこばしむる。そのあるじとすみかと、無常をあらそひ去るさま、いはゞ朝顏の露にことならず。或は露おちて花のこれり。";
source += "のこるといへども朝日に枯れぬ。或は花はしぼみて、露なほ消えず。消えずといへども、ゆふべを待つことなし。』およそ物の心を知れりしよりこのかた、";
source += "四十あまりの春秋をおくれる間に、世のふしぎを見ることやゝたびたびになりぬ。"

_textFlow = TextConverter.importToFlow(source, TextConverter.PLAIN_TEXT_FORMAT);
_textFlow.color = 0x0000FF;
_textFlow.fontFamily = "_ゴシック";
_textFlow.fontSize = 14;
_textFlow.lineHeight = 22;
// 両端揃え
_textFlow.textAlign = TextAlign.JUSTIFY;
_textFlow.justificationRule = JustificationRule.EAST_ASIAN;

// テキストフローのレイアウトと表示を管理
_textFlow.flowComposer = new StandardFlowComposer();

var n:int = 3;
for (var i:int = 0; i < n; i++)
{
var sprite:Sprite = new Sprite();
sprite.x = 8 + 155 * i;
sprite.y = 8 + 50 * i;
sprite.graphics.beginFill(0x990000);
sprite.graphics.drawRect(0, 0, 145, 330);
sprite.graphics.endFill();
addChild(sprite);

// ContainerController クラスは、TextFlow オブジェクトとコンテナ間の関係を定義します。
// TextFlow には、テキストを格納できる 1 つまたは複数の長方形の領域があり、そのコンテナを使用してテキストフローが行われます。
var containerController:ContainerController = new ContainerController(sprite, sprite.width, sprite.height);
// 文字量が文字エリアをオーバーした時もスクロールしない
containerController.verticalScrollPolicy = ScrollPolicy.OFF;
_textFlow.flowComposer.addController(containerController);
}

_textFlow.flowComposer.updateAllControllers();

// 編集を可能にする。
// EditManager クラスは、TextFlow への編集変更を管理します。
var editManager:EditManager = new EditManager();
_textFlow.interactionManager = editManager;

addTextArea();

_textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, textFlow_selectionChange);

textFlow_selectionChange(null);
}

private function textFlow_selectionChange(event:SelectionEvent):void
{
// 選択位置の取得のためにEditManagerを取得
var editManager:EditManager = _textFlow.interactionManager as EditManager;

// 選択した文字の位置
var anchorPosition:int = editManager.anchorPosition;
var activePosition:int = editManager.activePosition;
var absoluteStart:int = editManager.absoluteStart;
var absoluteEnd:int = editManager.absoluteEnd;

// 行取得のため、FlowComposerを取得
var flowComposer:IFlowComposer = _textFlow.flowComposer;

// 合計行数
var numLines:int = flowComposer.numLines;

// 文字の位置から、行数を返す
var lineIndex:int = flowComposer.findLineIndexAtPosition(absoluteEnd);

_textField.text = "";
_textField.appendText("anchorPosition:" + anchorPosition + "\n");
_textField.appendText("activePosition:" + activePosition + "\n");
_textField.appendText("absoluteStart:" + absoluteStart + "\n");
_textField.appendText("absoluteEnd:" + absoluteEnd + "\n");
_textField.appendText("numLines:" + numLines + "\n");
_textField.appendText("lineIndex:" + lineIndex);
}

private function addTextArea():void {
_textField.width = 145;
_textField.height = 100;
_textField.x = 8;
_textField.y = 465 – 100 – 8;
_textField.border = true;
_textField.background = true;
_textField.backgroundColor = 0xFFFFFF;
addChild(_textField);
}
}
}
[/sourcecode]