Utilisation de Text Layout Framework

Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures

Présentation de Text Layout Framework

Text Layout Framework (TLF) est une bibliothèque ActionScript évolutive. TLF est basé sur le moteur texte d’Adobe® Flash® Player 10 et d’Adobe® AIR® 1.5. Il propose des fonctions typographiques et de mise en forme du texte avancées qui assurent une typographie innovatrice sur le Web. TLF peut être utilisé avec Adobe® Flex® ou Adobe® Flash® Professional. Les développeurs peuvent utiliser ou étendre des composants existants ou faire appel à la structure pour créer leurs propres composants texte.

TLF intègre les fonctionnalités suivantes :
  • Texte bidirectionnel, texte vertical et plus de 30 scripts tels que l’arabe, le chinois, le coréen, l’hébreu, le japonais, le laotien, le thaï, le vietnamien, etc.

  • Sélection, modification et distribution du texte sur plusieurs colonnes et conteneurs liés

  • Texte vertical, Tate-Chu-Yoko (texte horizontal placé entre du texte vertical) et justificateur pour la typographie asiatique

  • Contrôles typographiques riches, tels que le crénage, les ligatures, la casse typographique, la casse des chiffres, la largeur des chiffres et les tirets conditionnels

  • Couper, copier, coller, annulation et mouvements de souris et clavier standard de modification

  • API riches de développement destinées à manipuler le contenu, la mise en forme et le balisage de texte, ainsi qu’à créer des composants texte personnalisés

  • Excellente prise en charge des listes, notamment les marques et formats de numérotation personnalisés

  • Règles de positionnement et images intégrées

Text Layout Framework est une bibliothèque ActionScript 3.0 basée sur la version de Flash Text Engine (FTE) introduite dans Flash Player 10. Vous pouvez accéder à FTE via le package flash.text.engine , qui fait partie intégrante de l’API (Application Programming Interface) de Flash Player 10.

Toutefois, l’API de Flash Player fournit un accès de bas niveau à FTE, ce qui signifie que certaines tâches nécessitent parfois un volume de code relativement important. TLF encapsule le code de bas niveau dans des API simplifiées. Il propose également une architecture conceptuelle qui organise les blocs de construction de base définis par FTE pour former un système convivial.

Contrairement à FTE, TLF n’est pas intégré à Flash Player. Il correspond à une bibliothèque de composants indépendants écrits entièrement en ActionScript 3.0. En raison de l’extensibilité de la structure, il peut être adapté à des environnements déterminés. Flash Professional et le kit de développement (SDK) de Flex contiennent tous deux des composants basés sur la structure TLF.

Prise en charge des scripts complexes

TLF prend en charge les scripts complexes, qui gèrent des fonctionnalités telles que la capacité d’afficher et de modifier les scripts rédigés de droite à gauche. TLF permet également d’afficher et de modifier un mélange de scripts écrits de gauche à droite et de droite à gauche, comme l’arabe et l’hébreu. TLF prend en charge non seulement la mise en forme du texte vertical chinois, coréen et japonais, mais également tate-chu-yoko (éléments TCY). Les éléments TCY sont des blocs de texte horizontaux intégrés à des segments verticaux de texte. Les scripts suivants sont pris en charge :

  • Latin (anglais, espagnol, français, vietnamien, etc.)

  • Arménien, cyrillique, éthiopien, géorgien et grec

  • Arabe et hébreu

  • Idéogrammes Han, Kana (chinois, coréen et japonais) et Hangul Johab (coréen)

  • Thaï, khmer et laotien

  • Bengali, dévanâgarî, gujarâtî, gourmoukhî, kannara, malayalam, oriya, tamoul, télougou et tibétain

  • Bouhid, chérokie, deseret, écriture syllabique canadienne, hanounoo, shavian, tagalog, tagbanoua, tifinaghe, vai et yi

Utilisation de Text Layout Framework (TLF) dans Flash Professional et Flex

