Korzystanie z architektury Text Layout Framework

Flash Player 10 i nowsze wersje, Adobe AIR 1.5 i nowsze wersje

Omówienie architektury Text Layout Framework

Architektura TLF (Text Layout Framework) jest rozszerzalną biblioteką języka ActionScript. Architektura TLF jest oparta na mechanizmie obsługi tekstu zawartym w programie Adobe® Flash® Player 10 i środowisku Adobe® AIR® 1.5. Architektura TLF oferuje zaawansowane funkcje dotyczące typografii oraz układów tekstu, dzięki czemu pozwala na innowacyjne podejście do tekstu w Internecie. Można z niej korzystać podczas pracy w programie Adobe® Flex® lub Adobe® Flash® Professional. Programiści mogą korzystać z istniejących składników, rozszerzać te składniki lub w ramach platformy opracowywać własne składniki do obsługi tekstu.

Niektóre możliwości architektury TLF:
  • Obsługa tekstu dwukierunkowego, tekstu pionowego i ponad 30 skryptów pisania — dla języków takich jak arabski, hebrajski, chiński, japoński, koreański, tajski, laoski czy wietnamski

  • Zaznaczanie, edytowanie, i układanie tekstu w wielu kolumnach oraz połączonych kontenerach

  • Tekst pionowy, Tate-Chu-Yoko (tekst poziomy w tekście pionowym) oraz wyrównywanie czcionek wschodnioazjatyckich

  • Zaawansowane sterowanie typografią, między innymi kerning, ligatury, wielkość liter, wielkość cyfr, szerokość cyfr i ozdobne dywizy

  • Wycinanie, kopiowanie, wklejanie, cofanie oraz standardowe gesty edycji obsługiwane za pomocą klawiatury i myszy

  • Rozbudowane interfejsy API umożliwiające programistom przekształcanie tekstu, układu i znaczników, a także tworzenie własnych składników do obsługi tekstu

  • Niezawodna obsługa list, w tym własne znaczniki i formaty numerowania

  • Obrazy w wierszu i reguły określania położenia

Architektura TLF jest biblioteką języka ActionScript 3.0 opartą na mechanizmie FTE (Flash Text Engine) wprowadzonym w programie Flash Player 10. Mechanizm FTE jest dostępny za pośrednictwem pakietu flash.text.engine wchodzącego w skład interfejsu API programu Flash Player 10.

Jednak interfejs API programu Flash Player zapewnia dostęp do mechanizmu tekstowego na bardzo niskim poziomie, co oznacza że realizacja niektórych zadań wymaga napisania skomplikowanego kodu. Architektura TLF obudowuje kod niskiego poziomu przy użyciu prostszych interfejsów API. Udostępnia także ogólną architekturę, która definiuje organizację podstawowych elementów zdefiniowanych w mechanizmie FTE, ujmując je w łatwiejszy w użytku system.

W przeciwieństwie do mechanizmu FTE architektura TLF nie jest wbudowana w program Flash Player. Stanowi niezależną bibliotekę składników napisaną w całości w języku ActionScript 3.0. Jest to rozszerzalna platforma, dzięki czemu można ją dostosować do konkretnych środowisk. Zarówno program Flash Professional, jak i zestaw SDK środowiska Flex zawierają składniki oparte na architekturze TLF.

Obsługa złożonych skryptów

Architektura TLF oferuje obsługę złożonych skryptów. Oznacza to między innymi możliwość wyświetlania i edytowania skryptów dla języków z zapisem od prawej do lewej. Architektura TLF pozwala również wyświetlać i edytować skrypty zawierające na przemian tekst z zapisem od lewej do prawej i od prawej do lewej, na przykład dla języków arabskiego i hebrajskiego. Platforma obsługuje nie tylko pionowy układ tekstu w językach chińskim, japońskim i koreańskim, lecz również elementy TCY (tate-chu-yoko). Elementy TCY są to bloki tekstu poziomego osadzone w pionowych ciągach tekstu. Obsługiwane są następujące skrypty:

  • Łaciński (angielski, hiszpański, francuski, wietnamski itd.)

  • Grecki, cyrylica, armeński, gruziński i etiopski

  • Arabski i hebrajski

  • Ideograficzny Han i Kana (chiński, japoński i koreański) oraz Hangul Johab (koreański)

  • Tajski, laoski, oraz khmerski

  • Dewanagari, bengalski, gurmukhi, malayalam, telugu, tamilski, gujarati, oriya, kannada, tybetański

  • Tifinagh, yi, cherokee, aborygenów kanadyjskich, deseret, shawa, vai, tagalog, hanunoo, buhid, tagbanwa

Korzystanie z architektury Text Layout Framework w programie Flash Professional i środowisku Flex

Klasy architektury TLF można stosować bezpośrednio do tworzenia własnych składników w programie Flash. Ponadto program Flash Professional CS5 udostępnia nową klasę fl.text.TLFTextField, która obudowuje funkcje architektury TLF. Klasa TLFTextField pozwala tworzyć w kodzie ActionScript pola tekstowe, w których są stosowane zaawansowane funkcje wyświetlania tekstu oferowane przez architekturę TLF. Obiekt TLFTextField tworzy się w taki sam sposób, jak pole tekstowe klasy TextField. Następnie można skorzystać z właściwości textFlow w celu przypisania zaawansowanych opcji formatowania udostępnianych przez klasy TLF.

