Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

26oct/099

Créer un projet FlexLibrary pour les assets (icônes, éléments graphiques, …)

Parfois, quand vous compilez un projet Flex, vous allez peut-être vous apercevoir que certaines classes ne sont pas compilées dans le dossier bin-release, car vous avez du code ActionScript qui instancié une classe sous certaines conditions et le compilateur Flex assume que cette classe n'est pas requise.

Cet article est une traduction de l'excellent Creating an image asset library de russback.com.

C'est assez frustrant mais il y a un moyen de contourner ce problème. En créant une instance "dummy" (une instance non utilisée) d'une de ces classes non-compilées, vous pouvez vous assurer  que la classe sera bien compilée dans votre répertoire de destination. Une autre solution consiste à créer une librairie d'assets externe qui va être compilée en un SWC.

Création d'un projet Flex Library

Un projet Flex Library peut être crée de la même manière que tout autre projet, choisissez simplement Flex Library Project dans le menu New au lieu de Flex Project.

asset-library-create-library-project

A première vue, rien n'a changé à part l'icône dans la vue Flex Navigator mais vous verrez vite les bénéfices de cette approche.

asset-library-flex-navigator-view

Création d'une Class

Tout d'abord, on va créer au moins une Class. Pour cet exemple, l'auteur a choisit d'utiliser l'excellente FamFamFam Silk Icon Library, une collection de 700+ images 16x16px qui sont utilisées par de nombreuses interface web (WebDevelopper Toolbar Firefox et autres). Pour cet article, on va ajouter tous les icônes de cette librairie et en exposer seulement deux pour notre application.

Import des Assets

C'est très simple, téléchargez la librairie et déplacez toutes les images dans le projet FlexLibrary. Pour cet exemple, on place les icones dans le dossier /assets/images/famfamfam/silkicons. Il peuvent être placés n'importe où mais cette structure rend l'ajout d'assets d'autres sources plus facile dans la librairie.

Exposition des assets

Pour cet exemple, on a juste besoin de deux de cet icônes. Pour les exposer, on crée une nouvelle classe appelée IconLibrary (dans le package com.russback). Cette classe est une classe Bindable qui a une public static constant de type Classe pour chacun des éléments graphiques que l'on veut exposer:

package com.russback
{
	/**
	 * Class containing constants for each icon image available for use in the application
	 */
	[Bindable]
	public final class IconLibrary
	{

		/**
		 * Displays the accept icon from the FamFamFam Silk Icons library
		 */
		[Embed(source="assets/images/famfamfam/silkicons/accept.png")]
		public static const ACCEPT:Class;

		/**
		 * Displays the bomb icon from the FamFamFam Silk Icons library
		 */
		[Embed(source="assets/images/famfamfam/silkicons/bomb.png")]
		public static const BOMB:Class;

		/**
		 * Constructor
		 */
		public function IconLibrary()
		{
		}

	}
}

Compilation de la librairie

Maintenant, il faut que l'on compile la librairie, et c'est là que les bénéfices de cette approche se ressentent. Si vous faîtes un clic droit sur le projet Flex Library, et choisissez Properties, vous obtiendrez les options de compilation. Cliquez sur le Flex Library Build Path et vous obtiendrez une vue avec une ButtonBar (Classes, Assets, Source Path, Library Path). Dans la vue Classes, vous pouvez sélectionner quelles classes vous voulez compiler afin qu'elles soient compilées dans la librairie. Ce qui est beau dans cette manipulation, c'est que vous prenez le contrôle sur ce que le compilateur va effectivement compiler, peut importe si vous avez utiliser cette classe ou pas. On va donc s'en servir pour s'assurer que notre classe IconLibrary soit bien compilée.

asset-library-include-classes

