Skinner un bouton avec Flex 4

La version alpha de Flex 4 étant disponible depuis un petit moment maintenant, il était temps de dépoussiérer (et finaliser) cet article qui traine dans mes brouillons WordPress depuis un bon moment.
Il s'agit d'un exemple assez simple d'un bouton skinné avec la version 4 du SDK Flex. L'idée est de commencer à déblayer ce nouveau terrain de jeu et de voir quels sont les changements apportés par cette nouvelle mouture. Bien évidemment, cet article n'a pas pour but d'énumérer exhaustivement tous ces changements, mais plutôt de donner un feedback par rapport à cette phase de skinning.



Waurqueflau kezako ?
Si vous avez déjà eu la chance (le temps ?) de lire des articles ou voir des conférences à propos de Gumbo, vous aurez sûrement remarqué le leitmotiv 'Designer-Developer Workflow' rabâchés par tous les "évangélistes" Adobe. A vrai dire, il s'agit quand même de l'axe majeur de l'évolution du SDK vers sa version 4 et qui justifie la sortie du nouvel outil : Flash Catalyst.
Pour améliorer ce workflow, Adobe a donc décidé de revoir l'architecture des composants visuels Flex, et tout particulièrement le principe de Skinning. Dans la version actuelle de Flex, le skin permet juste de changer l'apparence graphique d'un composant. Avec Gumbo, le skin à plus de responsabilités, c'est lui qui gère l'apparence des données, le changement visuel d'état en état ou encore les transitions.
Des choses qu'adorent faire les développeurs en somme ;) L'idée derrière tout ça, c'est donc bien que cette partie soit délégué au designer, et que la phase d'intégration devienne pratiquement nulle.



Skin.mxml
Comment se présente ce nouveau Skin ? Tout est déclaré sous forme de tags, y compris les éléments visuels, grâce au format d'échange FXG.
FXG, c'est du MXML mais pour tout ce qui concerne les graphiques (textes compris) . Ceux qui ont utilisé Degrafa connaissent déjà le principe.
Par exemple, pour dessiner un rectangle :

CODE:
  1. <Rect height="100" width="100" radiusX="5" radiusY="5">
  2.     <fill>
  3.         <SolidColor color="#CC3333" />
  4.     </fill>
  5. </Rect>

Effectivement, ça ressemble beaucoup à du SVG, avec des fonctionnalités supplémentaires !
Lesquelles ? Les spécifications sont disponibles ici.
Des outils comme Fireworks, Illustrator et bien sûr Thermo sont capables de générer du FXG.
Il faut bien comprendre que le FXG n'est qu'une sous-partie du MXML, ce qui implique qu'il ne supporte pas des concepts comme le data binding ou encore les states.
Mais on peut faire appel aux 2 namespaces au sein d'un même document afin de faire fonctionner ensemble les spécifités de chacun : voilà donc à quoi ressemble un fichier de Skin !


Bon, il est où ce bouton alors ?
Ça arrive, ça arrive. Merci au passage à Guillaume de http://www.forgeurdunumerique.net/ pour le design du bouton !

Get Adobe Flash player



Le fichier de skin :

