Tinytlf Overview
by Paul Taylor, Aug. 23, 2010, under [ actionscript, community ]

Last week I formally introduced tinytlf to the world, just in time for FITC. I was blown away at its reception, the outpouring of feedback and support was amazing, way more than I thought there would be. Thanks a ton if you were a part of that!

Part of that feedback was a request for more information. What makes tinytlf different? What are the features/goals of the project? And (truly) my favorite inquiries, “does tinytlf have feature X?” So I thought I’d write a followup, explaining a bit about my motivations for writing it, my goals for the framework, and a high level overview of some of its key processes.

Note: When I say TextField, I’m talking about Flash’s legacy TextField, flash.text.TextField.

Goals

Tinytlf has ambitious goals. With tinytlf, I want to create a small, extensible library for developers to write advanced text controls. I want to give developers full control over every facet of the TextField; nothing is sacred, and every piece replaceable with a more suitable implementation. I want a TextField that finally parses real HTML, and applies real CSS stylesheets. I want a TextField that, while still visually consistent, finally provides interactive capabilities on par with the OS native text controls.

Native

Flash’s TextField has never been as good as the native OS offering. Like it or not, text is a place where [the dreaded] HTML5 has a clear advantage over Flash. I’d be willing to go as far as to say that it’s one of the main reasons many web developers, “technologists” (yes I’ve seen that job description), and web-savvy users hate on Flash content. They expect their text to be selectable across TextField instances. They expect the mouse and keyboard interactions to be the same as their OS of choice. They expect the text decorations to be just as eye-popping as the rest of Flash’s visuals. And it’s sad to say they aren’t.

HTML and CSS

It’s never been very easy for Flash developers either. The most common representation of rich text on the web is HTML. The TextField does support a subset of HTML tags; 11 of them to be exact. But you are stuck with those 11, and you have virtually no control over the styling or rendering of the content. Want stars for list items instead of bullets? Too bad. Don’t want your links underlined? Tough luck.

The CSS support is pitiful too. You can import CSS into a StyleSheet object, then apply the StyleSheet to the TextField, but it too only supports a subset of styles. On top of that, the TextField is no longer editable. So bon voyage to a Rich Text Editor that respects CSS! For that, you have to use the alternate and incompatible TextFormat class, but that requires management by developers and doesn’t offer any more styling options than StyleSheet!

Modularity

These days, modularity is a buzz word thrown around for good measure. Writing modular systems is the goal of every developer and framework, but it’s a promise that is seldom kept. Tinytlf ensures modularity by keeping strict separation of concern and delegating the bulk of the functionality to small, externally defined controller classes. Tinytlf has four actor maps, which allows for controllers to be defined or replaced from the outside.

For example, every text decoration in tinytlf is written externally and mapped into the framework at startup. There’s nothing inherently special about the word “underline”, or the class that draws underline decorations. It’s only what was defined and mapped in at runtime. So if you want to write your own class that draws underlines, you can, and externally map it in and replace tinytlf’s default implementation.

This same pattern is used over and over throughout the system, and gives you a new level of control over the TextField like you’ve never had before. If you want to support a new HTML tag, you can write a controller which parses that HTML tag. If you want a new decoration, write the implementation and map it in! If you need to fix a bug in one of tinytlf’s controllers, write the fix and replace the default controller. (Then contribute it back!)

A Text Layout Framework

Allow me to define the general problems a TLF has to solve:

  • Model definition and resolution/parsing
  • Text decorations (underline, strikethrough, etc).
  • Text interaction (both generic and context-sensitive)
  • Styles/formatting (notably inline and cascading styles)
  • Rendering algorithms for the font glyphs that respects styles and formatting
  • Layout algorithms that respect the model, decorations, and styles of the text

Luckily, tinytlf doesn’t have to solve all these problems alone. Tinytlf gets a tremendous amount of help from the Flash Player, through the Flash Text Engine API.

Flash Text Engine’s responsibilities Tinytlf’s responsibilities
  • Model definition
  • Contextual text interactions
  • Inline styles
  • Glyph rendering algorithms
  • Model resolution and parsing
  • Generic text interactions
  • Cascading and inline style application
  • Layout algorithms, including text flow around images and flow between containers
  • Text decorations
  • The default definition of a TextField component

Architecture Overview

Tinytlf’s architecture allows all these pieces to come together, ensuring tinytlf is more than the sum of its parts.

Tinytlf is broken into five separate projects: utils, core, gestures, extensions, and components, respectively. Each project builds on the features of the previous project. You “pay as you go,” deciding for yourself what features you need and at what cost. For ease of use, you can use the components library, which is the default TextField, and depends on every project.

If you want, you can start over from core. Tinytlf is 100% interfaces, so, much like robotlegs, the default classes are just the reference implementation.

A Text Engine

The core of tinytlf is the TextEngine actor, responsible for invalidation, selection, and tracking the TextBlocks in the TextField. TextEngine is also a facade pattern, which unifies tinytlf’s four unique subsystems: TextLayout, TextDecor, TextStyler, and TextInteractor.

Every tinytlf actor or controller class receives a reference to the central TextEngine actor. Because TextEngine is a facade, any subsystem can call into any other subsystem. For example, the interaction controllers can add or remove text decorations by accessing the TextDecor actor from the TextEngine (e.g. when you mouse over, the controller can add an underline, then when you mouse out, remove it).

Engine Configuration

In tinytlf, every actor and controller class is externally defined. So tinytlf’s TextEngine accepts an ITextEngineConfiguration implementation to set up the default actors and mappings. For example, see the tinytlf TextField’s TextFieldEngineConfiguration.

Model Agnosticism

Tinytlf is model agnostic. It doesn’t care what format your data originally comes in, only if you can convert it into a tree of FTE ContentElements. The FTE already defined the model, it’s tinytlf’s job to resolve the differences between your model and FTE’s.

The default tinytlf TextField parses XHTML. There’s nothing inherently special about XHTML; XHTML is ubiquitous and easily converted into a tree of ContentElements. But if your model is not XHTML, you can write an implementation of ILayoutFactoryMap, then replace ITextLayout's textBlockFactory instance with your own.

Maps Maps Maps

Tinytlf exposes four maps, which allows for controllers to be externally defined. Tinytlf’s actors rely on definitions in their maps, then delegate functionality to the controllers. For example, tinytlf’s TextDecor exposes a map to define the classes which draw different text decorations. Then, when TextDecor receives instructions to decorate, it checks its map for the decoration definitions:

decor.mapDecoration("bgColor", BackgroundColorDecoration);
decor.mapDecoration("strike", StrikeThroughDecoration);
decor.decorate(someObj, {bgColor: 0xFF0000, bgAlpha: 0.7, strike:true});

In this example, TextDecor will instantiate two decorations, one for “bgColor” and one for “strike.” There’s nothing inherently special about those two strings, only that they exist in the map. Because of this, the TextDecor uses the mapped classes.

This is the pattern in three other areas as well: ILayoutFactoryMap, ITextInteractor, and ITextStyler.

Gestures

For context-insensitive text interaction, tinytlf includes a gestures library. A gesture is similar in spirit to iPhone and Android gestures; a sequence of events that occur in a certain order, so that when the last event occurs, the gesture is “unlocked,” and activates its behaviors. Behaviors are tiny command classes that are meant to control one facet of interaction. A great example is the IBeamBehavior, which controls whether the cursor is an IBeam or an arrow. Gestures can have multiple behaviors, and the same behavior can be mapped to multiple gestures.