Program Flash Professional pozwala utworzyć wystąpienie klasy TLFTextField na stole montażowym za pomocą narzędzia Tekst. Następnie można użyć kodu ActionScript do sterowania formatowaniem i układem pola tekstowego za pośrednictwem klas architektury TLF. Więcej informacji zawiera strona o klasie TLFTextField w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

W przypadku pracy w środowisku Flex należy używać klas architektury TLF. Więcej informacji zawiera sekcja Korzystanie z architektury Text Layout Framework .

Korzystanie z architektury Text Layout Framework

W przypadku pracy w środowisku Flex lub tworzenia własnych składników do obsługi tekstu należy stosować klasy architektury TLF. Architektura TLF jest biblioteką języka ActionScript 3.0 zawartą w całości w bibliotece textLayout.swc. Biblioteka TLF zawiera około stu klas i interfejsów języka ActionScript 3.0 pogrupowanych w dziesięć pakietów. Pakiety te są pakietami podrzędnymi pakietu flashx.textLayout.

Klasy w architekturze Text Layout Framework

Klasy architektury TLF można pogrupować w trzy kategorie:
  • Klasy struktur danych i formatowania

  • Klasy renderowania

  • Klasy interakcji z użytkownikiem

Klasy struktur danych i formatowania

Następujące pakiety zawierają klasy struktur danych i formatowania architektury TLF:

Podstawową strukturą danych architektury TLF jest hierarchia układu tekstu zdefiniowana w pakiecie elements. W ramach tej struktury można przypisywać style i atrybuty do fragmentów tekstu, korzystając z pakietu formats. Korzystając z pakietu conversion, można również sterować importowaniem tekstu do struktury danych i eksportowaniem tekstu ze struktury danych.

Klasy renderowania

Następujące pakiety zawierają klasy renderowania architektury TLF: Klasy zawarte w tych pakietach ułatwiają renderowanie tekstu na potrzeby wyświetlania w programie Flash Player. Pakiet factory udostępnia prosty sposób wyświetlania tekstu statycznego. Pakiet container zawiera klasy i interfejsy definiujące kontenery wyświetlania dla tekstu dynamicznego. Pakiet compose definiuje techniki pozycjonowania i wyświetlania tekstu dynamicznego w kontenerach.

Klasy interakcji z użytkownikiem

Następujące pakiety zawierają klasy interakcji z użytkownikiem architektury TLF: Pakiety edit i operations definiują klasy, które umożliwiają edytowanie tekstu przechowywanego w strukturach danych. Pakiet events zawiera klasy służące do obsługi zdarzeń.

Ogólna procedura tworzenia tekstu przy użyciu architektury Text Layout Framework

W następującej procedurze opisano ogólny proces tworzenia tekstu w architekturze TLF:

  1. Zaimportuj tekst sformatowany do struktur danych TLF. Więcej informacji zawierają sekcje Ustalanie struktury tekstu w architekturze Text Layout Framework oraz Formatowanie tekstu w architekturze Text Layout Framework .

  2. Utwórz co najmniej jeden kontener obiektu ekranowego przeznaczony na tekst. Więcej informacji zawiera sekcja Zarządzanie kontenerami tekstu w architekturze Text Layout Framework .

  3. Skojarz tekst w strukturach danych z kontenerami i ustaw opcje edytowania oraz przewijania. Więcej informacji zawiera sekcja Umożliwianie zaznaczania i edytowania tekstu oraz cofania operacji w architekturze Text Layout Framework .

  4. Utwórz moduł obsługi zdarzeń, który będzie aktualizować układ tekstu w związku ze zdarzeniami zmian rozmiaru (lub innymi). Więcej informacji zawiera sekcja Obsługa zdarzeń w architekturze Text Layout Framework .

Przykład użycia architektury Text Layout Framework: układ gazetowy

W poniższym przykładzie zademonstrowano użycie architektury TLF do przygotowania układu prostej strony gazety. Strona zawiera duży nagłówek, nagłówek podrzędny i wielokolumnową sekcję treści.