Vous pouvez créer des composants personnalisés dans Flash directement à partir de classes TLF. Flash Professional CS5 intègre en outre une nouvelle classe, fl.text.TLFTextField, qui encapsule la fonctionnalité TLF. La classe TLFTextField permet de créer des champs de texte en ActionScript qui utilisent les fonctions d’affichage de texte avancées de TLF. Créez un objet TLFTextField à l’instar d’un champ de texte par le biais de la classe TextField. Utilisez ensuite la propriété textFlow pour appliquer le formatage avancé à partir des classes de TLF.

Vous pouvez également créer l’occurrence de TLFTextField sur la scène à l’aide de l’outil texte de Flash Professional. Vous pouvez alors utiliser ActionScript pour contrôler le formatage et la mise en forme du champ de texte à l’aide de classes TLF. Pour plus d’informations, voir TLFTextField dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Dans Flex, utilisez les classes TLF. Pour plus d’informations, voir Utilisation de Text Layout Framework .

Utilisation de Text Layout Framework

Si vous travaillez dans Flex ou créez des composants texte personnalisés, faites appel aux classes TLF. TLF est une bibliothèque ActionScript 3.0 entièrement intégrée à la bibliothèque textLayout.swc. La bibliothèque TLF contient environ 100 classes et interfaces ActionScript 3.0 réparties dans dix packages. Ces packages sont des sous-packages du package flashx.textLayout.

Classes Text Layout Framework

Les classes TLF sont regroupées en trois catégories :
  • Classes de formatage et structures de données

  • Classes de rendu

  • Classes d’interaction utilisateur

Classes de formatage et structures de données

Les packages suivants contiennent les classes de formatage et structures de données de TLF :

La structure de données principale de TLF correspond à la hiérarchie d’enchaînements, définie dans le package d’éléments. Au sein de cette structure, vous pouvez attribuer des styles et attributs à des segments de texte en utilisant le package de formats. Le package de conversion permet de contrôler l’importation et l’exportation du texte dans la structure de données.

Classes de rendu

Les packages suivants contiennent les classes de rendu de TLF : Les classes de ces packages facilitent le rendu du texte affiché par Flash Player. Le package d’usine constitue un moyen simple d’afficher du texte statique. Le package de conteneur inclut les classes et les interfaces qui définissent les conteneurs d’affichage du texte dynamique. Le package de composition définit les techniques de positionnement et d’affichage de texte dynamique dans les conteneurs.

Classes d’interaction utilisateur

Les packages suivants contiennent les classes d’interaction utilisateur de TLF : Les packages de modification et d’opérations définissent les classes dont vous disposez pour autoriser la modification du texte stocké dans les structures de données. Le package des événements contient les classes de gestion des événements.

Procédure générale de création de texte à l’aide de Text Layout Framework

La procédure suivante décrit le processus général de création de texte à l’aide de Text Layout Format :

  1. Importez du texte formaté dans les structures de données TLF. Pour plus d’informations, voir Structuration du texte à l’aide de TLF et Formatage du texte à l’aide de TLF .

  2. Créez un ou plusieurs conteneurs d’objets d’affichage liés destinés au texte. Pour plus d’informations, voir Gestion des conteneurs de texte à l’aide de TLF .

  3. Associez le texte figurant dans les structures de données aux conteneurs et définissez les options de modification et de défilement. Pour plus d’informations, voir Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF .

  4. Créez un gestionnaire d’événement permettant de redistribuer le texte en réponse à des événements de redimensionnement (ou autre). Pour plus d’informations, voir Gestion des événements à l’aide de TLF .

Exemple Text Layout Framework : article de journal

L’exemple suivant illustre la mise en forme d’une page de journal simple à l’aide de TLF. Cette page comprend un gros titre, un sous-titre et une section sur plusieurs colonnes :

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(); 
        } 
    } 
} 

La classe TLFNewsLayout utilise deux conteneurs de texte. Le premier affiche un titre et un sous-titre, tandis que le second contient trois colonnes de texte. Pour raison de simplicité, le texte est codé en dur dans l’exemple au format TLF Markup. La variable headlineMarkup contient le titre et le sous-titre, tandis que la variable bodyMarkup contient le corps du texte. Pour plus d’informations sur TLF Markup, voir Structuration du texte à l’aide de TLF .

