Proches de l’Ohio??? Les états esthètes de Flex4

La gestion des States a été entièrement revue dans Flex 4. Déjà fervent utilisateur des states de flex2/3, j’ai entendu quelques critiques à leur propos, et il est vrai que les AddChild relativeTo et autres setEventHandler n’étaient peut-être pas… « idéaux »… Mais ils étaient utiles, car il est des situations, où au sein d’une application, l’utilisation d’états est bien plus « cohérente », voire performante, qu’une navigation « page à page » classique. Leur subtile utilité et leurs récentes améliorations, méritent de s’y intéresser.
Raison d’états
La principale différence entre les states et la navigation « page à page » ( type « viewStack » dans Flex ), est selon moi, que les states permettent la réutilisation et le « partage » d’éléments : l’affichage de l’application/composant ne doit pas être entièrement recréé à chaque changement.
Et c’est justement une des définitions des RIA. De même qu’un écran ne doit pas être entièrement « rechargé » à chaque chargement de données, il ne doit pas forcément être reconstruit entièrement à chaque changement « d’affichage ». En gros : contrairement à des pages, un même objet peut être facilement inclus/utilisé dans plusieurs états.
L’exemple classique est un panel de login qui « contient » un état « inscription », contenant les mêmes éléments que le state normal, mais qui y ajoute un champ de confirmation du mot de passe ( exemple dans Tour de Flex Online) .

Les states permettent de facilement ajouter/supprimer des éléments au cours « du cycle de vie d’un composant ».
Dans mon exemple, c’est plus globalement l’apparence de l’application entière qui varie en fonction de son état.

Les states permettent de modifier les attributs des différents élements MXML inclus dans le composant ( propriétés publiques, styles, événements et effets d’événements ). Ainsi un composant et ses « enfants » peuvent avoir une taille, une couleur, un comportement différent à chaque état.
Dans la documentation officielle, la définition d’un state est « une collection de changements applicables à une vue ». Avec Flex4, c’est principalement la syntaxe de la définitions de ces changements qui a été simplifiée.
Coups d’états : une nouvelle syntaxe
La nouvelle syntaxe des états s’appuie sur l’évolution du MXML avec sa version 2009 ( MXML 2009 ). Ce dernier intègre pleinement cette notion d’état, en permettant à chaque attribut de composant MXML d’être défini pour un état en particulier.
Déclaration
La première chose à noter est la déclaration, en début de fichier, de la liste des états du composant.
<s:states>
<s:State name="default"/>
<s:State name="Register"/>
</s:states>
Les « changements /actions d’états » ne sont donc plus définis de manière hiérarchique au sein du noeud State lui même.
Modification des propriétés de composants
En parcourant le code source de l’exemple, on tombe sur la déclaration du bouton de validation du formulaire :
<s:Button id="button1" click="clickHandler(event)"
label="Login"
label.Register="Register"
/>
Le label du Button varie en fonction de l’état du composant qui le contient, et une « syntaxe pointée » permet maintenant de préciser la valeur de l’attribut dans l’état « Register ».
Dans la définition d’un attribut MXML, il est maintenant possible de définir si la valeur est « globale » ou liée à un état ( ou même à plusieurs, cf. StateGroups plus bas ). L’id ne peut évidement pas être « state based ».
<s:Button id="bt"
label.default="login" label.Register="inscription"
width.default="80" width.Register="120"
color.default="#000000" color.Register="#0000FF"
click.default="trace('default»register');currentState = 'Register';"
click.Register="trace('register»default');currentState = 'default';"
rollOverEffect.default="{new Blur()}"
rollOverEffect.Register="{new Glow()}"
/>
FlashBuilder 4 beta 2 intègre déjà une aide à l’édition d’attribut « state based », et d’après ce que j’ai pu lire il y aura encore d’autres fonctionnalités liées dans la release…

