| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 flashx.textLayout.container |
| { |
| import flash.display.DisplayObject; |
| import flash.display.DisplayObjectContainer; |
| import flash.display.Sprite; |
| import flash.geom.Rectangle; |
| |
| import flashx.textLayout.compose.IFlowComposer; |
| import flashx.textLayout.compose.LayoutFlowComposer; |
| import flashx.textLayout.conversion.LayoutConfiguration; |
| import flashx.textLayout.debug.assert; |
| import flashx.textLayout.elements.ContainerFormattedElement; |
| import flashx.textLayout.elements.TextFlow; |
| import flashx.textLayout.tlf_internal; |
| |
| use namespace tlf_internal; |
| |
| |
| [ExcludeClass] |
| /** @private |
| * A container controller to be used for TextFlows that require extended feature set. |
| */ |
| public class LayoutContainerController extends ContainerController implements IFloatController |
| { |
| private var inlineChildren:Array; |
| private var lastInlineChildren:Array = []; // inlineChildren during the last compose pass |
| |
| private var _wrapList:IWrapManager; |
| |
| // Composition Results |
| private var _numWraps:int; // number of wraps in this text frame |
| |
| /** Constructor - creates a new LayoutContainerController instance. |
| * |
| * @param cont The DisplayObjectContainer in which to manage the text lines. |
| * @param compositionWidth The initial width for composing text in the container. |
| * @param compositionHeight The initial height for composing text in the container. |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| |
| public function LayoutContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100):void |
| { |
| super(container, compositionWidth, compositionHeight); |
| } |
| |
| public function get wraps():IWrapManager |
| { |
| return _wrapList; |
| } |
| |
| public function set wraps(wrapsValue:IWrapManager):void |
| { |
| if (!(flowComposer is LayoutFlowComposer)) |
| throw new Error("Layout feature set requires LayoutConfiguration"); |
| |
| _wrapList = wrapsValue; |
| invalidateContents(); |
| } |
| |
| public function get numWraps():int |
| { |
| return _numWraps; |
| } |
| |
| public function set numWraps(value:int):void |
| { |
| _numWraps = value; |
| } |
| /** @private */ |
| override tlf_internal function setRootElement(value:ContainerFormattedElement):void |
| { |
| if (value && wraps != null && !(flowComposer is LayoutFlowComposer)) |
| throw new Error("Layout feature set requires LayoutConfiguration"); |
| |
| super.setRootElement(value); |
| } |
| |
| /** Find the container of the position in the flow */ |
| //-------------------------------------------------------------------------- |
| // |
| // Inlines |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** inlines */ |
| private function addInlineChild(child:DisplayObject):void |
| { |
| if (!container.contains(child)) |
| { |
| container.addChildAt(child,container.numChildren>0 ? container.numChildren-1 : 0); |
| } |
| } |
| private function removeInlineChild(child:DisplayObject):void |
| { |
| // If the graphic was switched from float to inline ("none"), then it has been reparented to a TextLine, |
| // which causes it not to be a child of the container anymore. We catch this as an exception that we handle. |
| try |
| { |
| container.removeChild(child); |
| } |
| catch(e:Error) |
| { |
| if (e.errorID != 2025) |
| throw e; |
| } |
| } |
| |
| public function recordInlineChild(value:DisplayObject):void |
| { |
| if (!inlineChildren) |
| inlineChildren = []; |
| else if (inlineChildren.indexOf(value) != -1) |
| return; // don't read it |
| inlineChildren.push(value); |
| } |
| |
| public function computeInlineArea(value:DisplayObject):Rectangle |
| { |
| // HACK |
| var vbc:TextLayoutBaseContainer = value as TextLayoutBaseContainer; |
| if (vbc) |
| { |
| vbc.validateSize(); |
| return new Rectangle(0, 0, vbc.width, vbc.height); |
| } |
| |
| var cont:DisplayObjectContainer = value as DisplayObjectContainer; |
| |
| // HACK Currently using a few weak typing tricks to play |
| // nicely with Flex components without compiler dependencies. |
| // Undoubtedly there's a better way to do this. |
| if (cont.hasOwnProperty("validateNow")) |
| cont["validateNow"].call(cont); |
| |
| // This moves the container from the rawChildren into the parent container for the purpose of layout |
| // It gets moved back later in updateCompositionShapes/createShapes |
| // TODO: don't do this as its really expensive and forced a complete redraw |
| // cont.includeInLayout = false; |
| if (cont.hasOwnProperty("includeInLayout")) |
| cont["includeInLayout"] = false; |
| // TEMP - force add and remove |
| // if (container.parent != this && container.parent != null) |
| if (cont.parent) |
| cont.parent.removeChild(cont); |
| |
| if (isDamaged()) |
| { |
| // temporary hack until appropriate interface is determined |
| if (cont.hasOwnProperty("invalidateSize")) |
| Function(cont["invalidateSize"]).call(cont); |
| //cont.invalidateSize(); |
| } |
| if (cont.hasOwnProperty("validateNow")) |
| cont["validateNow"].call(cont); |
| |
| var inlineRect:Rectangle = new Rectangle(0, 0, cont.width, cont.height); |
| |
| return inlineRect; |
| } |
| |
| /** @private */ |
| override tlf_internal function clearCompositionResults():void |
| { |
| super.clearCompositionResults(); |
| |
| clearLastInlineChildren(); |
| numWraps = 0; |
| } |
| |
| private function clearLastInlineChildren():void |
| { |
| if (lastInlineChildren) |
| { |
| for (var i:int = 0; i < lastInlineChildren.length; i++) |
| { |
| var oldInline:DisplayObject = DisplayObject(lastInlineChildren[i]); |
| if ((inlineChildren.indexOf(oldInline) < 0)) |
| removeInlineChild(oldInline); |
| } |
| } |
| lastInlineChildren = []; |
| } |
| |
| /** @private */ |
| override tlf_internal function updateInlineChildren():void |
| { |
| // Remove the inlines from last time that are not part of what we are going to redisplay this time |
| clearLastInlineChildren(); |
| |
| // synchronize the inline shapes beginning at childIdx |
| // Add in the new shapes from this time that are not already in the list |
| for each (var inline:DisplayObject in inlineChildren) |
| { |
| addInlineChild(inline); |
| |
| // inlines can update themselves if necessary here |
| // We need this because editing a table, e.g., curently invalidates |
| // through the text flow, rather than through the component hierarchy. |
| // (Is this the right thing to do?) |
| if (inline is TextLayoutBaseContainer) |
| TextLayoutBaseContainer(inline).validateNow(); |
| } |
| if (inlineChildren) |
| { |
| lastInlineChildren = inlineChildren.slice(); |
| inlineChildren.length = 0; |
| } |
| } |
| |
| private function clearInlineSelectionShapes(c:DisplayObjectContainer):void |
| { |
| if (c.hasOwnProperty("controller")) |
| c["controller"].clearAllSelectionShapes(); |
| else |
| { |
| for (var idx:int = 0; idx < c.numChildren; idx++) |
| { |
| var child:DisplayObjectContainer = c.getChildAt(idx) as DisplayObjectContainer; |
| if (child) |
| clearInlineSelectionShapes(child); |
| } |
| } |
| } |
| |
| CONFIG::debug tlf_internal override function validateLines():void |
| { |
| // doesn't work in layout yet |
| } |
| |
| } |
| } |
| |