Ensuite, cliquez sur le bouton Assets pour vous assurer que toutes les images sont comprises dans la librairie. On pourrait simplement inclure seulement les deux classes que l'on souhaite utiliser et créer un SWC très léger mais ce qui est excellent avec les fichiers SWC, c'est que seules les classes et les assets référencées seront inclus dans un build "release". Comme on a simplement deux références vers nos assets (dans la classe IconLibrary), on n'a pas besoin de se préoccuper de l'encombrement de notre SWC.

asset-library-include-assets

L'auteur de cet article remercie Ronald Ferguson pour sa librairie gratuite qui fonctionne sur le même concept. Cependant, il y a des constantes pour chaque icône de la librairie, ce qui crée un gros fichier SWC avec 700+ icônes. D'un autre côté, la méthode exposée ici vous oblige à ajouter une nouvelle constante dans la classe IconLibrary à chaque fois que vous voulez utiliser un icône non référencé.

La Silk Icon Library est utilisée comme exemple ici mais vous pourriez facilement améliorer cette librairie pour contenir tous les set d'icônes que vous souhaitez. L'approche reste la même, il faut juste s'assurer que la nouvelle classe que vous allez ajouter sera bien compilée (vu au dessus).

Lier la librairie à une application externe

Nous avons maintenant une librairie qui va être compilée en un SWC dans le répertoire "bin" de notre projet Flex Library. Pour utiliser ce fichier SWC dans un Flex Project, on doit simplement le référencer dans chaque projet comme ceci:

  1. Clic droit que le projet dans le Flex Navigator puis Properties
  2. Flex Build Path > Library Path
  3. Cliquez sur le bouton Add SWC… et allez chercher votre fichier SWC dans le répertoire bin de votre projet Library
  4. Vous devriez avoir le SWC référencé comme ceci

asset-library-swc-reference

Utilisation de la librarie

L'utilisation de la librairie est on ne peut plus simple. Il suffit de fait un Bind entre la propriété "source" d'une Image et la constante de la librairie que l'on veut utiliser:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="vertical"
	width="553"
	height="200"
	viewSourceURL="srcview/index.html"
	>
	<mx:Script>
		<![CDATA[
			import com.russback.IconLibrary;
		]]>
	</mx:Script>

	<mx:HBox>
		<mx:Image source="{IconLibrary.BOMB}" />
		<mx:Text text="Add images inline?" />
	</mx:HBox>

	<mx:HBox>
		<mx:Image source="{IconLibrary.ACCEPT}" />
		<mx:Text text="Use an external image library?" />
	</mx:HBox>

</mx:Application>

L'utilisation de cette méthode semble contraignante mais elle vous permettra de garder votre code clean, avec tous vos assets dans un seul emplacement et ainsi d'éviter les problèmes de compilation.

Une petite remarque sur les Warnings qui apparaissent lors de la compilation ASDoc avec Ant

En utilisant cette méthode, vous allez peut-être être confrontés à un warning de compilation pour chaque constant que vous compilez dans la librairie, particulièrement si vous compilez la documentation ASDoc en utilisant Ant:

ant-build-warning

Rien de bien méchant, le compilateur essaie simplement de vous dire que vous n'avez crée aucune instance de cette constante. Si vous voulez vous débarasser de ces warnings, vous pouvez ajouter une ligne à votre build.xml utilisé par Ant pour qu'il reste silencieux.

<arg line="-warn-const-not-initialized=false" />

ant-build-successful

Articles similaires