The potential here is for interactivity on par with native text controls, but also allows for flexibility between platforms, like different gestures whether the user is on a PC or Mac. Moving from desktop to mobile? Just swap out mouse-based gestures for touch-based gestures, keeping all the same behaviors, allowing you to keep a consistent experience between devices.

Layout

Layout is a complicated problem, but tinytlf manages to cope. Tinytlf has a central ITextLayout actor for the ITextEngine, which renders lines from multiple TextBlocks between multiple DisplayObjectContainers (DOC). Each DOC gets its own layout controller, called an ITextContainer. I have previously blogged about various techniques for text layout, which are part of tinytlf’s default layout controllers. I’m still working on features for tinytlf v.1.0, but the current algorithm is pretty good.

During layout and re-render, tinytlf will only render the invalid TextLines from each TextBlock. This is one of many optimizations provided by the FTE of which tinytlf takes advantage.

Still rough around the edges…

Tinytlf isn’t finished. I’m working furiously to have 1.0 for my 360|Flex session. It needs more gestures and behaviors. I’m working on the layout algorithm to get text flow around images. Of course, editability is a huge feature everybody requests. I have a general idea of where the bottle necks in the framework are, but I haven’t done much formal testing. And of course I’m committed to releasing it with full test coverage.

If you would like to help, you can email me and/or jump in any time. The simplest thing you can do is request features. I’ve built this for myself, so I’m curious about other people’s requirements. I’ve already received some awesome feature requests that have kept my brain churning. At the very least I can keep them in the back of my mind, and try to keep from short-circuiting the framework, making those features impossible.

What are you waiting for? Fork it on github!

Tags: ,

Introducing tinytlf
by Paul Taylor, Aug. 18, 2010, under [ actionscript, community ]

Today I’m very proud to announce the official public beta release of tinytlf [tiny tee-el-eff], a new ActionScript 3.0 text layout framework I’ve been working on. I’m pushing it out as beta v.0.5, with 1.0 due out near the end of September.

Adobe’s TLF and tinytlf

Tinytlf isn’t affiliated in any way with Adobe’s TLF. Adobe has their project and I have mine. Tinytlf is not an add-on to Adobe’s TLF, it has no dependencies on Adobe’s TLF, and I haven’t recycled any TLF code. Tinytlf is a different effort than Adobe’s TLF.

Why?

If the TLF already exists, why create another rich-text framework? Because tinytlf represents a fundamental departure from the design concepts that drove Adobe’s TLF. Tinytlf has no dedicated model. Tinytlf doesn’t define the interactions, decorations, layouts, or styles in the framework code, tinytlf expects external definitions of what a “Text Field” is.

How does a TextField draw underlines or background colors? How does a TextField manage mouse and keyboard interaction? Instead of answering these questions in the core framework, tinytlf instead says: “here, you can draw decorations,” and “hey, you can interact with text, so how do you want to do it?”

Extreme modularity, everything is exposed and/or expected to be defined externally. Tinytlf has an interface specifically for external configuration. Take a look at the configuration for the default TextField component. Everything, from how to parse and interpret data, to which classes render text decorations, to the user gestures and behaviors that govern interaction, is mapped externally.

Tinytlf is 5 individual projects: utils, core, gestures, extensions, and components, respectively. Each adds new features and builds on top of the previous projects. It is explicitly structured with pay-as-you-go modularity. The core framework is tiny: 36kb. Including components, the whole project is 135kb.

Features

Here’s a quick list of features from the framework so far:

  • Standards compliant XHTML, including inline and some block-level styles.
  • Real CSS stylesheets: style inheritance, pseudo-classes, and cascading.
  • A completely configurable decoration engine for drawing shapes in with text.
  • A two pronged approach to interaction: inclusion of a powerful gestures API, but also the ability to keep interaction contextual to FTE ContentElements.
  • Complex text layouts, including text flow between DisplayObjectContainers.
  • Unordered and ordered lists.
  • Did I mention CSS pseudo-classes?
  • Hooking into the FTE’s performance enhancing techniques, such as only re-rendering invalid TextLines.
  • The speed you expect from a TextField, the power you expect from a Text Engine.

…and so much more.

Demos

Source for both demos


Fork it on github!

From Here?

Tinytlf still has a long way to go. In the next few days and weeks leading up to my 360|Flex D.C. session, I’m going to be putting more documentation on the github wiki. I have a lengthy “Deep Dive” article that I’m editing and will post soon, as well as break up for entry into the wiki. I am aiming for a 1.0 launch at 360|Flex D.C. As always, feel free to email me with any questions, feature requests, or general feedback. Thanks!

Tags: ,

The FTE Part 3: TextBlocks, TextLines, and Text Layout
by Paul Taylor, Aug. 9, 2010, under [ actionscript, community ]

This is part 3 in an ongoing series about the Flash Text Engine. Here’s part 1 and part 2.

By now you should know this series isn’t about Adobe’s Text Layout Framework, which is an advanced typography and text layout framework. The Flash Text Engine is the low-level API that TLF is built on. In Flash Player 10, the FTE resides in the flash.text.engine package.

FP 10 has this great new font rendering library, the Flash Text Engine, but it only fashions characters into TextLines of a specific width. When you think about everything else a TextField does, you begin to understand that rendering the glyphs is only a small (but still important!) percentage of the total work that’s done.

Text Layout

If you recall from my previous overview of the FTE, the main “Controller” class is TextBlock. TextBlock is a factory for TextLines. You supply a ContentElement to the TextBlock, it computes and creates the necessary TextLines to show that content. TextBlock’s rendering algorithms operate on a paragraph level; that is, one TextBlock per paragraph/one paragraph per TextBlock. For example, in the FTE, this paragraph should be represented as a single TextBlock, with multiple ContentElements that define formatting.

Paradigms from a superior layout engine

If you’re familiar with HTML styles, you know that HTML has two distinct layout paradigms: block layout and inline formatting. Block layout affects an entire block of text. Styles like padding, indentation, and margins affect layout on the block level. Inline formatting affects how the characters are rendered within blocks, such as color, size, posture, weight, justification, etc.

TextBlock’s algorithms take care of the inline formatting, because inline formatting affects whether characters flow between TextLines. It’s left up to you to apply any block formatting. For example, when you call the TextBlock’s createTextLine method, you choose the width of the TextLine. This simple option allows us, with some fancy math-e-matics, to achieve many properties of block level layout.

Layout Algorithms

We want some generalized methods for accomplishing various layouts. Everything from simple, single paragraph layouts, to layouts with block formatting, to complex mutli-TextBlock and multi-column (newspaper style) layouts.

I’ve already demonstrated the absolute simplest way: render all the lines in a while loop, finishing once the TextBlock returns null from createTextLine. This is easy and straightforward, and you can apply any kind of block formatting you wish.

var y:Number = 0;
var line:TextLine = block.createTextLine(null, 200);
while(line)
{
    addChild(line);
    y += line.ascent;
    line.y = y;
    y += line.descent;
    line = block.createTextLine(line, 200);
}


Source

Even though all it seems I’ve done is render a TextField, I’ve accomplished two tasks here: I’ve rendered every TextLine that the TextBlock decides I need, and, by incrementing a counter for the Y dimension, I’ve calculated a rudimentary layout for the TextLines.

Indentation

Now, applying indentation is super easy. Make the first line a little smaller, and change his x position to compensate.