CODE:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Skin
  3.     xmlns:s="http://ns.adobe.com/mxml/2009"
  4.     xmlns="library://ns.adobe.com/flex/spark"
  5.     >
  6.  
  7.     <!-- host component -->
  8.     <Metadata>
  9.         [HostComponent("spark.components.Button")]
  10.     </Metadata>
  11.  
  12.     <!-- states -->
  13.     <states>
  14.         <State name="up" />
  15.         <State name="over" />
  16.         <State name="down" />
  17.         <State name="disabled" />
  18.     </states>
  19.  
  20.  
  21.     <!-- layer 0: backgroundColor -->
  22.     <Rect left="0" top="0" right="0" bottom="0" radiusX="5" radiusY="5">
  23.         <fill>
  24.             <SolidColor color="#CC3333" />
  25.         </fill>
  26.         <filters>
  27.             <DropShadowFilter
  28.                 angle="90"
  29.                 distance="2"
  30.                 color="#999999"
  31.                 strength="1"
  32.                 blurX="0"
  33.                 blurY="0"
  34.                 quality="3"
  35.             />
  36.             <DropShadowFilter
  37.                 angle="90"
  38.                 distance="2"
  39.                 strength="1"
  40.                 color="#333333"
  41.                 blurX="0"
  42.                 blurY="0"
  43.                 inner="true"
  44.                 quality="3"
  45.             />
  46.         </filters>
  47.     </Rect>
  48.  
  49.     <!-- layer 1: gradient -->
  50.     <Rect left="0" top="2" right="0" bottom="0" radiusX="5" radiusY="5">
  51.         <fill>
  52.             <LinearGradient rotation="90">
  53.                 <GradientEntry
  54.                     color.up="#FF6666"
  55.                     color.over="#FF6666"
  56.                     color.down="#CC6666"
  57.                     color.disabled="#666666"
  58.                 />
  59.                 <GradientEntry
  60.                     id="gei"
  61.                     color.up="#CC3333"
  62.                     color.over="#FF3333"
  63.                     color.down="#993333"
  64.                     color.disabled="#333333"
  65.                 />
  66.             </LinearGradient>
  67.         </fill>
  68.     </Rect>
  69.  
  70.  
  71.     <!-- layer 2: text -->
  72.     <SimpleText
  73.         id="labelElement"
  74.         color.up="#E6E6E6"
  75.         color.over="#FFFFFF"
  76.         color.down="#CCCCCC"
  77.         color.disabled="#808080"
  78.         left="70"
  79.         bottom="15"
  80.         fontStyle="normal"
  81.         fontSize="18"
  82.         verticalAlign="middle"
  83.         fontLookup="embeddedCFF"
  84.         fontFamily="Tahoma"
  85.         >
  86.         <filters>
  87.                 <DropShadowFilter
  88.                    inner="false"
  89.                    distance="1"
  90.                    color="#333333"
  91.                    angle="-90"
  92.                    blurX="0"
  93.                    blurY="0"
  94.                 />
  95.          </filters>
  96.     </SimpleText>
  97.  
  98.     <!-- layer 3: logo -->
  99.     <BitmapImage
  100.         height="19"
  101.         width="31"
  102.         left="20"
  103.         bottom="15"
  104.         source.up="@Embed('assets/iconAStrois-up-31x19.png')"
  105.         source.over="@Embed('assets/iconAStrois-over-31x19.png')"
  106.         source.down="@Embed('assets/iconAStrois-down-31x19.png')"
  107.         source.disabled="@Embed('assets/iconAStrois-disabled-31x19.png')"
  108.         smooth="true"
  109.         >
  110.         <filters>
  111.             <DropShadowFilter
  112.                 color="#333333"
  113.                 distance="1"
  114.                 blurX="0"
  115.                 blurY="0"
  116.                 angle="-90"
  117.             />
  118.         </filters>
  119.     </BitmapImage>
  120.  
  121.     <!-- layer 4: top gradient -->
  122.     <Rect left="0" top="2" right="0" bottom="0" radiusX="5" radiusY="5" alpha="0.5" alpha.disabled="0.25">
  123.         <fill>
  124.             <LinearGradient rotation="90">
  125.                 <GradientEntry color="#FFFFFF" ratio="0.45" alpha="0.5" />
  126.                 <GradientEntry color="#FFFFFF" ratio="0.55" alpha="0"  />
  127.             </LinearGradient>
  128.         </fill>
  129.     </Rect>
  130.  
  131.  
  132. </Skin>



Examinons un peu le contenu de ce fichier :

CODE:
  1. <Metadata>
  2.     [HostComponent("spark.components.Button")]
  3. </Metadata>