Commentaires (9) Trackbacks (0)
  1. Bonjour,

    Traduction très utile.
    Néanmoins une petite question.

    Maintenant, que l'on a un SWC avec tous nos assets, comment les référencer dans un fichier CSS ou une propriété CSS en MXML ??

    n!co

  2. Et bien c'est une très bonne question dont je n'ai toujours pas trouvé la solution moi-même …
    Désolé

    Fabien

  3. Bonjour,
    Merci pour ce tuto ! une fois de plus tu as assuré ! :)
    petite question :
    J'ai
    - un projet FB4
    - un css compilé en swf
    - et des projets flex librairie liés chacun contenant des images / icones

    pour résumer je souhaite que la partie skinning soit séparé de l'application finale et modulable.
    je pourrais lié les CONST des images au skinning de mes composant.
    j'ai essayé ça :
    /* CSS file */
    @namespace s "library://ns.adobe.com/flex/spark";
    @namespace mx "library://ns.adobe.com/flex/mx";
    @namespace libImageFond "com.librairie.fonds.LibImageFond";

    s|Application
    {
    skin-class:ClassReference('skins.skinApplication');
    source:FOND_N;
    }

    dans mon skin application j'ai ça :

    MXML:
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
    3.         xmlns:s="library://ns.adobe.com/flex/spark"
    4.         xmlns:mx="library://ns.adobe.com/flex/mx">
    5.     <!-- host component -->
    6.     <fx:Metadata>
    7.         [HostComponent("spark.components.Application")]
    8.     </fx:Metadata>
    9.  
    10.     <!-- states -->
    11.     <s:states>
    12.         <s:State name="disabled" />
    13.         <s:State name="normal" />
    14.     </s:states>
    15.    
    16.  
    17.    
    18.     <s:BitmapImage id="img"
    19.                    width="100%" height="100%"
    20.                    source="{this.getStyle('source')}"/>
    21.  
    22.     <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0">
    23.        
    24.     </s:Group>
    25. </s:Skin>

    j'ai essayé également avec classReference, assetClass...ect je ne vois pas comment faire
    une solution peut être ?
    merci

  4. dsl je n'avais pas lu les messages précèdent, assé proche de ma demande .. enfin si j'ai bien compris...

  5. Salut,
    une partie de ton message a été coupée (tu peux me l'envoyer par mail pour que je l'intègre). Je n'ai malheureusement toujours pas de solution mais peut-être que les techniques de skinnning de Flex 4 vont pouvoir y répondre. Il faut que je m'y intéresse, pour l'instant, désolé, il faut bricoler ou coupler

    Fabien

  6. je t'enverrai la suite du message une fois que j'aurai trouvé ton mail ! :) il est surement écrit en grand au milieu de ton site ! mais c'est tout moi je vois tout sauf l'essentiel !
    sinon aurais tu une solution autre pour mon objectif ? en gros j'ai un projet qui doit accepté plusieurs template (thème) sans être re-compilé, modulable ( pouvoir mélanger les lib icone et bouton pour créer des theme différent a partir d'éléments graphiques encapsulés dans des libs),et que les composants puisse hérité de leurs parents ou ecraser la valeur du parent, un parent avec des valeur par defaut :
    BoutonIcon{
    icon:MACONST;
    }
    BoutonIcon.recherche{
    icon:CONSTRECH;
    }

    (dsl si je m'exprime mal :p )

  7. Mon mail est en bas de page ;)

    Sinon, pour avoir un comportement complètement dynamique et configurable, la "meilleure" soltution semble être le chargement d'un fichier de configuration (XML par exemple) et d'ensuite utiliser le StyleManager pour charger des thèmes SWF ou setter des Type/Class Selector.
    Tout en faisant bien attention à ne pas laisser tout le code et toutes les dépendances dans une seule classe, sans quoi tout cela ne servirai à rien ;) .
    Si tu es motivé, c'est le genre de technique qui est utilisé par l'Open Source Media Framework (voir l'article que je viens de publier). Dans la vidéo, tu verras comment le mec change de style à la volée. Et comme c'est Open Source, tu peux aller fouiller dans le code ! :D

    Fabien

  8. ok ! sympa la façon d'écrire ton mail :p ! je vais de suite lire ton nouvel article !
    merci encore pour ton super blog !
    bonne continuation !

  9. C'est pour contrer les crawler de spams ;)

    Fab


Leave a comment

(required)

Aucun trackbacks pour l'instant