var y:Number = 0;
var line:TextLine = block.createTextLine(null, 185);
line.x = 15;
while(line)
{
    addChild(line);
    y += line.ascent;
    line.y = y;
    y += line.descent;
    line = block.createTextLine(line, 200);
}


Source

Alignment

Center:

var y:Number = 0;
var line:TextLine = block.createTextLine(null, 200);
while(line)
{
    addChild(line);
    y += line.ascent;
    line.y = y;
    line.x = (200 - line.width) * 0.5;
    y += line.descent;
    line = block.createTextLine(line, 200);
}


Source

Right alignment is the same, only don’t multiply the calculated x by 0.5.

Source

See? Standard layout practices, ultimately the same math we use every day in component layouts. But, you say, “indentation and alignment are easy, it’s just calculating the x of the lines”. You’re right, it is easy. But so are the other block formatting properties like padding, margins, line spacing, etc. They’re all just calculating the correct x or y and conditionally applying them in the loop.

Multi-TextBlock layout

Ok, now we know how to layout lines from a single TextBlock. With a little code reuse, laying out multiple TextBlocks is a breeze:

var blocks:Vector.<TextBlock> = new <TextBlock>[block1, block2];
var y:Number = 0;
for(var i:int = 0; i < blocks.length; ++i)
{
    y = layoutBlock(blocks[i], y);
    y += 5;
}
// Returns the aggregate y after this layout operation
function layoutBlock(block:TextBlock, y:Number):Number
{
    var line:TextLine = block.createTextLine(null, 185);
    line.x = 15;
    while(line)
    {
        addChild(line);
        y += line.ascent;
        line.y = y;
        y += line.descent;
        line = block.createTextLine(line, 200);
    }
    return y;
}


Source

Multi-Container layout

Ah, now we’re getting to the good stuff. Multi-container layout is really cool, because it allows us to “overflow” text from one DisplayObjectContainer to another, which allows us, among other things, to achieve column layouts.

The general idea is to render as many TextLines into a DisplayObjectContainer (DOC) as possible. When we’ve hit his boundaries, switch to the next available DOC. We can accomplish this with a few modifications to the previous methods. The layout method needs to return the last TextLine that fit in the DOC. That way, we can re-enter the layout routine and pick up with the TextBlock where we left off.

var line:TextLine = layoutBlock(block, null, container1);
if(line)
    line = layoutBlock(block, line, container2);
 
// Returns the last line rendered out of the TextBlock
function layoutBlock(block:TextBlock, previousLine:TextLine, 
                             container:DisplayObjectContainer):TextLine
{
    var line:TextLine = block.createTextLine(previousLine, container.width);
    var y:Number = 0;
    while(line)
    {
        container.addChild(line);
        y += line.ascent;
        line.y = y;
        y += line.descent;
        //If we reached the height boundary, return the last line that fit.
        if(y + line.height > container.height)
            return line;
        line = block.createTextLine(line, container.width);
    }
    return line;
}


Source

Multi-TextBlock and Multi-Container layout

Here’s the really good stuff! Now we’re going to render multiple TextBlocks into multiple DisplayObjectContainers by merging the two methods above.

To solve this problem, lets identify our list of knowns:

  1. We have a list of TextBlocks.
  2. We have a list of DisplayObjectContainers to fit the TextBlocks into.
  3. We wish to render as many lines into each DOC as possible.
  4. When the DOC is full, switch to the next one and pick up where we left off.
  5. We need to keep track of the last TextLine rendered, so we know where we left off.

From our previous experience with rendering multiple TextBlocks, we know that TextBlock will return null when he can render no more lines. And from our previous experience with rendering across DisplayObjectContainers, we know that when a Container is full, we should return the last line that fit. Therefore the logic plays out as such:

  • Loop over each TextBlock.
  • Render as many TextLines into the DOC as possible, returning the last line rendered.
    1. If the TextLine is null, we know the TextBlock ran out of lines and there’s more space in the DOC. Keep the same DOC, but move to the next TextBlock.
    2. If the TextLine is not null, there are still more lines in the TextBlock, but this DOC ran out of space. Keep the same TextBlock, but move to the next DOC.
  • If we reach the end of either list, return.
var blocks:Vector.<TextBlock> = new <TextBlock>[block1, block2, block3, block4];
var containers:Vector.<DisplayObjectContainer> = 
    new <DisplayObjectContainer>[container1, container2, container3];
 
layout(blocks, containers);
 
function layout(blocks:Vector.<TextBlock>, containers:Vector.<DisplayObjectContainer>):void
{
    var blockIndex:int = 0;
    var containerIndex:int = 0;
 
    var block:TextBlock;
    var container:DisplayObjectContainer;
 
    var line:TextLine;
    while(blockIndex < blocks.length)
    {
        block = blocks[blockIndex];
        container = containers[containerIndex];
 
        line = layoutInContainer(container, block, line);
 
        if(line && ++containerIndex < containers.length)
        {
            container = containers[containerIndex];
            containerY = 0;
        }
        else if(++blockIndex < blocks.length)
            block = blocks[blockIndex];
        else
            return;
    }
}
 
var containerY:Number = 0;
 
function layoutInContainer(container:DisplayObjectContainer, 
                                   block:TextBlock, previousLine:TextLine):TextLine
{
    var line:TextLine = createTextLine(block, previousLine);
    while(line)
    {
        container.addChild(line);
        containerY += line.ascent;
        line.y = containerY;
        containerY += line.descent;
 
        if(containerY + line.height > container.height)
            return line;
 
        line = createTextLine(block, line);
    }
 
    //This will be null.
    return line;
}
 
function createTextLine(block:TextBlock, previousLine:TextLine):TextLine
{
    var w:Number = 190;
    var x:Number = 0;
    //Apply indention properties here.
    if(previousLine == null)
    {
        w -= 15;
        x += 15;
    }
    var line:TextLine = block.createTextLine(previousLine, w, 0.0, true);
    if(line)
        line.x = x;
    return line;
}


Source
Text Source

Woah! Take a breather

It’s a lot to digest, I know. But now you can see that TextLayout isn’t black-magic voodoo, and is entirely achievable in the new Flash Text Engine. If you have any questions, feel free to comment or email me. If you have any techniques for text layout, or have any comments on my techniques, I’d love to hear those too. I took some shortcuts with these demos, but I’ve built out more complete and performance-tuned layouts into tinytlf, the small text layout framework I’ve been working on clandestinely for a few months.

Aside: Text Layout vs. Component Layout

In typical component based layout engines (such as Flex’s), child creation is separate from layout. Usually all the children are added to the display list first, then laid out at some other time. Children aren’t created or destroyed based on their positions or sizes on the screen, and layout doesn’t affect the creation of future children (this is assuming we’re not talking about virtualized layout, which is a special case).

Working with the sizing and layout of TextLines, the block-level layout properties (like padding, indentation, etc.) dictate how each TextLine is created and laid out. This in turn affects how the TextBlock renders the next TextLine, and so on and so forth. I haven’t been able to separate block-level layout properties from the TextLine creation process. This isn’t so bad in practice, but sometimes it rubs me the wrong way, I feel like there should be a better way and I just haven’t found it yet.

Tags: , , ,

The Flash Text Engine, Part 2: Interaction
by Paul Taylor, Jun. 28, 2010, under [ actionscript, community ]

This is part 2 in an ongoing series about the Flash Text Engine. You can read part 1 here.