package 
{ 
    import flash.display.Sprite; 
    import flash.display.StageAlign; 
    import flash.display.StageScaleMode; 
    import flash.events.Event; 
    import flash.geom.Rectangle; 
     
    import flashx.textLayout.compose.StandardFlowComposer; 
    import flashx.textLayout.container.ContainerController; 
    import flashx.textLayout.container.ScrollPolicy; 
    import flashx.textLayout.conversion.TextConverter; 
    import flashx.textLayout.elements.TextFlow; 
    import flashx.textLayout.formats.TextLayoutFormat; 
     
    public class TLFNewsLayout extends Sprite 
    { 
        private var hTextFlow:TextFlow; 
        private var headContainer:Sprite; 
        private var headlineController:ContainerController; 
        private var hContainerFormat:TextLayoutFormat; 
         
        private var bTextFlow:TextFlow; 
        private var bodyTextContainer:Sprite; 
        private var bodyController:ContainerController; 
        private var bodyTextContainerFormat:TextLayoutFormat; 
         
        private const headlineMarkup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008'><flow:p textAlign='center'><flow:span fontFamily='Helvetica' fontSize='18'>TLF News Layout Example</flow:span><flow:br/><flow:span fontFamily='Helvetica' fontSize='14'>This example formats text like a newspaper page with a headline, a subtitle, and multiple columns</flow:span></flow:p></flow:TextFlow>"; 
         
        private const bodyMarkup:String = "<flow:TextFlow xmlns:flow='http://ns.adobe.com/textLayout/2008' fontSize='12' textIndent='10' marginBottom='15' paddingTop='4' paddingLeft='4'><flow:p marginBottom='inherit'><flow:span>There are many </flow:span><flow:span fontStyle='italic'>such</flow:span><flow:span> lime-kilns in that tract of country, for the purpose of burning the white marble which composes a large part of the substance of the hills. Some of them, built years ago, and long deserted, with weeds growing in the vacant round of the interior, which is open to the sky, and grass and wild-flowers rooting themselves into the chinks of the stones, look already like relics of antiquity, and may yet be overspread with the lichens of centuries to come. Others, where the lime-burner still feeds his daily and nightlong fire, afford points of interest to the wanderer among the hills, who seats himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. It is a lonesome, and, when the character is inclined to thought, may be an intensely thoughtful occupation; as it proved in the case of Ethan Brand, who had mused to such strange purpose, in days gone by, while the fire in this very kiln was burning.</flow:span></flow:p><flow:p marginBottom='inherit'><flow:span>The man who now watched the fire was of a different order, and troubled himself with no thoughts save the very few that were requisite to his business. At frequent intervals, he flung back the clashing weight of the iron door, and, turning his face from the insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a long pole. Within the furnace were seen the curling and riotous flames, and the burning marble, almost molten with the intensity of heat; while without, the reflection of the fire quivered on the dark intricacy of the surrounding forest, and showed in the foreground a bright and ruddy little picture of the hut, the spring beside its door, the athletic and coal-begrimed figure of the lime-burner, and the half-frightened child, shrinking into the protection of his father's shadow. And when again the iron door was closed, then reappeared the tender light of the half-full moon, which vainly strove to trace out the indistinct shapes of the neighboring mountains; and, in the upper sky, there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, though thus far down into the valley the sunshine had vanished long and long ago.</flow:span></flow:p></flow:TextFlow>"; 
         
        public function TLFNewsLayout() 
        {      
            //wait for stage to exist 
            addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);     
        } 
         
        private function onAddedToStage(evtObj:Event):void 
        { 
            removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 
            stage.scaleMode = StageScaleMode.NO_SCALE; 
            stage.align = StageAlign.TOP_LEFT; 
             
            // Headline text flow and flow composer 
            hTextFlow = TextConverter.importToFlow(headlineMarkup, TextConverter.TEXT_LAYOUT_FORMAT); 
             
            // initialize the headline container and controller objects 
            headContainer = new Sprite(); 
            headlineController = new ContainerController(headContainer); 
            headlineController.verticalScrollPolicy = ScrollPolicy.OFF; 
            hContainerFormat = new TextLayoutFormat(); 
            hContainerFormat.paddingTop = 4; 
            hContainerFormat.paddingRight = 4; 
            hContainerFormat.paddingBottom = 4; 
            hContainerFormat.paddingLeft = 4; 
             
            headlineController.format = hContainerFormat; 
            hTextFlow.flowComposer.addController(headlineController); 
            addChild(headContainer); 
            stage.addEventListener(flash.events.Event.RESIZE, resizeHandler); 
             
            // Body text TextFlow and flow composer 
            bTextFlow = TextConverter.importToFlow(bodyMarkup, TextConverter.TEXT_LAYOUT_FORMAT); 
             
            // The body text container is below, and has three columns 
            bodyTextContainer = new Sprite(); 
            bodyController = new ContainerController(bodyTextContainer); 
            bodyTextContainerFormat = new TextLayoutFormat(); 
            bodyTextContainerFormat.columnCount = 3; 
            bodyTextContainerFormat.columnGap = 30; 
             
            bodyController.format = bodyTextContainerFormat; 
            bTextFlow.flowComposer.addController(bodyController); 
            addChild(bodyTextContainer); 
            resizeHandler(null); 
        } 
         
        private function resizeHandler(event:Event):void 
        { 
            const verticalGap:Number = 25; 
            const stagePadding:Number = 16; 
            var stageWidth:Number = stage.stageWidth - stagePadding; 
            var stageHeight:Number = stage.stageHeight - stagePadding; 
            var headlineWidth:Number = stageWidth; 
            var headlineContainerHeight:Number = stageHeight; 
             
            // Initial compose to get height of headline after resize 
            headlineController.setCompositionSize(headlineWidth, 
headlineContainerHeight); 
            hTextFlow.flowComposer.compose(); 
            var rect:Rectangle = headlineController.getContentBounds(); 
            headlineContainerHeight = rect.height; 
             
            // Resize and place headline text container 
            // Call setCompositionSize() again with updated headline height 
            headlineController.setCompositionSize(headlineWidth, headlineContainerHeight ); 
            headlineController.container.x = stagePadding / 2; 
            headlineController.container.y = stagePadding / 2; 
            hTextFlow.flowComposer.updateAllControllers(); 
             
            // Resize and place body text container 
            var bodyContainerHeight:Number = (stageHeight - verticalGap - headlineContainerHeight); 
            bodyController.format = bodyTextContainerFormat; 
            bodyController.setCompositionSize(stageWidth, bodyContainerHeight ); 
            bodyController.container.x = (stagePadding/2); 
            bodyController.container.y = (stagePadding/2) + headlineContainerHeight + verticalGap; 
            bTextFlow.flowComposer.updateAllControllers(); 
        } 
    } 
} 

