Skip to main content
A_Shiyaz
Known Participant
October 8, 2010
Answered

How to keep cursor in focus for a TLF in ScrollPane?

  • October 8, 2010
  • 1 reply
  • 1589 views

How to keep cursor in focus for a TLF in ScrollPane? Consider this:

textFlow.addEventListener(UpdateCompleteEvent.UPDATE_COMPLETE, tlfUpdtHandler, false, 0, true);


private function tlfUpdtHandler(e:Event):void {
          var textFlow = e.currentTarget;
          var containerController = textFlow.flowComposer.getControllerAt(0) as ContainerController;
          var contentBounds:Rectangle = containerController.getContentBounds();
          var tlf_mc = containerController.container;
          containerController.setCompositionSize(containerController.compositionWidth, contentBounds.height);
          var sp:ScrollPane = tlf_mc.parent.parent;
          sp.update();
          trace(Math.ceil(sp.verticalScrollPosition), Math.ceil(sp.maxVerticalScrollPosition), sp.verticalScrollPosition, sp.maxVerticalScrollPosition);

          sp.verticalScrollPosition = sp.maxVerticalScrollPosition;

}

I cannot do this since the scroll position will always be at the last line. I would like the scrollpane to scroll to the line where the content is being typed.

Kindly help me out with pointers.

Thanks.

Shiyaz

This topic has been closed for replies.
Correct answer rdermer

Richard, thanks for the sample. The problem will be apparent if you attach the TLF within a ScrollPane. I've modified the Alice code (below). Kindly take a view... you might need to keep a ScrollPane in the library of the FLA.

//========================================================================================
//
//  ADOBE CONFIDENTIAL
//
//  Copyright 2007-2010 Adobe Systems Incorporated. All rights reserved.
//
//  NOTICE:  All information contained herein is, and remains
//  the property of Adobe Systems Incorporated and its suppliers,
//  if any.  The intellectual and technical concepts contained
//  herein are proprietary to Adobe Systems Incorporated and its
//  suppliers, and are protected by trade secret or copyright law.
//  Dissemination of this information or reproduction of this material
//  is strictly forbidden unless prior written permission is obtained
//  from Adobe Systems Incorporated.
//
//========================================================================================
package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.utils.ByteArray;
   
    import flashx.textLayout.container.ContainerController;
    import flashx.textLayout.conversion.TextConverter;
    import flashx.textLayout.edit.EditManager;
    import flashx.textLayout.events.UpdateCompleteEvent;
    import flashx.textLayout.elements.TextFlow;
   
    import fl.containers.ScrollPane;
    import fl.controls.ScrollPolicy;
   
    public class Alice extends Sprite
    {
        [Embed(source="alice.xml",mimeType="application/octet-stream")]
        private var AliceClass : Class;
        private var sp:ScrollPane;

        public function Alice()
        {
            if (stage)
            {
                stage.align = StageAlign.TOP_LEFT;
                stage.scaleMode = StageScaleMode.NO_SCALE;
            }
           
           /* [Shiyaz:] I need to create the TLF within a ScrollPane,
             * so the sprite 's' is supplied as source to the sp.
             * */

            sp = new ScrollPane();
            sp.move(100, 100);
            sp.setSize(500 + 20, 400);
            sp.verticalScrollPolicy = ScrollPolicy.AUTO;
            sp.horizontalScrollPolicy = ScrollPolicy.OFF;
           
           
            var s:Sprite = new Sprite();
            //s.x = 100;
            //s.y = 100;
            //addChild(s);

            var alice:ByteArray = new AliceClass();
            var aliceData:String = alice.readMultiByte(alice.length,"utf-8");

            // version doing a direct flowComopser
            var textFlow:TextFlow = TextConverter.importToFlow(aliceData, TextConverter.TEXT_LAYOUT_FORMAT);
           
            // version doing a direct flowComopser
            //textFlow.flowComposer.addController(new ContainerController(s, 500, 400));
           
            /* [Shiyaz:] If NaN is not used, the scrollpane content height will not be acquired
             * Is there any other way to fix this?
             * */

            textFlow.flowComposer.addController(new ContainerController(s, 500, NaN));
           
            textFlow.addEventListener(UpdateCompleteEvent.UPDATE_COMPLETE, tlfUpdtHandler, false, 0, true);
            textFlow.interactionManager = new EditManager();
            textFlow.flowComposer.updateAllControllers();
           
            sp.source = s;
            addChild(sp);
           
        }
       
        private function tlfUpdtHandler(e:Event):void
        {
            var textFlow:TextFlow = e.currentTarget as TextFlow;
            var containerController:ContainerController = textFlow.flowComposer.getControllerAt(0) as ContainerController;
            trace("update",containerController.getContentBounds());

            textFlow.flowComposer.composeToPosition();
            trace("fullCompose", containerController.getContentBounds());
           
           
            try {
                /* [Shiyaz:] This is the problem. When I type, the composeToPosition
                 * is not visible since the scrollpane is not updated to the current line.
                 * */

                sp.update();
            }catch (err:Error) {
                trace("err:", err);
            }
           
        }
    }
}