To clarify, this series isn’t about Adobe’s Text Layout Framework, which is an advanced typography and text layout framework. The Flash Text Engine is the low-level API that TLF is built on. In Flash Player 10, the FTE resides in the flash.text.engine package.

Interaction in the Flash Text Engine

In my previous post on the Flash Text Engine, I ran through the basics of what you need to get the FTE to render TextLines. While rendering lines on the screen is nice, this post is about how to add interaction to the TextLines that are produced.

TextLines are InteractiveObjects. You can add event listeners directly to them and listen for interaction events. The FTE also gives you the option to associate an individual EventDispatcher instance with a single ContentElement, so that when the user interacts with the data of the ContentElement, the events are cloned to the EventDispatcher instance you specified. As I discuss the details, you’ll see that each approach has its own strengths and weaknesses.

Approach 1: TextLines as InteractiveObjects

Since TextLine is an InteractiveObject, you can simply listen for Mouse and Keyboard events on each TextLine instance. With this approach, you know the TextLine that was interacted with. The main drawback here is that TextLine knows almost nothing about the ContentElement which it is rendering. Multiple ContentElements can be rendered into the same TextLine, and multiple TextLines can render the same (really long) ContentElement.

Interact with the lines in this demo:

Source

The fact that you don’t know about the content of the TextLines is ok though, for some problems that isn’t necessary. For example, you don’t really need to know about the contents of the TextLines to draw decorations, such as underline, strikethrough, or selection.

Select this text:

Source

Approach 2: Working with TextLineMirrorRegions (TLMRs)

The preferred method of managing interaction in the Flash Text Engine is with TextLineMirrorRegions.

If you read my previous post, you’ll remember that to render any text, you have to create instances of any of the Flash Text Engine’s model classes: TextElement, GraphicElement, or GroupElement. When you create an instance of these classes, you can specify an EventDispatcher as the eventMirror for the ContentElement. When the user interacts with the visual representation of this ContentElement via TextLines, the events are re-dispatched to the eventMirror you specified. This allows you to know when a user interacts only with a particular ContentElement.

In this code sample, I create an EventDispatcher to pass in as the eventMirror for the TextElement. Then I add a listener for mouseMove on the eventMirror instance. This will trace out every time you mouse over the TextElement.

var dispatcher:EventDispatcher = new EventDispatcher();
new TextElement('Inspiring quote here.', new ElementFormat(
                                         new FontDescription()), 
                                         dispatcher);
var onMouseMove:Function = function(e:MouseEvent):void{
    trace('Mouse move on ' + e.target.toString());
}
dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);

These two lines are part of the same TextElement:

Source

How is this different from the previous demo? TextLine has a property called mirrorRegions, a Vector of TextLineMirrorRegion instances. Since multiple ContentElements can be rendered by a single TextLine, TextLine creates TLMR instances for each ContentElement with an eventMirror, then associates the TLMRs with the eventMirrors respectively.

TextLine listens on itself for interaction events. When the events overlap with any of the TLMRs, TextLine notifies the appropriate TLMR of the event. After all normal event processing for the TextLine is done, each TLMR re-dispatches the events it was notified of to its eventMirror instance.

In this example, I added a listener for the “mouseDown” event on both the TextLine and the ContentElement’s eventMirror. Notice that the event dispatched on the eventMirror happens second.

Source

Here’s what the TLMRs look like (I’ve drawn boxes for each boundary of a TextLineMirrorRegion).

Source

Caveats

Of course, this wouldn’t be a Flash Player feature if it didn’t come with caveats ;).

TextLineMirrorRegion simulates the events, it doesn’t re-dispatch the exact instance it received from the TextLine. This is because TLMR isn’t an InteractiveObject itself. If you utilize the eventMirror to listen for MouseEvents, just realize they’re all faked — even though TextLine is the target, they didn’t originate from TextLine, and they don’t have feelings like real player-native events do.

rollOver/rollOut events

This event simulation means that we’re at the mercy of what Adobe chooses to simulate. They didn’t feel the need to simulate the roll events (rollOver/rollOut), so if you try to listen for them on the eventMirror, you won’t get them. Presumably this is because the roll events aren’t needed; since ContentElements don’t have display-list children, the roll events would be exactly the same as mouseOver/mouseOut.

Except the roll events are still very relevent.

It’s true, we’ve shifted from a display-list hierarchical structure (DisplayObjectContainers, etc.) to a ContentElement hierarchical structure. And it’s true, ContentElements don’t have display-list children. But they can have other ContentElement children, which means the roll events are still very relevant.

For example, if you had this XML model to render:

<p>
  Outside the group. 
  <group>
    <text color="#44AA00">
      First group child.
    </text>
    <text color="#AA0044">
      Second group child.
    </text>
  </group>
  Outside the group.
</p>

You might want to know only when the entire group node is interacted with (just like when you have a DisplayObjectContainer with children).

Here’s the demo of this model. Mouse between the boundary of the first child and the second child, and notice how you get a “mouseOut” and then another “mouseOver” from the group. If this were the roll events, you would only get the “mouseOut” and “mouseOver” from the children, but hear nothing from the group. FYI, “mouseDown” clears the debug lines.
Source

Comparison

So, how do the two techniques match up? The short answer is that each one accomplishes a different task. If you need the very base of interaction capabilities without the context of what you’re messing with (e.g. text selection), adding listeners straight on your TextLines is the way to go. However, if you need the context of which ContentElement the user interacts with (e.g. to mimic an HTML anchor tag), there’s no way around it, you have to use the event mirroring approach.

P.S. Isn’t it freaky interacting with text that you can’t select? Maybe I’m just OCD, but I feel a strong desire to see an I-Beam mouse cursor every time I hover over FTE text. My favorite demo to write was the second one, because not only did I get to come up with a quick selection-drawing method, I added the freakin’ I-Beam cursor. Anyway, hope you enjoyed this and good luck :).

Tags: , , , ,

The Flash Text Engine, Part 1: Overview
by Paul Taylor, Jun. 3, 2010, under [ actionscript, community ]

This is the first post in what will be a multi-part series about the Flash Text Engine, a new low level text API in Flash Player 10.

To clarify, this series isn’t about Adobe’s Text Layout Framework, which is an advanced typography and text layout framework. The Flash Text Engine is the low-level API that TLF is built on. In Flash Player 10, the FTE resides in the flash.text.engine package.

The FTE is designed to render text “document style”. It’s primarily meant to replace the TextField for advanced uses, not provide a whole framework for text layout on the scale of an HTML rendering engine.

The FTE handles what I call flow: formatting that causes text to be pushed to the next line in a paragraph. I don’t know if that’s the official term, but it seems to fit. It does not do layout, which is things like bullet points, indentation, wrapping around images, padding, etc., nor does it handle decoration, things like underline, strikethrough, background color, selection, etc. I believe the FTE leaves these out because 1.) layout is a much more complicated and nuanced problem than flow, one that you wouldn’t necessarily want in the FP core, and 2.) decorations don’t cause reflow, or affect whether and how text is wrapped to the next line.