W klasie TLFNewsLayout użyto dwóch kontenerów tekstu. Jeden kontener wyświetla nagłówek i nagłówek podrzędny, a drugi wyświetla tekst podstawowy w trzech kolumnach. Dla uproszczenia tekst został zakodowany na stałe jako tekst w formacie TLF Markup (formacie znaczników architektury TLF). Zmienna headlineMarkup zawiera zarówno nagłówek, jak i nagłówek podrzędny, zaś zmienna bodyMarkup zawiera tekst podstawowy. Więcej informacji o formacie TLF Markup zawiera sekcja Ustalanie struktury tekstu w architekturze Text Layout Framework .

Po operacjach związanych z inicjowaniem funkcja onAddedToStage() importuje tekst nagłówka do obiektu TextFlow, który stanowi podstawową strukturę danych w architekturze TLF.
hTextFlow = TextConverter.importToFlow(headlineMarkup, TextConverter.TEXT_LAYOUT_FORMAT); 
W kolejnym kroku jest tworzony obiekt Sprite (służący jako kontener) i następuje utworzenie kontrolera oraz skojarzenie go z kontenerem.
headContainer = new Sprite(); 
headlineController = new ContainerController(headContainer);
Kontener jest inicjowany — następuje ustawienie opcji dotyczących między innymi formatowania i przewijania. Kontroler zawiera informacje o geometrii określające obwiednię kontenera, w której jest umieszczany tekst. Obiekt TextLayoutFormat zawiera opcje formatowania.
hContainerFormat = new TextLayoutFormat();

Kontroler jest przypisywany do układacza typograficznego, po czym funkcja dodaje kontener do listy wyświetlania. Właściwe tworzenie kompozycji i wyświetlanie kontenerów odbywa się dopiero w metodzie resizeHandler() . Te same kroki są wykonywane w celu zainicjowania obiektu TextFlow.

Metoda resizeHandler() mierzy obszar dostępny do renderowania kontenerów i odpowiednio ustala ich wymiary. Pierwsze wywołanie metody compose() umożliwia obliczenie właściwej wysokości kontenera nagłówka. Metoda resizeHandler() może następnie umieścić i wyświetlić kontener nagłówka w ramach metody updateAllControllers() . Na koniec metoda resizeHandler() na podstawie wielkości kontenera nagłówka określa położenie kontenera tekstu treści.

Ustalanie struktury tekstu w architekturze Text Layout Framework

Tekst w architekturze TLF jest przechowywany w hierarchicznej strukturze drzewa. Każdy węzeł drzewa jest instancją klasy zdefiniowanej w pakiecie elements. Na przykład węzłem głównym drzewa jest zawsze instancja klasy TextFlow. Klasa TextFlow reprezentuje cały wątek tekstu. Historia jest to kolekcja tekstu i innych elementów traktowana jako jednostka (ciągły fragment). Pojedyncza historia może być wyświetlana w więcej niż jednej kolumnie lub w kilku kontenerach tekstu.

Wszystkie elementy z wyjątkiem węzła głównego są częściowo oparte na elementach XHTML. Na poniższym schemacie przedstawiono hierarchię stosowaną w architekturze:

Hierarchia obiektu TextFlow

Znaczniki architektury Text Layout Framework

Znajomość struktury architektury TLF jest pomocna podczas pracy ze znacznikami tej architektury — z formatem TLF Markup. Format TLF Markup to reprezentacja XML tekstu używanego w architekturze Text Layout Framework. Architektura obsługuje także inne formaty XML, jednak standard TFL Markup jest unikatowy, ponieważ jest oparty na strukturze hierarchii obiektu TextFlow. Hierarchia obiektu TextFlow wyeksportowana jako kod XML w tym formacie pozostanie nienaruszona.

Format TLF Markup zapewnia najwyższą dokładność wyświetlania tekstu umieszczonego w hierarchii obiektu TextFlow. Język znaczników udostępnia znaczniki dla każdego z podstawowych elementów hierarchii obiektu TextFlow, a także atrybuty związane ze wszystkimi właściwościami formatowania zawartymi w klasie TextLayoutFormat.

Poniższa tabela zawiera znaczniki, których można używać w kodzie TLF Markup.

Element

Opis

Elementy podrzędne

Klasa

textflow

Element główny kodu.

div, p

TextFlow

div

Podział tekstu w elemencie TextFlow. Może zawierać grupę akapitów

div, list, p

DivElement

p

Akapit.

a, tcy, span, img, tab, br, g

ParagraphElement

a

Łącze.

tcy, span, img, tab, br, g

LinkElement

tcy

Tekst poziomy (opcja stosowana wewnątrz pionowego obiektu TextFlow).

a, span, img, tab, br, g

TCYElement

span

Bieg tekstu w akapicie.

SpanElement

img

Obraz w akapicie.

InlineGraphicElement

tab

Znak tabulacji.

TabElement

br

Znak podziału. Służy jako zakończenie wiersza w akapicie. Tekst jest kontynuowany w następnym wierszu, ale w ramach tego samego akapitu.

BreakElement

linkNormalFormat

Definiuje atrybuty formatujące używane dla łączy w stanie normalnym.

TextLayoutFormat

TextLayoutFormat

linkActiveFormat

Definiuje atrybuty formatujące używane dla łączy w stanie aktywnym, gdy użytkownik trzyma naciśnięty przycisk myszy, a wskaźnik znajduje się nad łączem.

TextLayoutFormat