Regards,

Shiyaz


Thanks I better understand now.  I'm not that familiar with the fl classes but here goes.

1) Using NaN as the composition height this tlfUpdateHandler keeps the cursor in view.  This worked with some simple testing - there may be some details missing.  Do I need to call sp.update so it catches changes to the total height?

        private function tlfUpdtHandler(e:UpdateCompleteEvent):void
        {
            // find the current activePosition
            var activePos:int = e.textFlow.interactionManager.activePosition;
            if (activePos == -1)
                return;
           
            var tfl:TextFlowLine = e.textFlow.flowComposer.getLineAt(e.textFlow.flowComposer.findLineIndexAtPosition(activePos));
           
            // if its not in view scroll it into view
            if (sp.verticalScrollPosition > tfl.y || sp.verticalScrollPosition + sp.height < tfl.y)
                sp.verticalScrollPosition = tfl.y-20;    // just a number to give it some margin above
        }

2) If you don't want to use NaN as the composition height (less accurate but performs better) I don't think you'll be able to use ScrollPane.  TLF will automatically scroll the lines inside the Sprite using the composition bounds.  Instead you'll need to instantiate a  ScrollBar and synchronize the contentBounds with the maximum heights and also synchronize the scroll positions.  TLF generates a "scroll" event each time it scrolls the content.  ContainerController has a  r/w properties for verticalScrollPosition.

Hope that helps

Richard

1 reply

Adobe Employee
October 8, 2010

CompositionBounds/compositionHeight represents the visible area.  Since you've set compositionHeight it to the actual contentHeight its not going to scroll.  You've told TLF the content is visible.

I'm guessing you are doing this so you have accurate contentHeight for scrollbars.  Call composeToPosition(MAX_INT) to force a full compose and to generate accurate contentHeight.

Hope that helps,

Richard

A_Shiyaz
A_ShiyazAuthor
Known Participant
October 11, 2010

Hi Richard,

I did try composeToPosition() which does keep the cursor in view, but the problem is that the height of tlf_mc does not change. This leaves us with the initial problem of the scrollpane not activating the v-scrollbar, even though the contentBounds.height changes.

I did try a hack where I attached a simple spacer (mc with shape) to the scrollpane to adjust the height [spacer.height = contentBounds.height;] but this is not perfect, since the y position is not in line with the scroll position of the TLF. There should be an elegant way which still eludes me. Please help.

Thanks

Shiyaz

Adobe Employee
October 11, 2010


Seems to work for me.  Are you expecting the rectangle returned from getContentBounds to be updated?  I posted an example here.  The trace after the composeToPosition call in the event handler shows the precise non-estimated height.

Hope this helps,

Richard