TextFlowPro enables you to flow a series of text fields together so that they act as a single text container, and still allow users to select, edit, and copy/paste text between the textfields. It should work with any text formatting, including different text formatting on different fields. It even supports tabIndex.
In terms of the sheer number of problems I had to solve to get things working, this is one of the most complex classes I have released for free. I was originally going to release this as a commercial component alongside the Spelling Plus Library, but I never got it to a level of quality that I was happy with. While I think I could iron out the remaining bugs, I still don’t think it would reflect the quality I want our commercial offerings to show – there are simply too many player bugs, edge cases, and niggling user experience problems.
However, it represents a huge amount of work, and I didn’t want to just leave it to rot, so I’m releasing it in the hopes people can do really cool things with it. At the very least, I hope it serves as a crash course in working with some of the text metrics APIs in player 9. I’m more than happy to answer any questions about how it works in the comments below.
Here are a couple of simple demos to show what it can do. These will be familiar to you if you’ve checked out TextFlowLite or TextFlow, but these add one small thing: editing!
The first demo shows TextFlowPro being used for a dynamic multicolumn layout. Note that you can select, edit, copy/paste, navigate, and tab out of / into the text flow. You can even make a selection and have that selection remain intact as you resize the columns.
The second demo shows TextFlowPro being used to fit text to a shape. It’s flowing text between 21 textfields, spread between the 7 ornament clips. As with the demo above, you can select, edit, navigate, etc within the text as though it were a single text field. Also, in this demo a tabIndex was assigned to the text flow so that you can tab into and out of it.
I don’t have the time right now to fully document this class, but I think the usage is fairly straightforward. Here’s a quick overview:
// instantiation: var flds:Array = [fld1,fld2,fld3] ; var myTFP:TextFlowPro = new TextFlowPro(flds , text); // note that it will use the text from the first field if the second parameter is omitted. // methods: myTFP.reflow(); // forces reflow, ex. if you resize a textfield myTFP.setSelection(beginIndex:uint, endIndex:uint); // focuses and sets selection (similar to TextField method) myTFP.clearSelection(); // removes selection and focus myTFP.getOverflow(textFieldIndex:int=-1, ltrimString:Boolean=true); // returns the text that overflows (goes beyond) the specified field index, -1 for overflow of last field // properties: myTFP.alwaysShowSelection:Boolean; // similar to TextField property myTFP.type:String; // similar to TextField property myTFP.text:String; // sets text to display in the text flow myTFP.selectionBeginIndex:int; // Read-Only, similar to TextField property myTFP.selectionEndIndex:int; // Read-Only, similar to TextField property myTFP.tabIndex:int; // similar to TextField property myTFP.textFields:Array; // array of textFields to flow text through myTFP.orphans:uint; // minimum lines left at the start of a field myTFP.widows:uint; // minimum lines left at the end of a field |
There are also a few known issues:
- orphans doesn’t seem to be working properly.
- problems with setting the caret to the end of a line or on an empty line.
- caret draws at end of last textfield if there is an overflow.
- up/down arrow behaviour is (understandably) weird.
- double click to select word doesn’t work.
- right click menu operations don’t work (and probably never will).
- it has definitely not been tested, cleaned up, or optimized sufficiently (or really at all).
If enough people plan to use this class for something real, I might take the time to address these. I already have a pretty good idea as to how to fix most of them, but I don’t want to run the text API gauntlet if this is just going to be an interesting experiment that won’t see real use.
As usual, I am releasing TextFlowPro under MIT license. However, I would really appreciate hearing about what people do with it, and receiving credit where possible if you use it in your work. I kind of feel like a proud pappa releasing my child into the world, and hoping she will write back occasionally. 🙂
You can download TextFlowPro, with the demos above by clicking here.
Bad ass my friend! I think I’ll take a look at this and if needed look into some of the issues for my own usage!
Great work, this should be very useful!
(and a small bug: both demos freak out if you clear all the text)
christopher – thanks! If you make any fixes, feel free to fire them back to me so I can redistribute them.
grapefrukt – Oops… did I mention this wasn’t very well tested? 🙂 That should be an easy fix. I’ll probably post an update here later today.
awesome. many thanks for posting your hard work
Holy smoke, this is GREAT!
During my years as a Flash enthusiast, I have seen many flash applications but only three would I describe as exceptional: yours, http://www.joangarnet.com/blog/?p=207 and http://www.digitalflipbook.com/archives/2008/01/flashpaper_in_2.php. Congratulations. When my site formally opens within the next two weeks, I will honor your work. May you prosper.
wicked! i was just looking for this! can’t use the text layout framework yet because I need to publish to 9…Thank you for posting!
Nice one, though this class is really buggy like Hell.
There is only one Big Thing here – No HTML possible. So if i want to use Links or inlined Images your Class will definitely fail unfortunately. Otherwise it would have saved me some time now. But thanks for sharing your work.
I am actually working on a Flash 9 Textengine that will allow flowing, Links and everything with an own xhtml parser (which will come in handy for flash10) and your choice of releasing might let me consider this too 🙂
( http://www.neuronist.com/flowtest/ – does not look good and quite pre-alpha but one might get the point where this is heading)
Wow, if this worked with HTML Text it would be perfection. Nice work though.
I would imagine that if you change all the locations of fld.text to fld.htmlText then it would accept HTML.
Is there any reason it can’t /doesn’t do this?
HTML text is a potentially complicated thing to implement, because you need to deal with open and close tags that span the fields. You could likely solve this with either some RegEx to find and fix these, or by using the TextFormat object. Either way it’s definitely non-trivial.
Hi,
Your work is very usefull, you should merge your lib with the AS3 html/css render lib. Here is the link :
http://code.google.com/p/htmlwrapper/
It’s the first thing that annoyed me the first time I checked their work, we couldn’t simply select the text outside a single text field.
With this addition, they engine will be much more sexy.
Thx a lot for releasing this class.
Can you acheive the same by using Text Layout framework.I am trying to wrap the text with in circle(shape) which is resizable. I am trying to acheive this through linked containers. when i resize the circle , linked containers with in the circle should be resized. can you help me with this.
thanks in advance.
Hey Grant.
Thanks for this class – it is very nice, and works how it’s supposed to do. However, I have a problem.
I have textFields which are created in actionscript. They work, except when I use embedFonts = true; Then the text is not visible anymore. When I comment out the textFlow code, it is visible. Tracing the textfield.text shows the actual text …
Do you know what can cause this problem?
Thanks, Billy
hi there,
im using your library in the flex framewor an it seems it doesnt work
i generate a flash file an compile it to a swc. i import it in flex and when my “flash component” will be rendert theres an error looks like this:
is ther any solution?
TypeError: Error #1009: Der Zugriff auf eine Eigenschaft oder eine Methode eines null-Objektverweises ist nicht möglich.
at com.gskinner.text::TextFlowPro/set textFields()[/Users/sebastian_felix/workspaces/EnergySpiel/09_FL_BMBF_EnergyGame/src/module/character/com/gskinner/text/TextFlowPro.as:279]
at com.gskinner.text::TextFlowPro()[/Users/sebastian_felix/workspaces/EnergySpiel/09_FL_BMBF_EnergyGame/src/module/character/com/gskinner/text/TextFlowPro.as:101]
at Sprechblase()[/Users/sebastian_felix/workspaces/EnergySpiel/09_FL_BMBF_EnergyGame/src/module/character/Sprechblase.as:17]
at com.takomat.energygame.view.screens::StartScreen/_StartScreen_Sprechblase1_c()[/Users/sebastian_felix/workspaces/EnergySpiel/09_FL_BMBF_EnergyGame/src/com/takomat/energygame/view/screens/StartScreen.mxml:13]
at com.takomat.energygame.view.screens::StartScreen/_StartScreen_Array4_c()[/Users/sebastian_felix/workspaces/EnergySpiel/09_FL_BMBF_EnergyGame/src/com/takomat/energygame/view/screens/StartScreen.mxml:11]
at mx.core::DeferredInstanceFromFunction/getInstance()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\DeferredInstanceFromFunction.as:81]
at mx.states::AddChild/createInstance()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\states\AddChild.as:335]
at mx.states::AddChild/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\states\AddChild.as:347]
at mx.states::State/http://www.adobe.com/2006/flex/mx/internal::initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\states\State.as:199]
at mx.core::UIComponent/initializeState()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7381]
at mx.core::UIComponent/commitCurrentState()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7159]
at mx.core::UIComponent/creationCompleteHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8647]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9298]
at mx.core::UIComponent/set initialized()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:1169]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:718]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]
Due to huge problems with Adobe’s Text Layout Framework I am forced to use your TextFlowPro class for my project. I’m hoping some of the performance issues I’ve encountered with TLF and multiple A links in a single paragraph will not be a problem with the old school TextField class. Wish me luck.
*sob* No HTML text. Back to the drawing board.