Au terme d’une initialisation, la fonction onAddedToStage() importe le titre du titre dans un objet TextFlow, qui correspond à la principale structure de données de TLF :
hTextFlow = TextConverter.importToFlow(headlineMarkup, TextConverter.TEXT_LAYOUT_FORMAT); 
Le code suivant permet ensuite de créer un objet Sprite destiné au conteneur, puis de créer un contrôleur et de l’associer au conteneur :
headContainer = new Sprite(); 
headlineController = new ContainerController(headContainer);
Le contrôleur est initialisé de sorte à définir le formatage, le défilement et autres options. Il contient la géométrie qui définit les limites du conteneur dans lequel est distribué le texte. Un objet TextLayoutFormat contient les options de formatage suivantes :
hContainerFormat = new TextLayoutFormat();

Le contrôleur est affecté au compositeur d’enchaînements et la fonction ajoute le conteneur à la liste d’affichage. La composition et l’affichage à proprement parler des conteneurs relèvent de la méthode resizeHandler() . Une procédure identique permet d’initialiser l’objet TextFlow associé au corps du texte.

La méthode resizeHandler() mesure l’espace disponible pour le rendu des conteneurs et affecte à ces derniers la taille appropriée. Un appel initial de la méthode compose() permet de calculer la hauteur appropriée du conteneur de gros titre. La méthode resizeHandler() peut alors placer et afficher le conteneur de gros titre par le biais de la méthode updateAllControllers() . Enfin, la méthode resizeHandler() se base sur la taille du conteneur de gros titre pour déterminer le positionnement du conteneur de corps de texte.

Structuration du texte à l’aide de TLF

TLF représente le texte sous forme d’arborescence. Chaque nœud de l’arborescence est une occurrence d’une classe définie dans le package d’éléments. Par exemple, le nœud racine de l’arborescence est toujours une occurrence de la classe TextFlow. La class TextFlow représente un article de texte entier. Un article est un ensemble d’éléments texte ou autre assimilés à une seule unité, appelée enchaînement. Un article unique requiert parfois plusieurs colonnes ou conteneurs de texte pour s’afficher.

Exception faite du nœud racine, les éléments restants sont peu ou prou basés sur des éléments XHTML. Le schéma suivant illustre l’arborescence de la structure :

Arborescence TextFlow

Format TLF Markup

Une maîtrise de la structure de TLF s’avère également utile lorsque vous utilisez le format TLF Markup. Le format TLF Markup est une représentation XML du texte stocké dans TLF. Bien que la structure prenne également en charge d’autres formats XML, le format TLF Markup est unique, car il est basé spécifiquement sur la structure de l’arborescence TextFlow. Si vous exportez du code XML à partir d’une arborescence TextFlow à l’aide de ce format de balisage, le code XML est exporté en préservant sa structure arborescente.

TLF Markup assure la représentation du texte la plus fidèle dans une arborescence TextFlow. Le langage de balisage associe des balises à chaque élément de base de l’arborescence TextFlow et fournit également des attributs pour toutes les propriétés de formatage intégrées à la classe TextLayoutFormat.

Le tableau suivant dresse la liste les balises dont vous disposez dans TLF Markup.

Elément

Description

Enfants

Classe

textflow

Elément racine du balisage

div, p

TextFlow

div

Division au sein d’un flux TextFlow. Peut contenir un groupe de paragraphes.

div, list, p

DivElement

p

Paragraphe.

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

ParagraphElement

a

Lien

tcy, span, img, tab, br, g

LinkElement

tcy

Segment de texte horizontal (utilisé dans un élément TextFlow vertical)

a, span, img, tab, br, g

TCYElement

span

Segment de texte au sein d’un paragraphe

SpanElement

img

Image dans un paragraphe

InlineGraphicElement

tab

Caractère de tabulation

TabElement

br

Caractère de saut. Permet d’arrêter une ligne au sein d’un paragraphe. Le texte passe à la ligne suivante, mais sans changer de paragraphe.

BreakElement

linkNormalFormat

Définit les attributs de formatage utilisés pour les liens en état normal.

TextLayoutFormat

TextLayoutFormat

