TextAlign on TextFlow with contentWidth > compositionWidth
Hello,
I am encountering problematic behavior. On any condition that a TextFlow's text aligns right (textAlign = "right", textAlign = "end" & direction = "ltr", or textAlign = "start" & direction = "rtl"), and the TextFlow's ContainerController's compositionWidth is smaller than the contentWidth, the text is positioned outside of scrollable range.
In other words, with a textAlign = right, the text will position itself at the right-most point of the ContainerController's compositionWidth and continue to the right, but the scrollable view still extends to the left (this may be demonstrated by highlighting the visible text via mouse and dragging the mouse to the right).
Below is a test application to demonstrate this problem, which is a modification of Mihai Corlan's example app found here:
http://corlan.org/2009/02/12/how-to-add-a-scrollbar-to-text-layout-framework/
I have not tested this on the latest weekly builds (only Build 360 and the couple following it). This occurs in Gumbo, Flex 3.2, and Flex 3.3.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="left" creationComplete="init()">
<mx:Script>
<![CDATA[
import flashx.textLayout.formats.LineBreak;
import flash.events.Event;
import mx.events.MoveEvent;
import flashx.textLayout.container.IContainerController;
import flashx.textLayout.events.CompositionCompletionEvent;
import flashx.textLayout.edit.UndoManager;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.events.StatusChangeEvent;
import flashx.textLayout.container.DisplayObjectContainerController;
import flashx.textLayout.conversion.TextFilter;
import flashx.textLayout.elements.TextFlow;
[Bindable]
protected var tfTextAlignStr:String = "undefined";
[Bindable]
static public var _imgClass:Class;
private var _textContainer:Sprite = null;
protected var _textFlowStr:String = "Bacon is a cut of meat taken from the sides, belly, or back of " +
"a pig, then cured, smoked, or both. Meat from other animals, " +
"such as beef, lamb, chicken, goat, or turkey, may also be cut, " +
"cured, or otherwise prepared to resemble bacon. Bacon may be " +
"eaten fried, baked, or grilled, or used as a minor ingredient " +
"to flavour dishes. Bacon is also used for barding and larding " +
"roasts, especially game birds. The word is derived from the " +
"Old High German bacho, meaning \"buttock\", \"ham\", or \"side of " +
"bacon,\" and cognate with the Old French bacon.[1] " +
"The USDA defines bacon as \"the cured belly of a swine carcass\"; " +
"other cuts and characteristics must be separately qualified " +
"(e.g., \"smoked pork loin bacon\"). If bacon is USDA certified, " +
"then it has been treated for trichinella,[2] a parasitic " +
"roundworm which can be destroyed by heating, freezing, drying, " +
"or smoking.[3] " +
"In continental Europe, this part of the pig is usually not " +
"smoked like bacon is in America; it is used primarily in cubes " +
"(lardons) as a cooking ingredient, valued both as a source of " +
"fat and for its flavour. In Italy, this is called pancetta and " +
"is usually cooked in small cubes or served uncooked and thinly " +
"sliced as part of an antipasto.";
private var _textFlow:TextFlow;
private var _controller:IContainerController;
private function init():void
{
_textContainer = new Sprite();
canvas.rawChildren.addChild(_textContainer);
_controller = new DisplayObjectContainerController(_textContainer, canvas.width, canvas.height);
_textFlow = TextFilter.importToFlow(_textFlowStr, TextFilter.PLAIN_TEXT_FORMAT);
_textFlow.lineBreak = LineBreak.EXPLICIT;
_textFlow.flowComposer.addController(_controller);
_textFlow.addEventListener(CompositionCompletionEvent.COMPOSITION_COMPLETE, composeListener);
_textFlow.addEventListener(Event.SCROLL, scrollTextFlow);
//adding Select/Edit/Copy/Paste/Undo features
_textFlow.interactionManager = new EditManager(new UndoManager());
// initialize with a selection before the first character
_textFlow.interactionManager.setSelection(0,0);
_textFlow.flowComposer.updateAllContainers();
tfTextAlignStr = _textFlow.getStyle("textAlign");
}
/**
* the composing of the text was finished;
* now I can see if I my text overflow the container
*/
private function composeListener(event:CompositionCompletionEvent):void
{
var textWidth:int = Math.ceil(_controller.contentWidth);
var textHeight:int = Math.ceil(_controller.contentHeight);
if (textWidth < _controller.compositionWidth)
{
scroll.enabled = false;
}
else
{
scroll.enabled = true;
scroll.minScrollPosition = 0;
scroll.maxScrollPosition = textWidth - _controller.compositionWidth;
}
}
/**
* listener for the scroll event of the scrollbar
*/
private function scrollListener(event:Event):void
{
_textFlow.removeEventListener(Event.SCROLL, scrollTextFlow);
_controller.horizontalScrollPosition = scroll.scrollPosition;
_textFlow.addEventListener(Event.SCROLL, scrollTextFlow);
}
/**
* listener for the scroll event of the text flow container
*/
private function scrollTextFlow(event:Event):void
{
scroll.removeEventListener(Event.SCROLL, scrollListener);
scroll.scrollPosition = Math.ceil(_controller.horizontalScrollPosition);
scroll.addEventListener(Event.SCROLL, scrollListener);
}
private function toggleTFTextAlign():void
{
tfTextAlignStr = tfTextAlignStr == "right" ? "left" : "right";
_textFlow.setStyle("textAlign",tfTextAlignStr);
tfTextAlignStr = _textFlow.getStyle("textAlign");
_textFlow.flowComposer.updateAllContainers();
}
]]>
</mx:Script>
<mx:VBox x="20" y="20">
<mx:Canvas id="canvas" width="200" height="24" backgroundColor="#ffffff"/>
<mx:HScrollBar id="scroll" width="200" scroll="scrollListener(event)"/>
</mx:VBox>
<mx:HBox>
<mx:Button id="taBtn1" label="{tfTextAlignStr}" click="toggleTFTextAlign()"/>
</mx:HBox>
</mx:Application>