The FTE conforms to a small MVC architecture, there are about 10 core classes that provide most of the functionality, with the rest of them encapsulating constants. Something to note, every class in the FTE is final :( more on that later.

The FTE Model

The basis of the Flash Text Engine model is something called ContentElement. ContentElement is an abstract base class. You never call new ContentElement() (it’s similar to DisplayObject in this regard), instead you instantiate one of its 3 subclasses: TextElement, GraphicElement, or GroupElement. Collectively these classes describe a Tree hierarchy for text, but I want to talk a bit more about ContentElement before we get too deep into that.

ContentElement

Take a look at the constructor of ContentElement:

ContentElement(elementFormat:ElementFormat = null, eventMirror:EventDispatcher = null, textRotation:String = "rotate0")

It has two important arguments, elementFormat and eventMirror (as well as a third less important argument, unless you’re one of the crazy types who likes to rotate text). I will come back to the eventMirror later, but for now lets just talk about ElementFormat.

The ElementFormat class describes most of the properties that handle text flow. It has a fontDescription member, which is exactly what it sounds like. In FontDescription you’ve got your standard fontFamily, fontWeight, fontPosture (which is traditionally the fontStyle in Flash), along with how the font is supposed to be retrieved from the depths of the Flash Player (as Compact Font Format or a device font).

ElementFormat has properties like alpha, color, baselineShift, kerning, etc. Basically anything that can affect reflow.

Ok, so that describes all you need to know for now about the ElementFormat and FontDescription objects. Now onto the implementation class you’ll use.

TextElement

Out of the three, TextElement is the most straightforward. It simply accepts a string of text to take care of:

TextElement(text:String = null, elementFormat:ElementFormat = null, eventMirror:EventDispatcher = null, textRotation:String = "rotate0")

The ElementFormat you pass in is applied to the entire string of text that this TextElement owns. So if you specify an ElementFormat with a color of red, the entire string of text will render red.

GraphicElement

The next one to worry about is GraphicElement. He accepts any DisplayObject instance (instance!), as well as the width and height that you wish to allocate for the Graphic in the text:

GraphicElement(graphic:DisplayObject = null, elementWidth:Number = 15.0, elementHeight:Number = 15.0, elementFormat:ElementFormat = null, eventMirror:EventDispatcher = null, textRotation:String = "rotate0")

Some of the properties of the ElementFormat will apply to the GraphicElement, such as alpha, baselineShift, etc. Obviously the GraphicElement doesn’t respect font-specific settings from the ElementFormat and FontDescription objects.

GroupElement

Lastly there’s the GroupElement:

GroupElement(elements:Vector.<ContentElement> = null, elementFormat:ElementFormat = null, eventMirror:EventDispatcher = null, textRotation:String = "rotate0")

GroupElement is critical. GroupElement is a collection of any combination of TextElements, GraphicElements, or other GroupElements. GroupElement is the Tree functionality of FTE’s model. TextElement can’t have children, it controls a single String. Likewise, GraphicElement only describes a single DisplayObject instance. GroupElements tie it all together.

GroupElements provide an API for doing standard Tree functions; you can retrieve, split, merge, and group children using various methods. I speak from experience when I say you won’t often mess with this unless you’re writing an editable text field. And if you are writing an editable text field, God help you (just kidding, it is hella fun).

OK, enough Model talk. Onwards to…

The FTE View

There are two (2!) classes that make up the entirety of the Flash Text Engine’s View division: TextLine and TextLineMirrorRegion. Right now you can forget about TextLineMirrorRegion, as that has to do with interaction, which is a complicated topic and one which I will cover in detail later. So for now, only focus on TextLine.

TextLine

TextLine is a DisplayObjectContainer. Yes, that means it has the get/add/removeChild methods (they still work!), and is also an InteractiveObject. You can listen for all the normal interaction events. However, even though it inherits from InteractiveObject, there are a few properties that you can only read, not write. Those are detailed in the documentation for TextLine.

TextLine adds the concept of atoms, which are indivisible characters in a TextLine. Individual characters are atoms, as well as any graphics you have. The important thing to know here is that atoms can never be split between lines. The FTE will measure only to the atom level, no lower.

Atom information can be expensive to keep around… At first the TextLine only renders its text, it doesn’t know anything about the atoms it contains. However calling various methods will cause the TextLine to create its atom data. For example, if you call getAtomIndexAtPoint(), the TextLine must create the info about each atom so it can then calculate which atom occurs at the point you specify. This is all well and good, but be sure to call flushAtomData() once you’re done so the atom data will be GC’d.

TextLine has a reference to the previous and next lines, because TextLine is also a doubly-linked list! How convenient! Of course, if there is no previous or next, you know you’re the first or last lines, respectively.

TextLine also has a validity status, which is whether the ContentElement that the line represents has changed since the line was rendered. Values are described in the TextLineValidity class.

One thing that TextLine definitely is not: a Sprite. No, TextLine is a DisplayObjectContainer. The most important implication from this is that TextLine has no graphics context. This means you can’t call textLine.graphics.draw. :( Oh well.

TextLine is a concrete class, you use it directly, but you cannot instantiate one by calling its constructor. To do that you need…

The FTE Controller

There is arguably one class in the FTE’s Controller division: TextBlock. I say arguably because yeah, TextJustifier and TabStop exist, but they just affect how TextBlock does its rendering, not… hm. Ok, I’ve convinced myself that they count as Controller classes too, but only barely.

But believe me, you will come to think of TextBlock as the only Controller class too.

The TextBlock is a fairly standard Factory pattern implementation: TextBlock’s primary job is to accept a ContentElement as input and output as many TextLines as you want, given a width. ContentElement -> TextBlock -> TextLines. Got it? Me neither.

Ok, so TextBlock has this method called createTextLine():

createTextLine(previousLine:TextLine = null, width:Number = 1000000, lineOffset:Number = 0.0, fitSomething:Boolean = false):TextLine

Ok so what you do is you pass in the previous line that you created, plus the width that you want the current line to be, and TextBlock will measure out a TextLine for you. Are you seeing the doubly-linked list yet?

If you want to create the first line from a TextBlock, you should just pass in null to the createTextLine() method; assuming the TextBlock has content in his content property, and that content has at least one atom (characters or graphics), passing in null will always return a TextLine. If there are no more lines to be created, TextBlock will return null from the call to createTextLine().

So from this it is simple to render the lines for a TextBlock with width 200:

var y:Number = 0;
var line:TextLine = block.createTextLine(null, 200);
while(line)
{
    addChild(line);
    y += line.height;
    line.height = y;
    line = block.createTextLine(line, 200);
}

Ok, I’ve detailed a lot so far, now it’s time to get to at an example.

Flash:

Here’s the code for the above simple line rendering:

package
{
  import flash.display.Sprite;
  import flash.text.engine.ContentElement;
  import flash.text.engine.ElementFormat;
  import flash.text.engine.FontDescription;
  import flash.text.engine.FontPosture;
  import flash.text.engine.FontWeight;
  import flash.text.engine.GroupElement;
  import flash.text.engine.TextBlock;
  import flash.text.engine.TextElement;
  import flash.text.engine.TextLine;
 
  [SWF(width="450", height="32")]
  public class SimpleDemo1 extends Sprite
  {
    public function SimpleDemo1()
    {
      super();
 
      var e1:TextElement = new TextElement('Consider, what makes a text line a ', new ElementFormat(new FontDescription(), 24));
      var e2:TextElement = new TextElement('text line', new ElementFormat(new FontDescription("_serif", FontWeight.NORMAL, FontPosture.ITALIC), 24));
      var e3:TextElement = new TextElement('?', new ElementFormat(new FontDescription(), 24));
 
      var e:Vector. = new Vector.();
      e.push(e1, e2, e3);
 
      var block:TextBlock = new TextBlock(new GroupElement(e));
      var line:TextLine = block.createTextLine(null, stage.stageWidth);
 
      var _y:Number = 0;
      while(line)
      {
        addChild(line);
        _y += line.height;
        line.y = _y;
        line = block.createTextLine(line, stage.stageWidth);
      }
    }
  }
}

Holy crap Batman!
As you can see, it required 3 different TextElements and a GroupElement to render some freakin’ italic text in the middle of a sentence. Yeah. Par for the frickin’ course.

In part 2 I’ll get into more details about interaction, TextBlock manipulation, all of it.
Till then watch this project on github: tinytlf. It’s due for some major updates but it’s what I’m going to start talking about soon.

Tags: , , , , , , , , , , ,

Flex 3 Smooth Scrolling, Variable Row Height List
by Paul Taylor, Apr. 19, 2010, under [ actionscript, community ]

Today I’m releasing another component, a smooth scrolling List that supports variable row height. I’ve got three demos of it, the first compares the standard Flex 3 List with my List, the second is another comparison but with a larger data set, and the third is a demo using the eBay API to pull down and display search results.

Ok, it’s not a Flex 3 List and it doesn’t extend ListBase or even ScrollControlBase. It uses the virtualization feature of the Scroller component I demoed previously to manage scrollPosition.

There are a few reasons I didn’t use ListBase or ScrollControlBase. I’ve never felt comfortable with ListBase controlling the backgrounds and interactivity of its itemRenderers. It always seems like a violation of encapsulation, and it bloats the List classes. ScrollControlBase seemed like a place to start, until I realized I was writing tons of code in my List class just to handle scrollbars, so I pulled that out into the Scroller.

The class that really made it possible was RepeaterData. He’s the model class behind the list and the reason I know what item renderers to create, but he deserves a blog post of his own.

Right now it’s still very incomplete. It’s not very optimized, I can already think of places that speed could be improved. It doesn’t watch the data provider for refresh events. It doesn’t manage selection or selected items (yet). It’s up to the itemRenderer to handle all interaction, and it definitely doesn’t support any kind of drag and drop gestures. It’s really just a weekend experiment, but if you want to see it expounded on, leave a message in the comments. If you want to mess with it, it’s available at the PTLib github repository.

Flex 3 Scroller Component
by Paul Taylor, Apr. 18, 2010, under [ actionscript, community ]

Here’s a Scroller component similar to Flex 4′s Scroller. It takes a single DisplayObject child and creates scrollbars at the edges.

Scroller has an inset property, which controls whether the scrollbars overlap the content area or not. You can set the inset property to false, which will move the scrollbars outside the content area.

Scroller supports scroll “ramping”. When you hold one of the arrow buttons, instead of scrolling by 1 each time, it supports the ability to “ramp up” the scroll delta, which increments the position up to a certain threshold and scrolls that amount until the button is released.

Scroller also supports manual or virtualized scrolling. If you want to use Scroller, but don’t want Scroller to manually reposition the content area, you can specify which properties on the target to measure width and height, and which to set when the scrollPosition changes.

Here’s a demo, and you can find it in a common component library I’m releasing on github called PTLib. I’ve tried to test it in creative ways, but I’m sure there are still bugs. So if you find some, just fork it, fix it, pull request it!

The Flex Framework and Modularity: A Manifesto
by Paul Taylor, Jan. 20, 2010, under [ actionscript, bitching ]

If you haven’t watched Greg Burch’s excellent presentation on Slider at RIAdventure, you freakin should. Seriously, stop right now and watch it. But don’t forget about this blog post. Make sure to come back here after you’re done.

The Soul of Flex
Ok, from this point on I am going to assume you’ve done exactly as I told you and watched Greg Burch’s excellent presentation on Slider at RIAdventure. Around 6 minutes in, Greg starts talking about the Soul of Flex. I didn’t have much time to consider it, but two things immediately came to mind: invalidation and styles. In the video you’ll hear me mention CSS but later agree with Greg that CSS or not, styles is the true feature.

Of course, I agree with all the others he said were also part of the Soul: MXML, databinding, states, skinning, item renderers, containers, and components. But as I watched him remove items that weren’t part of the Soul of Flex, I thought to myself:

“Self, this list is completely subjective and based entirely on my opinion. It is extremely likely that someone else’s definition of the Soul of Flex is different than mine, and who’s to say which one is right? Is it Adobe’s job? Now that they’ve packed a framework full of features that real people use, they’re going to remove a good many features simply because the they do not fall into Adobe’s definition of what the Soul is? That’s not right. The community is too diverse for that. Flex is the Soul of Flex.”

The real Soul of Flex

I say Flex is the Soul of Flex.

This got me thinking about Flex with regards to mobile development. At the time of this writing, every Flex 4 component has a base class that is 13,246 lines of code (1412 blank lines, 6423 comment lines, and 5411 actual code lines.) If you’re using Flex 4 and skinning, you have two components, so multiply potentially everything the UIComponent does by 2:

  • 2x the UIComponents to initialize
  • 2x the UIComponents added to the inheriting style chain
  • 2x the UIComponents to make validation passes on
  • 2x the event listeners that are registered
  • 2x the number of objects for the DragProxy (in the DragManager) to find in its getObjectsUnderPoint() implementation
  • and on and on…

This means one of two things. Either the decision to abstract skins into another UIComponent was monumentally retarded, or the UIComponent is too large and tries to do to many things. Since I believe the new skins are wonderful from an architectural/modularity standpoint, I have to pick the second choice: the UIComponent is too damn big. It tries to do too damn much. Let me reiterate: I love the new Spark skins. I hate the size of the UIComponent.

The Question of Responsibility
Why is the UIComponent (at the time of this writing) 13,246 lines long? The answer is features. The UIComponent violates the Single Responsibility Principle. Here’s a list of most of the features the UIComponent encapsulates:

  • Invalidation – Implements IInvalidating.
    • Defines invalidate properties/size/displayList functions.
    • Defines validateNow function.
  • Validation – Implements ILayoutManagerClient.
    • Defines the initialized, nestLevel, processedDescriptors, and updateCompletePendingFlag properties.
    • Defines validate properties/size/displayList functions.
  • Styles – Implements IAdvancedStyleClient, the only visual class that does.
  • States – Implements IStateClient and IStateClient2 to support the new Fx4 states syntax.
  • Tooltips – Implements IToolTipManagerClient, the only component class that does.
  • Constraint-based layout.
  • IRepeaterClient – UIComponents (and subclasses) can be created by Repeaters.
  • Databinding.
  • Related to Databinding, implements IPropertyChangeNotifier.
  • Embedded fonts.
  • Focus – Doesn’t implement IFocusManagerComponent by name, but does implement the functions. Has a reference to the FocusManager and a focusPane property.
  • Validators – Implements IValidatorListener, which allows the UIComponent to respond to ValidationResultEvents dispatched by the Validator classes.
  • Modules – Implements IFlexModule, so if created by an IFlexModuleFactory, the factory stores a reference of itself on the UIComponent.
  • Explicit/measured- max/min – widths/heights.
  • Percent widths/heights.
  • Enabled/disabled.
  • Effects.
  • Special logic for adding/removing children.
  • All the events it creates and dispatches, including
    1. Initialization events, like preInit and creationComplete.
    2. FlexEvents like show, hide, move, resize
    3. StateChangeEvents.
    4. DragEvents for the List classes. Not part of the public API.
    5. ToolTipEvents
    6. FlexMouseEvents

Man, the UIComponent does a ton of stuff. We haven’t even gotten into the measurement, layout, containment, children handling, skinning, item renderers, or graphics functionality of Flex yet!

The UIComponent is the base class for… everything
At least, everything visual. Not including Flex 3 skins. It’s the base class for all non-Fx3-skin-related visual elements.

The UIComponent has so many responsibilities because it is the base class for so many controls. You want a Label or TextArea? They’re UIComponents. You want a Button? It’s a UIComponent. You want a container of Buttons? It’s a UIComponent.

But there are a few things I can’t figure out about this configuration:

  1. Why does a container need logic in its base class that accesses embedded fonts, or creates UITextFields from embedded font contexts (I checked, UITextField is the only class passed into createInFontContext()).
  2. Similarly, why does a Label require any knowledge about processedDescriptors, states, or validators? Labels can’t have children, states, or validators. In fact, Labels can’t do much except display text. Why do they need to be IFlexModule objects? I could go on, but I think you get the point.

There is a trend of WTFs like this about the UIComponent that can only be explained by, “it’s the base class and we’re trying to keep our API super clean.”

There is a better way: Composited Modularity
Most of the functionality is already segregated by the liberal use of interfaces… now lets actually implement it that way.

Almost all the functionality that the UIComponent (and subclasses of UIComponent for that matter) contains can be grouped into smaller, more discreet classes. Lets call them modules. Once this is done, the UIComponent simply exists to provide a unified API to the developer and glue with which to assemble the modules. More complex controls and components are simply composed of more complex modules.

For example, the functionality for embedded fonts should be isolated into its own module. Then, only the Label, Text, TextArea, and maybe some other controls that require direct access to embedded fonts need to include the “EmbeddedFontsModule.” This way, the VBox doesn’t have to include functionality for accessing embedded fonts.

Similarly, a VBox would include special modules for adding children, measurement, and layout. See, this is easy.

And while we’re at it, let’s rewrite the LayoutManager.

You heard me. The LayoutManager. It’s in my sights.
What’s so special about 3-phased validation that it has to be hard-coded into the Flex framework? Is it phase ordering? Nest-level ordering? That’s not special. That’s algorithms.

First, for those who don’t know, the LayoutManager is what enables Flex components to do the awesome 3-phase component lifecycle that we’ve all come to know and love. When a component is invalidated for a phase (say, invalidateProperties()), he registers with the LayoutManager. The LayoutManager adds the component to the proper invalidation queue. There are 3 invalidation queues, one for each validation phase. The invalidation queues are a special PriorityQueue implementation. This is important, because there is an order to the validation process.

Components have a nestLevel, which is really just their position in the display list. The Application’s nestLevel is 3. The nestLevel increases from there, so the lowest component in the display tree has the highest number.

When a component is added to the invalidatePropertiesQueue, it is added at its nestLevel priority. When the invalidatePropertiesQueue is processed, components with the lowest nestLevel, the ones closest to 0, are processed first. This is called “top-down” processing, because it starts at the top of the display list and processes to the bottom.

The commit phase does top-down processing, because generally parents can commit properties on themselves and change properties on their children, which will then get committed. The measure phase is from the bottom-up (can you guess what that means? If not, put it in the comments.), because a parent will often make a decision on his size based on the sizes of his children. The update phase is another top-down queue, because now that the sizes and positions are calculated, it’s time to lay them out. This is what makes percent widths/heights, scrollbars, etc. possible.

Rethinking validation
Does validation have to be hardcoded? Are the 3 phases all that are needed? How hard would it be to switch to just 2? 4? 100?

The fact is, the developer should be able to hook into the power of phased updates for himself. Why have a manager that only validates 3 hard-coded phases, when you could have a manager that validates an unlimited number of dynamic phases?
Well sure Paul, that sounds great and all, but it’s kind of a tough problem. <– Shut up alternate text, I’ve got a solution.

Keep the idea of nestLevel. It’s clear, clean, and definite. Change the idea of 3 hard-coded phases into an unlimited number of injected phases, based on priorities. Similar to nestLevel for components, priorities are arbitrarily defined by the developer. A priority is an Array of ints. It can be as simple as “1″ or as complex as “1.2.3.4.” It is only used as a basis for comparison between other priorities. For example, priority 1.2 is greater than priority 1.2.1, since it is assumed 1.2.1 is a subset of 1.2. However, 1.200 is much greater than 1.2, because 200 > 2. Do priorities make sense? If the answer is no, put it in the comments.

The idea is that a developer can invalidate a component for a certain phase. The phase has a priority (like 1.3), and a direction (UP or DOWN). The ValidationManager keeps a Heap of Heaps, sorted by priority. If it doesn’t find a Heap at the priority specified, it creates a new Heap, adds the IValidationClient to it, sets the proper sort direction (UP or DOWN) on it, then adds the new Heap to the Heap of Heaps. If it does find a Heap, it adds the IValidationClient to the Heap that it found.

When it comes time to Validate (on the next enter_frame event), the ValidationManager dequeues each Heap from the Heap of Heaps. Then it dequeues each item from each individual Heap, validating it as it goes.

The beauty of this is that the Flex component lifecycle can be perfectly mimicked. Set the three phases to happen one after another, and you can get the same results. For APIs sake, lets add a gap between them, so a third party developer can come by later and inject his own phases between the 3 usual phases. If we set commit at 1.3, measure at 1.5, and update at 1.7, this should give us enough of a gap for developers to use.

Say Developer X wants to add some extra umph to his custom component, but needs this processing needs to happen in-phase and inbetween the measure and update phases. He simply needs to inject his own validation phase anywhere between measure at 1.5 and update at 1.7, lets keep it simple and say 1.6, and BAM. ValidationManager will validate his phase right after measure and right before update.

This allows the developers a whole new avenue of development, something that they would have had to tack onto one of Flex’s 3 hard-coded phases before.

This is all words. Where are the actions. You fail.

This is where I introduce FlashWorks
FlashWorks is a component set for Flash and FlashBuilder, designed around the concepts of a tiny core API and modularity.

It includes the ValidationManager and validation scheme I’ve outlined here, as well as a few other things:

  • MXML development
  • Skinning similar to Flex 4
  • Graphics primitives (extend EventDispatcher)
  • Measurement and Layout controllers with support for percent widths/heights
  • Injectable Validation phases
  • States, including support for FB4′s new States syntax
  • Styles, through a controller that interfaces with Jesse Freeman’s F*CSS
  • Databinding
  • SystemManager that works with FB4′s code generation, so the FlashWorks movie is 2 frames, just like Flex.
  • A modular, pay-as-you-go system, so functionality is only included when it’s used. For instance, the States controller isn’t included unless States are defined on the component.

Alright, here’s the code and demos

[Edit] I’ve since moved from this project onto Reflex. I feel it has more of a chance for success than a solo framework by me would.
I’m keeping the demo and demo code here as a proof of concept:
Demo: http://guyinthechair.com/misc/flashworks/FlashWorks.html
Source code for demo: http://guyinthechair.com/misc/flashworks/srcview/index.html

Tags: , , , ,

Understanding the Flex SystemManager
by Paul Taylor, Jan. 17, 2010, under [ actionscript ]

Before I start, let me say that there has been a lot of discussion about the SystemManager on various blogs. Deepa posted a fantastic write-up on the SystemManager back in October 07, which really got me interested in learning about it more. Working on Flex-less MXML is what finally pushed me to understand exactly why it’s such a critical class. There’s a lot to cover about the SystemManager, from the behavior of the Flash Player to the behavior of the Flex compiler, so buckle up, cause this is a long one.

Note 1: A recurring theme in this post is the fundamental behavior of the Flash Player. Flex would be nowhere without Flash, so if we desire true understanding of Flex, we must also understand the Flash Player.
Note 2: For some of this, it is helpful to turn on the -keep-generated-actionscript flag in the FlashBuilder compiler options. To do this, go to Project –> Properties –> Flex Compiler. In the “Additional compiler arguments” field, type “-keep” at the end of the arguments list. FlashBuilder generates ActionScript from all your MXML, including a dynamic subclass of SystemManager. This will instruct FlashBuilder to place that code in the bin-debug/generated folder.

To understand the SystemManager, you must first understand that…

Every Flex Application is a 2-Frame Flash Movie

2 Frame Flash Movie Yes, every one of them. The Flash Player is capable of downloading just the data for the first frame and streaming the rest of the movie. Therefore a trend started in the earlier days of Flash-only developing; you typically put a very small loader object on your first frame that displays the loading progress of the rest of the SWF to the user. That way the user has a visual indication that something is happening, and the movie gets preloaded to a point where the user won’t experience any playback hiccups.

That is awesome… why do I care?
Good question. First, lets examine the implications of Flash’s load-and-stream feature:

From a movie perspective if frames aren’t loaded, the movie stops until they are loaded. If the movie is constantly experiencing this, the movie’s framerate essentially becomes a function of the speed of the user’s internet connection.
From a code perspective, if frames aren’t fully loaded, classes can’t be accessed. Calling new MyObject() will throw a runtime error, “1065: Variable MyObject is not defined.” This is because the frame that contains the definition for that class hasn’t been fully loaded.

Oh I see now, so we need a small preloader on the first frame?
Exactly. All that silly Flash that we thought we left behind when we became “Enterprise Flex Developers” has come back to bite us in the ass. But never fear, the SystemManager is here.

The SystemManager is a fancy MovieClip. The SystemManager has a few duties, including:

  • Create and initialize the pre-loader to show to the user during app load and startup.
  • Manage loading in RSLs.
  • Manage module logic. If the SystemManager is the root of the SWF, he knows he is a Flex Application. If he is not the root of the SWF, he knows he is a module, and must communicate with whichever SystemManager is the root of the SWF (see if you can spot the logical flaw of the assumption made in that sentence, there will be a quiz later). SystemManager must communicate events both ways between modules/app, such as mouse and keyboard events.
  • Manage Event.RESIZE events dispatched from the Stage.
  • Manages the embedded fonts list
  • Initializes the various manager singletons, such as ResourceManager and StylesManager.
  • Manages top-level application windows. The SystemManager maintains a cursorChildren list and a popUpChildren list, for tooltips and pop-up windows respectively.
  • Once all the code for the movie is loaded, SystemManager creates your actual Application instance and calls initialize().
  • Adds the Application to the stage once the Application dispatches its FlexEvent.CREATION_COMPLETE event. This is why the Application doesn’t have a reference to the stage when its FlexEvent.CREATION_COMPLETE is dispatched, when all the other components do.

How it works
How the SystemManager does its thing. Matching colors are event listening/dispatching pairs.

Frame 1

Frame 2

  • stop()
  • listen for player init event
  • init dispatched:
    1. get root SystemManager (if we’re not the top level)
    2. listen for enterFrame event
    3. create preloader
    4. listen for preloaderDocFrameReady from preloader
    5. listen for complete from preloader
    6. load RSLs and wait
    7. RSLs loaded. preloaderDocFrameReady dispatched by preloader
      • Timer created to go run nextFrame() after 100 milliseconds
    8. Exactly 10 milliseconds after preloaderDocFrameReady dispatched, complete dispatched by preloader
    9. Timer event dispatched, nextFrame() called/enterFrame handler triggered
  • Managers initialized.
  • Stage Resize listener added.
  • Application instance created.
  • listener for Application creationComplete added
  • nextFrame()
  • Application creationComplete dispatched
    1. Preloader removed
    2. Application added to the stage
    3. applicationComplete event dispatched

Hold on, I’m a Flex developer. I don’t work with frames.
I don’t have access to the timeline of my SWF. Actually, you do.

It’s through an undocumented meta tag, [Frame], which is really just a shortcut for the -frames compiler option. You can read all about the frame meta tag at Roger Gonzalez’s blog, but here’s the gist of it: If you add the [Frame] meta tag to the top of the Application class of your project, the Flex compiler will insert a frame before the frame that your Application is on. If you specify the factoryClass property on the meta tag, the Flex compiler will generate a subclass of whichever class you specify as the factory, and put that on the frame it creates. If you open up the mx.core.Application class, you’ll see the line [Frame(factoryClass="mx.managers.SystemManager")] near the top. This tells the Flex compiler to create a frame before the mx.core.Application, and attach a generated subclass of mx.managers.SystemManager.

The Flex compiler will generate a subclass of your factory class that implements IFlexModuleFactory. As long as your SystemManager implements IFlexModuleFactory, your code will compile. The Flex compiler overrides the info() method and returns information specific to your Application, such as a list of embedded fonts and the name of your Application.

And with this meta tag, you can override the default SystemManager implementation. As Roger says, “if the [Frame] metadata exists on the base class of your application, a subclass of the factory will be generated. If the metadata is directly on your application class, it will be honored, but no subclass will be generated; its assumed that you’ve already written the appropriate factory.”

Why this is cool

Most Flex developers will never even know the SystemManager exists, and they shouldn’t have to. Adobe has done a good job of masking Flash behind a more professional, Java-like framework with Flex. If you want to write an app with zero dependence on the Flex framework, but still use the fantastic FlashBuilder IDE, debugger/profiler, MXML, and binding, this is really good to know. You can write an Application based on Sprite, write your own stripped down version of the SystemManager, and then write MXML and take advantage of Flex’s bindings and generated code. Rock on.

Tags: , , ,

Particle Emitter Publishing Tool
by Paul Taylor, Nov. 23, 2009, under [ actionscript, misc ]

I’m tired, so I’m going to keep this quick. The Emitter class by Tweensy is fantastic and fun to use, but it’s not easy to imagine what an effect will look like without coding up an example.

That’s why I’ve put together a publishing tool for Tweensy’s particle Emitter. I’m using 15 sample particles embedded in a SWF, which you can download here. Launch the editor here.

Some features of this editor include:

  • The ability to save configurations to a file to be loaded again later (serializing the data to AMF and reading it in to restore state). This means your designers can fiddle with the animations and then email you the configuration.
  • A code generater for each Emitter and each BitmapFilter applied, which means you can load up the configuration the designers sent you and pretty much copy/paste the code into your project.

I will update to add more effects, like the PerlinDisplacementEffect that helps with the really cool fire effects Tweensy is capable of, but for now this is what I’ve got.

Once you add an emitter, you’ll need to set at least the emission frequency, emission randomness, and particle life to see anything happen. After that I suggest moving the X/Y coords and turning on either the Blur filter or the ColorTransform filter. Changing the start and end colors does some dramatic things, as well as fiddling with the blendMode (I suggest either Normal or Add). If you’ve got any questions or feature requests, leave them in the comments. Good luck!

Update: Here’s two sample emitters to start off with: Effect 1 and Fireworks (right click and “Save as…”, keeping the .amf extension).

Update 2: Added the PerlinDisplacementEffect. Try it out!

Tags: , , ,