linkActiveFormat

Définit les attributs de formatage utilisés pour les liens en état actif, c’est-à-dire lorsque l’utilisateur appuie sur un lien avec le bouton de la souris.

TextLayoutFormat

TextLayoutFormat

linkHoverFormat

Définit les attributs de formatage utilisés pour les liens en état suspendu, c’est-à-dire lorsque l’utilisateur survole un lien avec la souris.

TextLayoutFormat

TextLayoutFormat

li

Composant d’un élément de liste. Doit résider à l’intérieur d’un élément de liste.

div, li, list, p

ListItemElement

list

Liste. Les listes peuvent être imbriquées ou placées les unes à côté des autres. Différents modèles de libellé ou de numérotation peuvent être appliqués aux éléments de liste.

div, li, list, p

ListElement

g

Elément de groupe. Permet de regrouper les éléments dans un paragraphe. Permet d’imbriquer des éléments au-dessous du niveau paragraphe.

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

SubParagraphGroupElement

Utilisation des listes numérotées et des listes à puce

Les classes ListElement et ListItemElement permettent d’ajouter des listes à puce aux contrôles de texte. Il est possible d’imbriquer les listes à puce et de les personnaliser en vue d’utiliser plusieurs puces (ou marqueurs), ainsi que la numérotation automatique et la numérotation de style contour.

Pour créer des listes dans un enchaînement, utilisez la balise <list> . Vous utilisez ensuite les balises <li> au sein de la balise <list> pour chaque élément de la liste. La classe ListMarkerFormat permet de personnaliser l’aspect des puces.

L’exemple suivant crée des listes simples :
<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>
Comme l’illustre l’exemple ci-dessous, vous pouvez imbriquer des listes au sein d’autres listes :
<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>
Pour personnaliser le type de marques de la liste, utilisez la propriété listStyleType de la classe ListElement. Cette propriété peut posséder n’importe quelle valeur définie par la classe ListStyleType ( check , circle , decimal et box , par exemple). L’exemple suivant permet de créer des listes dotées de divers types de marques et d’un incrément de compteur personnalisé :
<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>

Vous utilisez la classe ListMarkerFormat pour définir le compteur. Parallèlement à la définition de l’incrément d’un compteur, vous pouvez personnaliser ce dernier en le réinitialisant à l’aide de la propriété counterReset .

Vous pouvez personnaliser plus encore l’aspect des marques de liste à l’aide des propriétés beforeContent et afterContent de la classe ListMarkerFormat. Ces propriétés s’appliquent au contenu affiché avant et après le contenu de la marque.

L’exemple suivant ajoute la chaîne « XX » avant la marque et la chaîne « YY » après ce dernier :
<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>
La propriété content définit quant à elle d’autres personnalisations du format de la marque. L’exemple suivant illustre une marque de type chiffre romain en majuscules :
<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>

Comme illustré par l’exemple précédent, la propriété content peut également insérer un suffixe, c’est-à-dire une chaîne insérée après la marque, mais avant la propriété afterContent . Pour insérer cette chaîne lorsque vous fournissez un contenu XML à l’enchaînement, entourez-la d’entités HTML &quote; plutôt que de guillemets ( "< chaîne >" ).

Utilisation de marges dans TLF

Chaque objet FlowElement prend en charge des propriétés de marge destinées à contrôler la position de la zone de contenu de chaque élément, ainsi que l’espace qui sépare les zones de contenu.

La largeur totale d’un élément correspond à la somme de la largeur de son contenu et des propriétés paddingLeft et paddingRight . La hauteur totale d’un élément correspond à la somme de la hauteur de son contenu et des propriétés paddingTop et paddingBottom .

La marge correspond à l’espace qui sépare la bordure du contenu. Les propriétés de marge sont paddingBottom , paddingTop , paddingLeft et paddingRight . Il est possible d’appliquer un remplissage à l’objet TextFlow, ainsi qu’aux éléments enfants suivants :
  • div

  • img

  • li

  • list

  • p

Il est impossible d’appliquer les propriétés de marge aux éléments span.

L’exemple suivant définit les propriétés de marge de l’objet 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">

