//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package { import flash.display.Sprite; import flash.events.Event; import flash.events.TimerEvent; import flash.system.Capabilities; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.utils.Timer; import flash.utils.getTimer; import flashx.textLayout.TextLayoutVersion; import flashx.textLayout.container.ContainerController; import flashx.textLayout.container.TextContainerManager; import flashx.textLayout.debug.Debugging; import flashx.textLayout.elements.Configuration; import flashx.textLayout.elements.InlineGraphicElementStatus; import flashx.textLayout.elements.TextFlow; import flashx.textLayout.events.CompositionCompleteEvent; import flashx.textLayout.events.StatusChangeEvent; import flashx.textLayout.formats.BlockProgression; import flashx.textLayout.formats.Direction; import flashx.textLayout.formats.LineBreak; import flashx.textLayout.formats.TextLayoutFormat; import flashx.textLayout.tlf_internal; use namespace tlf_internal; [SWF(width="500", height="500")] public class TCMTester extends FlowOpener { private var _tcm:TextContainerManager; private var _precompose:Boolean = false; private var _measureW:Boolean = false; private var _measureH:Boolean = false; private var _delay:Boolean = false; private var _timer:Timer; private var _blockProgression:String = BlockProgression.TB; private var _direction:String = Direction.LTR; private var _lineBreak:String = LineBreak.TO_FIT; private var _status:TextField; public const StatusHeight:Number = 100; // padding around the Sprite public const SpritePadding:Number = 25; public function TCMTester() { this.stage.addEventListener(Event.RESIZE,resizeHandler); var b:TextField = addButton("Reset",10,10,0,0,resetTCM); b = addButton("Load ..",b.x+b.width+10,10,0,0,openDialog); //b = addButton("Precompose OFF",b.x+b.width+10,10,0,0,togglePrecompose); //b = addButton("Delay OFF",b.x+b.width+10,10,0,0,toggleDelay); b = addButton("MeasureW OFF",b.x+b.width+10,10,0,0,toggleMeasureW); b = addButton("MeasureH OFF",b.x+b.width+10,10,0,0,toggleMeasureH); // b = addButton("IncColumnCount",b.x+b.width+10,10,0,0,increaseColumnCount); // b = addButton("DecColumnCount",b.x+b.width+10,10,0,0,decreaseColumnCount); b = addButton("BP " + _blockProgression,b.x+b.width+10,10,0,0,toggleBP); b = addButton("DIR " + _direction,b.x+b.width+10,10,0,0,toggleDirection); b = addButton("LineBreak " + _lineBreak,b.x+b.width+10,10,0,0,toggleLineBreak); _status = addButton("",10,40,500-20,StatusHeight,null); _status.autoSize = TextFieldAutoSize.NONE; _status.background = true; _status.backgroundColor = 0x99ffff; _status.selectable = true; var s:Sprite = new Sprite(); s.x = SpritePadding; s.y = _status.y+StatusHeight+SpritePadding; addChild(s); // CONFIG::debug { Debugging.generateDebugTrace = true; } _tcm = createInputManager(s,500-2*SpritePadding,500-StatusHeight-SpritePadding-_status.y-SpritePadding); _tcm.addEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE,updateComposeInformation); _tcm.updateContainer(); appendStatusText("Build: " + TextLayoutVersion.BUILD_NUMBER + Capabilities.version); } public function appendStatusText(str:String):void { _status.appendText(str); _status.appendText("\n"); _status.scrollV = _status.maxScrollV; } public override function parseDataFromFile(extension:String,fileData:String, config:Configuration = null):TextFlow { var beginParseTime:Number = getTimer(); var textFlow:TextFlow = super.parseDataFromFile(extension,fileData,config); var parseTime:Number = getTimer()-beginParseTime; appendStatusText("ParseTime: " + parseTime); return textFlow; } public function resizeHandler(e:Event):void { if (_tcm) { _tcm.compositionWidth = _measureW ? NaN : Math.max(10,stage.stageWidth-2*SpritePadding); _tcm.compositionHeight = _measureH ? NaN : Math.max(10,stage.stageHeight-StatusHeight-SpritePadding-_status.y-SpritePadding); _tcm.updateContainer(); _status.width = Math.max(10,stage.stageWidth-20); } } public function resetTCM(e:Event):void { if (_tcm.composeState == TextContainerManager.COMPOSE_COMPOSER) { var flow:TextFlow = _tcm.getTextFlow(); flow.interactionManager = null; _tcm.setText(""); _tcm.setTextFlow(flow); } else _tcm.setText("Hello World"); _tcm.updateContainer(); } public function togglePrecompose(e:Event):void { _precompose = !_precompose; TextField(e.target).text = _precompose ? "Precompose ON" : "Precompose OFF"; } public function toggleMeasureW(e:Event):void { _measureW = !_measureW; TextField(e.target).text = _measureW ? "MeasureW ON" : "MeasureW OFF"; resizeHandler(null); } public function toggleMeasureH(e:Event):void { _measureH = !_measureH; TextField(e.target).text = _measureH ? "MeasureH ON" : "MeasureH OFF"; resizeHandler(null); } public function toggleBP(e:Event):void { _blockProgression = _blockProgression == BlockProgression.TB ? BlockProgression.RL : BlockProgression.TB; TextField(e.target).text = "BP " + _blockProgression; var hostFormat:TextLayoutFormat = new TextLayoutFormat(_tcm.hostFormat); hostFormat.blockProgression = _blockProgression; _tcm.hostFormat = hostFormat; _tcm.updateContainer(); } public function toggleDirection(e:Event):void { _direction = _direction == Direction.LTR ? Direction.RTL : Direction.LTR; TextField(e.target).text = "DIR " + _direction; var hostFormat:TextLayoutFormat = new TextLayoutFormat(_tcm.hostFormat); hostFormat.direction = _direction; _tcm.hostFormat = hostFormat; _tcm.updateContainer(); } public function toggleLineBreak(e:Event):void { _lineBreak = _lineBreak == LineBreak.EXPLICIT ? LineBreak.TO_FIT : LineBreak.EXPLICIT; TextField(e.target).text = "LineBreak " + _lineBreak; var hostFormat:TextLayoutFormat = new TextLayoutFormat(_tcm.hostFormat); hostFormat.lineBreak = _lineBreak; _tcm.hostFormat = hostFormat; _tcm.updateContainer(); } public function toggleDelay(e:Event):void { _delay = !_delay; TextField(e.target).text = _delay ? "Delay ON" : "Delay OFF"; } public function get mode():String { return _tcm.composeState == TextContainerManager.COMPOSE_COMPOSER ? "Standard" : "Factory"; } public function updateComposeInformation(e:Event):void { appendStatusText(mode + " Bounds: " + _tcm.getContentBounds()); } public function displayActualLines(e:Event):void { // mode changes after getActualNumlines call appendStatusText(mode + " ActualNumLines: " + _tcm.getActualNumLines()); } public function increaseColumnCount(e:Event):void { if (_tcm) { var format:TextLayoutFormat = new TextLayoutFormat(_tcm.hostFormat); if (format.columnCount === undefined) format.columnCount = 2; else format.columnCount = Number(format.columnCount) + 1; _tcm.hostFormat = format; appendStatusText("ColumnCount: " + format.columnCount); _tcm.updateContainer(); } } public function decreaseColumnCount(e:Event):void { if (_tcm) { var format:TextLayoutFormat = new TextLayoutFormat(_tcm.hostFormat); if (format.columnCount !== undefined) { if (format.columnCount == 2) format.columnCount = undefined; else format.columnCount = Number(format.columnCount) - 1; _tcm.hostFormat = format; appendStatusText("ColumnCount: " + format.columnCount); _tcm.updateContainer(); } } } override public function useTextFlow():void { // first compose it so that we can test composing loaded graphics if (_precompose) { var s:Sprite = new Sprite(); _textFlow.flowComposer.addController(new ContainerController(s,NaN,NaN)); _textFlow.flowComposer.updateAllControllers(); if (_delay) { _textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,statusChangeHandler,false,0,true); if (_timer) _timer.stop(); // 15 second delay _timer = new Timer(15000, 1); _timer.addEventListener("timer", timerHandler); _timer.start(); return; } } _tcm.setTextFlow(_textFlow); _tcm.updateContainer(); } private function timerHandler(event:TimerEvent):void { if (event.target == _timer) { _timer.removeEventListener("timer", timerHandler); _timer = null; if (_textFlow) { _textFlow.removeEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,statusChangeHandler); _tcm.setTextFlow(_textFlow); _tcm.updateContainer(); } } } private function statusChangeHandler(e:StatusChangeEvent):void { // if the graphic has loaded update the display // set the loaded graphic's height to match text height if (e.status == InlineGraphicElementStatus.READY || e.status == InlineGraphicElementStatus.SIZE_PENDING) _textFlow.flowComposer.updateAllControllers(); } private function createInputManager(s:Sprite,width:Number,height:Number):CustomTextContainerManager { var tcm:CustomTextContainerManager = new CustomTextContainerManager(s); tcm.borderThickness = 3; tcm.compositionWidth = width < 50 ? 50 : width; tcm.compositionHeight = height < 50 ? 50 : height; tcm.setText("Hello World"); var hostFormat:TextLayoutFormat = new TextLayoutFormat(); hostFormat.fontSize = 12; hostFormat.paddingTop = 4; hostFormat.paddingLeft = 4; hostFormat.direction = _direction; hostFormat.blockProgression = _blockProgression; hostFormat.lineBreak = _lineBreak; tcm.hostFormat = hostFormat; return tcm; } } } import flash.display.BlendMode; import flash.display.Sprite; import flash.events.FocusEvent; import flash.geom.Rectangle; import flash.ui.ContextMenu; import flashx.textLayout.container.TextContainerManager; import flashx.textLayout.edit.ISelectionManager; import flashx.textLayout.edit.SelectionFormat; import flashx.textLayout.elements.Configuration; import flashx.textLayout.elements.IConfiguration; import flashx.textLayout.tlf_internal; import flashx.undo.IUndoManager; use namespace tlf_internal; class CustomTextContainerManager extends TextContainerManager { private var _borderThickness:Number; private var hasScrollRect:Boolean; public function CustomTextContainerManager(container:Sprite,configuration:Configuration = null) { super(container, configuration); } override public function drawBackgroundAndSetScrollRect(scrollx:Number,scrolly:Number):Boolean { // return super.drawBackgroundAndSetScrollRect(scrollx,scrolly); var contentBounds:Rectangle = getContentBounds(); var width:Number = isNaN(compositionWidth) ? contentBounds.x+contentBounds.width-scrollx : compositionWidth; var height:Number = isNaN(compositionHeight) ? contentBounds.y+contentBounds.height-scrolly : compositionHeight; if (scrollx == 0 && scrolly == 0 && contentBounds.width <= width && contentBounds.height <= height) { // skip the scrollRect if (hasScrollRect) { container.scrollRect = null; hasScrollRect = false; } } else { //trace("INPUT",scrollx,scrolly,compositionWidth,compositionHeight); // scrollRect = new Rectangle(scrollx-_borderThickness, scrolly-_borderThickness, compositionWidth+2*_borderThickness, compositionHeight+2*_borderThickness); container.scrollRect = new Rectangle(scrollx, scrolly, width+_borderThickness, height+_borderThickness); hasScrollRect = true; // adjust to the values actually in the scrollRect scrollx = container.scrollRect.x; scrolly = container.scrollRect.y; width = container.scrollRect.width-_borderThickness; height = container.scrollRect.height-_borderThickness; //trace("RESULT",scrollx,scrolly,width,height); } container.graphics.clear(); container.graphics.beginFill(0xFFFFF0); container.graphics.lineStyle(_borderThickness, composeState == TextContainerManager.COMPOSE_FACTORY ? 0x000000 : 0xff); // NOTE: client must draw a background - even it if is 100% transparent container.graphics.drawRect(scrollx,scrolly,width,height); container.graphics.endFill(); var r:Rectangle = this.getContentBounds(); container.graphics.lineStyle(_borderThickness,0xff0000); container.graphics.beginFill(0,0); container.graphics.drawRect(r.x,r.y,r.width,r.height); container.graphics.endFill(); return hasScrollRect; } static private var _focusedSelectionFormat:SelectionFormat = new SelectionFormat(0xffffff, 1.0, BlendMode.DIFFERENCE); static private var _unfocusedSelectionFormat:SelectionFormat = new SelectionFormat(0xa8c6ee, 1.0, BlendMode.NORMAL, 0xa8c6ee, 1.0, BlendMode.NORMAL, 0); static private var _inactiveSelectionFormat:SelectionFormat = new SelectionFormat(0xe8e8e8, 1.0, BlendMode.NORMAL, 0xe8e8e8, 1.0, BlendMode.NORMAL, 0); override protected function getFocusedSelectionFormat():SelectionFormat { return _focusedSelectionFormat; } override protected function getUnfocusedSelectionFormat():SelectionFormat { return _unfocusedSelectionFormat; } override protected function getInactiveSelectionFormat():SelectionFormat { return _inactiveSelectionFormat; } public function get borderThickness():Number { return _borderThickness; } public function set borderThickness(value:Number):void { _borderThickness = value; } override public function focusInHandler(event:FocusEvent):void { /* trace("focusInHandler"); var im:ISelectionManager = beginInteraction(); im.setSelection(0,0); updateContainer() endInteraction(); */ super.focusInHandler(event); } }