TextLayoutFormat

linkHoverFormat

Definiuje atrybuty formatujące używane dla łączy pod wskaźnikiem, gdy wskaźnik myszy znajduje się w granicach łącza („najazd”).

TextLayoutFormat

TextLayoutFormat

li

Element pozycji listy. Musi znajdować się wewnątrz pozycji listy.

div, li, list, p

ListItemElement

list

Lista. Listy mogą być zagnieżdżone lub umieszczone obok siebie. Do pozycji na liście można stosować różne schematy nazw lub numeracji.

div, li, list, p

ListElement

g

Element grupy. Służy do grupowania elementów w akapicie. Umożliwia zagnieżdżanie elementów poniżej poziomu akapitu.

a, tcy, span, img, tab, br, g

SubParagraphGroupElement

Używanie list numerowanych i punktowanych

Korzystając z klas ListElement i ListItemElement , można dodawać listy punktowane do tekstowych elementów sterujących. Listy punktowane można zagnieżdżać oraz dostosowywać w celu używania różnych punktorów (znaczników), automatycznego numerowania, a także numerowania w stylu konspektu.

Do tworzenia list w przepływie tekstu służy znacznik <list> . Następnie dla wszystkich pozycji listy należy wprowadzić znaczniki <li> w obrębie znacznika <list> . Wygląd punktorów można dostosować przy użyciu klasy ListMarkerFormat.

W poniższym przykładzie przedstawiono tworzenie prostych list.
<flow:list paddingRight="24" paddingLeft="24"> 
    <flow:li>Item 1</flow:li> 
    <flow:li>Item 2</flow:li> 
    <flow:li>Item 3</flow:li> 
</flow:list>
Listy można zagnieżdżać w innych listach, co ilustruje poniższy przykład.
<flow:list paddingRight="24" paddingLeft="24"> 
    <flow:li>Item 1</flow:li> 
    <flow:list paddingRight="24" paddingLeft="24"> 
        <flow:li>Item 1a</flow:li> 
        <flow:li>Item 1b</flow:li> 
        <flow:li>Item 1c</flow:li> 
    </flow:list> 
    <flow:li>Item 2</flow:li> 
    <flow:li>Item 3</flow:li> 
</flow:list>
Właściwość listStyleType obiektu ListElement pozwala dostosować typ znacznika na liście. Właściwość ta może mieć dowolną wartość zdefiniowaną w klasie ListStyleType, na przykład check (ptaszek), circle (kółko), decimal (liczba dziesiętna) czy box (kwadrat). W poniższym przykładzie są tworzone listy z różnymi typami znaczniku i własnymi krokami liczników.
<flow:list paddingRight="24" paddingLeft="24" listStyleType="upperAlpha">     <flow:li>upperAlpha item</flow:li>     <flow:li>another</flow:li> </flow:list> <flow:list paddingRight="24" paddingLeft="24" listStyleType="lowerAlpha">     <flow:li>lowerAlpha item</flow:li>     <flow:li>another</flow:li> </flow:list> <flow:list paddingRight="24" paddingLeft="24" listStyleType="upperRoman">     <flow:li>upperRoman item</flow:li>     <flow:li>another</flow:li> </flow:list> <flow:list paddingRight="24" paddingLeft="24" listStyleType="lowerRoman">     <flow:listMarkerFormat>         <!-- Increments the list by 2s rather than 1s. -->         <flow:ListMarkerFormat counterIncrement="ordered 2"/>     </flow:listMarkerFormat>     <flow:li>lowerRoman item</flow:li>     <flow:li>another</flow:li> </flow:list>

Klasa ListMarkerFormat pozwala zdefiniować licznik. Oprócz definiowania kroku licznika można dostosowywać licznik, zerując go za pomocą właściwości counterReset .

W celu dostosowania wyglądu znaczników na listach można użyć właściwości beforeContent i afterContent obiektu ListMarkerFormat. Właściwości te są stosowane do zawartości wyświetlanej przez zawartością znacznika i po niej.

W poniższym przykładzie przed znacznikiem jest dodawany ciąg „XX”, a po nim ciąg „YY”.
<flow:list listStyleType="upperRoman" paddingLeft="36" paddingRight="24"> 
    <flow:listMarkerFormat> 
        <flow:ListMarkerFormat fontSize="16" 
            beforeContent="XX" 
            afterContent="YY" 
            counterIncrement="ordered -1"/> 
        </flow:listMarkerFormat> 
    <flow:li>Item 1</flow:li> 
    <flow:li>Item 2</flow:li> 
    <flow:li>Item 3</flow:li> 
</flow:list>
Również sama właściwość content pozwala dostosowywać formatowanie znacznika. Poniższy przykład ilustruje sposób wyświetlania uporządkowanych znaczników opartych na cyfrach rzymskich.
<flow:list listStyleType="disc"  paddingLeft="96" paddingRight="24"> 
    <flow:listMarkerFormat> 
        <flow:ListMarkerFormat fontSize="16" 
            beforeContent="Section " 
            content="counters(ordered,&quot;*&quot;,upperRoman)" 
            afterContent=": "/> 
    </flow:listMarkerFormat> 
    <flow:li>Item 1</li> 
    <flow:li>Item 2</li> 
    <flow:li>Item 3</li> 
</flow:list>