Les valeurs valides des propriétés de remplissage sont un numéro (en pixels), « auto » et « inherit ». La valeur par défaut est « auto », qui signifie que la marge est automatiquement calculée et définie sur 0 pour tous les éléments, à l’exception de ListElement. Pour les objets ListElement, « auto » est défini sur 0, à l’exception du côté début de la liste, qui utilise la valeur de la propriété listAutoPadding . La valeur par défaut de listAutoPadding est de 40, qui donne aux listes un retrait par défaut.

Les propriétés de marge n’héritent par défaut d’aucune valeur. Les valeurs « auto » et « inherit » sont des constantes définies par la classe FormatValue .

Les propriétés de marge peuvent être des valeurs négatives.

Formatage du texte à l’aide de TLF

Le package flashx.textLayout.formats contient des interfaces et classes qui permettent d’affecter des formats à tout objet FlowElement de l’arborescence d’enchaînements. Il existe deux manières d’appliquer le formatage. Vous pouvez affecter individuellement un format donné ou affecter simultanément un groupe de formats par le biais d’un objet de formatage spécial.

L’interface ITextLayoutFormat rassemble tous les formats susceptibles d’être appliqués à un objet FlowElement. Certains formats s’appliquent à un paragraphe de texte ou conteneur entier mais pas, en toute logique, à des caractères individuels. Ainsi, les formats tels que la justification et les taquets de tabulation s’appliquent à des paragraphes entiers, mais pas à des caractères individuels.

Affectation de formats à une classe FlowElement à l’aide de propriétés

Vous pouvez affecter des formats à tout objet FlowElement par le biais de propriétés. La classe FlowElement implémente l’interface ITextLayoutFormat, c’est pourquoi toute sous-classe de la classe FlowElement doit également implémenter cette interface.

Ainsi, le code suivant illustre l’affectation de formats individuels à une occurrence de ParagraphElement :

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

Affectation de formats à une classe FlowElement à l’aide de la classe TextLayoutFormat

Vous pouvez appliquer des formats à un objet FlowElement à l’aide de la classe TextLayoutFormat. Cette classe permet de créer un objet de formatage spécial qui contient toutes les valeurs de formatage requises. Vous pouvez ensuite affecter cet objet à la propriété format de n’importe quel objet FlowElement. Les classes TextLayoutFormat et FlowElement implémentent toutes deux l’interface ITextLayoutFormat. Cette caractéristique garantit que les deux classes contiennent les mêmes propriétés de format.

Pour plus d’informations, voir TextLayoutFormat dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Héritage des formats

Les formats sont hérités par le biais de l’arborescence d’enchaînements. Si vous affectez une occurrence de TextLayoutFormat à une occurrence de FlowElement possédant des enfants, la structure déclenche un processus appelé cascade . Dans le cadre d’une cascade, la structure examine de manière récursive chaque nœud de la hiérarchie qui hérite de valeurs de l’objet FlowElement. Elle détermine ensuite s’il est nécessaire d’affecter les valeurs héritées à chaque propriété de formatage. La cascade est définie par les règles suivantes :

  1. Les valeurs des propriétés sont héritées uniquement d’un ancêtre proche (appelé également le parent).

  2. Les valeurs des propriétés sont héritées uniquement si la propriété ne possède aucune valeur (en d’autres termes, la valeur est non définie )..

  3. Certains attributs non définis n’héritent d’une valeur que si la valeur de l’attribut est définie sur « inherit » ou sur la constante flashx.textLayout.formats.FormatValue.INHERIT .

Par exemple, si vous définissez la valeur fontSize au niveau du flux TextFlow, ce paramètre s’applique à tous les éléments du flux TextFlow. En d’autres mots, les valeurs sont propagées en cascade vers le bas de l’arborescence d’enchaînements. Vous pouvez cependant remplacer la valeur d’un élément donné en lui affectant directement une nouvelle valeur. A titre de contre-exemple, si vous définissez la valeur backgroundColor au niveau TextFlow, les enfants du flux TextFlow n’en héritent pas. La propriété backgroundColor n’hérite en effet jamais de ses parents au cours d’une cascade. Vous pouvez éviter ce comportement en définissant la propriété backgroundColor de chaque enfant sur la valeur flashx.textLayout.formats.FormatValue.INHERIT ..