De même, il est possible de définir les propriétés d’un composant à l’aide d’un sous noeud plutôt qu’un attribut, et on peut, dans ce cas aussi, préciser à quel état le noeud est associé.
Dans mon exemple, profitant de la nouvelle gestion des Layouts de composants, mon Application peut être « verticale », « horizontale » ou en « tile ». Il suffit de préciser la valeur du layout pour chaque état.
<s:Group id="content" x="10" y="40" > <s:layout.vList><s:VerticalLayout /></s:layout.vList> <s:layout.hList><s:HorizontalLayout /></s:layout.hList> <s:layout.tile><s:TileLayout /></s:layout.tile> ... </s:Group>
ou encore telle bordure FXG visible uniquement dans l’état ’tile’ :
<s:Group styleName="box" > <s:Rect width="80" height="80" > <s:fill> <s:SolidColor color="#CCCCCC"/> </s:fill> <s:stroke.tile> <s:SolidColorStroke color="#999999" /> </s:stroke.tile> </s:Rect> <!--...--> </s:Group>
A l’heure des applications multi-devices, ce genre de souplesse est certainement bienvenue ( exemple d’application proposant un state « desktop » et un autre « mobile » )…
Inclusion / Exclusion
En plus des évolutions syntaxiques, 2 nouveaux attributs ( des « directives de compilation » en fait ) ont été ajoutées : includeIn et ExcludeFrom, remplacant les mx:AddChild et mx:RemoveChild de Flex 3.
<mx:LinkButton id="registerLink" color="0x336699"
includeIn="default"
label="Need to Register?"
click="currentState='Register'"/>
Ici, le bouton d’inscription n’est visible que dans l’état ‘default’.
Même fonctionnement, résultat inverse pour l’attribut excludeFrom, qui permet comme son nom l’indique de préciser qu’un « enfant » doit être supprimé de la liste d’affichage dans un état… ou dans un groupe d’état…
Les stateGroups : des états unis…
Une nouvelle propriété voit également le jour dans la définition des états : le stateGroups. Cette propriété permet de lier entre eux plusieurs états.
Voici par exemple la définition des états du composant ToggleButton version Spark.
<s:states>
<s:State name="up" />
<s:State name="over" stateGroups="overStates" />
<s:State name="down" stateGroups="downStates" />
<s:State name="disabled" stateGroups="disabledStates" />
<s:State name="upAndSelected" stateGroups="selectedStates, selectedUpStates" />
<s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
<s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
<s:State name="disabledAndSelected" stateGroups="selectedUpStates, disabledStates, selectedStates" />
</s:states>
Des groupes d’états sont ainsi définis, et vont nous permettre d’assigner des valeurs d’attributs non plus pour un, mais pour plusieurs états. Chaque state peut appartenir à un ou plusieurs groupes, et chacun de ces groupes n’est finalement défini que par une chaîne de caractères.
<s:Rect id="highlight" left="1" right="1" top="1" bottom="1" radiusX="2">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF"
ratio="0.0"
alpha="0.33"
alpha.selectedUpStates="0.22"
alpha.overStates="0.22"
alpha.downStates="0.12"/>
<s:GradientEntry color="0xFFFFFF"
ratio="0.48"
alpha="0.33"
alpha.selectedUpStates="0.22"
alpha.overStates="0.22"
alpha.downStates="0.12"/>
<s:GradientEntry color="0xFFFFFF"
ratio="0.48001"
alpha="0" />
</s:LinearGradient>
</s:fill>
</s:Rect>
Dans le ToggleButton, l’alpha du dégradé clair varie ici en fonction du groupe d’appartenance de l’état en cours.
En complément des groupes, la classe State propose toujours l’attribut basedOn, permettant à un état d’hériter de toutes les modifications définies pour un autre, et d’en ajouter.
Event d’états…
À l’instar des states Flex 3, des événements sont émis à chaque changement :
- enterState
- exitState ( attention : si l’état B est « basedOn » l’état A, l’event exitState n’est pas émis au passage de A à B. )
Toutefois, étant donné la séparation entre « logique » et « graphique » conseillée avec Spark, l’intérêt d’écouter ces événements « côté skin » devient à mon avis plus rare.
Des états stylés…
Les états ne sont pas les seuls à avoir connu une intéressante évolution dans Flex 4 : la gestion des styles CSS a également été considérablement enrichie. Cela pourrait constituer un article à part entière, mais je n’aborderais ici que les évolutions liées à notre sujet du jour.
Grâce à des pseudo-selecteurs CSS, il est maintenant possible de définir des styles basés sur l’état d’un composant.
<fx:Style>
@namespace "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/halo";
Application:hList Label
{
color:#0CF;
}
</fx:Style>
ici, la feuille de style définit que le texte des composants Label de l’application en état hList doivent être bleus.
Et puis quoi encore ?
Code source de l’exemple du layout « state based »
Il y aurait encore pas mal de choses à aborder à propos de cette nouvelle gestion de states : gestion des transitions, « ré-adoption parentale » ( Reparent ), « régles d’instanciation »…
Mais je vais finir aujourd’hui par une petite interlude musicale…
Bon weekend…

--> 5 mars 2010 ( 18:25 )
Clair et précis, bon résumé !!
--> 9 mars 2010 ( 2:56 )
I still love Flex states functionality.
Thanks for the info.-