Jak widać na poprzednim przykładzie, właściwość content pozwala też dodać przyrostek — ciąg wyświetlany po znaczniku, ale przed elementem afterContent . Aby wstawić ten ciąg podczas umieszczania zawartości XML w przepływie, należy umieścić ciąg w elementach HTML &quote; , a nie w cudzysłowach ( "< string >" ).

Stosowanie dopełnienia w architekturze TLF

Każdy obiekt FlowElement obsługuje właściwości dopełnienia, za pomocą których można sterować położeniem każdego elementu w obszarze zawartości, a także odstępami między obszarami zawartości.

Całkowita szerokość elementu jest sumą szerokości jego zawartości powiększoną o wartości właściwości paddingLeft i paddingRight . Całkowita wysokość elementu jest sumą wysokości jego zawartości powiększoną o wartości właściwości paddingTop i paddingBottom .

Dopełnienie jest to puste miejsce między krawędzią a zawartością. Właściwości dopełnienia to: paddingBottom , paddingTop , paddingLeft , paddingRight . Dopełnienie można stosować względem obiektu TextFlow, a także następujących elementów potomnych:
  • div

  • img

  • li

  • list

  • p

Właściwości dopełnienia nie można stosować do elementów zakresu.

W poniższym przykładzie są ustawiane właściwości dopełnienia obiektu TextFlow.
<flow:TextFlow version="2.0.0" xmlns:flow="http://ns.adobe.com/textLayout/2008" fontSize="14" textIndent="15" paddingTop="4" paddingLeft="4" fontFamily="Times New Roman">

Poprawne wartości właściwości dopełnienia to liczby (w pikselach) oraz ciągi „auto” (automatycznie) i „inherit” (dziedziczenie). Wartością domyślną jest „auto” (automatycznie). Oznacza ona obliczanie automatyczne i ustawianie na 0 dla wszystkich elementów oprócz obiektów typu ListElement. W przypadku obiektów typu ListElement opcja „auto” (automatycznie) oznacza wartość 0 z wyjątkiem początku listy, gdzie jest stosowana wartość właściwości listAutoPadding . Wartość domyślna właściwości listAutoPadding to 40 — domyślne wcięcie list.

Właściwości dopełnienia domyślnie nie są dziedziczone. Wartości „auto” (automatycznie) i „inherit” (dziedziczenie) są stałymi zdefiniowanymi w klasie FormatValue .

Właściwości dopełnienia nie mogą mieć wartości ujemnych.

Formatowanie tekstu w architekturze Text Layout Framework

Pakiet flashx.textLayout.formats zawiera interfejsy i klasy umożliwiające przypisywanie formatów do dowolnych elementów FlowElement w drzewie hierarchii przepływu tekstu. Istnieją dwa sposoby zastosowania formatowania. Można przypisywać formaty pojedynczo lub przypisać od razu całą grupę formatów, korzystając ze specjalnego obiektu formatowania.

Interfejs ITextLayoutFormat zawiera wszystkie formaty, jakie mogą być stosowane do obiektu FlowElement. Niektóre formaty mają zastosowanie do całego kontenera lub akapitu tekstu, ale logicznie nie mają zastosowania do poszczególnych znaków. Takie formaty, jak justowanie i znaczniki tabulacji, mają zastosowanie do całych akapitów, ale nie do poszczególnych znaków.

Przypisywanie formatów do obiektu FlowElement z właściwościami

Do dowolnego obiektu FlowElement można przypisywać formaty poprzez przypisanie właściwości. Klasa FlowElement implementuje interfejs ITextLayoutFormat, a zatem każda podklasa klasy FlowElement także musi implementować ten interfejs.

Poniższy przykładowy kod ilustruje przypisywanie pojedynczych formatów do wystąpienia klasy ParagraphElement.

var p:ParagraphElement = new ParagraphElement(); 
p.fontSize = 18; 
p.fontFamily = "Arial";

Przypisywanie formatów do obiektu FlowElement za pomocą klasy TextLayoutFormat

Możliwe jest stosowanie formatów względem obiektów FlowElement za pomocą klasy TextLayoutFormat. Ta klasa umożliwia utworzenie specjalnego obiektu formatowania, który zawiera wszystkie pożądane wartości formatowania. Następnie taki obiekt można przypisać do właściwości format dowolnego obiektu FlowElement. Klasy TextLayoutFormat i FlowElement implementują interfejs ITextLayoutFormat. Takie rozwiązanie gwarantuje, że obie klasy zawierają te same właściwości formatowania.

Więcej informacji zawiera strona o klasie TextLayoutFormat w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Dziedziczenie formatów

W hierarchii przepływu tekstu formaty są dziedziczone. Przypisanie instancji klasy TextLayoutFormat do instancji klasy FlowElement, która ma elementy podrzędne, inicjuje proces nazywany kaskadowaniem . W trakcie kaskadowania następuje rekurencyjne przeglądanie wszystkich węzłów hierarchii dziedziczących z obiektu FlowElement. Następnie architektura określa, czy odziedziczone wartości powinny być przypisane do poszczególnych właściwości formatowania. W trakcie kaskadowania stosowane są następujące reguły:

  1. Wartości właściwości są dziedziczone wyłącznie z bezpośredniego przodka (niekiedy nazywanego elementem nadrzędnym).

  2. Wartości właściwości są dziedziczone, o ile właściwość nie ma jeszcze wartości (tj. ma wartość undefined ).

  3. Niektóre atrybuty nie dziedziczą wartości, jeśli są niezdefiniowane (undefined) — muszą mieć wartość „inherit” lub równą stałej flashx.textLayout.formats.FormatValue.INHERIT .