Pour plus d’informations, voir TextLayoutFormat dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Importation et exportation de texte à l’aide de TLF

La classe TextConverter du package flashx.textLayout.conversion.* permet d’importer du texte dans TLF et d’en exporter hors de ce dernier. Utilisez cette classe si vous envisagez de charger du texte lors de l’exécution au lieu de le compiler dans le fichier SWF. Cette classe sert également à exporter du texte stocké dans une occurrence de TextFlow dans un objet String ou XML.

Les procédures d’importation et d’exportation sont simples. Il vous suffit d’appeler les méthodes export() ou importToFlow() , qui font toutes deux partie de la classe TextConverter. Ces deux méthodes sont statiques, ce qui signifie que vous les appelez sur la classe TextConverter plutôt que sur une occurrence de cette dernière.

Les classes intégrées au package flashx.textLayout.conversion sont d’une souplesse considérable en ce qui concerne l’emplacement de stockage du texte. Ainsi, si vous stockez le texte dans une base de données, vous pouvez l’importer dans la structure pour l’afficher. Grâce aux classes du package flashx.textLayout.edit, vous pouvez alors modifier le texte et réexporter le texte modifié dans la base de données.

Pour plus d’informations, voir flashx.textLayout.conversion dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Gestion des conteneurs de texte à l’aide de TLF

Une fois le texte stocké dans les structures de données TLF, Flash Player peut l’afficher. Le texte stocké dans l’arborescence d’enchaînements doit être converti dans un format géré par Flash Player. TLF propose deux méthodes de création d’objets d’affichage à partir d’un enchaînement. La première approche, plus simple, est adaptée à l’affichage de texte statique. La seconde, plus complexe, permet de créer du texte dynamique qui peut être sélectionné et modifié. Dans les deux cas, le texte est finalement converti en occurrences de la classe TextLine, qui fait partie du package flash.text.engine de Flash Player 10.

Création de texte statique

L’approche simple exploite la classe TextFlowTextLineFactory, qui se trouve dans le package flashx.textLayout.factory . L’avantage de cette approche, hormis sa simplicité, est qu’elle limite l’encombrement mémoire par rapport à l’approche FlowComposer. Il est recommandé d’y faire appel pour le texte statique que l’utilisateur ne doit ni modifier, ni sélectionner, ni faire défiler.

Pour plus d’informations, voir TextFlowTextLineFactory dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Création de texte dynamique et de conteneurs

Un compositeur d’enchaînements permet de mieux contrôler l’affichage du texte que la classe TextFlowTextLineFactory. Grâce à un compositeur d’enchaînements, les utilisateurs peuvent, par exemple, sélectionner et modifier le texte. Pour plus d’informations, voir Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF .

Un compositeur d’enchaînements est une occurrence de la classe StandardFlowComposer du package flashx.textLayout.compose . Il gère la conversion d’éléments TextFlow en occurrences de TextLine, ainsi que l’insertion de ces occurrences dans un ou plusieurs conteneurs.

Afficher le graphique en taille réelle
Un compositeur IFlowComposer possède un minimum de zéro objet ContainerController.

Chaque occurrence de TextFlow possède un objet correspondant qui implémente l’interface IFlowComposer. Cet objet IFlowComposer est accessible via la propriété TextFlow.flowComposer . Vous pouvez appeler les méthodes définies par l’interface IFlowComposer par le biais de cette propriété. Ces méthodes permettent d’associer le texte à un ou plusieurs conteneurs et de préparer le texte de sorte à l’afficher au sein d’un conteneur.

Un conteneur est une occurrence de la classe Sprite, qui est une sous-classe de la classe DisplayObjectContainer. Ces deux classes font partie intégrante de l’API de liste d’affichage Flash Player. Un conteneur est une forme plus avancée du rectangle de sélection utilisé par la classe TextLineFactory. A l’instar du rectangle de sélection, un conteneur circonscrit la zone dans laquelle s’affichent les occurrences de TextLine. A l’encontre d’un rectangle de sélection, à chaque conteneur correspond un objet de « contrôleur ». Le contrôleur gère le défilement, la composition, la liaison, le formatage et la gestion des événements à l’intention d’un conteneur ou d’un ensemble de conteneurs. A chaque conteneur correspond un objet de contrôleur, qui est une occurrence de la classe ContainerController du package flashx.textLayout.container.

