Skip to main content
June 14, 2009
Question

Iterating through flowElements in a TextFlow to get their bounds

  • June 14, 2009
  • 2 replies
  • 4327 views

Hi.

I created a textflow, added a ParagraphElement to it that includes a few SpanElements and InlineGraphicElements..

I've set the flowComposer with a ContainerController, and so far everything is fine:  I can see the text and the graphics displayed correctly.

I am listening to the COMPOSITION_COMPLETE event:

(_textFlow.addEventListener(CompositionCompletionEvent.COMPOSITION_COMPLETE, onCompositionComplete);)

on 'onCompositionComplete()' what I want to do is simply iterate through all the elements in the textflow and get their bounds (and other properties)

I've succeeded iterating through the FIRST TextLine's elements like so:

var tfl:TextFlowLine = _textFlow.flowComposer.findLineAtPosition(0); // get first textflowline

var tl:TextLine = tfl.getTextLine(0); // get corresponding textline

var regions:Vector.<TextLineMirrorRegion> = tl.mirrorRegions;

for (var i:int = 0; i < regions.length; i++) 

{

     // regions.element= the element

     // regions.bounds = the bounds of the element

}

I have two questions:

1. How do I get to ALL of the textlines in the flow, so I can iterate through ALL my elements?

2. It seems that the bounds of an InlineGraphicElement are incorrect. I am getting its size, but not its position in the container.

    For example, I add my element like so:

    var s:Sprite = new Sprite()

    s.graphics.lineStyle(1,0,1)

    s.graphics.drawRect(0,0,100,15)

    ge = new InlineGraphicElement();

    ge.source = s; // just a box

    ge.height = 15;

    ge.width = 100;

    p.addChild(ge);

     but then when i iterate through the regions (like i said, i managed to do it only for the first textline), the bounds i'm getting are:

     left = 0

     right = 100

     width = 100

     height = -15  (btw, why the Minus?)

     Obviously, this is not what I want; I want the position of this graphicElement, not its size (which is incorrect - left is not 0).

     The size I can already get using regions.element.elementWidth/Height - for bounds I expect to get the position in the textflow container.

Any ideas?

This topic has been closed for replies.

2 replies

Adobe Employee
June 15, 2009

The position of the ILG are relative to its parent.  Its parent is the TextLine.  TextLine positons are relative to the container and so on up the chain.  You will need to convert that position.

Richard

June 16, 2009

Richard, I tested it some and I believe it's a bug:

When the direction of the paragraph is right (p.textAlign = TextAlign.RIGHT), im always getting left=0, and top=0.

But, when I changed it to TextAlign.LEFT -  i got the real left and top!

What Im doing is very basic:

- creating textflow

- creating paragraphElement (direction: RTL, textAlign: RIGHT)

- adding the paragraph

- adding some textelements to the paragraph, and an inlineGraphicElement too between them.

- Assigning eventlisters like so:

     element.tlf_internal::getEventMirror().addEventListener(MouseEvent.CLICK, tfClickHandler);

- assigning controller to the flowcomposer.

- listening to COMPOSITION_COMPLETE

- on compositionComplete I iterate through the elements (see my other post to see how i do it without accessing atom data)

BTW, Can't I have the  mirrorRegions array (which is convenient to get the bounds of each element) without actually assigning any events the way Im doing?

Adobe Employee
June 17, 2009

I think what's missing is that the atoms are in reading order and the content is in logical order.  My test (posted http://drop.io/jm2w0hx/asset/alice-as as attaching in the new forums is working for me) draws everything nicely in RTL with bounding boxes.  See the example for mapping from the atoms to the TextLine to the leaf element and character in the TextFlow.

Hope that helps,

Richard

Participating Frequently
June 15, 2009

Hi,

1.

IFlowComposer.getLineAt - get TextFlowLine by index (iterate from 0 to numLines-1)

2.

a) From a TextFlowLine, get the corresponding TextLine using getTextLine.
b) Use TextLine.getAtomIndexAtCharIndex to get the index of the first atom on the line that corresponds to the FlowLeafElement you are interested in (note that getAtomIndexAtCharIndex takes a paragraph-relative character index). Get its bounds using TextLine.getAtomBounds.
c) Repeat for the last atom on the line corresponding to the FlowLeafElement.
d) Perform a union of the two rectangles and convert from line-relative coordinates to container-relative coordinates.

Hope this helps.

- Abhishek

(Adobe Systems Inc.)

June 16, 2009

abhishek.g thanks for the answer but I still don't get why I need to bother with atoms.

For example, in my textflow's paragraph each word is a textElement, so I tried to draw a little box around each word like this:

               // fc is the textFlow.flowComposer

              for (var i:int = 0; i < fc.numLines; i++)  // iterate textflowlines
              {
                var tfl:TextFlowLine = fc.getLineAt(i);
                var tl:TextLine = tfl.getTextLine();
                var regions:Vector.<TextLineMirrorRegion> = tl.mirrorRegions;             
                for (var j:int = 0; j < regions.length; j++)
                {
                    var region:TextLineMirrorRegion = tl.mirrorRegions;
                    var bounds:Rectangle = region.bounds;                               
                    var s:Sprite = new Sprite;
                    s.graphics.lineStyle(1, 0xffff00,0.6)
                    s.graphics.drawRect(bounds.x, bounds.y , bounds.width, bounds.height);
                    tl.addChild(s);               
                }
              }

this works, but the mirrorRegions array contains only TextElements , and not my  InlineGraphicElements (why?? don't inlinegraphicElements deserve a mirror region too? EDIT: Turns out the reason I'm not getting the InlineGraphicElement in the  'mirrorRegions' array is that I simply haven't assigned any events to it as I did with the textElements.).

So I tried with the atoms: this code draws a box around EVERY ATOM in my paragraph:

          for (var i:int = 0; i < fc.numLines; i++)
            {
                var _tfl:TextFlowLine = fc.getLineAt(i);
                var _tl:TextLine = _tfl.getTextLine();
   
                for (var j:int = 0; j < _tl.atomCount; j++)
                {
                    var bounds:Rectangle = _tl.getAtomBounds(j);               
                    var s:Sprite = new Sprite;
                    s.graphics.lineStyle(1, 0xffff00,0.6)
                    s.graphics.drawRect(bounds.x, bounds.y , bounds.width, bounds.height);
                    _tl.addChild(s);
                }
            }       

This time EACH LETTER got a box around it, AS WELL AS my  InlineGraphicElement.

Now, of course,  if mirrorRegions contained regions for ALL elements and not just TextElements, that would solve all my problems. EDIT: Not all my problems are solved because the bounds of InlineGraphicElements seem to be incorrect in case of textAlign=RIGHT (see my other post in this thread). Also, to get mirrorRegions to reflect your paragraph elements you must assign each one with some kind of event. I'd rather not have to do that)

But since this isn't the case.I guess I would need to somehow use the atom data, but - how do I make the connection between each atom and its corresponding FlowLeafElement?

Sorry for being so lenghty... I've got the feeling that I might be missing something very basic here..