Na przykład ustawienie wartości fontSize na poziomie obiektu TextFlow będzie obowiązywało we wszystkich elementach w obiekcie TextFlow. Innymi słowy, wartości są kaskadowo przenoszone w dół hierarchii przepływu tekstu. Można jednak przesłonić wartość w konkretnym elemencie, przypisując ją do właściwości tego elementu. Dla odmiany, jeśli ustawimy wartość backgroundColor na poziomie obiektu TextFlow, elementy podrzędne obiektu TextFlow jej nie odziedziczą. Właściwość backgroundColor nie jest dziedziczona z elementów nadrzędnych w trakcie kaskadowania. Można przesłonić to zachowanie, przypisując właściwości backgroundColor każdego elementu podrzędnego wartość flashx.textLayout.formats.FormatValue.INHERIT .

Więcej informacji zawiera strona o klasie TextLayoutFormat w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Importowanie i eksportowanie tekstu w architekturze Text Layout Framework

Klasa TextConverter w pakiecie flashx.textLayout.conversion.* Pakiet umożliwia importowanie tekstu do plików TLF i eksportowanie tekstu z takich plików. Tej klasy należy używać, gdy tekst ma być wczytywany w czasie wykonywania, a nie skompilowany w pliku SWF. Stosując tę klasę, można wyeksportować tekst przechowywany w wystąpieniu klasy TextFlow do obiektu String lub XML.

Procedury importu i eksportu nie są skomplikowane. Należy wywołać metodę export() albo metodę importToFlow() , które należą do klasy TextConverter. Obie metody są statyczne, co oznacza, że wywołuje się je z klasy TextConverter, a nie z jej instancji.

Klasy zawarte w pakiecie flashx.textLayout.conversion oferują znaczną elastyczność w zakresie wyboru miejsca przechowywania tekstu. Jeśli na przykład tekst jest przechowywany w bazie danych, można go zaimportować w celu wyświetlenia na platformie. Następnie można za pomocą klas z pakietu flashx.textLayout.edit zmienić tekst i wyeksportować go do bazy danych.

Więcej informacji zawiera strona o pakiecie flashx.textLayout.conversion w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Zarządzanie kontenerami tekstu w architekturze Text Layout Framework

Tekst przechowywany w strukturach danych architektury TLF można wyświetlać w programie Flash Player. Tekst przechowywany w hierarchii przepływu musi zostać przekonwertowany na format odpowiedni do wyświetlania w programie Flash Player. Architektura TLF udostępnia dwa sposoby tworzenia obiektów ekranowych z przepływu. Pierwszy, prostszy z nich, jest przydatny podczas wyświetlania tekstu statycznego. Drugi, bardziej złożony, umożliwia tworzenie tekstu dynamicznego z opcjami zaznaczania i edycji. W obu przypadkach tekst jest ostatecznie konwertowany na wystąpienia klasy TextLine, która wchodzi w skład pakietu flash.text.engine.* w programie Flash Player 10.

Tworzenie tekstu statycznego

W prostej metodzie używana jest klasa TextFlowTextLineFactory, która znajduje się w pakiecie flashx.textLayout.factory . Zaletą tej metody, obok jej prostoty, jest mniejsza zajętość pamięci niż w przypadku użycia klasy FlowComposer. Ta strategia jest zalecana w przypadku tekstu statycznego, który nie wymaga edycji, zaznaczania ani przewijania przez użytkownika.

Więcej informacji zawiera strona o klasie TextFlowTextLineFactory w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Tworzenie tekstu dynamicznego i kontenerów

Układacz typograficzny zapewnia większą kontrolę nad wyświetlaniem tekstu niż obiekt TextFlowTextLineFactory. Dzięki zastosowaniu układacza typograficznego użytkownicy mogą na przykład zaznaczać i edytować tekst. Więcej informacji zawiera sekcja Umożliwianie zaznaczania i edytowania tekstu oraz cofania operacji w architekturze Text Layout Framework .

Układacz typograficzny jest wystąpieniem klasy StandardFlowComposer zawartej w pakiecie flashx.textLayout.compose . Układacz typograficzny zarządza konwersją wystąpienia klasy TextFlow na wystąpienia klasy TextLine oraz rozmieszczeniem tych wystąpień klasy TextLine w kontenerze lub kontenerach.

Powiększ obraz
Z obiektem IFlowComposer skojarzonych jest zero lub więcej obiektów ContainerController

Z każdą instancją TextFlow skojarzony jest obiekt implementujący interfejs IFlowComposer. Ten obiekt IFlowComposer jest dostępny za pośrednictwem właściwości TextFlow.flowComposer . Korzystając z tej właściwości, można wywoływać metody zdefiniowane w interfejsie IFlowComposer. Metody te pozwalają skojarzyć tekst z kontenerem lub kontenerami oraz przygotować tekst do wyświetlania w kontenerze.

Kontener jest instancją klasy Sprite, która z kolei jest podklasą klasy DisplayObjectContainer. Obie te klasy wchodzą w skład interfejsu API listy wyświetlania programu Flash Player. Kontener jest bardziej zaawansowaną formą prostokąta ograniczającego używanego w klasie TextLineFactory. Podobnie jak obiekt rectangle, kontener otacza obszar, w którym widoczne są instancje klasy TextLine. W odróżnieniu od prostokątnej obwiedni kontener jest powiązany z obiektem kontrolera. Kontroler zarządza przewijaniem, tworzeniem kompozycji, tworzeniem połączeń, formatowaniem i obsługą zdarzeń. Steruje kontenerem lub zbiorem kontenerów. Każdy kontener ma odpowiadający mu obiekt kontrolera będący wystąpieniem klasy ContainerController z pakietu flashx.textLayout.container.