Pour afficher du texte, créez un objet de contrôleur destiné à gérer le conteneur et associez-le au compositeur d’enchaînements. Une fois le conteneur associé, composez le texte pour pouvoir l’afficher. Les conteneurs gèrent donc deux états, composition et affichage. La composition correspond au processus de conversion du texte issu de l’arborescence d’enchaînements en occurrences de TextLine, et de calcul de la position de ces occurrences dans le conteneur. L’affichage correspond au processus de mise à jour de la liste Flash Player.

Pour plus d’informations, voir IFlowComposer , StandardFlowComposer et ContainerController dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF

La possibilité de sélectionner ou modifier du texte est contrôlée au niveau de l’enchaînement. Chaque occurrence de la classe TextFlow est associée à un gestionnaire d’interaction. Vous pouvez accéder au gestionnaire d’interaction d’un objet TextFlow par le biais de la propriété TextFlow.interactionManager de ce dernier. Pour activer la sélection de texte, affectez une occurrence de la classe SelectionManager à la propriété interactionManager . Pour activer la sélection et la modification du texte, affectez une occurrence de la classe EditManager à la place d’une occurrence de la classe SelectionManager. Pour annuler une opération; créez une occurrence de la classe UndoManager et spécifiez-la en tant qu’argument lorsque vous appelez le constructeur associé à EditManager. La classe UndoManager gère un historique des activités de modification les plus récentes de l’utilisateur et autorise ce dernier à annuler ou rétablir des modifications spécifiques. Ces trois classes font partie du package de modification.

Pour plus d’informations, voir SelectionManager , EditManager et UndoManager dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Gestion des événements à l’aide de TLF

Les objets TextFlow distribuent des événements dans de nombreuses circonstances, à savoir :
  • lors d’un changement de texte ou de mise en forme ;

  • avant le début d’une opération ou après la fin de cette dernière ;

  • lors d’un changement d’état d’un objet FlowElement ;

  • au terme d’une opération de composition.

Pour plus d’informations, voir flashx.textLayout.events dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash.

Positionnement des images dans le texte

Pour positionner l’élément InlineGraphicElement dans le texte, vous disposez des propriétés suivantes :
  • Propriété float de la classe InlineGraphicElement

  • Propriété clearFloats de la classe FlowElement

La propriété float contrôle le positionnement du graphique et du texte qui l’entoure. La propriété clearFloats contrôle le positionnement des éléments du paragraphe par rapport à l’élément flottant .

Pour contrôler l’emplacement d’une image dans un élément de texte, vous disposez de la propriété float . L’exemple suivant insère une image dans un paragraphe et l’aligne à gauche de sorte que le texte l’habille sur la droite :
<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>

Les valeurs valides de la propriété float sont « left », « right », « start », « end » et « none ». La classe Float définit ces constantes. La valeur par défaut est « none ».

La propriété clearFloats s’avère utile lorsque vous souhaitez ajuster la position de départ des paragraphes suivants qui habilleraient normalement l’image. Supposons, par exemple, que la largeur d’une image excède celle du premier paragraphe. Pour s’assurer que le deuxième paragraphe débute après l’image, définissez la propriété clearFloats .

L’exemple suivant utilise une image dont la hauteur excède celle du texte dans le premier paragraphe. Pour que le deuxième paragraphe débute après l’image dans le bloc de texte, cet exemple définit la propriété clearFloats associée au deuxième paragraphe sur « end ».
<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>

Les valeurs valides de la propriété clearFloats sont « left », « right », « end », « start », « none » et « both ». La classe ClearFloats définit ces constantes. Vous pouvez également définir la propriété clearFloats sur « inherit » (constante définie par la classe FormatValue ). La valeur par défaut est « none ».