Archive for January, 2011

TLF 2.0 Changes: SubParagraphGroupElements and typeName applied to TextFieldHTMLImporter and CSSFormatResolver

Changes made to the TLF 2.0 are being used to improve theTextFieldHTML importer. First note that this importer is intended for compatibility with the TextField.htmlText property. It’s not intended to be a general purpose HTML importer.

The SubParagraphGroupElement

In TLF 1.1 and earlier There was no equivalent of HTML’s nested spans. TLF 2.0 adds the SubPargraphGroupElement (in markup <g>). SubParagraphGroupElements can be a child of a ParagraphElement, LinkElement, TCYElement or another SubParagraphGroupElement. These are useful for creating nested text elements that share some formatting.

The FlowElement typeName property

All TLF elements now have a typeName property. This property is initialized to the string used when exporting TLF markup. This table shows the default class names and default typeNames for new instances of that class. Note that typeName is a read/write property and clients may manipulate it.

DivElement div
InlineGraphicElement img
LinkElement a
ListElement list
ListItemElement li
ParagraphElement p
SpanElement span
SubParagraphGroupElement g
TabElement tab
TextFlow TextFlow

Note that TLF always converts TabElement and BreakElement elements into the tab and newline character so normally they disappear from the TextFlow and are left off this table.

HTMLImporter Changes to Support Unknown Tags

The HTML importer now preserves unrecognized element tags, for example <foo>Text</foo>, by creating a TLF element and setting its typeName to be an element of that tag. The goal of this is to allow importing of HTML with custom tags and connecting a stylesheet with typename selectors that match through an IFormatResolver. When the importer encounters an unknown tag the rule it uses is if the unknown tag has one child element that child gets its typeName set to the unknown tag. If two or more elements are created than a <div> or a <g> as the parent of the children with its typeName set.

For example :

Import this HTML:
to create TLFMarkup:
<p typeName=”foo”><span>Text</span></p>

Import this HTML:
to create TLFMarkup:
<div typeName=”foo”><p><span>Hello</span></p><p><span>World</span></p></div>

Import this HTML:
to create TLFMarkup::
<p><g typeName=”foo”><span fontWeight=”bold”>bold</span><span>normal</span></g></p>

Import this HTML:
to create TLFMarkup::
<p><span typeName=”foo”>asdf</span></p>

Warning: TLF’s HTMLExporter converts all tag names to uppercase. So typeName=”foo” exports to <FOO>. The TLF markup exporter preserves case as shown above.

SubPargraphGroupElement and the HTML Importer

Previously the importer was unable to preserve nested span elements with formatting. For example:
<font size=”18″><span>Normal <font color=”#0000ff”>BLUE</font> Normal</span></font>

In 1.0 this content created 3 spans with different formatting like this:
<p><span fontSize=”18″>Normal </span><span color=”#0000ff” fontSize=”18″>BLUE</span><span fontSize=”18″> Normal</span></p>

In 2.0 this content creates a group with three span elements:
<p><g fontSize=”18″ typeName=”span”><span>Normal </span><span color=”#0000ff”>BLUE</span><span> Normal</span></g></p>

This example becomes even more interesting if the <span> is changed to a <foo> and CSS formatting is connected.

typeName and CSSFormatResolver

This can all be used to improve the connection of CSS stylesheets to a TextFlow using the IFormatResolver interface. This was originally described in an older blog post.

I’ve updated the Flex based CSSFormatResolver example to leverage the typeName property as well as including a demonstration of a styled “foo” tag. It’s attached here. Note: You will have to adjust the library paths.

For those requesting a non-Flex version of CSSFormatResolver I attached a sample here. Note: You will have to adjust the library paths.

Decoration Example

There are a lot of cases where you might want to add additional DisplayObjects to the line when it is displayed. Sometimes these are called decorations or ornaments. We got this example from one of our users, Will Lin of Silicon Publishing. Will wanted to have a bulleted list, but he needed his list to work with TLF 1.1, which doesn’t have list support. So he added a decoration to the lines that adds the bullet at the start of the paragraph. Here’s how it works.

TLF’s ContainerController class takes the TextLines generated from composition and adds them to the container. To do this, it has a function, addTextLine, that is called on each TextLine as it is added. Will made a new class, BulletsContainerController, that inherits from ContainerController and overrides the addTextLine method. For each line that is added, he checks to see if the line is at the beginning of the paragraph. If it is, he generates a new DisplayObject for the bullet and makes it a child of the TextLine.

In the main body of his application, when he creates the TextFlow, instead of adding a controller that is a ContainerController instance he adds a BulletContainerController instead.

That’s pretty much all there is to it. Thanks to Will and to Silicon Publishing for making this example public!