W celu wyświetlenia tekstu należy utworzyć obiekt kontrolera przeznaczony do zarządzania kontenerem i skojarzyć go z układaczem typograficznym. Po skojarzeniu kontenera należy zdefiniować układ tekstu (dokonać kompozycji), aby można go było wyświetlić. W związku z tym kontenery mają dwa stany: kompozycji i wyświetlania. Kompozycja tekstu to proces przekształcania tekstu z hierarchii przepływu tekstu na instancje klasy TextLine i obliczania, w jaki sposób rozmieścić te instancje w kontenerach. Wyświetlanie to proces aktualizowania listy wyświetlania programu Flash Player.

Więcej informacji zawierają opisy klas IFlowComposer , StandardFlowComposer i ContainerController w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Umożliwianie zaznaczania i edytowania tekstu oraz cofania operacji w architekturze Text Layout Framework

Sterowanie możliwością zaznaczania i edytowania tekstu odbywa się na poziomie obiektu TextFlow. Z każdą instancją klasy TextFlow jest skojarzony menedżer interakcji. Dostęp do menedżera interakcji obiektu TextFlow można uzyskać za pośrednictwem właściwości TextFlow.interactionManager tego obiektu. Aby umożliwić zaznaczanie tekstu, należy przypisać instancję klasy SelectionManager do właściwości interactionManager . Aby umożliwić zarówno zaznaczanie tekstu, jak i edytowanie, należy przypisać instancję klasy EditManager zamiast instancji klasy SelectionManager. Aby umożliwić cofanie operacji, należy utworzyć instancję klasy UndoManager i przekazać ją jako argument w wywołaniu konstruktora EditManager. Klasa UndoManager umożliwia zarządzanie historią ostatnich czynności edycyjnych użytkownika oraz cofanie lub ponawianie konkretnych czynności. Wszystkie trzy klasy wchodzą w skład pakietu edit.

Więcej informacji zawierają opisy klas SelectionManager , EditManager i UndoManager w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Obsługa zdarzeń w architekturze Text Layout Framework

Obiekty TextFlow wywołują zdarzenia w wielu sytuacjach, między innymi:
  • przy zmianach tekstu lub układu,

  • przed rozpoczęciem operacji oraz po zakończeniu operacji,

  • w przypadku zmiany stanu obiektu FlowElement,

  • po zakończeniu operacji tworzenia kompozycji.

Więcej informacji zawiera opis pakietu flashx.textLayout.events w dokumentacji języka ActionScript 3.0 dla platformy Adobe Flash.

Określanie położenia obrazów w tekście

Do określania położenia obiektu InlineGraphicElement w tekście służą następujące właściwości:
  • Właściwość float klasy InlineGraphicElement

  • Właściwość clearFloats obiektu FlowElement

Właściwość float określa, jak grafika jest umieszczana w sąsiadującym z nią tekście. Właściwość clearFloats określa położenie elementów w akapicie względem obiektu o właściwości float .

Sterowanie położeniem obrazu w elemencie tekstowym odbywa się przy użyciu właściwości float . W poniższym przykładzie obraz jest dodawany do akapitu i wyrównywany do lewej w taki sposób, aby tekst był zawijany na prawo od niego.
<flow:p paragraphSpaceAfter="15" >Images in a flow are a good thing. For example, here is a float. It should show on the left: <flow:img float="left" height="50" width="19" source="../assets/bulldog.jpg"></flow:img> Don't you agree? Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here.</flow:p>

Poprawne wartości właściwości float : left (do lewej), right (do prawej), start (na początku), end (na końcu), none (brak). Są to stałe zdefiniowane w klasie Float. Wartością domyślną jest none (brak).

Właściwość clearFloats jest przydatna, gdy trzeba dopasować położenie początkowe kolejnych akapitów, które bez tej modyfikacji byłyby zawijane wokół obrazu. Załóżmy na przykład, że istnieje obraz większy niż pierwszy akapit. Aby mieć pewność, że drugi akapit zacznie się pod obrazem, należy ustawić właściwość clearFloats .

W poniższym przykładzie zastosowano obraz wyższy niż tekst w pierwszym akapicie. Aby drugi akapit zaczynał się w bloku tekstu pod obrazem, w przykładzie ustawiono właściwość clearFloats drugiego akapitu na end (na końcu).
<flow:p paragraphSpaceAfter="15" >Here is another float, it should show up on the right: <flow:img float="right" height="50" elementHeight="200" width="19" source="../assets/bulldog.jpg"></flow:img>We'll add another paragraph that should clear past it.</flow:p><flow:p clearFloats="end" >This should appear after the previous float on the right.</flow:p>

Poprawne wartości właściwości clearFloats : left (do lewej), right (do prawej), end (na końcu), start (na początku), none (brak), both (obydwa). Są to stałe zdefiniowane w klasie ClearFloats . Dla właściwości clearFloats można także ustawić wartość inherit (dziedziczenie). Jest to stała zdefiniowana w klasie FormatValue . Wartością domyślną jest none (brak).