Le metadata HostComponent indique que ce skin s'applique pour un Button. Comme tous les metadata, il donne des informations supplémentaires au compilateur. Dans le cas du HostComponent, il permet de :

  • Créer dynamiquement un objet hostComponent de type du composant donné en paramètre (Button ici). Ainsi on va avoir le droit à la complétion automatique sur les propriétés du bouton. Par exemple : hostComponent.label
  • Vérifier à la compilation si tous les parties et états de skin requis par le composant hôte ont bien été définies.

Ces notions de SkinPart et SkinState sont aussi des nouveautés dans Gumbo.
Je ne vais pas entrer en détail dans les explications, éventuellement dans un prochain article mais globalement :

  • SkinPart : Il s'agit d'un contrat qui est passé entre le composant hôte et son skin indiquant quelles sont les parties de skins obligatoires à implémenter et celles qui sont optionnelles. Si on parcours le code source du Button, on peut remarquer que le labelElement n'est pas obligatoire.
    CODE:
    1. [SkinPart(required="false")]
    2. public var labelElement:TextGraphicElement;

  • SkinState : Il s'agit d'un contrat qui est passé entre le composant hôte et son skin inidiquant quelles sont les états de skins obligatoires à implémenter et celles qui sont optionnelles.
    Pour le Button, 4 états sont à implémenter :

    CODE:
    1. [SkinState("up")]
    2. [SkinState("over")]
    3. [SkinState("down")]
    4. [SkinState("disabled")]

    On retrouve ainsi la définition des états dans le fichier de skin :

    CODE:
    1. <states>
    2.     <State name="up" />
    3.     <State name="over" />
    4.     <State name="down" />
    5.     <State name="disabled" />
    6. </states>


La reste du code est la représentation graphique du bouton grâce aux tags FXG. On peut noter plusieurs choses :

  • Le bouton est dessiné en parcourant le code de haut en bas. Si un tag Rect est suivi d'un tag BitmapGraphic, le bitmap sera dessiné au-dessus du rectangle. C'est un concept similaire aux calques de Photoshop.
  • La définition des états (states) est complètement différente par rapport aux versions précédentes de Flex. Elle est maintenant faite "inline", pour plus de lisibilité et de compréhension. Là encore, je vais éviter d'entrer dans les spécifications. Pour plus d'infos, celles-ci sont disponibles sur le wiki http://opensource.adobe.com. Ex :
    CODE:
    1. <SimpleText
    2.         color.up="#E6E6E6"
    3.         color.over="#FFFFFF"
    4.         color.down="#CCCCCC"
    5.         color.disabled="#808080" />

  • Pour embarquer une police externe , on fait :
    CODE:
    1. <Style>
    2. @font-face {
    3.        src: url("assets/tahomabd.ttf");
    4.        fontFamily: "Tahoma";
    5.        fontWeight: "bold";
    6.        cff: true;
    7. }
    8. </Style>

    Pour l'utiliser :

    CODE:
    1. <SimpleText
    2.                 ...
    3.         fontLookup="embeddedCFF"
    4.         fontFamily="Tahoma"
    5. />

    Je n'ai pas encore compris la réelle différence entre embedded et embeddedCFF si ce n'est que les polices embarquées en embeddedCFF sont plus légères. Si vous avez des connaissances à ce sujet, n'hésitez pas à laisser un commentaire ;)



Voilà pour ce premier aperçu de Flex 4. Attention toutefois, il s'agit de la version alpha, rien n'est stable et il ne faut bien sûr pas l'utiliser en production ! De même certains points risquent de changer et il ne faut donc pas considérer cet article comme référence. Je vais m'efforcer de le mettre à jour le plus souvent possible afin qu'il corresponde aux différents changements apportés jusqu'à la version stable.


Les sources.


Tags: , , , , ,


Fatal error: Call to undefined function: st_related_posts() in /homez.144/astrois/www/blog/wp-content/themes/simplicitybright/single.php on line 14