Programmation Flex 3 : Applications Internet riches avec Flash
Transcription
Programmation Flex 3 : Applications Internet riches avec Flash
Flex 3, framework de référence pour le développement Flash Open Source, le SDK de Flex offre un véritable environnement en phase avec les bonnes pratiques de génie logiciel (MVC…) et de gestion de projet (travail collaboratif…). Il propose des bibliothèques de composants graphiques et des fonctions pour dialoguer avec le serveur, et s’interfacer avec des bases de données via des serveurs PHP/J2EE. Une bible avec de nombreux cas pratiques et retours d’expérience Programmation Flex 3 explique aux développeurs web, qu’ils soient ou non rompus à Flash et ActionScript, comment utiliser le framework Flex pour concevoir et créer des applications web dites « riches » (RIA), à l’instar des applications Ajax ou Silverlight. Tout en rappelant les langages sur lesquels s’adosse cette technologie (ActionScript, MXML), l’ouvrage passe en revue l’intégralité des techniques de développement Flex : maîtrise de l’environnement de travail, création d’interfaces interactives et évoluées avec les vues, transitions et thèmes, gestion des données et échanges avec le serveur via RPC, mais aussi gestion et création des composants, débogage et optimisation. Il les met ensuite en situation avec deux études de cas détaillant la création d’un site e-commerce puis d’un lecteur MP3 tournant sur Adobe Air. Au sommaire Pourquoi utiliser Flex ? • Flex dans une architecture trois tiers • Flex et MVC • MXML et Actionscript • Procédures et fonctions • Programmation objet • Mécanisme client/serveur • Flex SDK et Flex Builder • Gestion d’un projet • Arborescence d’un projet Flex Builder • Exécution et test • Travail collaboratif • Export et import • Création d’interfaces graphiques • Composants de contrôles • Boutons • Listes • Zones de texte • Tableaux • Animations et vidéos Flash • Composants de navigation • Autres contrôles • Dimensionner et positionner • ApplicationControlBar • Canvas • Hbox • Grid • Panel • TitleWindow • Styles • CSS et ActionScript • Skinning • Utilisation d’images et de fichiers SWF • États, transitions et effets • Créer ses composants • MXML ou ActionScript ? • compc • Gestion des données • DataBinding • Validation des données • Accès aux services de la couche métier • HTTPService ou REST • RemoteObject • Flex et PHP • AMFPHP • HTTPService et ActionScript • Le générateur de Flex Builder • Flex et J2EE avec BlazeDS • Composants émetteurs et récepteurs • Créer des applications modulaires • Interagir avec le conteneur web • Deep linking • Flex-Ajax Bridge • Débogage d’une application • Points d’arrêt et exécution pas à pas • Analyse des performances • Optimisation et déploiement • Réduire la taille des fichiers SWF • Adobe AIR • Flex 4 Gumbo. A.Vannieuwenhuyze Ingénieur concepteur dans une SSII et responsable d’applications pour l’association Outcomerea, spécialisée dans le domaine de la recherche médicale, Aurélien Vannieuwenhuyze s’est d’abord investi dans la conception et la réalisation d’applications J2EE. Pour créer des applications Internet riches, il a étudié les frameworks alliant richesse et rapidité de réalisation. Son choix s’est porté sur Flex, avec lequel il a réalisé des applicatifs à vocation médicale et des extranets pour de grandes entreprises. R. Pouclet Passionné de développement multimédia depuis plusieurs années, Romain Pouclet se tourne aujourd’hui vers le développement d’interfaces riches et de solutions pour supports mobiles. À qui s’adresse cet ouvrage ? Conception : Nord Compo 9 782212 123876 @ Sur le site www.editions-eyrolles.com – Téléchargez le code source des exemples et cas pratiques du livre Code éditeur : G12387 ISBN : 978-2-212-12387-6 – À toute la communauté des concepteurs et développeurs web 2.0 (Flash, PHP, Java, Ajax, XHTML/CSS) qui désirent développer des applications Internet riches. – Aux webmestres et développeurs connaissant Flash et ActionScript, qui recherchent un framework pour industrialiser la création d’interfaces graphiques pour leurs applications. – Aux développeurs amenés à créer des applications autonomes exécutables avec ou sans navigateur web. 35 € Flex 3 Applications Internet riches avec Flash ActionScript 3, MXML et Flex Builder A. Vannieuwenhuyze Flex 3 Programmation Programmation Programmation e Couvr tés uveau o n s le x 4 de Fle Flex 3 Applications Internet riches avec Flash ActionScript 3, MXML et Flex Builder Aurélien Vannieuwenhuyze Programmation FLEX 3 Programmation FLEX 3 Applications Internet riches avec Flash ActionScript 3, MXML et Flex Builder Aurélien Vannieuwenhuyze Avec la contribution de Romain Pouclet CHEZ LE MÊME ÉDITEUR G. Leblanc. – Silverlight 2. N°12375, 2008, 330 pages. D. Séguy, P. Gamache. – Sécurité PHP 5 et MySQL. N°12114, 2007, 240 pages. G. Ponçon et J. Pauli. – Zend Framework. N°12392, 2008, 460 pages. R. Rimelé. – Mémento MySQL. N°12012, 2007, 14 pages. E. Daspet et C. Pierre de Geyer. – PHP 5 avancé. N°12369, 5e édition, 2008, 844 pages. M. Nebra. – Réussir son site web avec XHTML et CSS. N°12307, 2e édition, 2008, 316 pages. C. Porteneuve. – Bien développer pour le Web 2.0. N°12391, 2e édition 2008, 600 pages. A. Clarke. – Transcender CSS. Sublimez le design web ! N°12107, 2007, 370 pages. A. Boucher. – Ergonomie web. Pour des sites web efficaces. N°12158, 2007, 426 pages. J.-M. Defrance. – Premières applications Web 2.0 avec Ajax et PHP. N°12090, 2008, 450 pages (Collection Blanche). A. Boucher. – Mémento Ergonomie web. N°12386, 2008, 14 pages. K. Djaafar. – Développement JEE 5 avec Eclipse Europa. N°12061, 2008, 380 pages. R. Goetter. – CSS 2 : pratique du design web. N°11976, 2e édition, 2007, 324 pages. E. Sloïm. – Sites web. Les bonnes pratiques. N°12101, 2007, 14 pages. A. Tasso. – Apprendre à programmer en ActionScript. N°12199, 2007, 438 pages. S. Bordage, D. Thévenon, L. Dupaquier, F. Brousse. – Conduite de projets Web. N°12325, 4e édition 2008, 394 pages. N. Chu. – Réussir un projet de site Web. N°12400, 5e édition ,2008, 246 pages. S. Powers. – Débuter en JavaScript. N°12093, 2007, 386 pages. T. Templier, A. Gougeon. – JavaScript pour le Web 2.0. N°12009, 2007, 492 pages. D. Thomas et al. – Ruby on Rails. N°12079, 2e édition 2007, 800 pages. W. Altmann et al. – Typo3. N°11781, 2006, 532 pages. L. Bloch, C. Wolfhugel. – Sécurité informatique. Principes fondamentaux pour l’administrateur système. N°12021, 2007, 350 pages. O. Andrieu. – Réussir son référencement web. N°12264, 2008, 302 pages. G. Gete. – Mac OS X Leopard efficace. Déploiement, administration et réparation. N°12263, 2008, 476 pages. G. Ponçon. – Best practices PHP 5. Les meilleures pratiques de développement en PHP. N°11676, 2005, 480 pages. M. Mason. – Subversion. Pratique du développement collaboratif avec SVN. N°11919, 2006, 206 pages. ÉDITIONS EYROLLES 61, bd Saint-Germain 75240 Paris Cedex 05 www.editions-eyrolles.com Le code de la propriété intellectuelle du 1er juillet 1992 interdit en effet expressément la photocopie à usage collectif sans autorisation des ayants droit. Or, cette pratique s’est généralisée notamment dans les établissements d’enseignement, provoquant une baisse brutale des achats de livres, au point que la possibilité même pour les auteurs de créer des œuvres nouvelles et de les faire éditer correctement est aujourd’hui menacée. En application de la loi du 11 mars 1957, il est interdit de reproduire intégralement ou partiellement le présent ouvrage, sur quelque support que ce soit, sans autorisation de l’éditeur ou du Centre Français d’Exploitation du Droit de Copie, 20, rue des Grands-Augustins, 75006 Paris. © Groupe Eyrolles, 2009, ISBN : 978-2-212-12387-6 =Flex3 FM.book Page V Mardi, 2. décembre 2008 3:32 15 Table des matières Avant-propos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XIX Structure de l’ouvrage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XIX À qui s’adresse cet ouvrage ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XXI Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XXI PARTIE I Comprendre Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 CHAPITRE 1 Pourquoi Flex ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Les enjeux du développement d’applications web . . . . . . . . . . . . . . . . 3 Flex en questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Est-ce une technologie récente ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Qu’est-ce que Flex ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Quel est son fonctionnement ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sur quelles technologies repose t-il ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choisir la méthode Open Source ou propriétaire ? . . . . . . . . . . . . . . . . . . 5 6 6 6 7 Quelles différences avec Ajax ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Flex et ses concurrents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Les limites de Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Pourquoi choisir Flex ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 =Flex3 FM.book Page VI Mardi, 2. décembre 2008 3:32 15 VI Programmation Flex 3 CHAPITRE 2 À la découverte du framework Flex 3 . . . . . . . . . . . . . . . . . . . . . . . 13 Rôle du front end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Architecture n-tiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Positionnement d’une application Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . L’application et le modèle-vue-contrôleur . . . . . . . . . . . . . . . . . . . . . . . Le langage MXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le langage ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les boucles et les conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les procédures et les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La programmation objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le mécanisme client/serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 13 14 15 17 18 18 19 21 22 23 25 CHAPITRE 3 Développer avec le kit Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation du kit Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les compilateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mxmlc : le compilateur d’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . compc : le compilateur de composants . . . . . . . . . . . . . . . . . . . . . . . . . . . Première application Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conception graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Écriture du fichier MXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Écriture du fichier ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Liaison graphique et action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intégration dans une page web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Déploiement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Automatisation de la compilation à l’aide de Ant . . . . . . . . . . . . . . . . . Ant et Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation de Ant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création d’un script de compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 29 30 30 31 32 32 33 33 35 35 36 38 39 39 40 40 40 45 =Flex3 FM.book Page VII Mardi, 2. décembre 2008 3:32 15 Table des matières VII CHAPITRE 4 Développer des applications à l’aide de Flex Builder . . . . . . 47 Présentation de Flex Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les différentes versions de Flex Builder . . . . . . . . . . . . . . . . . . . . . . . . . . Les différents modes de distribution de Flex Builder . . . . . . . . . . . . . . . . 47 48 48 Installation de Flex Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le mode Autonome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le mode Plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Les perspectives de Flex Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La perspective de développement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La perspective de design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La perspective de débogage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La perspective de profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Créer un projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arborescence d’un projet Flex Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . Exécution et tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Travail collaboratif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 54 58 59 61 62 63 65 68 68 Exporter/importer un projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exportation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Importation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 72 73 CHAPITRE 5 Les composants de contrôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Les boutons et interrupteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ToogleButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Permettre le choix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Les zones de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les libellés : Label et Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les zones de saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les zones de texte « riches » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DataGrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AdvancedDataGrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 76 82 82 83 85 85 88 =Flex3 FM.book Page VIII Mardi, 2. décembre 2008 3:32 15 VIII Programmation Flex 3 Analyser un cube OLAP avec OLAPDataGrid . . . . . . . . . . . . . . . . . . Qu’est-ce qu’un cube OLAP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création d’un cube OLAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Requête sur le cube . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Insérer des images, des animations et vidéos Flash . . . . . . . . . . . . . . . Intégrer des animations Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Insérer des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lecteur vidéo Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Choisir une couleur dans une palette avec ColorPicker . . . . . . . . . . . 103 Contrôler le format de date avec DateChooser et DateField . . . . . . . 104 Ajouter un curseur avec HSlider et VSlider . . . . . . . . . . . . . . . . . . . . . 105 L’incrémentation avec NumericStepper . . . . . . . . . . . . . . . . . . . . . . . . . 106 Présentation de données avec HorizontalList et TileList . . . . . . . . . . 106 Réaliser des hyperliens grâce à LinkButton . . . . . . . . . . . . . . . . . . . . . 107 Afficher des données sous forme d’arborescence . . . . . . . . . . . . . . . . . Implémentation et alimentation en données . . . . . . . . . . . . . . . . . . . . . . . Interaction avec l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 92 93 95 100 100 101 108 109 CHAPITRE 6 Les composants conteneurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Créer une barre de menus avec ApplicationControlBar . . . . . . . . . . . 111 Le composant Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Aligner verticalement ou horizontalement les composants . . . . . . . . . Les composants HBox et VBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les composants HDividedBox et VDividedBox . . . . . . . . . . . . . . . . . . . . 113 Créer des formulaires avec Form, FormHeading et FormItem . . . . . 115 Créer une grille grâce à Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Les panneaux : Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Créer des fenêtres pop-ups avec TitleWindow . . . . . . . . . . . . . . . . . . . Création du pop-up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appel du pop-up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Communiquer avec le pop-up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 113 113 118 119 120 =Flex3 FM.book Page IX Mardi, 2. décembre 2008 3:32 15 Table des matières IX CHAPITRE 7 Les composants de navigation et de reporting . . . . . . . . . . . . . 123 Les composants de navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Navigation par onglets avec TabNavigator . . . . . . . . . . . . . . . . . . . . . . . . Vues empilées avec ViewStack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Navigation « en accordéon » : Accordion . . . . . . . . . . . . . . . . . . . . . . . . . Les composants de graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En pratique : création d’un outil de reporting . . . . . . . . . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 123 124 126 128 128 130 133 CHAPITRE 8 Réaliser le design des interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Dimensionner et positionner les composants . . . . . . . . . . . . . . . . . . . . . Spécifier les dimensions des composants . . . . . . . . . . . . . . . . . . . . . . . . . Positionner les composants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utiliser les styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La balise Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le fichier CSS externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CSS et ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Habiller les composants : skinning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utiliser des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utiliser des fichiers SWF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . L’habillage par programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 135 138 147 148 149 150 151 152 152 153 155 CHAPITRE 9 Le dynamisme applicatif à l’aide des états, des transitions et des effets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les états ou view states . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Étude de cas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combiner des effets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mise en pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Écrire des transitions en ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 157 158 163 165 166 169 172 =Flex3 FM.book Page X Mardi, 2. décembre 2008 3:32 15 X Programmation Flex 3 CHAPITRE 10 Créer des composants personnalisés . . . . . . . . . . . . . . . . . . . . . . 173 Penser composant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Qu’est–ce qu’un composant ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MXML ou ActionScript ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le compilateur compc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 174 174 Créer un composant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Description du composant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Méthodologie de création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Réemploi du composant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 175 177 195 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 CHAPITRE 11 Gérer les données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Lier des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation de la balise <mx:Binding> . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le DataBinding en ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 201 201 Stocker des données grâce au modèle . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémenter le modèle à l’aide de la balise <mx:Model> . . . . . . . . . . . . Les modèles et ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 206 209 Valider des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rendre la saisie obligatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vérification du format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Personnalisation des messages d’erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . Les événements de validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gestion de la validation en ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . 212 213 215 215 215 216 Formater des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 CHAPITRE 12 Accéder aux services de la couche métier . . . . . . . . . . . . . . . . . 223 Employer les requêtes HTTP avec HTTPService ou REST-Style webservice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Le composant WebService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le service web en détail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 230 =Flex3 FM.book Page XI Mardi, 2. décembre 2008 3:32 15 Table des matières XI Création de l’interface graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appel du service web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Analyse du fonctionnement de l’application . . . . . . . . . . . . . . . . . . . . . . . 234 235 236 Accéder aux classes distinctes grâce à RemoteObject . . . . . . . . . . . . . Comprendre RemoteObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémentation de RemoteObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 238 238 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 CHAPITRE 13 Flex et PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Accès aux services PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Installation et fonctionnement de la passerelle AMFPHP . . . . . . . . . . 241 Cas pratique : gestion d’un magasin informatique . . . . . . . . . . . . . . . Préparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémentation du composant HTTPService en ActionScript . . . . . . . . . RemoteObject en pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 244 247 250 Le générateur d’application de Flex Builder . . . . . . . . . . . . . . . . . . . . . 257 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 CHAPITRE 14 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications . . . . . . . . . . . . . . . . . . . . . . . . . Le projet BlazeDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les différentes versions du serveur BlazeDS . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le serveur Tomcat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Test d’installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 263 264 264 265 268 Interaction avec les méthodes J2EE . . . . . . . . . . . . . . . . . . . . . . . . . . . . Processus d’exécution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple d’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Échanger des données en temps réel . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuration du serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <mx:Producer> et <mx:Consumer> : les composants émetteurs et récepteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 269 270 277 278 279 =Flex3 FM.book Page XII Mardi, 2. décembre 2008 3:32 15 XII Programmation Flex 3 Les procédures de communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Test de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 282 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 CHAPITRE 15 Créer des applications modulaires . . . . . . . . . . . . . . . . . . . . . . . . . 285 La notion de module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Créer un module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Intégrer un module dans une application . . . . . . . . . . . . . . . . . . . . . . . . Charger les modules à l’aide du composant ModuleLoader . . . . . . . . . . . Gestion des modules avec ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 288 288 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 CHAPITRE 16 Interagir avec le conteneur web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 La notion de deep linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Principe de fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mise en pratique du deep linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Déploiement du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 299 301 305 Communiquer avec le conteneur web . . . . . . . . . . . . . . . . . . . . . . . . . . . De l’application Flex vers le conteneur web . . . . . . . . . . . . . . . . . . . . . . . Du conteneur web vers l’application Flex . . . . . . . . . . . . . . . . . . . . . . . . . 305 306 309 La bibliothèque Flex-Ajax Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ajout de la bibliothèque à un projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation de la bibliothèque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Déploiement et test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 313 313 315 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 CHAPITRE 17 Déboguer une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Création de l’application d’étude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Identifier et corriger les erreurs grâce à la vue Problems . . . . . . . . . . 321 Le débogage avancé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation des points d’arrêt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifier la valeur des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 322 325 =Flex3 FM.book Page XIII Mardi, 2. décembre 2008 3:32 15 Table des matières XIII Tracer un parcours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sélectionner les variables à surveiller . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 326 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 CHAPITRE 18 Analyser les performances et optimiser l’application . . . . . . 329 Présentation de l’analyseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 L’analyseur en action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 Analyse des performances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Analyse de l’occupation mémoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 333 Méthodes d’analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Détecter les allocations mémoire inutiles . . . . . . . . . . . . . . . . . . . . . . . . . Analyser le temps d’exécution des méthodes . . . . . . . . . . . . . . . . . . . . . . Déterminer le nombre d’instances d’une classe . . . . . . . . . . . . . . . . . . . . Visualiser les allocations d’objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 335 336 336 Bonnes pratiques d’optimisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 Calculer les performances applicatives . . . . . . . . . . . . . . . . . . . . . . . . . . . Améliorer l’exécution sur les postes clients . . . . . . . . . . . . . . . . . . . . . . . Réduire la taille des fichiers SWF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiplier les fichiers SWF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Améliorer les méthodes de codage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 338 339 340 340 Déployer une application Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 L’incontournable liste de contrôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mise en ligne de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 342 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 CHAPITRE 19 Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 Le projet Adobe AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 Fonctionnement d’une application AIR . . . . . . . . . . . . . . . . . . . . . . . . . . Nouveaux composants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 346 Première application AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Création du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Déploiement de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 352 =Flex3 FM.book Page XIV Mardi, 2. décembre 2008 3:32 15 XIV Programmation Flex 3 Gestion des données avec la bibliothèque SQLite . . . . . . . . . . . . . . . . . Utiliser la bibliothèque SQLite dans une application AIR . . . . . . . . . . . . SQLite par l’exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 355 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 354 PARTIE II Cas pratiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 CHAPITRE 20 Création d’un projet de site e-commerce . . . . . . . . . . . . . . . . . . . 365 Définition des besoins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Conception UML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 Architecture du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 Création du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le squelette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Accès à l’espace d’administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Préparation du serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 369 371 374 Faisons le point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 CHAPITRE 21 Module d’administration du site e-commerce . . . . . . . . . . . . . . 379 Création du module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Phase préparatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Design de l’interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Gestion des fournisseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création des services PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logique IHM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logique applicative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vérification des données transmises . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saisie obligatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vérifier le format du code postal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aspect graphique de la validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 381 386 386 389 392 394 398 399 400 401 =Flex3 FM.book Page XV Mardi, 2. décembre 2008 3:32 15 Table des matières À vos claviers : la gestion des produits . . . . . . . . . . . . . . . . . . . . . . . . . . Quelques pistes de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version de déploiement du module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intégration du module dans l’application principale . . . . . . . . . . . . . . En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XV 403 403 405 419 419 421 CHAPITRE 22 Module de vente en ligne : le panier d’achat . . . . . . . . . . . . . . . . 423 Création du module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Design de l’interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les états . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Affichage du détail d’un produit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 424 424 435 437 Gestion du panier d’achat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Design du panier avec ItemRenderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ajouter un produit au panier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vider le panier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 439 441 442 À vos claviers : création de l’interface graphique . . . . . . . . . . . . . . . . Ce qu’il faut réaliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 443 445 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 CHAPITRE 23 Module de vente en ligne : commande et facturation . . . . . . 451 Création de la commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémenter le glisser-déposer dans le tableau de commander . . . . . . . . Supprimer l’article du panier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calcul du prix total de la commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création de la facture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implémentation du pop-up de facturation . . . . . . . . . . . . . . . . . . . . . . . . . Impression de la facture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . À vos claviers : création d’un pop-up de paiement et de validation de la commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Répétition de composants : <mx:Repeater> . . . . . . . . . . . . . . . . . . . . . . . Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 452 453 455 457 457 462 463 464 465 =Flex3 FM.book Page XVI Mardi, 2. décembre 2008 3:32 15 XVI Programmation Flex 3 Déploiement du module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 Optimisation et déploiement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 Optimiser le temps de chargement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Faire patienter l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Déploiement de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 473 475 Fin du site E-Reflex ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 CHAPITRE 24 Créer un lecteur MP3 avec Adobe AIR . . . . . . . . . . . . . . . . . . . . . . 479 Rechercher des MP3 à l’aide de <mx :FileSystemTree> . . . . . . . . . . . 479 Implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interaction avec l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 481 Lire un fichier MP3 avec ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Principales fonctions de lecture d’un fichier audio . . . . . . . . . . . . . . . . 485 Stopper et mettre en pause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connaître la progression de la lecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple complet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485 485 486 Définition des fonctionnalités de notre application . . . . . . . . . . . . . . . . 488 Gestion de la liste de lecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interface de lecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489 492 À vos claviers : création d’un lecteur MP3 . . . . . . . . . . . . . . . . . . . . . . 493 Fichier de styles CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Code de la classe ClassesLecteurMp3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fichier LecteurMP3AS3.as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fichier principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 495 500 505 Déploiement du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 En résumé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 CHAPITRE 25 Flex 4 Gumbo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509 Les nouveautés de Flex 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509 Installer le Flash Player 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510 FXG 1.0, nouveau format graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 =Flex3 FM.book Page XVII Mardi, 2. décembre 2008 3:32 15 Table des matières XVII MXML 2009 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Un nouvel espace de noms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La balise <private> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le couple de balises <library> et <description> . . . . . . . . . . . . . . . . . . . . Le DataBinding bi-directionnel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 513 514 514 516 Amélioration de certains composants de Flex 3 . . . . . . . . . . . . . . . . . . Remplacement du composant <mx:Label> . . . . . . . . . . . . . . . . . . . . . . . . Le composant <TextInput> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le composant <TextArea> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 517 517 517 Installation de l’environnement de développement . . . . . . . . . . . . . . . 518 Première application 3D avec Flex 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création et configuration du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Création de l’interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Codage de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 520 521 523 En conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527 =Flex3 FM.book Page XVIII Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page XIX Mardi, 2. décembre 2008 3:32 15 Avant-propos Le marché des applications web est en plein essor, et la tendance actuelle est de développer mieux et plus vite. Deux solutions s’offrent à nous : se contenter de réaliser une application fonctionnelle reléguant l’aspect graphique au second plan, ou faire primer l’aspect graphique sur la qualité du développement. Comme aucune de ces deux propositions n’est satisfaisante, les méthodes de développement ont évolué pour donner naissance aux frameworks, des ensembles d’outils facilitant le travail du développeur. En effet, une application web doit être aussi attrayante et performante que n’importe quelle autre. De plus, la démocratisation des connexions haut débit fait sauter la contrainte technique majeure des application en ligne. Aussi les utilisateurs se montrent-ils de plus en plus exigeants et apprécient les clients riches (ou RIA, Rich Internet Application), capables de reproduire les fonctionnalités d’une application bureautique dans la fenêtre d’un navigateur. Pour répondre à une telle attente, les frameworks facilitent la création d’interfaces graphiques de qualité et d’applications complètes en un minimum de temps. Flex allie justement la puissance de Flash à des outils connus pour le développement rapide – comme le Flex Builder –, issus du fameux environnement Eclipse. Mais les applications riches ne se cantonnent pas à l’univers du Web : les techniques de développement sont applicables à la création d’applications pour les postes clients (ou RDA, Rich Desktop Application), grâce au runtime Adobe AIR. Structure de l’ouvrage Nous souhaitons qu’à l’issue de votre lecture, le développement d’applications Internet et bureautiques riches à l’aide du framework Flex 3 n’ait plus de secret pour vous. Nous en verrons donc toutes les facettes : de la conception de l’interface graphique au déploiement de votre projet, en passant par la gestion des données et du contrôle de la saisie de l’utilisateur. La première partie de cet ouvrage couvre l’ensemble des concepts fondamentaux. Présentation de Flex 3, le chapitre 1 vous donnera une vue d’ensemble sur les capacités du framework, sa structure et ses points forts. Le chapitre 2 se focalise ensuite sur la programmation de type MVC et situe Flex dans ce contexte. =Flex3 FM.book Page XX Mardi, 2. décembre 2008 3:32 15 XX Programmation Flex 3 Entrée en matière dans l’utilisation du framework, le chapitre 3 propose l’étude du SDK et des différents compilateurs. Ce sera l’occasion de créer une première application Flex. Nous passerons alors au chapitre 4 à la présentation de l’outil de développement Flex Builder. Le chapitre 5 est le premier d’une trilogie consacrée à la présentation des composants du framework. Nous commencerons par l’interaction entre l’utilisateur et l’interface. Dans un deuxième temps, le chapitre 6 passe en revue les composants chargés d’en contenir d’autres. Le chapitre 7 terminera notre trilogie des composants par ceux dédiés à la représentation d’analyses statistiques. Suite logique des trois chapitres précédents, le chapitre 8 présente les techniques d’agencement des composants afin de créer le design de nos applications. Dans le chapitre 9, nous verrons comment réaliser effets et transitions au sein de nos interfaces graphiques. Puis, le chapitre 10 se penchera sur la création de composants personnalisés. Le chapitre 11 explore les possibilités qu’offre le framework en matière de gestion de données au sein d’une interface (saisie obligatoire, formatage…) et le chapitre 12 étudie les méthodes d’accès aux données contenues dans une base de données. Le chapitre 13 présente l’interaction de Flex 3 avec PHP. Quant au chapitre 14, il aborde les relations de notre framework avec Java. Le chapitre 15 détaille la notion d’application modulaire et la création de modules. Au chapitre 16 nous verrons les méthodes qui permettent à une application Flex de communiquer avec la page web qui la contient. Le chapitre 17 explore les notions de débogage avant de passer, au chapitre 18, à l’étude des méthodes d’optimisation d’une application Flex. Enfin, le chapitre 19 terminera la première partie avec le runtime Adobe AIR. La seconde partie met en œuvre l’ensemble des concepts étudiés dans la première partie dans des cas pratiques. Nous détaillerons le développement d’une application e-commerce sur quatre chapitres et terminerons avec une application multimédia réalisée à l’aide du runtime Adobe AIR. Le chapitre 20 définit le cadre du projet qui sera développé au cours des trois chapitres suivants. Le chapitre 21 décrit le développement de la partie d’administration de l’application. Le chapitre 22 est consacré à la réalisation de son module principal, et le chapitre 23 détaille le déploiement de l’application. Le chapitre 24 propose la réalisation d’un lecteur MP3 avec Adobe AIR. Enfin, cet ouvrage se termine au chapitre 25, consacré à la future version du framework. Il vous permettra de vous familiariser dès aujourd’hui avec Flex 4 Gumbo. En pratique Chaque chapitre de la seconde partie commence par une partie d’accompagnement à la réalisation et se termine par une rubrique « À vos claviers » : en situation, vous pourrez ainsi vérifier que vous avez bien assimilé les différents concepts énoncés tout au long de cet ouvrage. =Flex3 FM.book Page XXI Mardi, 2. décembre 2008 3:32 15 Avant-propos À qui s’adresse cet ouvrage ? Cet ouvrage s’adresse autant : • aux étudiants en programmation qui veulent apprendre à réaliser des applications clientes riches basées sur Flash ; • aux développeurs aguerris qui souhaitent réaliser des interfaces graphiques performantes pouvant être intégrées à des projets Java ou PHP déjà existants ; • aux chefs de projets qui désirent se faire une idée de la richesse technologique et des possibilités techniques de ce framework, notamment au niveau de la productivité ; • aux décideurs qui cherchent à rendre leurs applications plus attrayantes du point de vue utilisateur. Remerciements Mes premiers remerciements vont tout naturellement à ma compagne, qui a fait preuve de compréhension pour tous les week-ends et soirées monopolisés par l’écriture de cet ouvrage, sans oublier les nombreux sacrifices que cela a pu engendrer. Je remercie toute l’équipe des éditions Eyrolles et plus particulièrement Muriel Shan Sei Fan, Eliza Gapenne, Matthieu Montaudouin et Sandrine Paniel. Merci également à Romain Pouclet pour sa relecture technique et son avis de premier lecteur. Je n’oublie pas le Professeur Jean-François Timsit et le Docteur Alexis Tabah de l’association Outcomerea (www.outcomerea.org), qui m’ont donné l’occasion de travailler sur des projets mettant en œuvre Flex. Pour finir, merci à mes parents de m’avoir aidé et accompagné dans la réalisation de mon plus grand souhait : faire de l’informatique mon métier. XXI =Flex3 FM.book Page XXII Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 1 Mardi, 2. décembre 2008 3:32 15 Partie I Comprendre Flex 3 =Flex3 FM.book Page 2 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 3 Mardi, 2. décembre 2008 3:32 15 1 Pourquoi Flex ? Les enjeux du développement d’applications web Commençons ce premier chapitre par une constatation : 75 % des nouvelles applications sont de type web, c’est-à-dire qu’elles ont pour support le navigateur Internet. Si nous analysons les raisons de cet engouement pour ce mode de développement, nous pouvons avancer trois points de réflexion : • Une application web est disponible à tout moment et en tout point du globe. En effet, dès lors que l’utilisateur dispose d’une connexion Internet, il peut profiter de son application. Citons comme exemple la possibilité de consulter les informations de son compte bancaire, indépendamment de l’endroit où l’on se trouve. • Une application web est compatible avec tous les systèmes d’exploitation. Ainsi, les problèmes d’incompatibilité rencontrés avec les clients lourds (applications s’exécutant sur le système d’exploitation) sur les environnements Windows, Linux ou Macintosh sont maintenant révolus. Cette compatibilité est rendue possible notamment par la mise en place de recommandations de développement (par le W3C, entre autres) et l’utilisation de langages normalisés, tels que le JavaScript ou le HTML, interprétables par l’ensemble des navigateurs web. W3C Le World Wide Web Consortium, fondé en 1994 par Tim Berners-Lee, n’a pas pour fonction première de créer des normes de développement mais plutôt des recommandations. Son domaine d’activité se concentre sur les langages orientés vers le développement d’applications Internet (HTML, XML…) afin d’assurer leur interopérabilité (http://www.w3.org/). =Flex3 FM.book Page 4 Mardi, 2. décembre 2008 3:32 15 4 Comprendre Flex 3 PARTIE I • Enfin, le dernier point est la légèreté du mode de distribution de ces applications. Si pour une application lourde nous devions posséder un CD-Rom d’installation, nous n’avons plus qu’à saisir une URL dans un navigateur. Notons également que ceci réduit d’autant le coût de distribution de l’application. Néanmoins, ce phénomène induit tout de même un effet secondaire néfaste. Les applications disponibles depuis le Web ou les différents intranets d’entreprise sont aujourd’hui tellement nombreuses que se développe le syndrome d’applications « jetables ». Ainsi, comme il suffit de saisir une simple URL dans un navigateur pour exécuter une application, si celle-ci ne nous convient pas pour des raisons X ou Y, nous n’aurons qu’à lancer une requête dans un moteur de recherche pour en trouver une autre, similaire. Dès lors, pour développer une application web viable et durable, les outils que nous pouvons désormais qualifier, de façon réductrice, de « simplistes » dédiés uniquement au développement et ne prenant pas en compte le processus complet de réalisation de l’application (de la conception au déploiement) ne sont plus de mise. Nous disposons maintenant de frameworks qui sont un ensemble d’outils réunis dans une seule application. Grâce à eux, nous pouvons à présent déboguer une application web, disposer d’autocomplétion de code et « designer » des interfaces. L’utilisation d’un framework facilite la mise en place de la standardisation du code et de méthodes d’optimisation. Les applications développées sont ainsi homogènes, ce qui diminue le temps d’analyse et facilite l’apport de correctifs, augmentant donc la productivité. Alternatives Notons que nous avons parlé de frameworks au pluriel. En effet, il n’existe pas un mais des frameworks. Citons par exemple le framework ZendStudio pour le langage PHP, le Google Web Toolkit et bien entendu Flex 3. Pourquoi choisir le framework Flex 3 plutôt qu’un autre ? Sans entrer dans le détail, car nous aurons l’occasion d’y revenir tout au long de ce chapitre, le framework Flex permet de créer des applications web basées sur la technologie Flash (employée dans les applications graphiques) procurant une qualité d’interface graphique très appréciée des utilisateurs. De plus, sa prise en main est facilitée par l’outil de développement Flex Builder basé sur le célèbre IDE Eclipse, très largement utilisé par les développeurs de nouvelles technologies. Cette facilité de prise en main séduira donc les développeurs juniors et seniors qui verront dans ce framework la possibilité de créer rapidement des applications web alliant esthétique et technique. Les jeunes développeurs seront sans doute intéressés par le coté « nouveau » de cette technologie, source de motivation et moteur de créativité, les plus aguerris y verront le moyen de créer des interfaces graphiques très performantes tout en minimisant le temps de développement. Notre framework ravira également les décideurs (chef de projets ou d’entreprise), car il permet, d’une part, de produire des applications esthétiques appréciées des utilisateurs et, d’autre part, de réduire les délais de développement grâce aux avantages énoncés précédemment. =Flex3 FM.book Page 5 Mardi, 2. décembre 2008 3:32 15 Pourquoi Flex ? CHAPITRE 1 Nous sommes sûrs qu’à la suite de ces quelques lignes, vous vous posez certaines questions. C’est pourquoi nous allons poursuivre ce chapitre en tentant d’y répondre. Flex en questions En tant que spécialiste, lorsque vous évoquez le framework avec des chefs de projets, développeurs ou tout autre acteur d’un projet de développement informatique, plusieurs questions reviennent immanquablement : • Est-ce une technologie récente ? • Qu’est-ce que le framework Flex ? • Comment fonctionne-t-il ? • De quoi est-il composé ? • S’agit-il d’un logiciel Open Source ou d’une solution propriétaire ? Voyons comment répondre à ces questions. Est-ce une technologie récente ? Flex vu le jour en mars 2004. Initié par Macromédia, repris en 2006 par Adobe, le projet a connu une évolution rapide comme le montre le tableau 1-1 qui récapitule les mises en production des différentes versions. Tableau 1-1 Historique des versions du framework Flex Date Événement Mars 2004 Sortie de Flex version 1.0 Octobre 2004 Flex 1.5 Octobre 2005 Flex 2.0 alpha Février 2006 Flex 2.0 bêta 1 Mars 2006 Flex 2.0 bêta 2 Mai 2006 Flex 2.0 bêta 3 Janvier 2007 Flex 2.01 Février 2008 Flex 3 Courant 2009 Flex 4 qui portera vraisemblablement le nom de « Gumbo ». Si l’on considère cette chronologie, on constate la mise en production d’une nouvelle version par an. On peut en déduire que cette technologie est chère à Adobe, qui investit largement dans ce projet. Sans chercher à décrire les différentes versions du framework, il est tout de même important de noter qu’à l’origine, Flex a été créé pour le développement de la couche graphique 5 =Flex3 FM.book Page 6 Mardi, 2. décembre 2008 3:32 15 6 Comprendre Flex 3 PARTIE I d’une application (partie front end) J2EE. Ceci nécessitait la présence d’un serveur Flex qui a totalement disparu dès la version 2. La version 3 apporte également son lot de nouveautés comme l’ouverture vers le monde libre de certaines parties du SDK, ou l’apparition de nouveaux composants. L’environnement de développement Flex Builder comporte aussi de nouvelles fonctionnalités telles que le mode de débogage avancé. Qu’est-ce que Flex ? Flex est un framework qui sert à la création d’interfaces client riches (front end de l’application) basé sur l’usage de la technologie Adobe Flash. En effet, si celle-ci apporte une grande souplesse pour la création d’interfaces graphiques riches, elle est souvent perçue par les non-initiés comme complexe. De plus, pour bon nombre de techniciens spécialisés dans le développement d’application, la conception et la réalisation de l’interface graphique de l’application semblent souvent secondaires : ils préfèrent se focaliser complètement sur la fonctionnalité à développer plutôt que sur la présentation du résultat. Le framework Flex a ainsi pour objectif de faciliter cette partie du développement, en supprimant la notion de time line. Time line Bien connu des développeurs Flash, le time line sert à définir des actions sur les composants selon un axe temporel. Ce mode de développement est réservé aux spécialistes de Flash et diffère du mode de développement standard basé sur la disposition de composants sur une page web. Grâce au framework Flex, l’utilisation de Flash n’est plus l’apanage des seuls designers : les développeurs peuvent maintenant créer des interfaces graphiques attrayantes grâce à un langage de description basé sur XML. Quel est son fonctionnement ? Une application Flex n’est autre qu’un fichier portant l’extension .swf (ShockWave Flash) issu de la compilation de fichiers MXML et ActionScript, insérés dans une page web. Les fichiers MXML (Macromedia XML) servent à la description des interfaces graphiques, en définissant la position des composants et leurs propriétés. Quant aux fichiers ActionScript 3, ils ont la charge de la logique applicative : gestion d’événements, écriture de procédure, fonctions… Sur quelles technologies repose t-il ? Voyons à présent le socle sur lequel repose Flex 3 et les technologies associées. Le framework Flex 3 s’articule autour des quatre éléments suivants : • Le Flash Player 9 – Équipant près de 97 % des ordinateurs (Windows, Mac OS et Linux), le Flash Player assure la compatibilité des applications développées en Flash sur l’ensemble des environnements et navigateurs web. =Flex3 FM.book Page 7 Mardi, 2. décembre 2008 3:32 15 Pourquoi Flex ? CHAPITRE 1 • Le Flex 3 SDK – Ouvert au monde Open Source, le SDK (Software Development Kit) permet de créer des applications Flex gratuitement à l’aide des compilateurs et du débogueur qu’il intègre. • Flex Builder 3 – Environnement de développement basé sur le célèbre IDE (Integrated Development Environment) Eclipse, il propose un ensemble de fonctionnalités permettant de réaliser facilement des interfaces graphiques conviviales. Depuis sa version 3, il offre également des fonctions avancées de débogage comme le profiling d’application (qui intervient notamment dans la description de la charge mémoire utilisée par l’application). Cet outil est disponible en version standard et professionnelle mais nécessitera cependant un investissement non négligeable (environ 600 € pour la version professionnelle). À noter qu’il existe une version pour les étudiants. • Blaze DS – Ce composant s’adresse à celles et ceux qui souhaitent créer des applications Flex communiquant avec le back end J2EE. Il s’agit d’un sous-ensemble de projets Open Source basés sur les briques principales de son homologue LiveCycle Data services d’Adobe, qui est payant. Front end et back end d’une application Le back end est chargé de contenir la logique métier de l’application (règles de gestion, traitements des données…). Le front end, quant à lui, gère la partie interface homme machine (IHM) de l’application. Flash 9 obsolète ? À l’heure ou nous écrivons ces lignes, Adobe vient de mettre à disposition le nouveau Flash Player 10. Cependant, la compatibilité descendante est respectée : les fonctionnalités du Flash Player 9 sont aussi disponibles dans le Flash Player 10. Cela n’a également aucun impact sur l’utilisation du framework Flex 3. Choisir la méthode Open Source ou propriétaire ? Voilà la grande question que tout le monde est en droit de se poser. Comportant l’ensemble des bibliothèques et compilateurs nécessaires au développement, certaines parties du Flex SDK sont à présent Open Source. Néanmoins, nous verrons, lors du chapitre 3, que son utilisation n’est pas des plus aisées. Cependant, pour faciliter le travail du développeur, Adobe propose l’environnement de développement propriétaire Flex Builder. Vous disposez ainsi d’un environnement de développement, de test et de déploiement efficace. Bien entendu, cet environnement de développement a un prix : il faut débourser environ 600 € pour acquérir une licence. Mais, comme nous venons de l’indiquer, le Flex Builder n’est qu’un « plus » qui facilite l’utilisation du framework. Il est donc tout à fait possible de développer vos applications avec Flex sans débourser un sou… si vous pouvez vous contenter d’un simple éditeur de texte et d’un compilateur en ligne de commande. 7 =Flex3 FM.book Page 8 Mardi, 2. décembre 2008 3:32 15 8 Comprendre Flex 3 PARTIE I Quelles différences avec Ajax ? Comme nous venons de l’indiquer, si vous souhaitez recourir à l’IDE Flex Builder, il faudra bourse délier. Bien entendu, cet investissement financier sera d’autant plus important que les développeurs amenés à l’utiliser seront nombreux. Vous êtes donc en droit de vous demander pourquoi effectuer une telle dépense, alors qu’en optant pour un framework Ajax, vous pourriez tout à fait réaliser des RIA (Rich Internet Application) et, ce, de façon totalement gratuite tout en profitant des forces des projets Open Source. Qu’est-ce qu’Ajax ? Ajax (Asynchronous Javascript and XML, XML et JavaScript asynchrone) est une méthode de développement d’application web combinant différentes technologies telles que HTML, Javascript, XML ou encore le protocole HTTP. On l’utilise notamment pour créer des interfaces interactives. Pour en résumer le principe, Ajax permet d’interagir avec un serveur web sans devoir recharger l’intégralité de la page. De nombreux frameworks Ajax – comme Openlaszlo (http://www.openlaszlo.org/) – mettent à profit cette méthode de développement pour la réalisation d’interfaces client riches. Le principal argument que nous pouvons avancer est le suivant : Ajax se base sur le langage JavaScript dont l’interprétation peut varier d’un navigateur à l’autre. Ceci implique donc l’adaptation du code pour chaque navigateur. Une application Flash reposant exclusivement sur le Flash Player, son comportement sera identique quelle que soit la plateforme ou l’environnement dans lequel elle est exécutée. Un second argument peut également être avancé : il est plus facile et rapide de développer une interface graphique à fonctionnalités équivalentes avec le framework Flex qu’avec la technologie Ajax. Comme nous l’avons évoqué au début de ce chapitre, nous sommes dans une société de consommation d’applications web, où la durée de vie de celles-ci est limitée et où l’aspect esthétique est devenu primordial. Par conséquent, si nous souhaitons réaliser une application ayant une interface attrayante tout en réduisant son coût de développement, nous avons tout intérêt à nous diriger vers l’usage du framework Flex. Tableau 1-2 Comparaison entre une application développée avec Flex et avec Ajax Critère Flex Ajax Nécessité d’un plug-in sur le poste client pour l’exécution de l’application Oui Non, même s’il nécessite l’activation de JavaScript sur le poste client Coût du développement de l’application Gratuit pour l’utilisation du SDK. Payant pour l’utilisation de l’IDE Gratuit Portabilité de l’application Comportement identique sur l’ensemble des navigateurs Le comportement de l’application peut différer selon le navigateur web (hors utilisation d’un framework) Insertion de contenu multimédia (vidéo, son…) dans l’application à l’aide de fonctionnalités pré-existantes De par son lien avec Flash, les fonctionnalités multimédias sont incluses dans le framework Les fonctionnalités multimédias ne sont pas incluses =Flex3 FM.book Page 9 Mardi, 2. décembre 2008 3:32 15 Pourquoi Flex ? CHAPITRE 1 Tableau 1-2 Comparaison entre une application développée avec Flex et avec Ajax (suite) Critère Flex Ajax Composants graphiques prêts à l’emploi Flex intègre de nombreux composants graphiques (menus accordéon…) Ajax ne comporte pas de composants graphiques, c’est au développeur de les créer Nombre de langages utilisés 2 : MXML et ActionScript 2 : JavaScript et XML Le tableau 1-2 établit une comparaison entre l’utilisation du framework Flex et la méthode de développement Ajax. Bien entendu, il s’agit là moins de comparer le framework Flex à l’ensemble des frameworks Ajax (tels que OpenLazlo ou bien encore Google Web Toolkit), que de mesurer le résultat obtenu. Comme vous le constatez, la frontière séparant le framework Flex de la méthode de développement Ajax est très mince. Mais si nous faisons le bilan de cette comparaison, il est évident que l’atout majeur de Flex est sa faculté à rendre les applications compatibles avec l’ensemble des navigateurs, grâce à Flash tout en proposant un panel de composants prêts à l’emploi. C’est également grâce à Flash et ses possibilités multimédias et de mise en forme des composants que Flex se démarque d’Ajax. Néanmoins, le principal inconvénient des applications Flex est qu’elles sont hermétiques à leur environnement : au sein d’une page web, la communication avec les éléments HTML, JavaScript, etc. est inexistante, à moins de passer par un pont de communication, réalisé en JavaScript et portant le nom de Flex-Ajax Bridge. Mais nous aurons l’occasion de revenir sur cette notion dans le chapitre 16. Plutôt que de chercher à se démarquer de la solution Ajax, les développeurs du framework Flex ont pris conscience de ses faiblesses et ont opté pour une alliance de technologies. De plus, on souligne souvent que l’exécution d’une application Flash est plus lente qu’une application HTML utilisant Ajax. Si ce point n’est pas négligeable, rappelons qu’une application Flex est développée pour un Flash Player précis, et compilée pour fonctionner avec ce dernier, ce qui permet une meilleure interopérabilité et donc un gain de performance. Nous verrons qu’il nous est possible d’optimiser ce temps d’exécution grâce à l’analyse des processus et à l’étude de l’occupation mémoire de certaines procédures. Flex et ses concurrents Encore restreint il y a quelques années, le marché de la RIA, tend peu à peu à se développer : • La technologie XUL (XML-based User interface Language), initiée par Mozilla, consiste, tout comme le framework Flex, à décrire les interfaces graphiques à l’aide de XML. • Le framework OpenLazlo se rapproche du framework Flex par la génération d’interfaces graphiques basées sur la technologie Flash (http://www.openlaszlo.org/). • Entièrement basé sur la technologie Ajax, le framework Google Web Toolkit, permet de créer également des interfaces client riches assez intéressantes en termes de 9 =Flex3 FM.book Page 10 Mardi, 2. décembre 2008 3:32 15 10 Comprendre Flex 3 PARTIE I fonctionnalités. Citons par exemple l’application de géolocalisation Google Map (http://maps.google.fr/). Néanmoins, le principal concurrent de Flex 3 est la plate-forme de développement Silverlight de Microsoft. Elle offre un environnement de développement semblable en termes de fonctionnalités, tout en se différenciant par l’utilisation du langage XAML pour la description des interfaces et de JavaScript pour la partie logique applicative. L’exécution de ces applications diffère également par l’utilisation d’un plug-in à installer sur le navigateur. Alors, vers quelle solution faut il se diriger ? La première chose à prendre en compte est la politique informatique de l’entreprise. Si la norme est de limiter l’usage des projets libres ou si l’entreprise est en partenariat avec Microsoft, le choix s’orientera naturellement vers Silverlight, sinon l’usage de Flex semble être tout indiqué. Le second argument en faveur de la technologie Flex est qu’elle utilise le Flash Player, compatible avec toutes les plates-formes, pour exécuter l’application, alors qu’il faudra télécharger un plug-in propre à Microsoft, qui ne semble pas encore être officiellement compatible avec Linux. Silverlight et Linux Selon certaines sources, ce problème de compatibilité avec Linux devrait bientôt complètement disparaître. Enfin, pour utiliser Silverlight, il faut employer l’environnement de développement Visual Studio dont le prix avoisine les 1 000 €. Ce point peut éventuellement porter préjudice à Silverlight et avantager Flex. En effet, là où nous avons besoin d’un module applicatif, nous sommes obligés d’acquérir l’ensemble de l’environnement de développement. Mais les choses devraient sans doute évoluer au cours de l’année 2009. Ce produit est donc à suivre de très près. Bibliographie Silverlight 2 de Gérard Leblanc, éditions Eyrolles, 2008. Les limites de Flex Comme toute solution informatique, Flex a ses propres limites, parfois décriées par les développeurs Ajax ou Flash désireux de remettre en question jusqu’à l’utilité de ce framework. Nous allons donc essayer d’apporter quelques éléments de réponse afin d’éclaircir tout ceci. « L’exécution d’une application Flex nécessite la présence du Flash Player sur le poste client ! » Cette condition sine qua non peut en effet être un frein à l’utilisation des applications Flex. Néanmoins, le lecteur Flash assure une stabilité d’exécution des applications sur l’ensemble des machines à l’inverse d’Ajax dont le comportement peut différer d’un navigateur à un autre. Il s’agit donc d’un mal pour un bien. Sachant que la plupart des =Flex3 FM.book Page 11 Mardi, 2. décembre 2008 3:32 15 Pourquoi Flex ? CHAPITRE 1 machines sont équipées du Flash Player… est-ce une raison valable pour en dénigrer l’utilisation ? « Le framework Flex ne propose pas d’outils dédiés au graphisme ! » Comme nous l’avons évoqué précédemment, Flex est basé sur Flash, ce qui simplifie beaucoup la réalisation d’interfaces graphiques riches. Il n’est nullement question de créer des animations comme nous pourrions le faire avec Flash CS3 ! Pour pallier ce problème, Flex contient un composant, nommé SWFLoader, permettant d’importer des animations Flash. « Le Flash Player n’est pas compatible avec les processeurs 64 bits ! » En effet, à l’heure ou nous écrivons ces lignes, le Flash Player n’est pas supporté par les machines équipées d’un processeur 64 bits. Bien que cela concerne actuellement peu de machines, la solution préconisée par Adobe consiste à exécuter un navigateur 32 bits compatible avec les machines 64 bits pouvant alors afficher les applications Flash. « Dans une application Flash, il est impossible d’utiliser les boutons Précédent et Suivant du navigateur ! » Depuis la version 3 du framework, ceci est tout à fait possible grâce à la notion de deep linking. En effet, elle permet de naviguer à l’intérieur d’une application à l’aide des boutons Suivant et Précédent du navigateur, comme il est possible de le faire dans toute application web. Nous développerons cette fonctionnalité dans le chapitre 16. « Une application Flash est difficile à référencer dans les moteurs de recherche ! » Certains moteurs de recherche comme Google sont dorénavant capables d’analyser le contenu d’un fichier SWF. Le référencement d’une animation Flash est donc possible. Dans tous les cas, n’oublions pas qu’une application Flash est généralement contenue dans une page HTML. Ceci permet alors d’y stocker l’ensemble des informations de référencement même si, à l’heure où nous écrivons ces lignes, les informations indexées ne sont pas aussi pertinentes que celles d’un site HTML. Bien entendu, nous n’avons pas recensé l’ensemble des remarques soulevées par les « proAjax » ou « pro-Flash ». Il est important de retenir qu’Adobe met tout en œuvre pour pallier l’ensemble des problèmes qui pourraient mettre son produit en difficulté. Ceci nous amène donc à dire que le projet Flex 3 a atteint un degré de maturité non négligeable et qu’il s’agit d’une valeur sûre. Pourquoi choisir Flex ? Il ne s’agit pas de reprendre les arguments commerciaux édictés par Adobe mais de vous faire part de nos constatations suite à notre expérience de l’utilisation de ce framework à travers des projets de différentes natures. Si nous devions vous convaincre d’utiliser Flex plutôt qu’une autre technologie, voici ce que nous vous avancerions : 11 =Flex3 FM.book Page 12 Mardi, 2. décembre 2008 3:32 15 12 Comprendre Flex 3 PARTIE I • Flex apporte une valeur ajoutée indéniable au niveau commercial par la richesse des interfaces développées (ce qui est beau est vendeur). Pour vous en rendre compte, il vous suffit de visiter la page d’exemple du site d’Adobe : http://www.adobe.com/devnet /flex/?tab:samples=1. • Ce framework augmente la rapidité et la qualité de développement grâce à l’IDE Flex Builder. • Il s’adapte aux besoins en offrant la possibilité de créer ses propres composants. Nous nous pencherons sur ce point au chapitre 10. • Les applications se comportent de manière identique quelles que soient les plates-formes et les conditions d’utilisation. • Flex permet de réaliser des applications bureautiques riches (ou RDA, Rich Desktop Application) grâce à la machine virtuelle Adobe AIR (ce que nous verrons au chapitre 19). =Flex3 FM.book Page 13 Mardi, 2. décembre 2008 3:32 15 2 À la découverte du framework Flex 3 Dans ce chapitre – peut être l’un des plus importants de cet ouvrage – nous allons disposer les premières briques qui vont nous permettre de comprendre les fondements essentiels du framework Flex. Ces fondements sont la base de l’utilisation du framework car ils permettent d’en connaître le fonctionnement et les possibilités mais également les limites. Rôle du front end La notion de découpage d’une application en trois couches distinctes est bien connue des développeurs de nouvelles technologies (J2EE, PHP…). Néanmoins, si vous êtes néophyte en la matière et que cela ne vous évoque rien, ne vous inquiétez pas, nous allons tout de suite remédier à cela. Architecture n-tiers Une application peut être divisée en plusieurs couches ou tiers applicatifs, nous parlons alors d’une architecture n-tiers. Ainsi, si nous subdivisons une application en trois couches distinctes, nous obtenons une architecture 3-tiers : • La couche Présentation est chargée, comme son nom l’indique, de présenter les données (interface Homme-Machine ou IHM). • La couche Métier implémente la logique métier (règle de gestion, etc.). • La couche d’accès aux données réalise la tâche de persistance des données (stockage) via l’utilisation d’une base de données, par exemple. =Flex3 FM.book Page 14 Mardi, 2. décembre 2008 3:32 15 14 Comprendre Flex 3 PARTIE I Chaque couche propose des services qu’elle met à disposition de la couche qui lui est directement supérieure. Ainsi, la couche la plus élevée ne peut communiquer avec la couche la plus basse de l’architecture que par la couche intermédiaire, comme l’illustre la figure 2-1. Figure 2-1 Architecture 3-tiers Positionnement d’une application Flex Au cours du chapitre précédent, nous avons défini le rôle du framework Flex comme étant un outil de création d’interfaces clientes riches (RIA). De ce fait, le positionnement des applications réalisées à l’aide de ce framework dans une architecture de type 3-tiers, se fera naturellement au niveau de la couche Présentation (tiers 1). Ce positionnement en haut de l’architecture implique donc une notion que nous devrons toujours prendre en compte lors de la création d’une nouvelle application : une application réalisée à l’aide du framework Flex ne peut pas accéder directement aux informations contenues dans une base de données, comme c’est le cas pour les applications Java ou PHP. Par conséquent, si nous souhaitons développer une application utilisant des informations contenues dans une base de données, nous devrons implanter une couche Métier intermédiaire offrant un certain nombre de services écrits dans un langage serveur (PHP, Java, ColdFusion…). Ces services seront capables de se connecter à la base de données et d’y effectuer des requêtes pour ensuite renvoyer les résultats à notre application. L’appel de ces services à partir de l’application se fera via des composants spécifiques du framework Flex tels que les composants HTTPService ou RemoteObject (voir chapitre 13). =Flex3 FM.book Page 15 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 Dans cette section, nous avons donc vu un élément essentiel du framework Flex dont l’impact n’est pas négligeable si vous souhaitez créer des applications accédant à des données : la mise en place impérative d’une couche Métier écrite dans un langage serveur. Néanmoins, toutes les applications Flex n’utilisent pas forcément des données, c’est le cas par exemple d’une calculatrice ou d’un simulateur d’emprunt. Qui plus est, il nous est également possible de stocker des informations de façon temporaire au sein de notre application à l’aide d’un modèle de données qui, là encore, est bien connu des développeurs Java. L’application et le modèle-vue-contrôleur Maintenant que nous savons que le framework Flex n’a pour but que la création de la partie graphique d’une application, nous pouvons entrer dans le détail de la couche graphique en abordant la notion de modèle-vue-contrôleur (MVC). Cette couche peut elle aussi se découper en trois éléments : • Le modèle représente les données et les règles métiers via un ensemble de classes et de méthodes associées. Il permet également l’accès aux services décrits dans la couche Métier de l’architecture 3-tiers. Enfin, c’est lui qui se chargera de prévenir la vue d’un changement de données afin que celle-ci se mette à jour. • La vue va afficher les données du modèle et permettre l’interaction avec l’utilisateur, c’est l’interface homme-machine (IHM) de votre application. Notons, qu’il est tout à fait possible d’avoir plusieurs vues affichant les données d’un même modèle. • Le contrôleur, quant à lui, va jouer le rôle d’interface entre la ou les vues et le modèle. Il récupère les actions de l’utilisateur pour ensuite les rediriger vers le modèle sous forme d’événements et mettre à jour la vue appropriée. Si vous n’avez jamais été confronté à la notion de MVC, ce qui vient d’être énoncé doit vous paraître assez obscur. Pour vous aider à mieux comprendre cette notion, nous allons l’illustrer à l’aide d’un petit exemple. Considérons l’action sur un bouton permettant de lister l’ensemble des données contenues dans une table et de les afficher dans une grille de résultats (figure 2-2). 1. L’utilisateur clique sur le bouton Afficher les données. Cette action déclenche alors un événement que la vue se charge de faire suivre au contrôleur. 2. Le contrôleur approprié à cette action traite l’information reçue. Ce traitement consiste à choisir la vue appropriée et à lui fournir les informations dont elle a besoin en les choisissant à partir du modèle. 3. Le modèle fait appel au service de la couche Métier de l’architecture 3-tiers permettant d’exécuter la requête de sélection, et se met à jour en fonction des données reçues. Cette mise à jour peut être notifiée à la vue afin que cette dernière puisse être actualisée. 4. Le modèle indique au contrôleur que le traitement est terminé et envoie les données au contrôleur. 5. Le contrôleur met à jour la vue afin de présenter les données à l’utilisateur. 15 =Flex3 FM.book Page 16 Mardi, 2. décembre 2008 3:32 15 16 Comprendre Flex 3 PARTIE I Figure 2-2 Architecture MVC Le modèle MVC et la notion de design pattern Le modèle MVC est un design pattern (modèle de conception), ce qui signifie qu’il peut être appliqué dans tout type d’application et ne se limite donc pas aux applications Flex. Si nous transposons cette explication à l’utilisation du framework Flex, l’implémentation du modèle peut s’effectuer à l’aide du langage ActionScript, dont l’orientation objet, très poussée depuis la dernière version en date, permet de créer facilement des classes et des méthodes associées. Le contrôleur dont le rôle principal est l’interfaçage entre le modèle et la vue sera lui aussi développé à l’aide de ce langage et souvent mis en application grâce à la notion de DataBinding (voir chapitre 11). La vue sera quant à elle implémentée à l’aide du langage MXML prévu à cet effet ; celui-ci ayant pour fonction principale la description des interfaces graphiques. Balise MODEL Le langage MXML met à disposition la balise MODEL qui permet, comme son nom l’indique, de déclarer un modèle de données. Les langages ActionScript et MXML peuvent vous être totalement inconnus si vous n’êtes pas habitué à développer des applications Flash. Comme nous l’avons déjà évoqué, une application Flex est le résultat du mariage de ces deux langages où l’un permet de créer l’interface graphique et l’autre de mettre en place la logique applicative. C’est donc tout naturellement que nous allons poursuivre par la présentation de ces deux langages. =Flex3 FM.book Page 17 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 Le langage MXML Le MXML (Macromedia fleX Markup Language) est avant tout un langage de balises basé sur XML. Son rôle principal est de permettre l’agencement des composants au sein d’une interface graphique. Ainsi, chaque composant est défini par des balises spécifiques : • Un bouton est défini par les balises <mx:Button></mx:Button>. • Une zone de saisie est définie par les balises <mx:TextInput></mx:TextInput>. • Un panel servant de conteneur de composants est défini par les balises <mx:Panel> </mx:Panel>. Bien entendu, le langage MXML ne se limite pas uniquement à la mise en place de composants graphiques. Il permet également d’implémenter des composants capables de faire appel à des services web, par exemple les composants HTTPService (<mx:HTTPService/>) et WebService (<mx:WebServices/>). Dans la mesure où le framework Flex a pour rôle de créer la couche graphique d’une application, il est indispensable que toute application soit composée d’au moins un fichier portant l’extension .mxml et dont le contenu de base sera le suivant (cas d’une application exécutée dans le navigateur web) : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> </mx:Application> La balise mx:Application permet d’indiquer qu’il s’agit du fichier applicatif principal. La référence à l’espace de noms http://www.adobe.com/2006/mxml sert à définir l’ensemble des balises du langage. Cet espace de noms est préfixé par la valeur mx, ce qui est fort apprécié lors de l’utilisation de plusieurs espaces de noms au sein d’un même fichier MXML. En effet, le préfixe permet d’identifier l’espace de noms concerné et de faire appel aux balises associées, évitant ainsi toute confusion possible. De ce fait, les balises du langage MXML seront appelées comme suit : <mx:Button></mx:Button> Chaque balise MXML correspond à une classe ou à des propriétés de classes d’ActionScript. Lors de la phase de compilation du fichier applicatif principal, l’ensemble du fichier MXML est analysé et transformé en classes ActionScript, ces dernières étant compilées en code-octet (pour être exécutées par le Flash Player) et stockées dans un fichier au format SWF. Vous l’aurez compris, tout ce qui est effectué à l’aide du langage MXML pourrait être réalisé directement avec ActionScript. Multiplicité des espaces de noms dans le framework Flex Il est nécessaire de préfixer les espaces de noms afin d’éviter toute confusion quant à leur utilisation dans le code. La question que l’on est en droit de se poser est l’utilité d’en déclarer plusieurs au sein d’une même application Flex. Au chapitre 10, nous verrons que pour utiliser des composants personnalisés, nous aurons recours à plusieurs espaces de noms, chacun étant associé à un composant. 17 =Flex3 FM.book Page 18 Mardi, 2. décembre 2008 3:32 15 18 Comprendre Flex 3 PARTIE I Flex 4 Flex 4 n’est annoncé que pour la seconde partie de l’année 2009. Mais nous savons dores et déjà, que l’utilisation du MXML y sera quelque peu différente. En effet, le FXG, nouveau langage dédié à la réalisation du design des interfaces, laissera à MXML 2009 les fonctions que l’on pourrait qualifier de « fonctions métiers », à savoir la gestion d’appel du service web, de validation de données, etc. Nous aurons l’occasion de revenir sur ce point au chapitre 25. Le langage ActionScript L’ECMA (European Computer Manufacturers Association) est une organisation travaillant dans le domaine de la standardisation informatique, notamment des langages de scripts grâce au standard ECMAScript. Ce standard couvre, entre autres choses, les langages ActionScript et JavaScript. C’est la raison pour laquelle leurs syntaxes se ressemblent en bien des points. ActionScript est donc un langage standardisé (via le standard ECMA-262) dont l’usage est restreint aux applications Flash et donc à celles créées à l’aide du framework Flex. Ce langage est orienté objet et permet le développement de la partie dynamique de l’application ainsi que l’implémentation de la notion de modèle abordée précédemment. Afin que vous puissiez lire facilement les extraits de code ActionScript présents dans cet ouvrage, nous avons jugé bon de vous apporter les bases de ce langage en abordant des notions communes à tout apprentissage d’un nouveau langage : • les variables ; • les boucles et les conditions ; • les opérations booléennes ; • les procédures et les fonctions ; • la programmation objet. Version d’ActionScript Le framework Flex 3 utilise le langage ActionScript dans sa version 3. Les variables Les variables permettent de stocker des informations en vue de les utiliser dans divers traitements. Une variable est déclarée par un nom précédé de la mention var. Il est également indispensable de spécifier le type de la variable déclarée : var nomVariable:type =Flex3 FM.book Page 19 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 Le tableau 2-1 présente des exemples de déclaration de variables. Tableau 2-1 Déclaration de variables Code Description var maChaine:String Chaîne de caractères. var monNombre:Number Nombre décimal pouvant être positif ou négatif. var monEntier:int Nombre entier pouvant être positif ou négatif. var monBooleen:Boolean Booléen prenant pour valeur 0, 1, true ou false. var monTableau:Array = new Array("1","2","3") Tableau contenant trois éléments. Les boucles et les conditions Nous sommes souvent confrontés à la mise en place de boucles de traitement et à la vérification de conditions. Voyons comment les implémenter. Les boucles Le tableau 2-2 présente la transcription en langage ActionScript des principaux algorithmes de boucles. Ils permettent de réaliser un traitement selon un nombre d’itérations prédéfinies. Tableau 2-2 Les boucles Algorithme Transcription Pour i est un entier = 1 à i<10 Faire [Traitement] I = i +1 Fin pour For (i:int=1; i<10;i++) { [Traitement] } I est un entier = 1 Tant que I<10 faire I = i + 1 Fin tant que i:int = 1; while (i<10){ i++ } Les conditions Il existe deux types de conditions : la première consiste à vérifier si une situation est vraie, la seconde à exécuter un traitement selon un cas précis. Le tableau 2-3 présente leur implémentation. Vous pourriez très bien utiliser une suite de if, else… if et else à la place d’un switch, mais ce dernier vous apporte un plus non négligeable en matière de lisibilité du code. 19 =Flex3 FM.book Page 20 Mardi, 2. décembre 2008 3:32 15 20 Comprendre Flex 3 PARTIE I Tableau 2-3 Les conditions Algorithme Transcription X est un entier = 2 Si x est supérieur à 10 Alors [Traitement] Sinon [Traitement] Fin Si var x:int =2 if (x>10) { [Traitement] } else { [Traitement] } X est un entier = 10 Selon x Cas 10 : Cas 20 : Fin selon var x:int = 2 Switch (i) { Case 10 : [Traitement] Break; Case 20 : [Traitment] Break; } Pour pouvoir vérifier si une condition est vraie, nous avons besoin d’opérateurs de comparaison. Le tableau 2-4 en dresse la liste exhaustive : Tableau 2-4 Les opérateurs Expression Description X == Y X est égal à Y. X != Y X est différent de Y. X === Y X est strictement égal à Y. X !== Y X est strictement différent de Y. X > Y X est supérieur à Y. X < Y X est inférieur à Y. X >= Y X est supérieur ou égal à Y. X <= Y X est inférieur ou égal à Y. Les opérations booléennes Comment déclencher un traitement lorsque deux conditions sont vraies ou lorsque l’une des deux est vraie ? Le tableau 2-5 présente les opérateurs capables de réaliser ces opérations de vérification. =Flex3 FM.book Page 21 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 Tableau 2-5 Les opérations booléennnes Expression Description ! X X prend la valeur opposée. Ainsi, si X = vrai alors ! X = faux. X && Y X ET Y doivent être vérifiés (égaux à vrai) pour que le traitement puisse être effectué. X || Y X OU Y doit être vrai pour que le traitement soit effectué. Les procédures et les fonctions Les procédures et les fonctions sont déclarées par un nom, précédé de la mention function. Elles ont pour rôle d’exécuter un traitement susceptible d’être appelé plusieurs fois dans un script. Une fonction retourne un résultat dont le type est spécifié en fin de déclaration. A contrario, une procédure ne retourne rien, nous spécifierons donc void à la place d’un type de retour. Portée des procédures et des fonctions La portée des procédures et des fonctions doit obligatoirement être mentionnée : • private (privée) : la procédure ou la fonction ne peut être appelée que par la classe qui la contient. • protected (protégée) : la procédure ou la fonction ne peut être appelée que par la classe qui la contient ou par la classe héritant de cette classe. • public (publique) : la procédure ou la fonction peut être appelée par l’ensemble des procédures et fonctions du projet. • static (statique) : la procédure ou la fonction n’est créée qu’une seule fois par classe et non pas dans chaque objet instancié par la classe. On peut donc l’appeler sans instancier l’objet dans lequel elle est déclarée. Notons que ces portées peuvent également être appliquées aux variables. L’exemple de code suivant présente la déclaration d’une procédure dont la portée est publique et qui accepte un paramètre de type chaîne. public function enregistrerDonnees(donnees:string):void { [Traitement d’enregistrement] } Par la mention :String, on identifie qu’il s’agit d’une fonction renvoyant une chaîne de caractères. On constate également que la portée de la fonction est privée par la présence du terme private. private function afficherDonnee():String{ var laDonneeARenvoyer:String="info" Return laDonneeARenvoyer } 21 =Flex3 FM.book Page 22 Mardi, 2. décembre 2008 3:32 15 22 Comprendre Flex 3 PARTIE I La programmation objet Décrire l’ensemble des fonctionnalités d’ActionScript en termes de programmation objet prendrait une place trop importante au sein de cet ouvrage et n’y apporterait pas de réelle valeur. C’est par l’analyse de quelques lignes de code que nous vous proposons de découvrir comment implémenter une classe et ses méthodes. Package com.monpackage { import mx.containers.Canvas; public class MaClasse extends Canvas { // Attribut private var _nom:String // Constructeur de la classe public function MaClasse(parametre:String) { super(); _nom = parametre; } // Setter et Getter de l’attribut public function set nom(parametre:String):void{ _nom = parametre } public function get nom():String{ return _nom; } } } Analysons à présent ce code. La première ligne sert à définir le package dans lequel se situe la classe. La notion de package Le fait de séparer votre code en différents packages vous permettra par la suite de pouvoir le relire ou le modifier facilement. Il s’agit ni plus ni moins de le structurer en dossiers et sous-dossiers. Vient ensuite l’importation des classes nécessaires aux traitements décrits dans les méthodes ou à la notion d’héritage. En effet, le compilateur ne connaissant pas votre code, il vous faut lui indiquer explicitement quelles classes seront utilisées. On constate qu’une classe est déclarée par la mention class suivie du nom attribué à cette classe. La notion d’héritage est ici implémentée à l’aide du mot-clé extends. Dans notre cas, la classe MaClasse hérite de la classe Canvas. =Flex3 FM.book Page 23 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 Les attributs sont ensuite déclarés à la manière d’une variable dont le nom est précédé du caractère de soulignement (_). Il est ainsi possible d’écrire les méthodes d’accès à cet attribut comme suit : set nomattribut() et get nomattribut():type. La méthode set a pour fonction d’affecter une valeur à un attribut, laquelle peut ensuite être récupérée par l’emploi de la méthode get. Enfin, pour créer des objets à partir d’une classe, il est nécessaire d’instancier cette dernière. Pour cela, nous disposons d’un constructeur. Il s’agit d’une méthode portant le nom de la classe et qui sera automatiquement appelée au moment de l’instanciation de l’objet. À noter que le type de retour n’est pas précisé pour un constructeur. Nous venons de décrire les éléments de bases du langage ActionScript dont vous aurez besoin pour comprendre au mieux les différents extraits de code présentés dans cet ouvrage. Néanmoins, les subtilités de ce langage n’ayant pas été abordées, nous ne saurions que trop vous recommander l’acquisition d’un ouvrage spécialisé ou la pratique d’ActionScript. Nous vous conseillons également de consulter les sites web spécialisés tels que le site ActionScript.org (http://www.actionscript.org/), qui constitue une mine d’informations sur ce langage et propose des cours et tutoriaux en téléchargement. Intéressons nous à présent au mécanisme client/serveur d’une application Flex. Le mécanisme client/serveur Comme nous l’avons vu, une application Flex est composée d’un fichier MXML principal faisant appel à des fichiers ActionScript permettant d’intégrer la notion d’architecture MVC. L’ensemble de ces fichiers est ensuite compilé, donnant naissance à un fichier SWF pouvant être intégré dans une page HTML. Ceci n’est qu’une petite partie du processus. Nous allons à présent rassembler l’ensemble des informations véhiculées tout au long de ce chapitre afin d’observer le mécanisme complet d’une application Flex. Tout d’abord, nous avons vu qu’il est possible d’architecturer une application en trois couches distinctes, chacune d’entre elles pouvant être hébergée (sous sa forme extrême) sur trois serveurs différents : • le serveur de base de données (couche Accès aux données) ; • le serveur d’application (couche Métier) ; • le serveur Flex (couche Présentation contenant le fichier SWF et la page web associée). Imaginons à présent un utilisateur souhaitant utiliser l’application Flex située à l’adresse http://www.monapplicationflex.com et pointant bien évidemment sur le serveur de présentation qui sera le point d’entrée du processus (figure 2-6). La première phase va consister à offrir l’application au client connecté (figure 2-6, ➊ et ➋). Nous entendons par « offrir » le fait que l’application sera téléchargée et exécutée sur le poste client, ce qui nécessite par conséquent que Flash Player soit installé sur celui-ci. 23 =Flex3 FM.book Page 24 Mardi, 2. décembre 2008 3:32 15 24 Comprendre Flex 3 PARTIE I Attention Le fait qu’une application soit exécutée sur le poste client induit un paramétrage consciencieux de cette dernière. Lors du développement de l’application, nous devons faire appel aux services situés sur des serveurs présents sur notre réseau local. Lorsque l’application est mise en ligne, n’oubliez pas que ces serveurs ne sont plus accessibles via l’adresse IP locale mais à l’aide de leur adresse publique ! Les schémas des figures 2-3, 2-4 et 2-5 illustrent ce principe. Figure 2-3 Accès aux services dans un environnement de développement Sur ce schéma, nous pouvons accéder facilement aux services présents sur le serveur puisqu’il fait partie de notre réseau local. Figure 2-4 Paramétrage incorrecte de l’application : recherche des services sur le réseau local du client Si le changement d’adresse IP du serveur contenant les services n’est pas effectué lors du déploiement, ces derniers ne seront plus accessibles par le poste client. Figure 2-5 Paramétrage correcte de l’application : recherche des services via l’adresse IP Wan du serveur Pour résoudre ce problème, nous vous conseillons de définir l’ensemble des paramétrages dans un fichier XML qui sera lu lors de l’initialisation de l’application sur le poste client. L’usage de ce type de fichier exclut de ce fait une recompilation de l’application pour chaque modification de paramétrage. =Flex3 FM.book Page 25 Mardi, 2. décembre 2008 3:32 15 À la découverte du framework Flex 3 CHAPITRE 2 L’application présente sur le serveur permettant de lister les produits d’un magasin, la deuxième étape va consister à faire appel à une suite de services permettant d’obtenir le résultat attendu (ici, la liste des produits). Lorsque l’utilisateur cliquera sur le bouton Mise à jour situé sur l’interface graphique, cela déclenchera un événement qui sera transmis au contrôleur (figure 2-6, ➌), lequel ira chercher le modèle concerné par cet événement (➍). Le modèle va ensuite faire appel au service approprié situé sur le serveur d’application (➎). Ce service va alors exécuter une requête sur le serveur de base de données (➏), s’en suivra une succession de réponses de la part des différents serveurs concernés (➐ et ➑). La dernière étape consistera ensuite à mettre à jour la couche de présentation via l’interaction du modèle avec le contrôleur (➒ et ➓). Figure 2-6 Mécanisme client/serveur En résumé Dans ce chapitre, nous avons voulu poser les premières pierres de l’édifice en vous apportant les connaissances de base sur le rôle et l’utilisation du framework Flex. Les points essentiels à retenir sont les suivants : • Flex ne concerne que la partie graphique d’une application (front end). • Une application Flex est composée de fichiers aux formats MXML et ActionScript. Le langage MXML sert au développement de l’interface graphique et chacune de ses balises correspond à une classe ou une propriété du langage ActionScript. Tout ce qui est réalisé à l’aide du langage MXML peut également l’être réalisé à l’aide d’ActionScript. 25 =Flex3 FM.book Page 26 Mardi, 2. décembre 2008 3:32 15 26 Comprendre Flex 3 PARTIE I • La partie graphique peut être implémentée selon l’architecture MVC, largement répandue dans la plupart des grosses applications et ce, à l’aide de la combinaison des langages ActionScript (modèle et contrôleur) et MXML (vues). Flex ne peut interagir directement avec une source de données, mais uniquement en faisant appel à des services externes ayant cette capacité. • Une application Flex est téléchargée et exécutée sur le poste client, ce qui nécessite un paramétrage assidu de l’application lorsque celle-ci fait appel à des services. Ce chapitre nous a permis de délimiter le périmètre d’action du framework Flex. À ce stade, vous pouvez légitimement vous interroger sur l’utilité de développer vos interfaces en Flex alors que le langage HTML sait très bien le faire. À cette interrogation, nous pouvons répondre que Flex étant basé sur la technologie Flash, dont la réputation en termes d’animation n’est plus à faire, la richesse des IHM en termes de design et de fonctionnalité s’en trouve accrue, ce qui augmente le pouvoir de séduction de vos applications et par conséquent leur rentabilité ! Il ne nous reste plus qu’à nous mettre au travail et à poursuivre par l’étude du SDK du framework Flex. =Flex3 FM.book Page 27 Mardi, 2. décembre 2008 3:32 15 3 Développer avec le kit Flex SDK Un peu à la manière de Java et son SDK (Software Development Kit), le kit de développement Flex SDK offre un ensemble de fonctionnalités permettant de réaliser gratuitement des applications à l’aide du framework Flex. Ce kit comprend des compilateurs, un débogueur ainsi que les bibliothèques de composants du framework permettant de créer des applications. Depuis la version 3 de Flex, la volonté d’Adobe est de rendre le SDK disponible sous licence MPL (Mozilla Public License). Selon l’éditeur, le passage à l’Open Source permettra une augmentation de l’utilisation de son produit. En effet, le SDK pourra être intégré au sein de divers IDE (Integrated Development Environment) et les entreprises à philosophie Open Source pourront opter pour l’utilisation de Flex. Enfin, comme chacun le sait, les produits libres sont souvent supportés par une communauté active, ce qui permet de les faire évoluer et d’offrir un support très réactif. Ceci assure ainsi à Flex une place prédominante par rapport à ses concurrents, notamment le géant Microsoft et son produit SilverLight, dont le choix stratégique viserait à imiter Adobe. Licence MPL Contrairement à la licence GPL (General Public License), qui oblige à fournir les sources de l’ensemble d’un programme, la MPL permet de ne pas divulguer certaines parties du programme. Ainsi, l’entreprise éditrice peut ne communiquer que certaines parties du code de son logiciel et garder secrètes les parties qu’elle juge sensibles. =Flex3 FM.book Page 28 Mardi, 2. décembre 2008 3:32 15 28 Comprendre Flex 3 PARTIE I Prérequis Avant d’aller plus loin, il convient de vérifier la présence des éléments indispensables au bon fonctionnement du SDK. Du point de vue matériel, vous devez disposer au minimum de 512 Mo de RAM et de 200 Mo d’espace disque. Pour l’aspect logiciel, il est impératif que Java soit installé et correctement configuré sur votre machine, bien que le Runtime de Java (JRE, Java Runtime Environment) suffise pour exécuter Flex SDK. JRE et JDK (Java Developpement Kit) Il peut être intéressant d’installer le Java Developpement Kit (JDK) si vous souhaitez par la suite développer vos propres applications Java. Sur ce point, nous verrons au chapitre 14 que Flex est capable d’interagir avec les applications développées dans ce langage. De plus, vous en aurez besoin pour mener à bien les exemples mentionnés dans ce chapitre. Étant donné que le JRE est contenu dans le JDK, pourquoi s’en priver ? Dans cet ouvrage, nous utiliserons la version 6 du JDK (Java SE6), qui peut être téléchargée sur le site web de Sun Microsystems à l’adresse suivante : http://java.sun.com/ (rubrique Downloads>Java SE). Une fois l’archive téléchargée, procédez à son installation en suivant les indications de l’assistant. Vous pouvez éventuellement configurer la variable d’environnement PATH de votre système en y ajoutant le chemin du répertoire bin de Java. Ceci vous permettra d’appeler les programmes Java (java.exe, javac.exe, etc.) à partir de n’importe quel répertoire de votre système. Important Les instructions d’installation de logiciel ou de configuration d’environnement présentées dans cet ouvrage sont essentiellement orientées vers le système d’exploitation Windows, car il s’agit de l’environnement le plus utilisé. Voici la marche à suivre pour modifier la variable PATH : 1. Cliquez sur Démarrer et sélectionnez Panneau de configuration>Système. 2. Dans la fenêtre qui apparaît alors à l’écran, cliquez sur l’onglet Avancé puis sur le bouton Variables d’environnement. 3. Dans la zone Variables système, sélectionnez la variable PATH et cliquez sur le bouton Modifier. 4. À la suite des valeurs déjà présentes, ajoutez le chemin du répertoire bin de Java (par défaut, C:\Program Files\Java\jdk1.6.0_<version>\bin) précédé d’un point-virgule. 5. Validez la saisie et fermer l’ensemble des fenêtres précédemment ouvertes. =Flex3 FM.book Page 29 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 L’installation du JDK de Java est à présent terminée. Pour vérifier la bonne configuration de votre système, ouvrez l’invite de commandes MS-DOS et saisissez l’instruction suivante : java –version Le résultat obtenu doit être semblable à celui de la figure 3-1. Figure 3-1 Vérification de la bonne configuration de Java Vous aurez également besoin du Flash Player 9 d’Adobe, grâce auquel vous pourrez exécuter les applications Flex. Son installation s’effectue en ligne à partir du site web d’Adobe : http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=Shockwave Flash. Vous disposez à présent de tous les outils nécessaires pour utiliser le kit Flex SDK correctement. Passons maintenant à son installation. Mise en garde quant au choix du Flash Player Comme nous l’avons vu au chapitre précédent, la version actuelle du Flash Player est la version 10. Cependant, il se peut que vous possédiez encore la version 9. Mettre à jour le Flash Player alors que vous avez déjà installé l’environnement de développement peut engendrer des disfonctionnements du Flex Builder, notamment pour la fonctionnalité de débogage. Afin de réaliser l’ensemble des cas pratiques de cet ouvrage dans les meilleurs conditions, nous vous conseillons de choisir l’une ou l’autre version et de ne pas procéder encore à la mise à jour. Si pour une raison ou une autre, votre Flash Player est mis à jour pour la version 10, reportez-vous au chapitre 25, où nous expliquerons comment adapter votre projet à la version 10. Enfin, nous attirons votre attention sur le fait que la version 10 du Flash Player étant récente, nous n’avons pas pu tester dessus l’ensemble des fonctionnalités de Flex 3. Par prudence, nous vous conseillons d’installer la version 9 (http://www.adobe.com/support/flashplayer/downloads.html), dans le cas où vous auriez déjà effectué la mise à jour de votre système. Installation du kit Flex SDK Pour commencer, téléchargez le kit Flex SDK sur le site d’Adobe à l’adresse suivante : http://www.adobe.com/products/flex/flexdownloads/. Une fois le téléchargement terminé, décompressez l’archive obtenue dans un répertoire de votre choix. Nous avons ici choisi le répertoire C:\flex_sdk que nous nommerons 29 =Flex3 FM.book Page 30 Mardi, 2. décembre 2008 3:32 15 30 Comprendre Flex 3 PARTIE I root_flexsdk par convention. Le répertoire root_flexsdk contient désormais les dossiers présentés et décrits dans le tableau 3-1. Tableau 3-1 Les différents dossiers du répertoire root_flexsdk Nom du dossier Description ant Contient un ensemble de tâches Ant permettant d’automatiser certaines opérations lors des phases de compilation et de déploiement. asdoc Contient l’ensemble de la documentation de l’outil ASDoc permettant de créer la documentation de votre application sous forme de pages HTML. bin Contient un ensemble d’exécutables, tels que mxmlc.exe, compc.exe (voir sections suivantes) ou encore asdoc.exe. frameworks Contient l’ensemble des classes, des fichiers de configuration et du code source du framework. lib Contient l’ensemble des bibliothèques Java du framework. runtimes Contient les exécutables permettant d’installer l’environnement Adobe AIR et le module de débogage de Flash Player 10. samples Contient des exemples d’applications. templates Contient des templates de pages HTML contenant l’application Flex. Ceux-ci contiennent notamment la fonctionnalité de détection du Flash Player. Ainsi, si vous utilisez un template proposant cette fonctionnalité et que l’utilisateur ne possède pas le Flash Player, son téléchargement sera automatiquement proposé. L’installation est à présent terminée et le Flex SDK est opérationnel. Voyons à présent le cœur du SDK, dont les compilateurs sont les principaux éléments. Les compilateurs Comme nous l’avons vu au chapitre précédent, une application Flex est composée de fichiers MXML et ActionScript. Ces fichiers sont ensuite compilés, donnant naissance à un fichier SWF. Flex distingue deux types de compilations qui dépendent chacune d’un compilateur spécifique : la compilation d’application et la compilation de composants. mxmlc : le compilateur d’application Le rôle principal du compilateur mxmlc est de créer un fichier de type SWF (Shockwave Flash) à partir des fichiers ActionScript et MXML d’une application Flex (figure 3-2). Ce compilateur s’exécute en ligne de commande à l’aide de l’exécutable mxmlc.exe situé dans le dossier bin du répertoire root_flexsdk. =Flex3 FM.book Page 31 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Figure 3-2 Mécanisme de compilation mxmlc La syntaxe générale d’exécution de la compilation est la suivante : mxmlc options fichier où mxmlc fait appel au compilateur mxmlc.exe, options spécifie les options de compilation (date de création, nom du fichier SWF généré…) et fichier indique le fichier MXML à compiler. Le fichier MXML principal de l’application est spécifié en omettant les fichiers ActionScript associés à celle-ci. Cependant, les fichiers ActionScript liés à l’application ne sont pas oubliés lors de la compilation grâce aux liens spécifiés dans le fichier MXML principal. Il est également important de noter que ce compilateur ne génère pas la page HTML chargée de contenir le SWF créé. Elle devra être créée manuellement. compc : le compilateur de composants Flex offre la possibilité de créer des composants afin de les réutiliser dans plusieurs applications différentes. Un composant peut être assimilé à une application Flex dans la mesure où il est également composé d’un fichier MXML et de fichiers ActionScript. La compilation de ces composants est réalisée à l’aide du compilateur compc dont la syntaxe est décrite par l’exemple suivant : compc -o composant.swc -root fichierMXML.mxml où l’option –o permet de spécifier le nom du composant compilé et l’option –root indique le nom du fichier MXML utilisé pour la compilation du composant. Cette simple ligne de code permet de générer un composant (composant.swc) à partir d’un fichier MXML. 31 =Flex3 FM.book Page 32 Mardi, 2. décembre 2008 3:32 15 32 Comprendre Flex 3 PARTIE I Le fonctionnement du compilateur compc est identique à celui du compilateur mxmlc à la seule différence qu’il génère un fichier de type SWC (Shockwave Component) et non SWF (figure 3-3). Figure 3-3 Mécanisme de compilation compc Si nous récapitulons, voici ce que nous avons appris jusqu’à présent : • Comment configurer un environnement pour exécuter le kit de développement Flex SDK et les applications Flex. • Comment installer le kit Flex SDK. • Quelques connaissances de base sur les différents compilateurs. Cela peut paraître léger, mais nous allons voir qu’avec ces trois éléments seulement, nous sommes en mesure de créer notre première application Flex. Première application Flex Nous vous proposons ici de développer le fameux programme cher à tout informaticien et informaticienne, à savoir l’incontournable Hello World ! dont le but est d’afficher un message de bienvenue à l’écran. Conception graphique Nombreux sont les projets prenant naissance à partir d’un dessin griffonné sur un coin de table. Notre projet n’a pas échappé à cette règle comme l’illustre la figure 3-4. =Flex3 FM.book Page 33 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Figure 3-4 Conception graphique Le principe de cette application est simple : un composant, nommé Panel contient un bouton qui, lorsqu’on clique dessus, affiche le message « Hello World ! ». Création du projet Au cours du chapitre précédent, nous avons abordé la notion d’arborescence des projets Flex et nous avons vu que tout projet doit posséder un répertoire racine contenant un sous-répertoire src dans lequel seront enregistrées les sources de l’application. Le kit Flex SDK propose différents exemples d’applications situés dans le dossier samples. C’est dans ce dossier que nous allons placer la racine de notre projet, que l’on nommera HelloWorld. Dans la mesure où il s’agit du fichier racine de l’application, ce répertoire contiendra un sous-répertoire nommé src (figure 3-5). Figure 3-5 Arborescence du projet Écriture du fichier MXML Tout projet Flex comporte un fichier portant l’extension .mxml servant de base à l’application et permettant, entre autres choses, la description des interfaces graphiques. Mais il ne suffit pas de créer des composants, il faut également définir leurs caractéristiques (nom, hauteur, largeur...) et leur positionnement. Les tableaux 3-2 et 3-3 présentent les différentes caractéristiques des composants Panel et Button que nous allons créer. 33 =Flex3 FM.book Page 34 Mardi, 2. décembre 2008 3:32 15 34 Comprendre Flex 3 PARTIE I Tableau 3-2 Les différentes caractéristiques du composant Panel Caractéristique Description Rôle Conteneur principal de l’application Nom pn_principal Titre (title) Hello World ! Largeur (width) 270 pixels Hauteur (height) 150 pixels Position sur l’axe des X 10 pixels Position sur l’axe des Y 10 pixels Disposition (layout) absolute (permet le positionnement des composants à l’aide de leurs coordonnées x et y). Tableau 3-3 Les différentes caractéristiques du composant Button Caractéristique Description Rôle Bouton déclenchant l’affichage du message. Nom btn_message Label Hello !! Largeur (width) 120 pixels horizontalCenter 0 (centre le bouton à l’intérieur du panel sur l’axe horizontal de celui-ci). verticalCenter 0 (centre le bouton à l’intérieur du panel sur l’axe vertical de celui-ci). Figure 3-6 Mise en place des composants =Flex3 FM.book Page 35 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Nous allons à présent nous placer dans le répertoire src et créer un nouveau fichier nommé HelloWorld.mxml, dans lequel nous saisirons le code suivant à l’aide du Bloc-notes de Windows : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Ajout du panneau --> <mx:Panel id="panneau" x="10" y="10" width="270" height="150" layout="absolute" ➥title="Hello World !!"> <!-- Ajout du bouton --> <mx:Button id="bouton_action" label="Hello !!" width="120" horizontalCenter="0" ➥verticalCenter="0"/> </mx:Panel> </mx:Application> Les caractéristiques décrites aux tableaux 3-2 et 3-3 sont bien spécifiées pour chacun des composants. Notre interface graphique est à présent terminée. Passons maintenant à la partie ActionScript qui permettra d’afficher le message « Hello World !! ». Écriture du fichier ActionScript Tout d’abord, créez un nouveau fichier nommé HelloActionScript.as dans le répertoire src de l’application qui va contenir la procédure permettant d’afficher le message. Saisissez ensuite le code suivant dans ce fichier : import mx.controls.Alert; public function afficherMessage():void { Alert.show("Hello World !!"); } Nous importons tout d’abord la bibliothèque nécessaire à l’utilisation de la classe Alert. Vient ensuite la création de la procédure afficherMessage() de type void étant donné qu’aucune valeur de retour n’est attendue. Cette procédure fait appel à la méthode show de la classe Alert dont l’analyse syntaxique du code suffit à sa compréhension. Liaison graphique et action Nous possédons à présent un fichier MXML servant à la description de l’interface graphique et un fichier ActionScript permettant d’afficher le message « Hello World !! ». L’étape suivante va consister à créer la liaison entre ces deux fichiers et à définir l’action qui fera appel à la fonction afficherMessage(). Cette liaison s’effectue dans le fichier MXML à l’aide de la balise <mx:Script> pour laquelle il suffit de spécifier la source du script à utiliser, c’est-à-dire le chemin relatif du fichier ActionScript : <mx:Script source="HelloActionScript.as"></mx:Script> 35 =Flex3 FM.book Page 36 Mardi, 2. décembre 2008 3:32 15 36 Comprendre Flex 3 PARTIE I Lors de la phase de conception graphique, nous avons décidé que le message doit s’afficher lorsque l’utilisateur clique sur l’unique bouton de l’interface. Cela se fera via la définition de l’action sur click du bouton faisant appel à la fonction afficherMessage(). <mx:Button id="bouton_action" label="Hello !!" width="120" horizontalCenter="0" ➥verticalCenter="0" click="afficherMessage()"/> Pour plus de clarté, voici le script complet du fichier HelloWorld.mxml : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script source="HelloActionScript.as"></mx:Script> <mx:Panel id="panneau" x="10" y="10" width="270" height="150" layout="absolute" ➥title="Hello World !!"> <mx:Button id="bouton_action" label="Hello !!" width="120" horizontalCenter="0" ➥verticalCenter="0" click="afficherMessage()"/> </mx:Panel> </mx:Application> Compilation Il nous faut à présent compiler notre application, ce qui aura pour effet de créer un fichier SWF pouvant être inséré dans une page HTML et diffusé sur Internet. Pour cela, ouvrez, l’invite de commandes MSDOS et placez-vous dans le répertoire root_flexsdk\bin avec la commande cd root_flexsdk\bin. Étant donné qu’il s’agit d’une application, il convient d’utiliser le compilateur mxmlc. Voici donc la commande à saisir pour générer le fichier SWF de notre application : mxmlc ../samples/HelloWorld/src/Helloworld.mxml Placez-vous ensuite dans le répertoire src du projet, vous devriez à présent y trouver le fichier HelloWorld.swf issu de la compilation. Que s’est-il passé ? Le compilateur mxmlc a analysé le fichier .mxml de l’application et a constaté qu’il possédait un lien vers un fichier ActionScript. Il a donc pris en compte ce fichier et a transformé le fichier MXML en un ensemble de classes ActionScript pour ensuite les intégrer dans un fichier de type SWF. À ce stade, nous pouvons déjà tester notre application à l’aide du Flash Player. En cliquant sur le bouton, vous devriez en effet voir apparaître le message « Hello World !! » (figures 3-7 et 3-8). =Flex3 FM.book Page 37 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Figure 3-7 Exécution de l’application dans le Flash Player 9 Figure 3-8 Affichage du message « Hello World !! » 37 =Flex3 FM.book Page 38 Mardi, 2. décembre 2008 3:32 15 38 Comprendre Flex 3 PARTIE I Nous disposons maintenant d’un fichier SWF complet et autonome. Nous entendons par là que ce fichier n’a pas besoin des fichiers sources (MXML et ActionScript) pour son exécution car ceux-ci ont été compilés et intégrés au fichier SWF. L’étape suivante va consister à intégrer ce fichier dans une page web afin de diffuser notre application sur Internet. Intégration dans une page web Pour intégrer notre application dans une page web, que nous nommerons index.html, nous allons utiliser le langage HTML et ses balises <object> qui nous permettront de faire référence au fichier SWF. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/1998/ ➥REC-html40-19980424/strict.dtd"> <html> <head> <title>Hello World !</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <p> <object type="application/x-shockwave-flash" data="HelloWorld.swf" ➥width="100%" height="100%"> <param name="movie" value="HelloWorld.swf"> </object> </p> </body> </html> Cette insertion est des plus simples. Notez l’utilisation des propriétés width et height permettant de spécifier la taille de l’objet SWF par rapport à celle de la page HTML. Dans notre cas, l’application prendra la taille de la page HTML affichée dans le navigateur (figure 3-9). Nous verrons dans la section « Création d’un script de compilation » qu’il est possible de définir plusieurs options pour l’inclusion du fichier SWF, notamment la détection de la présence du Flash Player sur le poste client, nécessaire à l’exécution de l’application (cette fonctionnalité n’est pas implémentée ici). =Flex3 FM.book Page 39 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Figure 3-9 Application insérée dans une page HTML Déploiement Si vous possédez un serveur web, il vous suffit de placer les fichiers HelloWorld.swf et index.html dans l’un de ses répertoires, cela terminant par ailleurs la phase de déploiement. Libre à vous ensuite de communiquer l’URL de votre application à l’ensemble de vos contacts. Dans la mesure où celle-ci ne permet pas de détecter la présence du Flash Player sur le poste client, n’oubliez pas de mentionner qu’il est nécessaire et doit être installé pour pouvoir exécuter votre application. Automatisation de la compilation à l’aide de Ant Nous verrons au chapitre suivant que l’utilisation de Flex Builder facilite grandement le déploiement d’une application Flex. Néanmoins, en fonction de votre budget, vous préférerez peut-être le kit Flex SDK. Vous devrez alors procéder à une compilation manuelle, mais cette tâche est particulièrement fastidieuse (notamment lors des phases de test). Nous vous proposons donc de voir comment automatiser les tâches de compilation à l’aide de Ant, outil développé par la Apache Software Foundation et communément utilisé dans le déploiement des applications Java. 39 =Flex3 FM.book Page 40 Mardi, 2. décembre 2008 3:32 15 40 Comprendre Flex 3 PARTIE I Ant Projet de la Apache Software Foundation, Ant, signifie Another Neat Tool. Il est écrit en Java et a été développé par James Duncan Davidson en 2000. Ant permet d’automatiser la compilation et le déploiement des projets. Il repose sur l’exécution de scripts de « build » au format XML comportant un projet et un ensemble de tâches, organisées ou non, qui y sont liées. Ant et Flex Lors de l’analyse du répertoire principal de Flex, nous avons noté la présence d’un dossier nommé ant. Ce répertoire contient la bibliothèque nécessaire à Ant pour pouvoir compiler et déployer des projets Flex. Cette bibliothèque est nommée flexTasks.jar et se trouve dans le répertoire lib du dossier ant. Elle contient trois tâches Ant qui permettent d’utiliser : • le compilateur mxmlc ; • le compilateur compc ; • la tâche html-wrapper permettant de générer la page HTML intégrant le fichier .swf créé lors de la compilation. Voyons comment utiliser le couple Ant/flexTasks pour automatiser la compilation et le déploiement d’une application Flex. Installation de Ant Commencez par télécharger Ant à partir de l’adresse suivante : http://ant.apache.org. Décompressez ensuite l’archive obtenue dans le répertoire de votre choix et configurez votre système d’exploitation comme suit : 1. Créez une variable d’environnement nommée ANT_HOME pointant sur le répertoire ant (par exemple, c:\ant). 2. Modifiez la variable PATH en ajoutant le chemin du répertoire bin comme suit : %ANT_HOME%\bin 3. Ouvrez ensuite l’invite de commandes MS-DOS et tapez la commande ant. Si l’environnement est correctement configuré, vous devriez voir apparaître ceci : Buildfile: build.mxml does not exist ! BuildFailed Passons maintenant aux choses sérieuses ! Création d’un script de compilation Avant tout, récapitulons : nous disposons d’un fichier MXML nommé HelloWorld.mxl situé dans le répertoire root_flexsdk\samples\HelloWorld\src, ainsi que d’un fichier ActionScript =Flex3 FM.book Page 41 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 nommé HelloActionScript.as. Notre objectif est de compiler et d’intégrer automatiquement le fichier SWF issu de la compilation dans une page HTML. Voyons comment procéder. Nous avons choisi de placer les scripts de compilation Ant dans le répertoire root_flexsdk \ant. Comme nous l’avons vu, un script de compilation est un fichier XML contenant une suite de tâches. La première étape va donc consister à créer ce fichier XML, que l’on nommera HelloWorld.xml. Nous devrons ensuite spécifier le projet Ant en lui affectant un nom. <?xml version="1.0" encoding="utf-8"?> <project name="Compilateur HelloWorld"> </project> Une fois cela fait, nous devrons préciser le chemin du fichier flexTasks.jar. Si vous avez choisi de placer le fichier de compilation dans le répertoire ant du Flex SDK, le fichier attendu se situe dans le répertoire suivant root_flexsdk\ant\lib : <taskdef resource="flexTasks.tasks" classpath="c:/root_flexsdk/ant/lib/flexTasks.jar" /> Vous devrez ensuite paramétrer les variables qui seront utilisées lors de la compilation : • FLEX_HOME : répertoire d’installation du kit Flex SDK (root_flexsdk) ; • APPLICATION_HOME : répertoire du fichier à compiler (root_flexsdk/samples/HelloWorld/ src). <property name="FLEX_HOME" value="c:/root_flexsdk"/> <property name="APPLICATION_HOME" value="c:/root_flexsdk/samples/HelloWorld/src"/> Vient ensuite la spécification de la tâche à réaliser. Une tâche (<target>) est définie par un nom qui sera invoqué lors de l’utilisation de Ant. <target name="compilation"> </target> Chaque tâche doit comporter un certain nombre d’instructions. La première que nous allons écrire est l’action de création du fichier SWF. Comme nous l’avons vu précédemment, pour compiler un fichier ActionScript ou MXML relatif à une application, nous devons utiliser le compilateur mxmlc : <echo message=">> Génération du fichier SWF" /> <mxmlc file="${APPLICATION_HOME}/HelloWorld.mxml"></mxmlc> Ce script a pour résultat d’afficher un message « Génération du fichier SWF » et de réaliser la compilation de l’application en prenant les fichiers MXML et ActionScript situés dans le répertoire source spécifié dans la variable ${APPLICATION_HOME}. 41 =Flex3 FM.book Page 42 Mardi, 2. décembre 2008 3:32 15 42 Comprendre Flex 3 PARTIE I Avant d’aller plus loin, testons notre script. Vérifiez d’abord que son contenu est indique à cela : <?xml version="1.0" encoding="utf-8"?> <project name="My App Builder"> <taskdef resource="flexTasks.tasks" classpath="c:/root_flexsdk/ant/lib/flexTasks ➥.jar" /> <property name="FLEX_HOME" value="c:/root_flexsdk"/> <property name="APPLICATION_HOME" value="c:/root_flexsdk/samples/HelloWorld/src"/> <target name="compilation"> <echo message=">> Génération du fichier SWF" /> <mxmlc file="${APPLICATION_HOME}/HelloWorld.mxml"></mxmlc> </target> </project> Ensuite, ouvrez l’invite de commandes MS-DOS et placez-vous dans le répertoire contenant le fichier de build que nous venons de créer : cd c:\root_flexsdk\ant Pour exécuter le script, saisissez la commande suivante, faisant appel à la tâche de compilation : ant -buildfile HelloWorld.xml compilation Si tout s’est correctement déroulé lors de la compilation, le fichier SWF est créé dans le répertoire de l’application Flex, root_flexsdk/samples/HelloWorld/src. Passons maintenant à l’instruction qui permet de générer le fichier HTML contenant le fichier SWF. Cette action est possible grâce à la tâche html-wrapper qui fournit plusieurs templates de génération. Le tableau 3-4 présente les différents arguments de la tâche html-wrapper. Tableau 3-4 Les arguments de la tâche html-wrapper Arguments Description application Nom de l’application SWF. bgcolor Couleur d’arrière-plan de la page HTML (blanc par défaut). height Hauteur de l’application SWF (400 pixels par défaut). width Largeur de l’application SWF (400 pixels par défaut). output Chemin de génération de la page HTML. swf Nom du fichier SWF à inclure (ne pas spécifier l’extension .swf du fichier). =Flex3 FM.book Page 43 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 Tableau 3-4 Les arguments de la tâche html-wrapper (suite) Arguments Description template Trois types de templates sont disponibles : • client-side-detection : détecte la version du Flash Player installée sur le poste client et propose son téléchargement le cas échéant. • express-installation : détecte si Flash Player est présent et propose son installation en mode Express s’il n’est pas installé. • no-player-detection : ne vérifie pas la présence du Flash Player. history Permet d’utiliser la fonction de DeepLinking, c’est-à-dire la navigation à l’aide des boutons Précédent et Suivant du navigateur ( false par défaut). title Titre de la page HTML ( Flex application par défaut). version-major Indique la version majeure du Flash Player à utiliser (version 9 par défaut). Cet argument n’a de sens que si le type de template spécifié est client-side-detection ou express-installation. version-minor Indique la version mineure du Flash Player à utiliser (version 0 par défaut). Cet argument n’a de sens que si le type de template spécifié est client-side-detection ou express-installation. version-revision Indique la version de mise à jour du Flash Player à utiliser (version 0 par défaut). Cet argument n’a de sens que si le type de template spécifié est client-side-detection ou express-installation. Ajoutons donc une nouvelle action de génération de fichier HTML : <target name="generationHTML" depends="compilation"> <echo message=">> Génération du fichier HTML" /> <html-wrapper swf = "HelloWorld" height = "100%" width = "100%" application = "HelloWorld" template = "express-installation" version-major = "9" version-minor = "0" version-revision = "0" output="${APPLICATION_HOME}" title = "Hello World !!"/> </target> Avant d’exécuter ce script, attardons-nous sur la notion de dépendance entre les différentes tâches dans un fichier de compilation de Ant. En analysant l’exemple de code précédent, nous voyons que le terme depends a été ajouté à la tâche generationHTML. Cela signifie qu’elle ne pourra être exécutée que si la tâche compilation l’a été au préalable. 43 =Flex3 FM.book Page 44 Mardi, 2. décembre 2008 3:32 15 44 Comprendre Flex 3 PARTIE I Ajoutons également la propriété default au projet, qui permet de spécifier la première tâche à réaliser lors de la compilation. <project name="My App Builder" default="generationHTML"> On définit la première tâche comme étant celle réalisant la génération du fichier HTML. Ne pouvant s’exécuter avant la tâche de compilation, Ant va d’abord compiler le projet puis terminer son travail par la génération de la page web. Lors de l’exécution du script Ant, il ne nous sera plus nécessaire de spécifier la tâche à exécuter étant donné que celle-ci est maintenant précisée. La nouvelle commande de compilation est donc : ant -buildfile HelloWorld.xml Afin que tout ceci soit plus clair, voici le script de compilation dans sa totalité : <?xml version="1.0" encoding="utf-8"?> <project name="My App Builder" default="generationHTML"> <taskdef resource="flexTasks.tasks" classpath="c:/root_flexsdk/ant/lib/flexTasks.jar" /> <property name="APPLICATION_HOME" value="c:/root_flexsdk/samples/HelloWorld/src"/> <target name="compilation"> <echo message=">> Génération du fichier SWF" /> <mxmlc file="${APPLICATION_HOME}/HelloWorld.mxml"></mxmlc> </target> <target name="generationHTML" depends="compilation"> <echo message=">> Génération du fichier HTML" /> <html-wrapper swf = "HelloWorld" height = "100%" width = "100%" application = "HelloWorld" template = "express-installation" version-major = "9" version-minor = "0" version-revision = "0" output="${APPLICATION_HOME}" title = "Hello World !!"/> </target> </project> Procédons à la compilation et rendons-nous ensuite dans le répertoire src de l’application. Nous notons alors la création des fichiers suivants : • AC_OETags.js : il s’agit du fichier JavaScript vérifiant la version du Flash Player installée en fonction des paramètres version-major, version-minor et version-revision spécifiés dans la tâche html-wrapper. =Flex3 FM.book Page 45 Mardi, 2. décembre 2008 3:32 15 Développer avec le kit Flex SDK CHAPITRE 3 • playerProductInstall.swf : application permettant l’installation du Flash Player requis si le client ne le possède pas. • index.html : page HTML contenant le fichier SWF généré lors de la compilation. Nous pourrions nous arrêter là, mais nous avons décidé de pousser l’automatisation jusqu’au bout en évitant la saisie de la commande ant dans la console MS-DOS. Pour ce faire, nous vous proposons de créer un script bat qui s’exécutera en double-cliquant dessus. Nous vous invitons donc à créer un fichier nommé compilation.bat dans le répertoire src de l’application et contenant les paramètres suivants (à adapter selon votre configuration) : @ECHO OFF cls echo *************************************** echo .::::: COMPILATION ANT :::::. echo *************************************** ant -buildfile c:\root_flexsdk\ant\HelloWorld.xml Double-cliquez ensuite dessus pour l’exécuter. Grâce à ce script exécutant la tâche ant spécifiée auparavant, nous automatisons les tâches de déploiement et diminuons ainsi le nombre d’opérations à effectuer dans la console MS-DOS. Ceci réduit le temps requis pour le déploiement et les tests d’exécution de l’application. En résumé Ce chapitre vous a permis de créer votre première application Flex. Certes, elle est très simple, mais elle nous a néanmoins permis de découvrir les principaux aspects de la réalisation d’une application. Nous avons également vu les différentes phases de développement d’une application : • la conception de l’interface graphique ; • la création du fichier MXML dérivé de la conception ; • le développement des traitements ActionScript ; • la mise en relation entre les actions et l’interface graphique ; • la compilation ; • le déploiement. De toutes ces phases, la plus compliquée est sans doute celle visant à concevoir l’interface graphique, car elle demande une grande part d’abstraction, notamment pour disposer les composants à l’aide de leurs coordonnées. Le rêve serait qu’un un outil WYSIWG regroupant toutes ces phases existe ! Eh bien ce rêve est devenu réalité grâce à Flex Builder, que nous vous invitons à découvrir grâce au chapitre suivant. 45 =Flex3 FM.book Page 46 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 47 Mardi, 2. décembre 2008 3:32 15 4 Développer des applications à l’aide de Flex Builder Flex Builder est un environnement de développement intégré (EDI ou IDE en anglais), basé sur l’outil Eclipse, bien connu des développeurs Java. Son principal objectif est de faciliter le développement des applications Flex en offrant au sein d’un seul environnement, toutes les fonctionnalités nécessaires au cycle de vie d’un projet (développement, compilation, tests et déploiement). Son interface conviviale fait de Flex Builder l’outil de prédilection pour la création d’applications Flex. Dans ce chapitre, nous allons tout d’abord présenter cet outil, puis nous verrons comment l’installer sur notre environnement de travail. Enfin, nous nous intéresserons aux nombreuses fonctionnalités qu’il propose. Présentation de Flex Builder Au cours du chapitre précédent, nous avons vu qu’il est possible de créer une application à partir du kit de développement Flex SDK. Le résultat obtenu est certes concluant, mais le développement à l’aide du SDK n’est pas des plus aisés, car la tâche de compilation peut très rapidement devenir lourde à mettre en place, le design de l’interface graphique est difficile à réaliser et la phase de développement manque de convivialité. Avec Flex Builder, toutes ces difficultés disparaissent. Pour vous faire une petite idée de la puissance de cet outil, voici une liste non exhaustive des fonctionnalités qu’il offre : • un mode Design de type WYSIWYG pour la création d’interface graphique ; =Flex3 FM.book Page 48 Mardi, 2. décembre 2008 3:32 15 48 Comprendre Flex 3 PARTIE I • un mode Code évolué permettant la détection des éventuelles erreurs de programmation et offrant une aide au développement grâce à la fonction d’auto-complétion ; • un débogueur ; • un outil de tests intégré (gestion de la mémoire, test de régression, etc.) ; • la prise en charge native des applications Adobe AIR ; • la refactorisation (maintenance) du code ; • la création de composants personnalisés ; • la génération des fichiers SWF et HTML associées. Les différentes versions de Flex Builder Flex Builder est disponible en version standard ou en version professionnelle. Dans sa version standard, il offre les fonctionnalités de base nécessaires à la création d’applications. La version professionnelle, quant à elle, permet la réalisation de graphiques utiles dans les applications de reporting. Elle met également à la disposition des développeurs un outil de tests très performant permettant, entre autres, de visualiser la capacité mémoire utilisée par l’application et de générer des tests automatisés. Le choix de la version dépend donc du type d’applications que vous souhaitez développer et de votre budget. Les différents modes de distribution de Flex Builder Deux modes de distribution de Flex Builder sont proposés : • Le mode Plug-in, qui concerne les développeurs possédant déjà l’IDE Eclipse, plateforme sur laquelle Flex Builder peut être ajouté sous forme de plug-in. • Le mode Autonome, qui consiste à installer une version « autonome », contenant l’IDE Eclipse et le plug-in Flex Builder pré-installé. L’intérêt du second mode de distribution est qu’il permet de disposer d’un environnement entièrement dédié au développement d’applications Flex, non pollué par les divers plug-ins pouvant déjà être installés dans Eclipse. Néanmoins, si votre espace disque est limité, optez pour le premier mode car il évite de réinstaller l’IDE Eclipse qui nécessite 400 Mo ! Version de Flex Builder Cet ouvrage traite de Flex Builder dans sa version professionnelle. Le mode de distribution retenu est le mode Autonome. Évaluer avant d’acheter une licence À ce stade de l’ouvrage, il est prématuré de faire l’acquisition d’une licence. Faites-vous d’abord une idée de Flex Builder professionnel en téléchargeant une version de démonstration limitée dans le temps sur le site d’Adobe. Pour cela, rendez-vous à l’adresse suivante : http://www.adobe.com. =Flex3 FM.book Page 49 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Installation de Flex Builder Il est temps à présent de passer à la phase d’installation de Flex Builder qui nous permettra de l’étudier en détail. Flex Builder est disponible sous Mac et sous Windows. Nous avons choisi ici de détailler son installation sous Windows. À noter que si vous optez pour le mode de distribution Plug-in et que vous êtes dans un environnement Mac, vous devez disposer au minimum de la version 3.2 d’Eclipse pour que l’installation soit concluante. Flex Builder 3 et Linux La version commerciale de Flex Builder n’est malheureusement pas compatible avec Linux. Néanmoins, pour les utilisateurs de cet environnement, Adobe a développé le projet Flex Builder Public Alpha, qui consiste en un plug-in à ajouter à l’IDE Eclipse et offrant notamment les fonctionnalités de coloration syntaxique, de compilation, de débogage… Ce plug-in est téléchargeable à l’adresse suivante : http://labs.adobe.com/technologies/flex/flexbuilder_linux/. Le mode Autonome Voici la marche à suivre pour installer Flex Builder professionnel en mode Autonome : 1. Enregistrez-vous sur le site d’Adobe. Vous pouvez acheter soit une version téléchargeable soit un CD-Rom. Si vous optez pour la version téléchargeable, vous disposez alors d’un exécutable nommé FB3_win.exe. Version d’évaluation Avant d’acquérir Flex Builder, vous pouvez télécharger la version d’évaluation (disponible uniquement en anglais) sur le site d’Adobe. 2. Double-cliquez sur ce fichier pour lancer la procédure d’installation (figure 4-1). Figure 4-1 Extraction des fichiers d’installation 49 =Flex3 FM.book Page 50 Mardi, 2. décembre 2008 3:32 15 50 Comprendre Flex 3 PARTIE I 3. La fenêtre qui s’affiche à la fin de la procédure d’extraction des fichiers d’installation permet de sélectionner la langue souhaitée. Cliquez sur OK pour poursuivre l’installation. Figure 4-2 Choix de la langue d’installation 4. Acceptez les termes de la licence d’utilisation (figure 4-3) et cliquez sur le bouton Next. Figure 4-3 Acception des termes de la licence d’utilisation de Flex Builder 5. Sélectionnez le répertoire souhaité pour l’installation (figure 4-4) et cliquez sur Next. =Flex3 FM.book Page 51 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Figure 4-4 Choix du répertoire d’installation 6. Cochez les deux options permettant d’installer Flash Player 9 et, éventuellement, les options permettant d’installer les extensions ColdFusion pour Flex Builder et le plug-in JSEclipse (figure 4-5), si vous utilisez l’un des deux éléments. Cliquez ensuite sur le bouton Next pour continuer. Figure 4-5 Sélection des éléments additionnels à installer (Flash Player 9, extensions ColdFusion et plug-in JSEclipse) 51 =Flex3 FM.book Page 52 Mardi, 2. décembre 2008 3:32 15 52 Comprendre Flex 3 PARTIE I ColdFusion Actuellement disponible dans sa version 8, Adobe ColdFusion est un langage de balises permettant la réalisation d’applications web. Pour plus d’informations sur ce produit, nous vous invitons à vous rendre à l’adresse suivante : http://www.adobe.com/fr/products/coldfusion/. JSEclipse JSEclipse est un plug-in gratuit développé par interAKT (qui est une branche d’Adobe), permettant l’édition de fichier JavaScript en proposant une coloration syntaxique, l’auto-complétion… 7. Cliquez sur le bouton Install de la fenêtre récapitulant les paramètres d’installation (figure 4-6). L’installation démarre alors (figure 4-7), suivie de sa configuration (figure 4-8). Figure 4-6 Récapitulatif des paramètres de l’installation =Flex3 FM.book Page 53 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Figure 4-7 État d’avancement de l’installation de Flex Builder Figure 4-8 Configuration de Flex Builder 53 =Flex3 FM.book Page 54 Mardi, 2. décembre 2008 3:32 15 54 Comprendre Flex 3 PARTIE I Figure 4-9 Fin de l’installation Voilà, l’installation est terminée (figure 4-9). Double-cliquez sur le programme flexBuilder .exe situé dans le répertoire d’installation spécifié afin de vérifier que tout s’est déroulé correctement et que le logiciel se lance bien. Le mode Plug-in Le principal prérequis pour ce mode de distribution est la présence de l’IDE Open Source Eclipse, Flex Builder étant basé sur cet outil, qui peut être téléchargé à l’adresse suivante : http://www.eclipse.org/. L’installation d’Eclipse se résume en la décompression de l’archive téléchargée sur le site de l’éditeur dans un répertoire du disque dur de votre machine. Un nouveau répertoire est alors créé, contenant le fichier eclipse.exe (figure 4-10). Figure 4-10 Répertoire d’installation d’Eclipse =Flex3 FM.book Page 55 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Si vous avez opté pour l’installation du plug-in Eclipse, vous devez être en possession du programme FB3_WWEJ_Plugin.exe, préalablement téléchargé depuis le site d’Adobe. Doublecliquez alors sur cet exécutable pour lancer la procédure d’installation dont les différentes étapes sont les suivantes : 1. Extraction des fichiers d’installation. 2. Choix de la langue d’installation souhaitée (anglais par défaut). 3. Acception des termes de la licence d’utilisation. 4. Spécification du chemin d’installation du plug-in. 5. Indication du chemin d’installation d’Eclipse. 6. Configuration du plug-in. 7. Installation de Flash Player 9 et des extensions ColdFusion et JSEclipse optionnelles. 8. Après une reconfiguration du plug-in, un récapitulatif d’installation est affiché. 9. Installation du plug-in. 10. Fin de l’installation. Pour vérifier que l’installation du plug-in s’est correctement déroulée, exécutez l’IDE Eclipse et créez un nouveau projet de type Flex Project en procédant comme suit : 1. Sélectionnez le menu File>New>Other. 2. Dans la fenêtre qui s’ouvre alors, sélectionnez Flex Builder puis Flex Projet. 3. Une série de questions vous est alors posée. Acceptez les options proposées par défaut en indiquant Test pour le nom du projet. 4. Après validation, une perspective Eclipse s’affiche, identique à celle de Flex Builder en mode Autonome (figure 4-11). Flex Builder est désormais correctement installé. Étudions à présent ses caractéristiques et son mode de fonctionnement dans le détail. 55 =Flex3 FM.book Page 56 Mardi, 2. décembre 2008 3:32 15 56 Comprendre Flex 3 PARTIE I Figure 4-11 Perspective Eclipse de Flex Builder Les perspectives de Flex Builder Dans cette partie, nous allons aborder les deux notions essentielles de Flex Builder que nous retrouverons tout au long de cet ouvrage : la perspective et la vue. Le terme « perspective » peut être défini par une combinaison d’éditeurs et de vues permettant de réaliser des tâches précises. Comme son nom l’indique, un éditeur permet d’éditer des fichiers. Dans le cas d’une application Flex, il existe trois éditeurs : • un éditeur MXML ; • un éditeur ActionScript ; • un éditeur CSS. Une vue, quant à elle, est liée à un éditeur. Si, par exemple, on souhaite éditer un fichier de type MXML dont le rôle principal est la description d’une interface graphique, nous verrons apparaître à l’écran les composants disponibles pouvant être insérés dans cette interface ainsi =Flex3 FM.book Page 57 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 que leurs propriétés respectives. Si nous éditons à présent un fichier ActionScript, une autre vue sera affichée présentant les variables et les classes du fichier en cours d’édition. Flex Builder professionnel est composé de quatre perspectives : • la perspective de développement, permettant de visualiser le code de l’application ; • la perspective de design qui nous permet de créer les interfaces graphiques de nos applications ; • la perspective de débogage nous offre une aide précieuse pour corriger les problèmes rencontrés lors de l’exécution d’une application ; • la perspective de profiling ajoute des fonctionnalités à la perspective de débogage en permettant d’étudier le temps processeur ou l’occupation mémoire de certaines procédures. Lors de la création d’un nouveau projet, la perspective Design est sélectionnée par défaut (figure 4-12). Pour passer à la perspective de développement, il suffit de cliquer sur le bouton Source situé dans la barre de menus de la vue centrale (figure 4-13). Figure 4-12 La perspective de design 57 =Flex3 FM.book Page 58 Mardi, 2. décembre 2008 3:32 15 58 Comprendre Flex 3 PARTIE I Figure 4-13 Boutons permettant d’afficher les perspectives de design et de développement La perspective de développement La perspective de développement comprend les éditeurs et les vues nécessaires à la création des fichiers en mode Code. Nous pouvons ainsi éditer des fichiers ActionScript, CSS, MXML… Au centre de cette perspective (figure 4-14) se trouve l’éditeur principal permettant la saisie du code. La vue Flex Navigator, située en haut à gauche, affiche l’arborescence du projet et l’ensemble des fichiers qu’il contient. La vue Outline présente la structure hiérarchique du code saisi et permet également de visualiser les alertes et erreurs présentes. Enfin, la vue Problems, située sous l’éditeur, présente l’ensemble des alertes et erreurs de compilation pouvant perturber le bon déroulement de l’application. Figure 4-14 La perspective de développement =Flex3 FM.book Page 59 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 La perspective de design Cette perspective vous permettra de disposer facilement les composants d’une interface graphique comme nous le ferions avec un éditeur WYSWYG (figure 4-15). Figure 4-15 La perspective de design Au centre de cette perspective se trouve l’éditeur MXML. Pour y ajouter des composants, il suffit de les sélectionner dans la vue Components et de les faire glisser dans l’éditeur. Par ailleurs, leurs propriétés peuvent être modifiées dans la vue Flex Properties, située à droite de l’éditeur MXML. La vue States permet, quant à elle, de créer des états d’interface. Il est ainsi possible de définir différents états pour une interface donnée. Prenons pour exemple une interface graphique contenant un panneau permettant de saisir un identifiant et un mot de passe. À l’état initial, sont affichés les deux zones de saisie, le 59 =Flex3 FM.book Page 60 Mardi, 2. décembre 2008 3:32 15 60 Comprendre Flex 3 PARTIE I bouton Valider et le bouton Perte du mot de passe. Cet état est représenté par l’état principal (Base state, figure 4-16). Si l’utilisateur clique sur le bouton Perte du mot de passe, un nouvel état apparaîtra dans la vue States (perteMDP) et une zone de texte s’affichera demandant la saisie de l’adresse e-mail à laquelle envoyer le mot de passe oublié. Ce nouvel état, créé à partir de l’état principal, est illustré par la figure 4-17. Pour le moment, nous ne développerons pas davantage la notion d’état, que nous détaillerons au chapitre 9. Figure 4-16 L’état « Saisie du mot de passe » Figure 4-17 L’état « Perte du mot de passe » =Flex3 FM.book Page 61 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 La perspective de débogage La perspective de débogage (figure 4-18) est activée lors de l’exécution de l’application en mode Débogage (menu Run>Debug). Elle est très intéressante pour résoudre les problèmes dans vos applications, comme lorsqu’une fonction renvoie une erreur ou bien lorsqu’un appel à un service web échoue. Figure 4-18 La perspective de débogage La vue Debug affiche les différentes tâches (thread/processus) réalisées par l’application. Cette vue permet de suspendre ou de reprendre l’exécution d’une tâche précédemment suspendue afin d’analyser l’exécution de l’application. 61 =Flex3 FM.book Page 62 Mardi, 2. décembre 2008 3:32 15 62 Comprendre Flex 3 PARTIE I Multithreading Il est important de souligner qu’une application Flex n’est pas multithread (multi-tâche). Par conséquent, l’implémentation d’une barre de progression permettant d’afficher l’état d’avancement de l’exécution d’un traitement n’est pas envisageable. Il peut parfois s’avérer intéressant de stopper l’exécution à un point précis de son avancement. Pour cela, il suffit de placer des points d’arrêt dans le code applicatif. La vue Breakpoints présente les différents points d’arrêt insérés et permet de les gérer (désactivation, passage au point d’arrêt suivant et suppression). Par ailleurs, pour vérifier qu’un traitement a bien été effectué, il peut parfois être nécessaire de « tracer » son passage. Pour cela, il convient d’utiliser la fonction trace du langage ActionScript. La vue Console permet de visualiser l’ensemble du traçage réalisé. La vue Variables, quant à elle, affiche les valeurs prises par les différentes variables déclarées dans le code ce qui permet de résoudre les problèmes de variables non affectées. Enfin, la vue Expressions permet de surveiller les variables jugées critiques pour l’application (saisie d’un mot de passe, etc.). Les valeurs des variables présentes dans cette vue peuvent être modifiées dynamiquement à l’aide de la vue Variables. Affichage des différentes vues Il se peut que l’ensemble des vues ne soit pas affiché par défaut. Dans ce cas, il suffit de sélectionner le menu Window et de choisir la vue désirée parmi la liste proposée. Néanmoins, lors de l’exécution du projet en mode Débogage, Flex Builder vous demandera si vous souhaitez ou non utiliser la perspective de débogage. La perspective de profiling Cette perspective est la grande nouveauté de la version 3 de Flex Builder professionnel. Grâce à elle, il est désormais possible d’analyser en profondeur l’exécution d’une application Flex. En effet, la perspective Profile permet d’effectuer une analyse statistique du nombre d’objets instanciés, de la place mémoire qu’ils occupent, des méthodes exécutées et de leur temps d’exécution. La perspective Profile (figure 4-19) comprend deux vues essentielles : • la vue Live Objects, qui permet de visualiser les objets créés et les méthodes exécutées ; • la vue Memory usage, dédiée à la visualisation du taux d’utilisation de la mémoire. Maintenant que nous avons passé en revue les différentes perspectives, nous allons nous consacrer à la création de projets Flex. =Flex3 FM.book Page 63 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Figure 4-19 La perspective de profiling Créer un projet Tout nouveau développement commence inévitablement par la création d’un nouveau projet ; voici la marche à suivre pour effectuer cela dans Flex Builder : 1. Sélectionnez le menu File>New>Flex Project. 2. Dans la fenêtre qui s’ouvre alors (figure 4-20), saisissez le nom projet (ici ProjetFlex) et choisissez le type d’application souhaité : – Web application permet de créer une page HTML contenant le fichier SWF issu de la compilation ; – Desktop application permet de créer une application Adobe AIR. 3. Pour spécifier le répertoire de destination du projet, désactivez l’option Use Default Location et spécifiez le chemin du répertoire dans le champ Folder. 63 =Flex3 FM.book Page 64 Mardi, 2. décembre 2008 3:32 15 64 Comprendre Flex 3 PARTIE I 4. Indiquez ensuite la technologie serveur à utiliser grâce à la liste déroulante Application server type. En effet, pour pouvoir accéder à des données stockées dans une base, Flex doit être couplé à un langage serveur (ASP.Net, ColdFusion, J2EE, PHP, etc.) qui servira de passerelle. Notez que si vous sélectionnez J2EE ou ColdFusion, Flex propose d’utiliser l’outil LiveCycle Data Services ES (voir encadré) permettant d’accéder aux services de la couche métier développée dans ces technologies. LiveCycle Data Services ES et ColdFusion Flash Remoting LiveCycle Data Services ES permet une intégration complète de Flex dans une architecture J2EE en autorisant la simplification du code et en offrant certaines fonctionnalités telles que l’édition de rapports PDF. ColdFusion Flash Remoting facilite l’intégration de Flex à la technologie ColdFusion qui offre une fonction de création d'applications Internet riches (RIA) côté serveur. Il rend également Flex et la technologie J2EE interopérables. Ces deux produits sont développés par Adobe. Figure 4-20 Création d’un nouveau projet 5. Cliquez ensuite sur le bouton Next. La fenêtre qui apparaît alors permet de préciser le répertoire dans lequel les fichiers issus de la compilation seront enregistrés (bin-debug par défaut). Même si le chemin du répertoire est spécifié manuellement, il apparaîtra =Flex3 FM.book Page 65 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 tout de même sous le nom bin-debug dans l’arborescence du projet, mais il s’agira d’un raccourci vers le répertoire spécifié. 6. Cliquez à nouveau sur le bouton Next. La fenêtre qui s’affiche alors permet de configurer le répertoire dans lequel les sources du projet seront enregistrées (src par défaut), ainsi que le nom du fichier principal de l’application (figure 4-21). Il est également possible de désigner des répertoires de sources externes et d’importer des bibliothèques telles que des composants personnalisés. Figure 4-21 Spécification des répertoires 7. Cliquez enfin Finish pour terminer la création du projet. Arborescence d’un projet Flex Builder L’arborescence d’un projet Flex Builder dépend du type d’application choisi lors de la création du projet. 65 =Flex3 FM.book Page 66 Mardi, 2. décembre 2008 3:32 15 66 Comprendre Flex 3 PARTIE I Les applications de type web Lorsque l’option Web Application est activée (figure 4-20), votre projet aura une arborescence semblable à celle illustrée par la figure 4-22. Figure 4-22 Arborescence d’un projet Flex Builder Le tableau 4-1 détaille les répertoires et fichiers de cette arborescence. Tableau 4-1 Arborescence d’un projet de type Web Répertoire/Fichier Description \ProjetFlex Répertoire racine du projet. \bin-debug Répertoire de compilation. \history Répertoire contenant un ensemble de fichiers dédiés à la prise en charge des actions sur les boutons Suivant et Précédent du navigateur web history.css Feuille de styles utilisée par la page historyFrame.html. history.js Fichier JavaScript traitant les actions sur les boutons Suivant et Précédent du navigateur web. historyFrame.html Page HTML affichant le résultat du traitement réalisé par le fichier history .js. AC_OETags.js Script détectant la présence du Flash Player sur le poste client. Associé au fichier playerProductInstall.swf, il permet son exécution le cas échéant. playerProductInstall.swf Fichier SWF réalisant l’installation du Flash Player si ce dernier n’est pas présent sur le poste client. =Flex3 FM.book Page 67 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Tableau 4-1 Arborescence d’un projet de type Web (suite) Répertoire/Fichier Description ProjetFlex.html Page HTML contenant le fichier SWF de l’application. ProjetFlex.swf Fichier SWF de l’application. \html-template Répertoire dans lequel sont placés les fichiers nécessaires à la génération de la page HTML contenant le fichier SWF. index.template.html Page HTML utilisée comme modèle pour la création de la page w eb contenant le fichier SWF. \libs Répertoire accueillant les bibliothèques. \src Répertoire des sources de l’application. ProjetFlex.mxml Fichier MXML de l’application. Les applications Adobe AIR Une application Adobe AIR s’exécute sur le poste client à la manière d’une application standard (figure 4-23). De ce fait, le fichier SWF n’est pas contenu dans une page web, ce qui implique que nous ne trouverons pas les fichiers relatifs à la gestion des événements sur les boutons Suivant et Précédent du navigateur dans le répertoire \history, ni ceux nécessaires à la création de la page web, normalement situés dans le répertoire \html-template. Nous constatons cependant l’apparition d’un nouveau fichier XML, nommé nomDuProjet app.xml situé dans le répertoire src contenant l’ensemble des informations permettant de créer la fenêtre applicative. Figure 4-23 Application de type Adobe AIR 67 =Flex3 FM.book Page 68 Mardi, 2. décembre 2008 3:32 15 68 Comprendre Flex 3 PARTIE I Le tableau 4-2 détaille l’ensemble des répertoires et des fichiers de l’arborescence représentée à la figure 4-24. Tableau 4-2 Arborescence d’un projet Adobe AIR Répertoire/fichier Description \ProjetAir Répertoire racine du projet. \bin-debug Répertoire de compilation. ProjetAir.swf Fichier SWF de l’application. ProjetAir-app.xml Fichier XML chargé de décrire les spécificités de la fenêtre d’exécution du projet. \libs Répertoire contenant les bibliothèques du projet. \src Répertoire contenant les sources du projet. ProjetAir.mxml Fichier applicatif principal. Figure 4-24 Arborescence d’un projet de type AIR Exécution et tests L’exécution d’un projet s’effectue en cliquant sur l’icône Run de la barre d’outils de Flex Builder. Si vous souhaitez l’exécuter en mode Débogage, cliquez sur l’icône . La perspective de débogage, dont les fonctionnalités ont été décrites précédemment, s’affiche alors. Nous ne nous étendrons pas d’avantage sur ces notions de test et de débogage qui seront abordées en détail dans le chapitre 17. Travail collaboratif Flex Builder offre la possibilité d’effectuer un travail collaboratif sur un projet, ce qui peut s’avérer très intéressant pour les projets de grande envergure. Néanmoins, vous devrez pour cela disposer d’un serveur CVS (Concurrent Versions System) capable de gérer les différentes versions du projet, de répercuter les modifications effectuées par chaque développeur tout en analysant leurs impacts. Un système CVS fonctionne selon le principe suivant. Les sources du projet sont copiées dans un répertoire de synchronisation situé sur un serveur. Les acteurs participant au développement du projet peuvent ainsi télécharger ces sources sur leur poste de travail à l’aide d’un client CVS. Chaque développeur possède alors une copie des sources =Flex3 FM.book Page 69 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 (working copy) qu’il peut modifier à l’envi. Une fois toutes les modifications apportées, il transfère les nouveaux fichiers sur le serveur CVS, on parle alors de commit. Les autres développeurs sont alors informés que des modifications ont été apportées et peuvent récupérer les nouveaux fichiers mis à jour en effectuant un update. Pour vous permettre de mieux comprendre ce point, nous allons à présent détailler la configuration d’un serveur CVS dans un environnement Windows. Configuration du serveur CVSNT Sous Windows, vous devrez utiliser le serveur CVSNT. Cet outil est gratuit et peut être téléchargé à l’adresse suivante : http://www.march-hare.com/cvspro/. Son installation est des plus simples car il vous suffira de suivre les différentes étapes de l’assistant. Pour configurer le serveur, suivez la procédure suivante : 1. Exécutez le programme CVSNT Control Panel (menu Démarrer>Tous les programmes>CVSNT). 2. Cliquez sur l’onglet Repository Configuration permettant de définir le répertoire dans lequel les sources du projet à synchroniser seront enregistrées. Pour cela, cliquez sur le bouton ADD afin d’afficher la fenêtre Server Settings (figure 4-25). Figure 4-25 Création du répertoire de synchronisation Configuration des utilisateurs Les utilisateurs pouvant accéder au serveur CVSNT sont définis dans le fichier passwd situé dans le sous-répertoire CVSROOT du répertoire de synchronisation défini précédemment. Nous allons ajouter l’utilisateur Administrateur qui possédera tous les droits sur le répertoire de synchronisation et dont le mot de passe sera vide. Pour ce faire, éditez le fichier passwd et ajoutez-y la ligne suivante : Administrateur::Administrateur 69 =Flex3 FM.book Page 70 Mardi, 2. décembre 2008 3:32 15 70 Comprendre Flex 3 PARTIE I Paramétrage du projet Flex Builder La phase de configuration des utilisateurs terminée, il ne nous reste plus qu’à paramétrer le travail collaboratif pour un projet Flex Builder : 1. Effectuez un clic droit sur l’icône du projet et sélectionnez Team>Share Project. 2. Dans la fenêtre qui s’affiche alors, spécifiez les différents paramètres nécessaires à la réalisation de la connexion au serveur CVS (figure 4-26). Cliquez ensuite sur le bouton Next. Figure 4-26 Paramétrage de la connexion au serveur CVS 3. Dans la fenêtre suivante, conservez l’option cochée par défaut spécifiant que le nom du module CVS portera le nom du projet. Un répertoire du même nom que celui du projet sera alors créé dans le dossier de synchronisation de CVS. Cliquez ensuite sur le bouton Next > pour valider. 4. Le récapitulatif de la configuration s’affiche alors. Cliquez sur le bouton Finish pour terminer (figure 4-27). 5. Une nouvelle fenêtre apparaît alors, vous informant que des nouveaux fichiers ont été détectés et qu’une synchronisation est nécessaire. Cliquez sur le bouton Next. 6. Dans la fenêtre suivante, saisissez un commentaire sur la raison de la synchronisation et validez en cliquant sur le bouton Finish (figure 4-28). =Flex3 FM.book Page 71 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Figure 4-27 Récapitulatif du paramétrage CVS Figure 4-28 Première synchronisation du projet 71 =Flex3 FM.book Page 72 Mardi, 2. décembre 2008 3:32 15 72 Comprendre Flex 3 PARTIE I Synchronisation des sources Si nous sélectionnons à nouveau le menu Team du projet, nous pouvons constater qu’il comporte désormais des nouvelles entrées, dont les principales sont : • Commit, permettant de déposer les modifications effectuées sur le serveur ; • Update, offrant la possibilité de mettre à jour les sources du projet à partir de celles situées sur le serveur ; • Synchronize with repository, perspective de synchronisation du projet chargée d’analyser les modifications effectuées et leur impact. Nous n’allons pas nous attarder davantage sur le travail collaboratif. Cette section nous a permis de voir que Flex Builder est capable de s’adapter à toutes les tailles de projets, du plus petit aux projets de grande envergure développés par plusieurs personnes nécessitant une architecture de développement bien définie. Exporter/importer un projet Nous venons de voir qu’il est possible de travailler en collaboration sur un même projet, l’ensemble des développeurs partagent alors les sources. Cependant, il arrive que nous soyons seuls à développer et que nous devions exporter notre projet afin de l’utiliser sur un autre poste équipé du Framework Flex 3, à des fins de démonstration ou de sauvegarde. Dans cette partie, nous allons donc voir comment il est possible d’exporter mais aussi d’importer un projet au sein de l’environnement de développement. Exportation Voici la marche à suivre pour exporter un projet en vue de le déployer ou de l’archiver : 1. Effectuez un clic droit sur la vue Flex Navigator et sélectionnez Export. 2. Dans la fenêtre qui s’ouvre alors, indiquez le type d’exportation souhaité (figure 4-29) : – Flex Project Archive, crée une archive pouvant être stockée afin de conserver, par exemple, plusieurs versions différentes du projet ; – Release Build, exporte le projet vers l’environnement de production, le rendant ainsi disponible pour l’ensemble des utilisateurs concernés. 3. Cliquez ensuite sur le bouton Next afin de sélectionner le projet concerné par l’exportation. =Flex3 FM.book Page 73 Mardi, 2. décembre 2008 3:32 15 Développer des applications à l’aide de Flex Builder CHAPITRE 4 Figure 4-29 Choix du type d’exportation Importation Pour importer un projet, suivez les étapes suivantes : 1. Effectuez un clic droit sur la vue Flex Navigator et sélectionnez Import. 2. Dans la fenêtre qui s’ouvre alors, indiquez le type de fichier à importer dans Flex Builder. Un projet Flex Builder peut être importé à partir d’un fichier archive ou du fichier .project présent dans le répertoire racine de chaque projet Flex Builder (figure 4-30). Figure 4-30 Fichier .project 73 =Flex3 FM.book Page 74 Mardi, 2. décembre 2008 3:32 15 74 Comprendre Flex 3 PARTIE I 3. Cliquez sur le bouton Next. Dans la fenêtre présente à l’écran, si vous souhaitez importer un projet archivé (zip), cliquez sur le bouton Browse situé en regard de la ligne Archive file afin de parcourir votre disque dur et sélectionner l’archive correspondante, puis cliquez sur le bouton OK. Si vous souhaitez importer un projet non archivé, cliquez alors le bouton Browse situé en regard de la ligne Project Folder, puis parcourez votre disque dur jusqu’au répertoire racine du projet souhaité. Cette action sélectionne automatiquement le fichier .project qui y est situé. Cliquez enfin sur le bouton OK. 4. Une fois le projet sélectionné, cliquez sur le bouton Finish afin d’importer le projet dans l’environnement de développement. En résumé Au cours de ce chapitre, nous avons découvert les nombreuses fonctionnalités de développement offertes par Flex Builder. Cet environnement de développement complet offre des fonctionnalités de design, de codage, de débogage et de gestion de projets, le tout intégré à l’outil Eclipse, ce qui rend son utilisation conviviale, contrairement au mode de développement étudié dans le chapitre précédent. De plus, le développeur dispose de l’ensemble des outils nécessaires au sein d’un même environnement lui permettant d’optimiser et d’accélérer son développement. Avant de poursuivre avec l’étude des composants graphiques proposés par le framework Flex, nous vous conseillons de vous familiariser avec l’utilisation de Flex Builder et de ses perspectives. Vous serez ainsi tout à fait à l’aise pour réaliser les exemples et cas pratiques proposés dans la suite de cet ouvrage. =Flex3 FM.book Page 75 Mardi, 2. décembre 2008 3:32 15 5 Les composants de contrôle Comme nous le savons à présent, Flex est le framework dédié à la création de la partie front end d’une application. Pour cela, il convient de disposer de composants permettant de réaliser cette interface graphique. Les composants proposés par Flex peuvent se diviser en quatre catégories : • les composants de contrôle de type boutons, zones de texte, etc. ; • les conteneurs comme les panneaux, canevas, etc. ; • les composants de navigation (menus, onglets, etc.) ; • et enfin les composants permettant de générer des graphiques et autres histogrammes pour la visualisation de statistiques. Au cours des trois chapitres suivants, nous n’allons pas vous présenter l’ensemble des composants dans leurs moindres détails, car cela pourrait faire l’objet d’un ouvrage à part entière, mais découvrir l’usage des composants les plus fréquemment utilisés dans les applications Flex. Nous allons donc commencer par l’étude des composants de contrôle dont le rôle est de permettre l’interaction entre l’utilisateur et l’application. Soulignons que certains d’entre eux permettent également de présenter des données (tableaux, images, etc.). Les boutons et interrupteurs Commençons notre étude des composants par la présentation des plus fréquemment utilisés : les boutons et interrupteurs. =Flex3 FM.book Page 76 Mardi, 2. décembre 2008 3:32 15 76 Comprendre Flex 3 PARTIE I Button Les boutons sont communément utilisés pour déclencher l’exécution de procédures ou de fonctions. Voici un exemple d’implémentation : <mx:Button id="btn_chercher" x="10" y="24" label="Rechercher" icon="@Embed(source='../image/iconeRechercher.gif')" click="rechercher()"/> Le bouton correspondant à cet extrait de code possède les caractéristiques suivantes : • un identifiant (id="btn_chercher") ; • un label correspondant au texte affiché sur le bouton (label="Rechercher") ; • une icône (icon="@Embed(source='../image/iconeRechercher.gif')") ; • une action déclenchée en cliquant sur le bouton (click="rechercher()"). Dans notre exemple, lorsque l’utilisateur clique sur le bouton, la procédure rechercher() est alors déclenchée. ToogleButton En ajoutant la propriété toogle="true" au composant Button, nous obtenons un bouton de type interrupteur. Il peut être utilisé pour visualiser l’état d’une action, par exemple, le partage d’un fichier. <mx:Button id="btn_partager" label="Partager Dossier" toggle="true" /> Si l’utilisateur clique sur l’interrupteur, le fichier est partagé et reste dans cet état (le fond du bouton apparaît alors en grisé, comme sur la figure 5-1). Pour annuler le partage, il suffit de cliquer une seconde fois sur le bouton. Figure 5-1 État « partagé » Permettre le choix CheckBox : les cases à cocher Les cases à cocher permettent à l’utilisateur de réaliser plusieurs choix parmi une liste proposée (figure 5-2). =Flex3 FM.book Page 77 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 Figure 5-2 Cases à cocher Voici comment implémenter ce composant de contrôle : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥borderColor="#F7F9FA" themeColor="#F6F9FB" horizontalAlign="center"> <mx:Label x="15" y="74" text="Pourquoi avez-vous choisi Flex ?"/> <mx:CheckBox x="49" y="100" label="Facilité d'utilisation" width="130" id="chbx_1"/> <mx:CheckBox x="49" y="130" label="Complexité du code" width="156" id="chbx_2"/> <mx:CheckBox x="49" y="160" label="Offre de nombreux composants" width="230" ➥id="chbx_3" selected="true"/> </mx:Application> La propriété booléenne selected permet de connaître l’état de la case à cocher. Ainsi, si elle est égale à true, la case est cochée. Dans l’exemple ci-dessus, la troisième case est cochée par défaut. Grâce aux cases à cocher, il nous est possible de déclencher des exécutions de procédures lors de la réalisation de certains événements. L’exemple ci-dessous permet de lancer la procédure changementEtat() lors du changement d’état de la case à cocher : <mx:CheckBox x="49" y="160" label="Age > 18 ans ?" width="230" id="chbx_4" ➥selected="true" change="changementEtat()"/> Les listes simples et déroulantes Les composants ListBox et ComboBox ayant un mode de fonctionnement identique, nous avons fait le choix d’illustrer la mise en place d’une liste déroulante dont l’usage semble être plus répandu. Implémentation <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Liste --> <mx:List id="maListe" x="20" y="10"></mx:List> <!-- Liste déroulante --> <mx:ComboBox id="maListeDeroulante" x="268" y="11"></mx:ComboBox> </mx:Application> 77 =Flex3 FM.book Page 78 Mardi, 2. décembre 2008 3:32 15 78 Comprendre Flex 3 PARTIE I En analysant ce code, nous voyons que l’implémentation des ListBox s’effectue à l’aide des balises <mx:list></mx:list> et grâce aux balises <mx:ComboBox></mx:ComboBox> pour les ComboBox. Nous profitons de cet exemple pour insister sur le fait que chaque composant implémenté doit comporter un identifiant, soit l’attribut id. En effet, c’est grâce à cet identifiant que le composant pourra être utilisé au sein de vos procédures ActionScript. Par ce biais, nous pourrons modifier ses propriétés mais aussi récupérer la ou les valeurs sélectionnées lorsque cela est nécessaire et lorsque le composant en offre la possibilité. Alimentation en données Considérons la liste d’enregistrements issus d’une table contenue dans une base de données ornithologiques dont le contenu est décrit par le tableau 5-1. Tableau 5-1 Enregistrements de base de données ornithologiques Identifiant Oiseau 1 Merle 2 Colibri 3 Mésange Voyons comment alimenter une ComboBox à partir de ces éléments : <mx:ComboBox id="combo_oiseau" x="10" y="29" selectedIndex="0"> <mx:ArrayCollection> <mx:Object data="1" label="Merle"/> <mx:Object data="2" label="Colibri"/> <mx:Object data="3" label="Mésange"/> </mx:ArrayCollection> </mx:ComboBox> Une collection d’objets, présentant les attributs label et data, a été créée en reprenant les données du tableau 5-1. Cette collection est source d’alimentation pour le dataProvider de la ComboBox car elle a été créée entre les deux balises <mx:ComboBox></mx:ComboBox> de cette dernière. À retenir L’alimentation d’une liste simple ou d’une liste déroulante s’effectue toujours à l’aide de deux éléments : • l’attribut label stipulant la donnée à afficher ; • l’attribut data permettant d’affecter un identifiant à la donnée affichée dans la liste déroulante. Notons également la propriété selectedIndex="0" qui indique que nous sélectionnons par défaut le premier élément de la liste (figure 5-3). =Flex3 FM.book Page 79 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 Figure 5-3 Sélection du premier élément de la liste Nous aurions également pu alimenter le dataProvider de la ComboBox à l’aide d’ActionScript : <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] public var listeOiseau:ArrayCollection = new ArrayCollection([ {data:"1", label:"Merle"}, {data:"2", label:"Colibri"}, {data:"3", label:"Mésange"} ]) ]]> </mx:Script> <mx:ComboBox id="combo_oiseau" x="10" y="29" selectedIndex="1" ➥dataProvider="{listeOiseau}"> </mx:ComboBox> Signification de la balise <![CDATA[ ]]> <![CDATA[ ]]> est utilisée pour spécifier que le code situé à l’intérieur de celle-ci n’est pas du XML. Dans notre cas, il s’agit d’un ensemble de lignes de code ActionScript. Si nous observons l’alimentation du dataProvider de la ComboBox à l’aide de la collection listeOiseau, nous notons que l’emploi de variables ActionScript au sein du code MXML s’effectue à l’aide d’accolades ouvrante et fermante. Cette notation permet de spécifier la relation existant entre le composant et la variable ; on parle alors de DataBinding. Le DataBinding ou la liaison de données Vous avez sans doute remarqué la présence de la mention [Bindable] juste avant la déclaration du tableau d’objets listeOiseau. Nous reviendrons sur ce point en détail lors du chapitre 11 qui traite de la gestion des données. Mais vous pouvez d’ores et déjà retenir qu’elle permet de créer une liaison entre le tableau listeOiseau et le dataProvider de la liste déroulante. Ainsi, si le tableau listeOiseau est mis à jour, les données contenues dans la liste déroulante le seront également. 79 =Flex3 FM.book Page 80 Mardi, 2. décembre 2008 3:32 15 80 Comprendre Flex 3 PARTIE I Interaction avec l’utilisateur Il est intéressant de pouvoir récupérer l’attribut data de la valeur sélectionnée par l’utilisateur afin de l’utiliser dans un traitement. Pour ce faire, il suffit d’utiliser la propriété selectedItem du composant : Combo_oiseau.selectedItem.data Précisons que ce qui vient d’être énoncé pour le composant ComboBox est également valable pour le composant ListBox : <mx:List x="10" y="59" dataProvider="{listeOiseau}" id="liste_oiseau" selectedIndex="0"> </mx:List> Les boutons radio Un bouton radio seul est apparenté à une case à cocher. Utilisé dans un groupe, il permet de contraindre l’utilisateur à ne faire qu’un seul choix parmi plusieurs propositions (figure 5-4). Figure 5-4 Boutons radio Implémentation <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Groupe --> <mx:RadioButtonGroup id="groupeRadioBoutons"/> <!-- Boutons --> <mx:RadioButton id="rb_1" x="55" ➥groupName="groupeRadioBoutons" <mx:RadioButton id="rb_2" x="55" ➥groupName="groupeRadioBoutons" y="45.0" label="Masculin" value="M" /> y="69.0" label="Féminin" value="F" /> </mx:Application> Il convient tout d’abord de créer un groupe qui va contenir l’ensemble des boutons radio, puis les boutons radio proprement dits. Chaque bouton créé devra ensuite être intégré au groupe à l’aide de la propriété groupName. Alimentation en données Pour pouvoir exploiter les boutons radio dans les traitements, il est nécessaire de leur affecter une valeur grâce à la propriété value. Attention à ne pas la confondre avec la propriété label dont la valeur correspond au libellé du composant. =Flex3 FM.book Page 81 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 Interaction avec l’utilisateur Pour récupérer la valeur d’un bouton radio sélectionné au sein d’un groupe, nous devons utiliser l’écouteur d’événement ItemClickEvent de ce groupe. En guise d’illustration, l’exemple ci-dessous permet d’afficher le choix de l’utilisateur lors de chaque sélection (itemClick) : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.events.ItemClickEvent; import mx.controls.Alert public function selection(evenement:ItemClickEvent):void { Alert.show(String(evenement.item)); } ]]> </mx:Script> <mx:Label id="lab" x="10" y="19" text="Votre sexe :"/> <mx:RadioButtonGroup id="groupeRadioBoutons" itemClick="selection(event)"/> <mx:RadioButton id="r1" x="55" y="45.0" label="Masculin" value="M" ➥groupName="groupeRadioBoutons"/> <mx:RadioButton id="r2" x="55" y="69.0" label="Féminin" value="F" ➥groupName="groupeRadioBoutons"/> </mx:Application> Lorsque l’utilisateur sélectionne un bouton radio, il déclenche l’exécution de la procédure selection(). Cette procédure reçoit en paramètre l’événement de type ItemClickEvent qui permet de déterminer quel bouton radio du groupe a été sélectionné. Dès lors, il nous est possible de récupérer la valeur de celui-ci. Notez cependant que la propriété value est ici remplacée par la propriété item. En modifiant quelque peu le code ActionScript, il nous est possible de récupérer le libellé du bouton radio sélectionné (label) : <mx:Script> <![CDATA[ import mx.events.ItemClickEvent; import mx.controls.Alert public function selection(evenement:ItemClickEvent):void { Alert.show(String(evenement.label)); } ]]> </mx:Script> 81 =Flex3 FM.book Page 82 Mardi, 2. décembre 2008 3:32 15 82 Comprendre Flex 3 PARTIE I Les zones de texte L’unique moyen de communication mis à la disposition du développeur pour guider l’utilisateur à travers son application, ou pour récolter les données saisies par ce dernier, sont les zones de texte. Dans cette partie, nous allons voir comment utiliser ces composants. Les libellés : Label et Text Les libellés permettent d’afficher du texte de taille réduite (par exemple un intitulé de champ) et non modifiable par l’utilisateur. Contrairement au champ Label, le champ Text permet d’afficher un texte sur plusieurs lignes (figure 5-5). <mx:Label id="lab" x="26" y="29" text="Label : Prénom de l'utilisateur" width="88"/> <mx:Text id="txt" x="26" y="55" text="Text : Prénom de l'utilisateur" width="88"/> Figure 5-5 Les libellés Flex 4 Ce composant est voué à disparaître dans la version 4 du framework. Son successeur portera le nom de TextBox. Les zones de saisie Permettre la saisie d’informations est l’une des fonctions principales de toute interface homme-machine. C’est le rôle des composants TextInput et TextArea grâce auxquelles l’utilisateur saisira des données, qui seront ensuite interprétées et traitées par l’application. Implémentation TextInput et TextArea permettent tous deux à l’utilisateur de saisir des informations. La différence entre ces composants réside dans la possibilité offerte par le composant TextArea de saisir un texte sur plusieurs lignes, contrairement au composant TextInput (figure 5-6). Figure 5-6 Les zones de texte =Flex3 FM.book Page 83 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 <mx:TextInput x="10" y="10" text="TextInput" id=”txt_ti”/> <mx:TextArea x="10" y="40" height="128" text="TextArea : permet la saisie sur ➥plusieurs lignes" id="txt_tm" /> Alimentation en données et interaction avec l’utilisateur La propriété text des composants TextInput et TextArea a été affectée du texte que l’on souhaite afficher. Cette même propriété peut être utilisée en ActionScript afin de récupérer ou d’alimenter le contenu de la zone de texte. <!-- Récupération des données --> public var texteEcrit:String = nomZoneTexte.text <!-- Alimentation de la zone de texte --> nomZoneTexte.text = "texte à afficher" Flex 4 Grâce à la propriété withInChars, Flex 4 permettra de dimensionner automatiquement les zones de texte en longueur, en fonction du nombre de caractères maximum que l’utilisateur pourra saisir. Pour le composant textArea, nous aurons en plus la possibilité de définir le nombre de lignes visibles à l’écran via la propriété heightInLines. Les zones de texte « riches » Les composants RichTextEditor offrent de nombreuses possibilités : • modification de la police (choix de la police, taille, gras, souligné, italique) ; • mise en forme du texte (modification de la couleur, aligné à gauche ou à droite, centré, justifié) ; • utilisation de listes à puces ; • insertion de liens hypertextes. Implémentation Le code suivant montre comment alimenter la zone de texte du composant. La mise en forme du texte (gras, italique…) est effectuée à l’aide de balises HTML alimentant la propriété htmlText du composant. Les balises sont ensuite interprétées par le composant qui en affiche le rendu final (figure 5-7). <mx:Script> <![CDATA[ public function alimenterZoneDeTexte():void { zoneTexteRiche.htmlText = "<TEXTFORMAT LEADING='2'>" + "<LI>" + "<FONT FACE='Verdana' SIZE='12' COLOR='#0B333C' LETTERSPACING= ➥'0' KERNING='0'>" + "<B>Ceci</B>" + 83 =Flex3 FM.book Page 84 Mardi, 2. décembre 2008 3:32 15 84 Comprendre Flex 3 PARTIE I "<FONT SIZE='10'> est <FONT FACE='Times New Roman' SIZE='14'>" + "un lien" + "</FONT> " + "vers " + "<FONT COLOR='#0000FF'>" + "<A HREF='http://www.google.fr' TARGET='_blank'>" + "<U>Google</U>" + "</A>" + "</FONT>" + "</FONT>" + "</FONT>" + "</LI>" + "</TEXTFORMAT>" } ]]> </mx:Script> <mx:RichTextEditor x="10" y="10" width="354" id="zoneTexteRiche" ➥creationComplete="alimenterZoneDeTexte()"> </mx:RichTextEditor> L’événement creationComplete appelle la fonction d’alimentation de la zone de texte une fois le composant créé. Il peut également être utilisé pour l’ensemble des composants y compris l’application. Ceci peut s’avérer utile si une procédure doit être exécutée après la création de l’application. Figure 5-7 Composant RichTextEditor Informer l’utilisateur Si vous souhaitez mettre en place ce composant au sein de vos interfaces, il est nécessaire d’informer l’utilisateur sur la méthode de création des liens hypertextes, car la tâche n’est pas des plus faciles. En effet, il devra tout d’abord sélectionner le texte faisant office de lien. La zone de texte contenant http:// s’activera alors et l’invitera à saisir le lien souhaité. Une fois la saisie effectuée, il suffira d’appuyer sur la touche Entrée du clavier pour valider la saisie et créer le lien. =Flex3 FM.book Page 85 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 Les tableaux DataGrid Pour présenter des données tabulaires de façon classique, le plus simple est de recourir au composant DataGrid. Nous verrons que malgré cet aspect simpliste, il offre tout de même différentes fonctionnalités dont la possibilité de trier des colonnes par un simple clic sur leur en-tête. Implémentation et alimentation en données Le code suivant permet d’implémenter le composant DataGrid et de l’alimenter en données à l’aide d’une collection d’objets (figure 5-8) (ArrayCollection). <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="alimenterDatagrid()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] public var tableauUtilisateurs:ArrayCollection = new ArrayCollection ([ {id:"1",prenom:"Jean",nom:"Dupont"}, {id:"2",prenom:"Annie",nom:"Lagrange"}, {id:"3",prenom:"Pierre",nom:"Jaures"} ]) public function alimenterDatagrid():void { dg_utilisateur.dataProvider = tableauUtilisateurs; } ]]> </mx:Script> <mx:DataGrid id="dg_utilisateur" x="71" y="98" width="329" > <mx:columns> <mx:DataGridColumn headerText="Id" dataField="id"/> <mx:DataGridColumn headerText="Prenom" dataField="prenom"/> <mx:DataGridColumn headerText="Nom" dataField="nom"/> </mx:columns> </mx:DataGrid> </mx:Application> Ici, nous avons tout d’abord créé une collection d’objets ayant pour attributs id, prenom et nom. Nous avons ensuite créé le tableau, la propriété dataField permettant de faire le lien entre la source de données et la colonne du tableau. Ainsi, la première colonne affichera l’attribut id de la collection d’objets. Puis, la fonction alimenterDatagrid() est appelée 85 =Flex3 FM.book Page 86 Mardi, 2. décembre 2008 3:32 15 86 Comprendre Flex 3 PARTIE I après la création de l’application (creationCompleted) et affecte la collection d’objets au dataProvider du DataGrid. Il est également possible de cacher une colonne en affectant la propriété visible à false. Figure 5-8 Le composant DataGrid Interaction avec l’utilisateur Comme pour les composants précédents, il est intéressant de savoir comment exploiter l’interaction du composant DataGrid avec l’utilisateur. La question souvent posée dans ce cas est « Comment récupérer les valeurs de la ligne sélectionnée ?». Pour y répondre, nous allons écrire une fonction mettant en œuvre l’utilisation de la propriété selectedItem du composant. Voici comment procéder si nous souhaitons récupérer l’identifiant de l’individu sélectionné dans le tableau : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="alimenterDatagrid()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] public var tableauUtilisateurs:ArrayCollection = new ArrayCollection ([ {id:"1",prenom:"Jean",nom:"Dupont"}, {id:"2",prenom:"Annie",nom:"Lagrange"}, {id:"3",prenom:"Pierre",nom:"Jaures"} ]) public function alimenterDatagrid():void { dg_utilisateur.dataProvider = tableauUtilisateurs; } =Flex3 FM.book Page 87 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 import mx.controls.Alert public function infoLigneSelectionnee():void { Alert.show(dg_utilisateur.selectedItem.id); } ]]> </mx:Script> <mx:DataGrid id="dg_utilisateur" x="71" y="98" width="329" ➥itemClick="ligneSelectionnee()" > <mx:columns> <mx:DataGridColumn headerText="Id" dataField="id"/> <mx:DataGridColumn headerText="Prenom" dataField="prenom"/> <mx:DataGridColumn headerText="Nom" dataField="nom"/> </mx:columns> </mx:DataGrid> </mx:Application> Comme pour les boutons radio, on utilise l’événement itemClick faisant appel à la procédure infoLigneSelectionnee dont le rôle est d’afficher la valeur de l’attribut id. Manipuler les colonnes par programmation Toujours dans l’objectif d’offrir à l’utilisateur une part importante d’interaction avec l’interface graphique, il est intéressant de mettre en place des fonctionnalités liées aux colonnes du tableau et, pourquoi pas, de lui permettre de masquer ou non certaines d’entre elles. Pour ce faire, il convient d’affecter un identifiant à chaque colonne, ce qui permettra de les identifier et d’invoquer leur méthode dans le code ActionScript. L’exemple de code suivant illustre la mise en place d’une procédure permettant de cacher la colonne Id du tableau : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="alimenterDatagrid()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] public var tableauUtilisateurs:ArrayCollection = new ArrayCollection ([ {id:"1",prenom:"Jean",nom:"Dupont"}, {id:"2",prenom:"Annie",nom:"Lagrange"}, {id:"3",prenom:"Pierre",nom:"Jaures"} ]) public function alimenterDatagrid():void { dg_utilisateur.dataProvider = tableauUtilisateurs; 87 =Flex3 FM.book Page 88 Mardi, 2. décembre 2008 3:32 15 88 Comprendre Flex 3 PARTIE I } // Procédure de manipulation de la colonne colIdentifiant public function manipulerColonne():void{ if (colIdentifiant.visible == false){ colIdentifiant.visible = true }else{ colIdentifiant.visible = false } } ]]> </mx:Script> <mx:DataGrid id="dg_utilisateur" x="71" y="98" width="329" > <mx:columns> <!-- Mise en place d'un identifiant --> <mx:DataGridColumn id="colIdentifiant" headerText="Id" dataField="id"/> <mx:DataGridColumn headerText="Prenom" dataField="prenom"/> <mx:DataGridColumn headerText="Nom" dataField="nom"/> </mx:columns> </mx:DataGrid> <!-- Bouton faisant appel à la procédure manipulerColonne() --> <mx:Button x="71" y="276" label="cacher" id="btn_cacherColonne" ➥click="manipulerColonne()"/> </mx:Application> AdvancedDataGrid Nouveauté du framework Flex 3, le composant AdvancedDataGrid apporte des nombreuses fonctionnalités concernant la présentation des données tabulaires : • la présentation de données hiérarchiques (sous forme d’arborescence) ; • le regroupement de colonnes ; • le tri sur plusieurs colonnes. Implémentation et alimentation en données Voici un exemple permettant de créer un tableau avancé mettant en œuvre la présentation hiérarchique des données ainsi que le regroupement de colonnes : =Flex3 FM.book Page 89 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var tableau:ArrayCollection = new ArrayCollection([ {Pays:"Fance", children: [ {Pays:"Importation", children: [{matiere:"Matière A", Quantite:10, Montant:5000}, {matiere:"Matière A", Quantite:30, Montant:9000}, {matiere:"Matière B", Quantite:800, Montant:25000}, {matiere:"Matière B", Quantite:562, Montant:764}, {matiere:"Matière C", Quantite:5, Montant:25658}, ] }, {Pays:"Exportation", children: [{matiere:"Matiere B", Quantite:58564, Montant:30000}] }] } ]); ]]> </mx:Script> <mx:AdvancedDataGrid x="32" y="69" id="adg1" designViewDataType="tree" width="634" height="314"> <mx:dataProvider> <mx:HierarchicalData source="{tableau}"/> </mx:dataProvider> <mx:groupedColumns> <mx:AdvancedDataGridColumn headerText="Pays / Catégorie" dataField="Pays"/> <mx:AdvancedDataGridColumn headerText="Matière" dataField="matiere"/> <mx:AdvancedDataGridColumnGroup headerText="Quantité et montant"> <mx:AdvancedDataGridColumn headerText="Quantité" dataField="Quantite"/> <mx:AdvancedDataGridColumn headerText="Montant en ¤" dataField= ➥"Montant"/> </mx:AdvancedDataGridColumnGroup> </mx:groupedColumns> 89 =Flex3 FM.book Page 90 Mardi, 2. décembre 2008 3:32 15 90 Comprendre Flex 3 PARTIE I </mx:AdvancedDataGrid> </mx:Application> La figure 5-9 illustre le résultat obtenu à l’aide de ce code. Figure 5-9 Les tableaux avancés Par l’instanciation de la classe HierarchicalData, nous indiquons au composant Advanced DataGrid que les données alimentant son dataProvider sont de type hiérarchiques. Notons également la spécification du mode de visualisation des données grâce à la propriété designViewDataType, ici affectée à tree, précisant que les données seront présentées sous la forme d’une arborescence. Il nous est également possible de présenter les données de la même manière que pour le composant DataGrid, c’est-à-dire de façon non hiérarchisée, en affectant la valeur Flat à la propriété designViewDataType. Enfin, notons la présence d’un regroupement de colonnes, obtenu grâce à la présence des balises <mx:groupedColumns> et <mx:AdvancedDataGridColumn>. La première indique au composant AdvancedDataGrid que certaines de ces colonnes feront l’objet d’un regroupement, la seconde balise permet de préciser les colonnes devant être regroupées. Interaction avec l’utilisateur La première interaction avec l’utilisateur est la possibilité de trier le tableau sur plusieurs colonnes. Pour ce faire, nous devons activer le mode de tri Expert du composant Advanced DataGrid en affectant la valeur de la propriété sortExpertMode à true. <mx:AdvancedDataGrid x="32" y="69" id="adg1" designViewDataType="tree" width="634" =Flex3 FM.book Page 91 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 height="314" sortExpertMode="true"> </mx:AdvancedDataGrid> Voici comment procéder si nous souhaitons trier la colonne Matière et les valeurs de la colonne Quantité associées : 1. Sélectionnez la colonne Matière en cliquant sur son en-tête. 2. Cliquez ensuite sur la colonne Quantité tout en maintenant la touche Ctrl du clavier enfoncée. Les matières seront alors triées par ordre alphabétique et par quantité croissante (figure 5-10). L’ordre du tri est spécifié par les numéros 1 et 2 apparus à droite des en-têtes des colonnes utilisées pour le tri, et le critère croissant/décroissant est, quant à lui, indiqué par la flèche pointant vers le haut/vers le bas. Notons qu’il est également possible de trier le tableau sur plusieurs colonnes sans activer le mode Expert. Voici la marche à suivre pour cela : 1. Sélectionnez la colonne Matière en cliquant sur son en-tête. 2. Choisissez une seconde colonne pour le tri. 3. En survolant avec la souris l’emplacement où se trouve le numéro d’ordre de tri, celui-ci est alors incrémenté de un. En cliquant sur ce dernier, il est possible d’ajouter un filtre supplémentaire. Figure 5-10 Tri croissant sur les colonnes Matière et Quantité Comme précédemment, si nous maintenons la touche Ctrl enfoncée et cliquons sur la colonne Quantité, les matières seront triées par ordre alphabétique et seront regroupées cette fois-ci par quantité décroissante (figure 5-11). Figure 5-11 Tri croissant sur la colonne Matière et décroissant sur la colonne Quantité 91 =Flex3 FM.book Page 92 Mardi, 2. décembre 2008 3:32 15 92 Comprendre Flex 3 PARTIE I En ce qui concerne la récupération des données de la ligne sélectionnée par l’utilisateur, la méthode employée est identique à celle utilisée pour le composant DataGrid. Analyser un cube OLAP avec OLAPDataGrid L’introduction de ce composant dans la version 3 du framework ouvre les applications Flex vers le monde décisionnel. En effet, grâce au composant OLAPDataGrid, il est possible d’afficher les données issues de requêtes effectuées sur un cube OLAP (OnLine Analytical Processing). Qu’est-ce qu’un cube OLAP ? Dans la mesure où les requêtes décisionnelles exécutées sur des bases de données relationnelles demandaient un nombre important de ressources système pour leur exécution, il convenait d’apporter une solution aux utilisateurs cherchant une réponse à leurs besoins tout en minimisant le temps d’exécution. C’est dans ce but que les bases de données OLAP ont été mises au point, permettant de stocker les données sous forme de dimensions, lesquelles représentent les axes de recherche des utilisateurs. Il devient ainsi possible de combiner ces dimensions afin d’obtenir les résultats voulus. Les bases de données OLAP peuvent être représentées sous forme de cube, appelé cube OLAP. Sur la figure 5-12 illustrant ce concept de base de données, nous pouvons distinguer trois dimensions : • D1 : produit ; • D2 : région ; • D3 : montant des ventes. Figure 5-12 Cube OLAP =Flex3 FM.book Page 93 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 Ces trois dimensions nous permettent de calculer le montant des ventes par région et par produit, représenté par le sous-cube grisé symbolisant la rencontre des trois données. Ce sous-cube sera appelé mesure dans le composant OLAPDataGrid. Le nombre de dimensions étant illimité, il nous sera ainsi possible de déterminer le chiffre d’affaires (dimension 1) d’une filiale (dimension 2) sur une période de 4 mois (dimension 3) pour un certain produit (dimension 4) d’une certaine gamme (dimension 5). L’interrogation des données sur un cube OLAP s’effectue donc par la combinaison de dimensions. Aller plus loin Si vous souhaitez en savoir davantage sur ce point, nous vous conseillons de consulter le site Internet suivant : http://pagesperso-orange.fr/bernard.lupin/index.htm. Création d’un cube OLAP Pour créer notre cube OLAP, nous allons nous baser sur une liste d’enregistrements issus d’une base de données. Nous pourrons ainsi en déduire les dimensions du cube et procéder à sa création. Tableau de données Le tableau 5-2 présente les enregistrements issus d’une base de données totalisant le nombre skieurs annuels sur les trois stations de ski S1, S2 et S3. Tableau 5-2 Données à analyser avec un cube OLAP Station Année Nombre de skieurs S1 2008 12 000 S1 2007 11 000 S1 2006 18 000 S1 2005 17 444 S2 2008 1 200 S2 2007 4 500 S2 2006 8 000 S2 2005 500 S3 2008 12 500 S3 2007 40 000 S3 2006 8 550 S3 2005 6 000 93 =Flex3 FM.book Page 94 Mardi, 2. décembre 2008 3:32 15 94 Comprendre Flex 3 PARTIE I Ce tableau peut être dès à présent implémenté en ActionScript comme suit : <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var donnees:ArrayCollection = new ArrayCollection( [ {station:"S1", skieurs:12000, annee:"2008"}, {station:"S1", skieurs:11000, annee:"2007"}, {station:"S1", skieurs:18000, annee:"2006"}, {station:"S1", skieurs:17444, annee:"2005"}, {station:"S2", {station:"S2", {station:"S2", {station:"S2", skieurs:1200, annee:"2008"}, skieurs:4500, annee:"2007"}, skieurs:8000, annee:"2006"}, skieurs:500, annee:"2005"}, {station:"S3", {station:"S3", {station:"S3", {station:"S3", skieurs:12500, annee:"2008"}, skieurs:40000, annee:"2007"}, skieurs:8550, annee:"2006"}, skieurs:6000, annee:"2005"} ]); ]]> Pour l’instant, nous n’avons fait que réaliser l’implémentation d’un tableau de données. Nous allons à présent voir comment l’utiliser afin de créer les dimensions du cube OLAP. Mise en place des dimensions Grâce au tableau que nous venons de créer, nous pouvons déduire la composition du cube. Celui-ci contiendra ainsi trois dimensions et un champ qui nous servira de mesure : • dimension 1 : le champ station ; • dimension 2 : le champ skieurs ; • dimension 3 : le champ annee ; • champ de mesure : skieurs, dont nous calculerons la somme. Voyons comment créer le cube et ses dimensions : <mx:OLAPCube name="cubeOLAP" dataProvider="{donnees}" id="id_cube" > <mx:OLAPDimension name="dim_station"> <mx:OLAPAttribute name="att_station" dataField="station"/> <mx:OLAPHierarchy name="hier_station" hasAll="true"> <mx:OLAPLevel attributeName="att_station"/> =Flex3 FM.book Page 95 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPDimension name="dim_skieurs"> <mx:OLAPAttribute name="att_skieurs" dataField="skieurs"/> <mx:OLAPHierarchy name="hier_skieurs" hasAll="true"> <mx:OLAPLevel attributeName="att_skieurs"/> </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPDimension name="dim_annee"> <mx:OLAPAttribute name="att_annee" dataField="annee"/> <mx:OLAPHierarchy name="hier_annee" hasAll="true"> <mx:OLAPLevel attributeName="att_annee"/> </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPMeasure name="SommeSkieurs" dataField="skieurs" aggregator="SUM"/> </mx:OLAPCube> Notre cube OLAP est créé à l’aide de la balise <mx:OLAPCube>. Les dimensions, quant à elles, sont créées à l’aide de la balise <mx:OLAPDimension>. Chaque dimension est définie par un attribut (<mx:OLAPAttribut>) et un niveau de hiérarchie (<mx:OLAPHierarchy> et <mx:OLAPLevel>). Une hiérarchie représente, de façon simplifiée, le nombre de champs contenus dans la dimension. Dans notre exemple, chaque dimension possède une hiérarchie à un seul niveau. Enfin, nous devons créer une mesure, c’est-à-dire une valeur que nous pourrons visualiser lorsque nous effectuerons des opérations sur le cube. Nous avons ici choisi comme mesure la somme du nombre de skieurs (<mx:OLAPMeasure>). Le cube sera alimenté en données à l’aide de sa propriété dataProvider qui doit être liée à au tableau. Notre cube est à présent créé et nous pouvons désormais effectuer notre première requête. Requête sur le cube La requête que nous allons effectuer nous permettra de visualiser le nombre de skieurs par station et par année. Le résultat obtenu sera affiché dans le composant OLAPDataGrid. La liste des stations s’affichera en lignes et la liste des années en colonnes. À chaque intersection, nous retrouverons notre mesure spécifiée lors de la création du cube, c’està-dire la somme du nombre de skieurs. Le code suivant correspond au code complet de l’application. Nous l’avons commenté pour vous permettre de comprendre la méthode de création d’une requête sur un cube OLAP afin d’en afficher le résultat. 95 =Flex3 FM.book Page 96 Mardi, 2. décembre 2008 3:32 15 96 Comprendre Flex 3 PARTIE I Important Le composant OLAPDataGrid sert uniquement à afficher le résultat d’une requête réalisée sur un cube OLAP. Il est donc impossible d’afficher les données du cube dans le composant OLAPDataGrid. En effet, un cube possédant plusieurs dimensions, il serait très difficile de les représenter dans un composant ne présentant que deux dimensions (lignes et colonnes) ! <?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="afficherOLAPDataGrid();"> <mx:Script> <![CDATA[ import mx.rpc.AsyncResponder; import mx.rpc.AsyncToken; import mx.olap.OLAPQuery; import mx.olap.OLAPSet; import mx.olap.IOLAPQuery; import mx.olap.IOLAPQueryAxis; import mx.olap.IOLAPCube; import mx.olap.OLAPResult; import mx.events.CubeEvent; import mx.controls.Alert; import mx.collections.ArrayCollection; [Bindable] private var donnees:ArrayCollection = new ArrayCollection( [ {station:"S1", skieurs:12000, annee:"2008"}, {station:"S1", skieurs:11000, annee:"2007"}, {station:"S1", skieurs:18000, annee:"2006"}, {station:"S1", skieurs:17444, annee:"2005"}, {station:"S2", {station:"S2", {station:"S2", {station:"S2", skieurs:1200, annee:"2008"}, skieurs:4500, annee:"2007"}, skieurs:8000, annee:"2006"}, skieurs:500, annee:"2005"}, {station:"S3", {station:"S3", {station:"S3", {station:"S3", skieurs:12500, annee:"2008"}, skieurs:40000, annee:"2007"}, skieurs:8550, annee:"2006"}, skieurs:6000, annee:"2005"} ]); /***************************** * 1 : CRÉATION DE LA REQUÊTE * ***************************/ =Flex3 FM.book Page 97 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 private function creerRequete(cube:IOLAPCube):IOLAPQuery { // Instanciation de la classe OLAPQUery permettant de créer un objet requête var requete:OLAPQuery = new OLAPQuery; // Création de "l’axe" des lignes var ligne:IOLAPQueryAxis = requete.getAxis(OLAPQuery.ROW_AXIS); // Création de "l’axe" des colonnes var colonne:IOLAPQueryAxis = requete.getAxis(OLAPQuery.COLUMN_AXIS); // --- AJOUT DES STATIONS DANS L’AXE DES LIGNES --var lg_stations:OLAPSet = new OLAPSet; lg_stations.addElements(cube.findDimension("dim_station"). ➥findAttribute("att_station").children); ligne.addSet(lg_stations); // --- AJOUT DES ANNÉES DANS L’AXE DES COLONNES --var col_annee:OLAPSet= new OLAPSet; col_annee.addElements( cube.findDimension("dim_annee").findAttribute("att_annee").children); colonne.addSet(col_annee); // Envoi de la requête pour être exécutée par la procédure ➥executerRequête() return requete; } /***************************** * 2 : EXÉCUTION DE LA REQUÊTE * ***************************/ private function executerRequete(event:CubeEvent):void { // Chargement du cube var cube:IOLAPCube = IOLAPCube(event.currentTarget); // Réception de la requête par la fonction creerRequete() précédemment ➥créée var requete:IOLAPQuery = creerRequete(cube); // Exécution de la requête var execution:AsyncToken = cube.execute(requete); // Exécution des procédures afficherResultat ou afficherErreur en 97 =Flex3 FM.book Page 98 Mardi, 2. décembre 2008 3:32 15 98 Comprendre Flex 3 PARTIE I ➥fonction du résultat d’exécution de la requête execution.addResponder(new AsyncResponder(afficherResultat, ➥afficherErreur)); } /***************************** * 3 : AFFICHAGE DU RÉSULTAT * ***************************/ private function afficherErreur(result:Object, token:Object):void { Alert.show("Erreur d’exécution de la requête"); } private function afficherResultat(result:Object, token:Object):void { if (!result) { Alert.show("Aucun résultat à afficher"); return; } // Mise à jour du composant OLAPDataGrid OLAPDg.dataProvider= result as OLAPResult; } /********************************************* * 4 : MISE À JOUR DU COMPOSANT OLAPDATAGRID * Dès la fin de la création de l’application * (creationCompleted) * *******************************************/ private function afficherOLAPDataGrid():void { // On rafraîchit le cube qui va exécuter la requête // L’exécution de la procédure executerRequete est appelée // Après création du cube : complete="executerRequete(event)" id_cube.refresh(); } ]]> </mx:Script> <mx:OLAPCube name="cubeOLAP" dataProvider="{donnees}" id="id_cube" complete="executerRequete(event)"> <mx:OLAPDimension name="dim_station"> <mx:OLAPAttribute name="att_station" dataField="station"/> =Flex3 FM.book Page 99 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 <mx:OLAPHierarchy name="hier_station" hasAll="true"> <mx:OLAPLevel attributeName="att_station"/> </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPDimension name="dim_skieurs"> <mx:OLAPAttribute name="att_skieurs" dataField="skieurs"/> <mx:OLAPHierarchy name="hier_skieurs" hasAll="true"> <mx:OLAPLevel attributeName="att_skieurs"/> </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPDimension name="dim_annee"> <mx:OLAPAttribute name="att_annee" dataField="annee"/> <mx:OLAPHierarchy name="hier_annee" hasAll="true"> <mx:OLAPLevel attributeName="att_annee"/> </mx:OLAPHierarchy> </mx:OLAPDimension> <mx:OLAPMeasure name="TotSkieurs" dataField="skieurs" aggregator="SUM"/> </mx:OLAPCube> <!-- IMPLÉMENTATION DU COMPOSANT OLAPDATAGRID --> <mx:OLAPDataGrid id="OLAPDg" width="100%" height="275"/> </mx:Application> La figure 5-13 illustre le résultat obtenu lors de l’exécution de la requête sur le cube OLAP. Les lignes correspondent comme convenu aux stations et les années s’affichent en colonnes. À l’intersection de ces lignes et colonnes, nous pouvons voir la valeur de la mesure. Figure 5-13 Utilisation du composant OLAPDataGrid 99 =Flex3 FM.book Page 100 Mardi, 2. décembre 2008 3:32 15 100 Comprendre Flex 3 PARTIE I Tri des colonnes Le composant OLAPDataGrid ne permet pas de tri sur les colonnes affichées alors que c’est le cas avec le composant AdvancedDataGrid. Insérer des images, des animations et vidéos Flash Intégrer des animations Flash Grâce au composant SWFLoader, il est possible d’intégrer des animations ou tout autre programme Flash dans les applications Flex. <mx:SWFLoader width="148" height="133" id="animation_flash" scaleContent="true" autoLoad="true" source="animation.swf"> </mx:SWFLoader> L’attribut scaleContent permet d’adapter la taille de l’animation par rapport à celle du composant. La propriété autoLoad sert, quant à elle, à spécifier si l’animation doit être lue automatiquement (true) ou non (false). Pour charger une animation par programmation, il convient donc de spécifier la source et d’exécuter la procédure load() du composant : public function chargerSWF():void { animation_flash.source = "animation.swf"; animation_flash.load(); } Insérer des images L’insertion d’images est possible par l’utilisation du composant Image. L’implémentation de ce composant est identique à celle du composant SWFLoader. Nous retrouvons donc les propriétés source et scaleContent. <mx:Image width="128" height="73" id="img_image" scaleContent="false" source="image.gif" /> Conseil Afin que vos images et animations Flash soient prises en compte lors de la compilation de votre projet, nous vous conseillons de créer un dossier images dans le répertoire src du projet et d’y ajouter l’ensemble de vos images ou animations Flash. =Flex3 FM.book Page 101 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 101 Lecteur vidéo Flash Le composant VideoDisplay permet de lire des vidéos Flash (fichiers .flv), comme le propose par exemple le site de YouTube. Le code suivant illustre l’utilisation du composant VideoDisplay et de ses méthodes Play() et Stop() permettant respectivement de démarrer et de stopper la lecture d’une vidéo (figure 5-14) : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:VideoDisplay x="28" y="31" width="292" height="263" source="DSCF1311.flv" ➥id="cpVideo" autoPlay="false"/> <mx:Button x="28" y="302" label="Jouer" click="cpVideo.play();" id="btn_play"/> <mx:Button x="94" y="302" label="Stop" id="btn_stop" click="cpVideo.stop();"/> </mx:Application> La propriété source permet de définir le chemin de la vidéo qui doit être lue par le composant. La lecture de la vidéo s’effectue par l’appel de la méthode Play() de la classe Video Display.L’arrêt passe par l’emploi de la méthode Stop(). Notez qu’il est également possible de lire automatiquement la vidéo en affectant la valeur true à la propriété autoPlay du composant. Figure 5-14 Lecture d’une vidéo Flash =Flex3 FM.book Page 102 Mardi, 2. décembre 2008 3:32 15 102 Comprendre Flex 3 PARTIE I Afficher la progression du chargement de la vidéo Le composant VideoDisplay ne dispose pas d’une barre de progression intégrée. Pour l’afficher, il convient de développer cette fonctionnalité en utilisant la méthode progress du composant qui tout au long du chargement exécutera une procédure permettant de calculer le nombre d’octets chargés. L’exemple de code suivant montre comment procéder pour afficher le pourcentage du chargement de la vidéo dans une zone de texte : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ // Procédure d’affichage de la barre de progression du chargement de la vidéo [Bindable] public var texte:String public function afficherProgression(e:ProgressEvent):void { // Affichage de la barre de progression txt_progression.visible = true; // Taille de la vidéo var tailleVideo:Number = e.bytesTotal; // Nombre d’octets chargés: var nbOctets:Number = e.bytesLoaded; // Calcul du pourcentage de chargement var pourcentage:Number = Math.round((nbOctets/tailleVideo)*100) // Affichage du texte texte = "Chargement de la vidéo : "+ String(pourcentage)+"%"; } ]]> </mx:Script> <mx:VideoDisplay progress="afficherProgression(event)" x="28" y="31" width="292" ➥height="263" source="DSCF1311.flv" id="cpVideo" autoPlay="false"/> <mx:Button x="28" y="302" label="Jouer" click="cpVideo.play();" id="btn_play"/> <mx:Button x="94" y="302" label="Stop" id="btn_stop" click="cpVideo.stop();"/> =Flex3 FM.book Page 103 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 103 <!-- AFFICHAGE DE LA PROGRESSION DU CHARGEMENT --> <mx:Label text="{texte}" fontWeight="bold" fontSize="12" x="28" y="330" width="325" id="txt_progression" visible="false"> </mx:Label> </mx:Application> Choisir une couleur dans une palette avec ColorPicker Ce composant trouve sa place dans une application à vocation graphique. En effet, il permet de choisir une couleur dans une palette par défaut ou définie par le développeur (figure 5-15). Figure 5-15 Composant ColorPicker Prenons comme exemple de travail un jeu de Mastermind où l’utilisateur peut choisir une couleur parmi les suivantes (figure 5-16) : Couleur Code correspondant Bleu 0x0033CC 0x33CC00 0xFF0000 0xFFFF00 0xFF9900 0x9900CC 0xFF00FF Vert Rouge Jaune Orange Violet Fuchsia =Flex3 FM.book Page 104 Mardi, 2. décembre 2008 3:32 15 104 Comprendre Flex 3 PARTIE I Figure 5-16 Exemple d’utilisation du composant ColorPicker dans le jeu Mastermind <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var tableauCouleurs:Array = ['0x0033CC','0x33CC00', ➥'0xFF0000','0xFFFF00','0xFF9900','0x9900CC','0xFF00FF' ]; ]]> </mx:Script> <mx:ColorPicker id="selecteurCouleur" x="86" y="75" dataProvider="{tableauCouleurs}" /> </mx:Application> La liste des couleurs est contenue dans un tableau servant à alimenter le dataProvider du composant. Pour récupérer le code couleur sélectionné, on utilisera la propriété selected Item du composant, comme nous l’aurions fait pour une simple liste. Contrôler le format de date avec DateChooser et DateField Afin de faciliter la saisie et d’éviter les erreurs de format de date, Flex met à votre disposition deux composants : • Le composant dateChooser qui se présente sous la forme d’un calendrier grâce auquel l’utilisateur peut sélectionner la date souhaitée. Notez néanmoins que la date ainsi choisie n’est pas présente sous forme littérale (par exemple : 16 octobre 2008). • Le composant dateField qui se présente sous la forme d’une zone de texte contenant la date au format littéral et dont le contenu ne peut être modifié qu’en sélectionnant une date dans le calendrier associé. =Flex3 FM.book Page 105 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 105 De nombreux paramétrages peuvent être effectués sur ces composants. Dans l’exemple suivant, nous avons choisi de les « franciser » en affichant les mois en français dans les calendriers et la date au format jour/mois/année dans le composant dateField. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var moisFrancais:Array = ['Janvier','Février','Mars','Avril', ➥'Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre']; ]]> </mx:Script> <mx:DateChooser id="calendrier" x="35" y="31" monthNames="{moisFrancais}"/> <mx:DateField id="zoneDeTexte" x="35" y="219" formatString="DD/MM/YYYY" ➥monthNames="{moisFrancais}"/> </mx:Application> Il est possible de connaître la date sélectionnée à l’aide de la propriété selectedDate accompagnée de la donnée choisie. Prenons pour exemple la date 02/03/2008, sélectionnée dans le composant Calendrier : • Calendrier.selectedDate.date renverra la valeur 2. • Calendrier.selectedDate.month retournera la valeur 2 étant donné que le premier mois de l’année porte le numéro 0. • Calendrier.selectedDate.fullYear retournera la valeur 2008. Ajouter un curseur avec HSlider et VSlider L’intérêt de ces composants est qu’ils permettent à l’utilisateur de sélectionner une valeur dans un intervalle défini en déplaçant simplement un curseur sur une barre horizontale (HSlider) ou verticale (VSlider). Voyons comment implémenter ce composant à travers les quelques lignes suivantes : <mx:HSlider id=”intervalHorizontal” x="10" y="21" tickInterval="2" minimum="0" snapInterval="2" maximum="20" labels="[0,2,4,6,8,10,12,14,16,18,20]" width="270"/> =Flex3 FM.book Page 106 Mardi, 2. décembre 2008 3:32 15 106 Comprendre Flex 3 PARTIE I Figure 5-17 Composant HSlider Comme le montre la figure 5-17, le composant créé pour le code précédent est de type horizontal et propose un intervalle de valeurs comprises entre 0 et 20 avec un pas de 2 (tickInterval). Le déplacement du curseur sera également effectué à l’aide d’un pas de 2 grâce à la propriété snapInterval portée à cette valeur. Par ailleurs, les libellés ont été définis manuellement afin de rendre l’utilisation du composant plus conviviale, car les libellés ne sont pas spécifiés par défaut lors de la mise en place de ces deux composants. Enfin, la valeur sur laquelle est positionné le curseur peut aisément être récupérée grâce à la propriété value du composant. L’incrémentation avec NumericStepper Le composant NumericStepper est semblable aux composants HSlider et Vslider à la seule différence que l’utilisateur utilise dans ce cas un ascenseur et non un curseur (figure 5-18). Figure 5-18 Composant NumericStepper <mx:NumericStepper id="numStepper" x="10" y="28" minimum="0" maximum="20" stepSize="2"/> Au titre des différences, soulignons également l’emploi la propriété stepSize (au lieu de tickInterval pour les composants Hslider et Vslider) qui permet de définir le pas. Présentation de données avec HorizontalList et TileList Ces composants permettent de présenter des données en combinant aspect graphique et données. En d’autres termes, si nous considérons une application spécifique au domaine du e-commerce, ces composants peuvent êtres utilisés afin de visualiser l’image d’un produit ainsi que ses caractéristiques (prix, description, etc.). Dans un autre domaine, nous pouvons utiliser ces composants dans le milieu médical afin d’afficher la liste des lits hospitaliers occupés ou non avec le nom du patient le cas échéant (figure 5-19). Pour cela, il convient de placer deux images dans le répertoire images préalablement créé dans le répertoire src du projet. =Flex3 FM.book Page 107 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 107 Figure 5-19 Composant HorizontalList <mx:HorizontalList id="hzliste" x="10" y="28" width="381"> <mx:dataProvider> <mx:Array> <mx:Object label="M. Dupont" icon="@Embed(source='images/litOccupe ➥.jpg')"/> <mx:Object label="--" icon="@Embed(source='images/litVide.jpg')"/> <mx:Object label="Mme Lesage" icon="@Embed(source='images/litOccupe ➥.jpg')"/> </mx:Array> </mx:dataProvider> </mx:HorizontalList> Cet exemple permet d’introduire la méthode d’alimentation du dataProvider de notre composant ; elle est bien évidemment identique pour l’ensemble des composants utilisant un dataProvider. Il s’agit d’illustrer en MXML le ArrayCollection du langage ActionScript. On retrouve la balise Array, contenant l’ensemble des objets (object) possédant les attributs label et icon. Réaliser des hyperliens grâce à LinkButton Ce composant permet à l’utilisateur d’ouvrir la page web associée à un hyperlien après avoir cliqué dessus (figure 5-20), grâce à la méthode navigateToUrl. Figure 5-20 Composant LinkButton <mx:LinkButton x="21" y="37" label="Lien vers les éditions Eyrolles" click="navigateToURL(new URLRequest('http://www.eyrolles.com'))" /> =Flex3 FM.book Page 108 Mardi, 2. décembre 2008 3:32 15 108 Comprendre Flex 3 PARTIE I Cette portion de code provoque l’ouverture d’une nouvelle fenêtre dans le navigateur web. Notez que l’affichage de cette fenêtre peut être bloqué en fonction des paramètres de sécurité spécifiés sur votre poste de travail. Afficher des données sous forme d’arborescence Le composant Tree est très souvent utilisé pour afficher des données organisées de façon hiérarchique (listing des fichiers d’un répertoire, e-mails contenus dans la boîte de réception d’un logiciel de messagerie électronique…). Implémentation et alimentation en données <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var listeXML:XML = new XML( <fichiers> <niveau1 label='N1'> <niveau2 label='N2'> <element id='1' label='Fichier 1'/> </niveau2> </niveau1> <niveau1 label='N1'> <niveau2 label='N2'> <element id='2' label='Fichier 2'/> </niveau2> </niveau1> <niveau1 label='N1'> <niveau2 label='N2'> <element id='3' label='Fichier 3'/> </niveau2> </niveau1> </fichiers> ); ]]> </mx:Script> <mx:Tree x="10" y="10" width="258" height="376" id="arbre" dataProvider="{listeXML.niveau1}" labelField="@label"> </mx:Tree> </mx:Application> =Flex3 FM.book Page 109 Mardi, 2. décembre 2008 3:32 15 Les composants de contrôle CHAPITRE 5 109 Un arbre (figure 5-21) ayant pour vocation d’afficher des données hiérarchiques telles que celles contenues dans un fichier XML, nous avons donc tout naturellement créé une variable XML contenant un ensemble de données. Cette variable va alimenter le dataProvider du composant Tree en prenant soin de sélectionner le niveau1 comme premier niveau hiérarchique. Il faut également spécifier les libellés pour assurer la présentation des données (labelField). Pour cela que nous faisons appel à la propriété label (@label) de chaque nœud. Figure 5-21 Affichage de données hiérarchiques à l’aide du composant Tree Interaction avec l’utilisateur La principale interaction consiste à récupérer la valeur d’un nœud de l’arbre sélectionné par l’utilisateur afin de l’exploiter dans un traitement. Voici comment procéder : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.events.ListEvent; import mx.controls.Alert [Bindable] public var listeXML:XML = new XML( <fichiers> <niveau1 label='N1'> =Flex3 FM.book Page 110 Mardi, 2. décembre 2008 3:32 15 110 Comprendre Flex 3 PARTIE I <niveau2 label='N2'> <element id='1' label='Fichier 1'/> </niveau2> </niveau1> <niveau1 label='N1'> <niveau2 label='N2'> <element id='2' label='Fichier 2'/> </niveau2> </niveau1> <niveau1 label='N1'> <niveau2 label='N2'> <element id='3' label='Fichier 3'/> </niveau2> </niveau1> </fichiers> ); public function afficherLabel(e:ListEvent):void { Alert.show(e.currentTarget.selectedItem.@label); } ]]> </mx:Script> <mx:Tree x="10" y="10" width="258" height="376" id="arbre" dataProvider="{listeXML.niveau1}" labelField="@label" itemClick="afficherLabel(event)"> </mx:Tree> </mx:Application> Lorsque l’utilisateur clique sur un élément de l’arbre (itemClick), cela déclenche l’exécution de la procédure afficherLabel() dont l’événement de type ListeEvent est passé en paramètre, permettant ainsi de déterminer l’élément de l’arbre sélectionné et d’en extraire sa propriété label (@label) En résumé Dans ce chapitre, nous avons étudié les composants permettant une interaction avec l’utilisateur de l’application. Nous sommes à présent en mesure de créer des listes déroulantes, de déclencher des actions à l’aide de boutons, de présenter des données sous forme tabulaire, etc. L’étape suivante va consister à étudier les composants qui vont nous permettre de positionner ces composants de contrôle. =Flex3 FM.book Page 111 Mardi, 2. décembre 2008 3:32 15 6 Les composants conteneurs Grâce à la lecture du chapitre précédent, vous connaissez maintenant les principaux composants de contrôle. Nous allons désormais vous présenter les différents composants chargés de jouer le rôle de « conteneur de composants » et permettant d’agencer et d’organiser ces derniers. Créer une barre de menus avec ApplicationControlBar Le composant ApplicationControlBar permet de créer une barre de menus utile à la navigation dans laquelle diverses actions, comme un champ de recherche, peuvent être proposées. Le code suivant permet de créer une barre de menus contenant une zone de texte et un bouton Rechercher afin que l’utilisateur puisse effectuer une recherche dans un champ d’une base de données (figure 6-1). <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ApplicationControlBar x="10" y="10" dock="true"> <mx:Label text="Rechercher :" id="lab_rechercher"/> <mx:TextInput id="txt_rechercher"/> <mx:Button label="Ok" width="42" id="btn_ok"/> </mx:ApplicationControlBar> </mx:Application> =Flex3 FM.book Page 112 Mardi, 2. décembre 2008 3:32 15 112 Comprendre Flex 3 PARTIE I En affectant la valeur true à la propriété dock, nous indiquons que nous souhaitons que la barre de menus soit positionnée en haut de l’application. Pour la placer à un autre endroit dans l’application, il suffit de passer cette valeur à false. Figure 6-1 Utilisation du composant ApplicationControlBar Le composant Canvas Ce composant conteneur Canvas permet de placer d’autres composants à l’intérieur de celui-ci à l’aide de leurs coordonnées x et y. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Canvas id="cn1" x="54" y="48" width="200" height="200"> <mx:Button x="51" y="93" label="Valider" id="btn_valider"/> </mx:Canvas> </mx:Application> Nous constatons que le composant Button est positionné à l’intérieur du canevas à l’aide de ses propriétés x et y (figure 6-2). Exactement comme en algèbre, les coordonnées (x,y) des éléments situés dans le canevas ont pour coordonnées relatives le coin supérieur gauche du canevas. Ainsi, notre bouton est espacé de 51 pixels sur l’axe horizontal et de 93 pixels sur l’axe vertical du coin supérieur gauche du canevas. Figure 6-2 Utilisation du composant Canvas =Flex3 FM.book Page 113 Mardi, 2. décembre 2008 3:32 15 Les composants conteneurs CHAPITRE 6 113 Aligner verticalement ou horizontalement les composants Nous allons à présent voir comment aligner automatiquement les composants selon un axe horizontal ou vertical. Les composants HBox et VBox Le composant HBox permet d’aligner automatiquement les composants sur l’axe horizontal (les uns à côté des autres), alors que le composant VBox permet de les aligner sur l’axe vertical (les uns en dessous des autres). À l’aide du code suivant, nous avons illustré l’implémentation des composants HBox et VBox via l’organisation horizontale (HBox) et ou verticale (VBox) de trois boutons. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Label id="lab" x="10" y="5" text="HBox" width="151" fontWeight="bold"/> <mx:HBox id="hb" x="10" y="29" width="151"> <mx:Button label="B1" id="btn_1"/> <mx:Button label="B2" id="btn_2"/> <mx:Button label="B3" id="btn_3"/> </mx:HBox> <mx:Label id="lab2" x="220" y="5" text="VBox" width="151" fontWeight="bold"/> <mx:VBox id="vb" x="220" y="29" height="116"> <mx:Button label="B4" id="btn_4"/> <mx:Button label="B5" id="btn_5"/> <mx:Button label="B6" id="btn_6"/> </mx:VBox> </mx:Application> La figure 6-3 présente le résultat ainsi obtenu. Figure 6-3 Composants HBox et VBox Les composants HDividedBox et VDividedBox Ces composants ont le même rôle que les composants HBox et VBox à la seule différence qu’ils permettent d’afficher un séparateur mobile. =Flex3 FM.book Page 114 Mardi, 2. décembre 2008 3:32 15 114 Comprendre Flex 3 PARTIE I Le code suivant illustre un exemple d’implémentation de ces deux composants : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Label id="lab" x="10" y="17" text="HDividedBox" fontWeight="bold"/> <mx:HDividedBox id="hdb" x="10" y="43" width="540" height="116"> <mx:Canvas id="cv1" width="200" height="115" backgroundColor="#BCB8B8"> </mx:Canvas> <mx:Canvas id="cv2" width="230" height="115" backgroundColor="#F9F8F8"> </mx:Canvas> </mx:HDividedBox> <mx:Label id="lab2" x="10" y="172" text="VDividedBox" fontWeight="bold"/> <mx:VDividedBox id="vdb" x="10" y="198" height="312" width="540"> <mx:Canvas id="cv3" width="539" height="200" backgroundColor="#BCB8B8"> </mx:Canvas> <mx:Canvas id="cv4" width="541" height="200" backgroundColor="#FBFBFB"> </mx:Canvas> </mx:VDividedBox> </mx:Application> La figure 6-4 illustre le résultat obtenu après exécution de ce code. On constate la présence d’un séparateur pouvant être déplacé vers la gauche ou vers la droite pour le composant HDividedBox, et vers le haut ou vers le bas pour le composant VdividedBox. L’utilisateur peut ainsi agrandir ou réduire la zone de son choix en sélectionnant ce séparateur et en déplaçant sa souris de droite à gauche ou de haut en bas. Figure 6-4 Implémentation des composants HDividedBox et VDividedBox =Flex3 FM.book Page 115 Mardi, 2. décembre 2008 3:32 15 Les composants conteneurs CHAPITRE 6 115 Créer des formulaires avec Form, FormHeading et FormItem Les composants Form, FormHeading et FormItem sont les plus communément utilisés au sein des applications Flex car ils permettent de créer des formulaires de saisie. Le code suivant permet de créer un formulaire d’inscription intitulé « Nouvel utilisateur : » (FormHeading) ainsi que les trois items de formulaire (FormItem) suivants : • l’item Prénom, dont la saisie est obligatoire (required="true") ; • l’item Nom ; • le bouton Valider. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Form x="10" y="19" width="269" height="168"> <mx:FormHeading label="Nouvel utilisateur :"/> <mx:FormItem id="fit1" label="Prénom :" required="true"> <mx:TextInput id="txt_prenom"/> </mx:FormItem> <mx:FormItem id="fit2" label="Nom :"> <mx:TextInput id="txt_nom"/> </mx:FormItem> <mx:FormItem id="fit3"> <mx:Button label="Valider" id="btn_valider"/> </mx:FormItem> </mx:Form> </mx:Application> La figure 6-5 illustre le résultat obtenu. Figure 6-5 Création d’un formulaire =Flex3 FM.book Page 116 Mardi, 2. décembre 2008 3:32 15 116 Comprendre Flex 3 PARTIE I Créer une grille grâce à Grid Le composant Grid permet d’organiser les composants selon une grille. Le code suivant illustre son implémentation constitué de trois lignes et de trois colonnes dont certaines doivent contenir un chiffre. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Grid id="gd" x="10" y="10" width="212" height="198"> <mx:GridRow width="100%" height="100%"> <mx:GridItem width="100%" height="43"> <mx:Label text="1" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l1"/> </mx:GridItem> <mx:GridItem width="100%" height="100%"> <mx:Label text="3" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l2"/> </mx:GridItem> <mx:GridItem width="100%" height="100%"> </mx:GridItem> </mx:GridRow> <mx:GridRow width="100%" height="100%"> <mx:GridItem width="100%" height="100%"> </mx:GridItem> <mx:GridItem width="100%" height="100%"> <mx:Label text="2" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l3"/> </mx:GridItem> <mx:GridItem width="100%" height="100%"> <mx:Label text="1" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l4"/> </mx:GridItem> </mx:GridRow> <mx:GridRow width="100%" height="100%"> <mx:GridItem width="100%" height="100%"> <mx:Label text="3" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l5"/> </mx:GridItem> <mx:GridItem width="100%" height="100%"> <mx:Label text="1" fontWeight="bold" fontSize="28" height="39" width="65" ➥textAlign="center" id="l6"/> </mx:GridItem> <mx:GridItem width="100%" height="100%"> </mx:GridItem> </mx:GridRow> </mx:Grid> </mx:Application> =Flex3 FM.book Page 117 Mardi, 2. décembre 2008 3:32 15 Les composants conteneurs CHAPITRE 6 117 Chaque ligne est créée grâce à la balise <mx:GridRow> et le nombre de cellules qu’elle contient est spécifié par la balise <mx:GridItem>. La figure 6-6 illustre le résultat obtenu après exécution du code. Figure 6-6 Utilisation du composant Grid Les panneaux : Panel Le composant Panel est l’un des composants de type conteneur les plus utilisés. Il permet en effet de disposer les composants à l’aide de leur coordonnées x et y, tout comme le composant Canvas mais en offrant un aspect graphique plus intéressant comme la présence d’un titre ou la possibilité d’ajouter une icône. Le code suivant met en place un composant Panel contenant un formulaire d’identification et une icône. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel x="10" y="10" width="355" height="182" titleIcon="@Embed('login.jpg')" ➥layout="absolute" title="Identification" id="panel_identification"> <mx:Form id="form" x="10" y="10" width="315" height="117"> <mx:FormItem id="fit1" label="Identifiant :"> <mx:TextInput id="id_txt"/> </mx:FormItem> <mx:FormItem id="fit2" label="Mot de passe :"> <mx:TextInput displayAsPassword="true" id="mdp_txt" text=”1234”/> </mx:FormItem> <mx:FormItem id="fit3"> <mx:Button label="OK" id="btn_ok"/> </mx:FormItem> </mx:Form> </mx:Panel> </mx:Application> =Flex3 FM.book Page 118 Mardi, 2. décembre 2008 3:32 15 118 Comprendre Flex 3 PARTIE I Par l’utilisation de la propriété titleIcon, il nous est possible d’affecter une icône au composant Panel. Notez également que nous avons affecté la valeur true à la propriété displayPassword du composant mdp_txt. Ceci a pour effet de remplacer le texte en cours de saisie par des astérisques, permettant ainsi de cacher le mot de passe. Le résultat obtenu après exécution de ce code est représenté à la figure 6-7. Figure 6-7 Composant Panel Créer des fenêtres pop-ups avec TitleWindow La création d’une fenêtre pop-up s’effectue en deux temps : la première étape consiste à créer le pop-up et la seconde, à faire appel à ce dernier dans la fenêtre de l’application principale. Nous allons voir cela en détail. Création du pop-up Pour réaliser un pop-up, il convient tout d’abord de créer un projet que nous nommerons projetPopUp, dans lequel nous créerons un nouveau fichier composant MXML, nommé popUp.mxml, via le menu File>New>MXML Component. Ce fichier doit être basé sur le composant TitleWindow, et va décrire l’interface graphique du pop-up grâce au code suivant : <?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" width="248" height="204" title="Fenêtre pop-up" showCloseButton="true" close="fermerPopUp()" > <mx:Script> <![CDATA[ import mx.managers.PopUpManager public function fermerPopUp():void { PopUpManager.removePopUp(this); } ]]> =Flex3 FM.book Page 119 Mardi, 2. décembre 2008 3:32 15 Les composants conteneurs CHAPITRE 6 119 </mx:Script> <mx:TextInput id="txt_message"/> <mx:Button label="Ok" id="btn_ok"/> </mx:TitleWindow> Ici, nous avons implémenté une procédure faisant appel à la classe PopUpManager qui permet de gérer les pop-ups. Cette classe propose deux méthodes principales pour cela : • createPopUp(fenêtre chargée de contenir le pop-up, Nom du pop-up, pop-up modal (true/false)) permet de créer et d’afficher le pop-up ; • removePopUp(nom du pop-up) supprime le pop-up. Grâce à ces méthodes, nous avons créé une procédure déclenchant la fermeture du popup lorsque l’utilisateur clique sur la croix de fermeture située en haut à droite du pop-up, dont nous avons spécifié la présence en affectant la valeur true à la propriété showCloseButton (figure 6-8). Figure 6-8 Création de la fenêtre pop-up Appel du pop-up Maintenant que nous avons créé le pop-up, nous allons voir comment l’utiliser au sein de notre application. Plaçons-nous à présent dans le fichier principal de l’application (projetPopUp.mxml) et saisissons le code suivant : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.managers.PopUpManager; public function ouvrirPopUp():void{ =Flex3 FM.book Page 120 Mardi, 2. décembre 2008 3:32 15 120 Comprendre Flex 3 PARTIE I PopUpManager.createPopUp(this,popUp,true); } ]]> </mx:Script> <mx:Button x="32" y="32" label="Afficher pop-up" click="ouvrirPopUp()" ➥id="btn_ouvrirpopup"/> </mx:Application> Dans cet exemple, le bouton btn_ouvrirpopup déclenche l’exécution de la procédure ouvrirPopUp() qui crée un nouveau pop-up à partir du fichier popUp.mxml que nous venons d’enregistrer (figure 6-9). La création de cette fenêtre pop-up est réalisée à l’aide de la méthode createPopUp de la classe PopUpManager. Voyons sa syntaxe en détail : • This = fenêtre parent (dans notre cas, il s’agit de la fenêtre principale de l’application). • popUp = nom du fichier MXML implémentant le composant TitleWindow. • true = spécifie si le pop-up doit être modal (c’est-à-dire s’il doit être fermé pour permettre l’utilisation de la fenêtre parent) ou non. Figure 6-9 Ouverture d’un pop-up Communiquer avec le pop-up Créer un pop-up c’est bien, mais pouvoir communiquer avec lui c’est encore mieux ! Nous allons, à travers le code suivant, montrer comment envoyer des données au pop-up. Ces dernières seront ensuite affichées dans une zone de texte du pop-up. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.managers.PopUpManager; =Flex3 FM.book Page 121 Mardi, 2. décembre 2008 3:32 15 Les composants conteneurs CHAPITRE 6 121 public function ouvrirPopUp():void{ <!-- Création d’un objet de type pop-up issu du fichier popUp.mxml --> var objetPopUp:popUp = popUp(PopUpManager.createPopUp(this,popUp,true)); <!-- Modification de la propriété text du champ txt_message de l’objet ➥objetPopUp --> objetPopUp.txt_message.text = "Message transferé !"; } ]]> </mx:Script> <mx:Button x="32" y="32" label="Afficher pop-up" click="ouvrirPopUp()" ➥id="btn_ouvrirpopup"/> <mx:TextInput x="32" y="71" id="txt_messageapplication"/> </mx:Application> En premier lieu, nous avons ajouté une zone de texte dans le fichier MXML de l’application, afin que les données transmises puissent y être affichées : <mx:TextInput x="32" y="71" id="txt_messageapplication"/> Nous avons ensuite modifié le code du pop-up comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" width="248" height="204" title="Fenêtre pop-up" showCloseButton="true" close="fermerPopUp()" > <mx:Script> <![CDATA[ import mx.managers.PopUpManager public function fermerPopUp():void { PopUpManager.removePopUp(this); } public function envoyerMessage():void { parentApplication.txt_messageapplication.text = "Message reçu !"; } ]]> </mx:Script> <mx:TextInput id="txt_message"/> <mx:Button label="Ok" id="btn_ok" click="envoyerMessage()"/> </mx:TitleWindow> =Flex3 FM.book Page 122 Mardi, 2. décembre 2008 3:32 15 122 Comprendre Flex 3 PARTIE I Lorsque l’utilisateur cliquera sur le bouton btn_ok, la propriété text du champ txt_messageapplication de l’application parente (celle contenant le pop-up) sera mise à jour. C’est donc en utilisant la propriété parentApplication reprenant la notion de parenté qu’il devient possible de communiquer à partir du pop-up vers l’application qui le contient. La figure 6-10, illustre les résultats obtenus par la communication de l’application avec le pop-up et inversement. Figure 6-10 Communication de l’application vers le pop-up puis du pop-up vers l’application En résumé Au cours de ce chapitre, nous avons découvert les principaux composants conteneurs qui vont nous permettre d’agencer les différents composants de contrôle au sein de nos interfaces. Nous avons également vu qu’il est possible de créer un pop-up et de communiquer avec lui. Ce dernier point nous a permis d’aborder la notion de composant que nous étudierons en détail au chapitre 10 de cet ouvrage. Nous pouvons à présent poursuivre notre apprentissage en découvrant les composants qui vont nous permettre de naviguer à travers nos applications et ceux dédiés à la notion de reporting : les composants graphiques. =Flex3 FM.book Page 123 Mardi, 2. décembre 2008 3:32 15 7 Les composants de navigation et de reporting Nous voici à présent au dernier chapitre consacré aux différents composants contenus dans le framework Flex. Après les composants de contrôle et les composants conteneurs, nous allons à nous concentrer sur les composants chargés de la navigation au sein de notre application (onglets, menus en accordéon…), ainsi que ceux permettant de créer des applications de reporting (analyse statistique) : les composants de graphiques. Les composants de navigation Au cours de cette section, nous allons étudier les composants proposant aux utilisateurs des options de navigation dans l’application. Nous allons ici décrire les trois composants les plus utilisés : TabNavigator, ViewStack et Accordion. Navigation par onglets avec TabNavigator Lorsque le nombre de composants devient trop important pour que l’ensemble soit contenu dans un seul panneau, il est préférable d’utiliser des onglets, ce que permet le composant TabNavigator. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:TabNavigator x="10" y="10" width="516" height="400" id="tbn"> <mx:Canvas label="Onglet 1" width="100%" height="100%" > </mx:Canvas> =Flex3 FM.book Page 124 Mardi, 2. décembre 2008 3:32 15 124 Comprendre Flex 3 PARTIE I <mx:Canvas label="Onglet 2" width="100%" height="100%"> </mx:Canvas> </mx:TabNavigator> </mx:Application> Cette portion de code permet de créer deux onglets. Si nous observons attentivement ces quelques lignes, nous voyons qu’un onglet n’est rien d’autre qu’un composant Canvas dont le libellé servira à définir le titre de l’onglet (figure 7-1). Figure 7-1 Exemple d’implémentation de deux onglets Le libellé du composant Canvas ne s’affichera pas si ce dernier n’est pas contenu dans un composant TabNavigator. Vues empilées avec ViewStack Ce type de navigation s’apparente à la navigation par onglets. Cependant, à l’inverse du composant TabNavigator, le composant ViewStack utilise un système de vues empilées et la navigation entre chacune de ces vues peut être réalisée à l’aide des composants suivants : • LinkBar ; • TabBar ; • ButtonBar ; • ToggleButtonBar. En alimentant le dataProvider de chacun de ces composants avec le nom du composant ViewStack, ces derniers sont alors capables de récupérer les libellés des vues et de les afficher. Voici un exemple utilisant le composant ViewStack couplé au composant ToggleButtonBar. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ToggleButtonBar x="10" y="10" width="503" dataProvider="ensembleVues" ➥id="tg_barre"> </mx:ToggleButtonBar> =Flex3 FM.book Page 125 Mardi, 2. décembre 2008 3:32 15 Les composants de navigation et de reporting CHAPITRE 7 125 <mx:ViewStack x="10" y="38" id="ensembleVues" width="497" height="327"> <mx:Canvas label="Vue 1" width="100%" height="100%" id="Vue_1" ➥backgroundColor="#E0BCBC"> </mx:Canvas> <mx:Canvas label="Vue 2" width="100%" height="100%" id="Vue_2" ➥backgroundColor="#444697"> </mx:Canvas> <mx:Canvas label="Vue 3" width="100%" height="100%" id="Vue_3" ➥backgroundColor="#A254B5"> </mx:Canvas> </mx:ViewStack> </mx:Application> Chaque vue n’est autre qu’un composant Canvas. Nous pouvons également observer que le composant ViewStack alimente le dataProvider du composant ToggleButtonBar, permettant ainsi l’affichage du libellé de chaque vue dans ce dernier (figure 7-2). Figure 7-2 Utilisation des composants ViewStack et ToggleButtonBar =Flex3 FM.book Page 126 Mardi, 2. décembre 2008 3:32 15 126 Comprendre Flex 3 PARTIE I Si nous souhaitons sélectionner une vue par défaut, il suffit d’affecter son numéro d’index à la méthode selectedIndex du composant ToogleButtonBar : < !-- Sélection de la vue 2 ayant pour numéro d’index 1 --> <mx:ToggleButtonBar x="10" y="10" width="503" dataProvider="ensembleVues" ➥id="tg_barre" selectedIndex="1"> </mx:ToggleButtonBar> Attention Le premier élément du composant ViewStack a pour numéro d’index la valeur 0, le deuxième le numéro 1, et ainsi de suite. Il en va de même pour les éléments de type tabulaire en ActionScript (ArrayList, ArrayCollection…). Navigation « en accordéon » : Accordion Grâce au composant Accordion, il est possible de proposer une navigation entre chaque écran sous la forme d’un accordéon (menu empilé). Pour vous faire une idée de ce type de navigation, nous vous invitons à saisir ces quelques lignes de code au sein d’une nouvelle application Flex et à tester l’application. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Accordion x="10" y="10" width="483" height="301" id="acn"> <mx:Canvas label="Partie A" width="100%" height="100%"> <mx:Panel x="115.5" y="10" width="250" height="200" layout="absolute" ➥title="Panel Partie A"> </mx:Panel> </mx:Canvas> <mx:Canvas label="Partie B" width="100%" height="100%"> <mx:Panel x="115.5" y="23" width="250" height="200" layout="absolute" ➥title="Panel Partie B"> </mx:Panel> </mx:Canvas> </mx:Accordion> </mx:Application> La figure 7-3 illustre le résultat obtenu après exécution du code. =Flex3 FM.book Page 127 Mardi, 2. décembre 2008 3:32 15 Les composants de navigation et de reporting CHAPITRE 7 127 Figure 7-3 Exemple de navigation « en accordéon » Nous constatons que nos panneaux (panels) sont positionnés dans des parties mobiles, permettant un gain de place important sur l’interface graphique principale de l’application. Le composant Accordion est souvent utilisé pour la création de menus car il permet d’obtenir un aspect graphique assez intéressant et prisé par les utilisateurs. =Flex3 FM.book Page 128 Mardi, 2. décembre 2008 3:32 15 128 Comprendre Flex 3 PARTIE I Les composants de graphique Ces composants servant pour la génération de graphiques sont uniquement disponibles dans la version professionnelle de Flex Builder 3. Le tableau 7-1 en dresse la liste exhaustive : Tableau 7-1 Nom du composant Les composants à vocation statistiques Icône Utilisation AreaChart Représentation sous forme d’aires BarChart Représentation sous forme d’histogramme horizontal ColumnChart Représentation sous forme d’histogramme vertical BubbleChart Graphique sous forme de bulles CandlestickChart Représentation sous forme de chandelles LineChart Graphique linéaire PieChart Graphique en secteurs PlotChart Représentation sous forme d’un nuage de points HLOCChart (HLOC (Hight, Low, Open, Close)) Graphique boursier Implémentation L’implémentation de chacun de ces composants étant plus ou moins semblable, nous avons choisi de présenter l’utilisation du composant PieChart, car c’est le plus fréquemment utilisé dans les applications de reporting. Dans la portion de code suivante, nous représentons le nombre de dossiers médicaux non clôturés au sein d’un service hospitalier : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] =Flex3 FM.book Page 129 Mardi, 2. décembre 2008 3:32 15 Les composants de navigation et de reporting CHAPITRE 7 129 public var etatDossiers:ArrayCollection = new ArrayCollection([ {Dossier:"Clôturés", nombre:1500}, {Dossier:"Ouverts", nombre:200}, {Dossier:"En attente", nombre:30}, ]); ]]> </mx:Script> <mx:PieChart id="graphique" dataProvider="{etatDossiers}" showDataTips="true" width="203" height="140" x="10" y="5"> <mx:series> <mx:PieSeries field="nombre" nameField="Dossier" /> </mx:series> </mx:PieChart> </mx:Application> Les données présentées dans le graphique sont obtenues grâce au tableau etatDossier venant alimenter le dataProvider du composant. La valeur du champ Dossier est alors extraite, ce qui permet de générer le graphique. La propriété showDataTips affectée de la valeur true affiche les légendes de chaque quartier lorsque l’utilisateur les survole. La figure 7-4 illustre le résultat obtenu après exécution du code. Figure 7-4 Implémentation du composant PieChart Les légendes (dataTip) sont automatiquement créées par le composant PieChart : « Clôturés : 86,7 % (1 500) ». Si nous souhaitons personnaliser cet affichage, nous devrons utiliser la méthode dataTipFunction comme suit : <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] =Flex3 FM.book Page 130 Mardi, 2. décembre 2008 3:32 15 130 Comprendre Flex 3 PARTIE I public var etatDossiers:ArrayCollection = new ArrayCollection([ {Dossier:"Clôturés", nombre:1500}, {Dossier:"Ouverts", nombre:200}, {Dossier:"En attente", nombre:30}, ]); import mx.charts.HitData public function modifierDataTip(e:HitData):String{ var etiquette:String; etiquette= "Nombre de dossiers :"+e.item.nombre; return etiquette; } ]]> </mx:Script> <mx:PieChart id="graphique" dataProvider="{etatDossiers}" showDataTips="true" width="203" height="140" x="10" y="5" dataTipFunction="modifierDataTip"> <mx:series> <mx:PieSeries field="nombre" nameField="Dossier" /> </mx:series> </mx:PieChart> </mx:Application> Si nous exécutons ce code, nous notons que les légendes ont à présent la valeur « Nombre de dossiers : valeur du quartier survolé par la souris ». En pratique : création d’un outil de reporting En guise de synthèse, réalisons une petite application permettant d’afficher le reporting des ventes par produit pour un mois donné, sélectionné par l’utilisateur. Le graphique utilisé est un histogramme BarChart et les données visualisées correspondront au mois sélectionné par l’utilisateur à l’aide du composant HSlider étudié au chapitre 5. Étape 1 : création des données La première étape (outre la création d’un nouveau projet Flex) va consister à créer les tableaux de données. Nous avons ici choisi de créer trois tableaux contenant la somme des ventes réalisées pour trois produits aux mois de janvier, février et mars. =Flex3 FM.book Page 131 Mardi, 2. décembre 2008 3:32 15 Les composants de navigation et de reporting CHAPITRE 7 131 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; // Tableaux de données [Bindable] private var Janvier:ArrayCollection = new ArrayCollection([ {produit:"P1", vente:500}, {produit:"P2", vente:700}, {produit:"P3", vente:2000}]); private var Fevrier:ArrayCollection = new ArrayCollection([ {produit:"P1", vente:2500}, {produit:"P2", vente:800}, {produit:"P3", vente:4000}]); private var Mars:ArrayCollection = new ArrayCollection([ {produit:"P1", vente:800}, {produit:"P2", vente:1200}, {produit:"P3", vente:1500}]); ]]> </mx:Script> </mx:Application> Étape 2 : mise en place de l’histogramme Nous souhaitons afficher par défaut les données du mois de janvier. Pour cela, nous affectons le dataProvider de l’histogramme du tableau Janvier créé précédemment. <mx:ColumnChart x="10" y="67" id="histogramme" dataProvider="{Janvier}"> <mx:horizontalAxis> <mx:CategoryAxis id="donneesGraphiques" dataProvider="{Janvier}" categoryField="produit" /> </mx:horizontalAxis> <mx:series> <mx:ColumnSeries xField="produit" yField="vente" /> </mx:series> </mx:ColumnChart> Sur l’axe horizontal (HorizontalAxis), qui sera alimenté en données, nous allons afficher les libellés des produits, soit P1, P2 et P3. À partir des données contenues sur cet axe, =Flex3 FM.book Page 132 Mardi, 2. décembre 2008 3:32 15 132 Comprendre Flex 3 PARTIE I nous allons créer une série qui nous permettra d’extraire les valeurs devant être affichées sur l’axe vertical (yField) et sur l’axe horizontal (xField). À ce stade, si nous exécutons le projet, nous pouvons visualiser les données du mois de janvier. Cependant nous souhaitons donner la possibilité à l’utilisateur de choisir le mois de visualisation à l’aide du composant HSlider. Étape 3 : utilisation du composant HSlider Nous ajoutons un composant HSlider afin de mettre à jour le dataProvider du graphique en fonction du mois sélectionné. Pour cela, il convient tout d’abord d’implémenter notre composant : <mx:HSlider id="choixDuMois" x="38" y="23" width="372" minimum="1" maximum="3" tickInterval="1" snapInterval="1" liveDragging="true" labels="[Janvier,Février,Mars]" showDataTip="false" change="afficherGraphique()" /> HSlider va donc comporter les libellés Janvier, Février et Mars. Chaque mois va corres- pondre à un numéro précis correspondant à l’indice sélectionné dans le composant : 1 = Janvier, 2 = Février et 3 = Mars. À partir de cette information, il sera aisé de déterminer le mois sélectionné et de mettre à jour les données contenues dans l’histogramme. Remarquez également la suppression des infobulles par l’utilisation de la propriété showDataTip portée à false. Il ne nous reste plus qu’à mettre en place la partie dynamique de l’application en écrivant le code de la fonction afficherGraphique() qui sera déclenchée à chaque changement de valeur du composant HSlider : // Affichage des données en fonction du mois sélectionné // dans le HSlider import mx.controls.Alert; public function afficherGraphique():void { switch (choixDuMois.value){ case 1 : histogramme.dataProvider = Janvier; break; case 2 : histogramme.dataProvider = Fevrier; break; =Flex3 FM.book Page 133 Mardi, 2. décembre 2008 3:32 15 Les composants de navigation et de reporting CHAPITRE 7 133 case 3 : histogramme.dataProvider = Mars; break; } // Mise à jour du dataProvider du composant HorizontalAxis donneesGraphiques.dataProvider = histogramme.dataProvider; } Ainsi, lorsque l’utilisateur sélectionne un mois dans le composant HSlider, sa valeur est récupérée et le tableau de données correspondant est chargé dans le dataProvider de l’histogramme et de l’axe horizontal (donneesGraphiques.dataProvider = histogramme.dataProvider). La figure 7-5 illustre le résultat obtenu après exécution de l’application. Figure 7-5 Outil de reporting En résumé Après la lecture des chapitres 5 à 7, vous connaissez à présent les principaux composants que Flex met à votre disposition pour créer les interfaces de vos applications. Vous savez donc résoudre les problèmes les plus fréquemment rencontrés lors de la phase de développement : comment alimenter une liste déroulante ? Comment en récupérer la valeur sélectionnée ? et bien d’autres… Pour poursuivre notre apprentissage du framework Flex, nous allons à présent étudier les méthodes qui vont nous permettre d’agencer ces composants au sein d’une interface graphique. =Flex3 FM.book Page 134 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 135 Mardi, 2. décembre 2008 3:32 15 8 Réaliser le design des interfaces Au cours de ce chapitre, vous allez apprendre à personnaliser le design des interfaces graphiques grâce au framework Flex et à Flex Builder. Nous découvrirons tout d’abord comment positionner et dimensionner les composants de Flex, puis nous aborderons la notion de style et nous terminerons par la réalisation de nos propres habillages de composants. Dimensionner et positionner les composants L’une des premières étapes dans la conception d’interfaces graphiques consiste à agencer les composants au sein de cette interface. Le designer devra trouver la taille et la disposition adéquates pour les différents composants de l’application afin d’obtenir une certaine harmonie dans l’interface, ce qui la rendra conviviale. Nous allons donc dans un premier temps nous attarder sur les méthodes permettant de définir les dimensions des composants et de les positionner. Spécifier les dimensions des composants Il existe plusieurs méthodes permettant de définir les dimensions des composants au sein d’une interface graphique : • Vous pouvez laisser cette tâche au framework Flex qui vous proposera alors une taille par défaut pour chaque composant inséré dans l’interface. • Vous pouvez préciser manuellement la taille en pixels de chaque composant. • Enfin, vous pouvez spécifier les dimensions des composants en pourcentage des dimensions de leur conteneur. =Flex3 FM.book Page 136 Mardi, 2. décembre 2008 3:32 15 136 Comprendre Flex 3 PARTIE I La spécification des dimensions d’un composant consiste ni plus ni moins à modifier certaines des propriétés présentées dans le tableau 8-1. Tableau 8-1 Propriétés permettant de déterminer la taille des composants Propriété Rôle Height Hauteur du composant exprimée en pixels. Width Largeur du composant exprimée en pixels. minHeight Hauteur minimale du composant exprimée en pixels. minWidth Largeur minimale du composant exprimée en pixels. maxHeight Hauteur maximale du composant exprimée en pixels. maxWidth Largeur maximale du composant exprimée en pixels. percentHeigth Hauteur du composant exprimée en pourcentage de la hauteur de son conteneur. percentWidth Largeur du composant exprimée en pourcentage de la largeur de son conteneur. Quelques exemples Les exemples suivants vous permettront de voir comment implémenter les différentes propriétés présentées au tableau 8-1 et les résultats obtenus pour chaque type de dimensionnement. Dimensionnement par défaut <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Conteneur : VBox --> <mx:VBox x="20" y="27" height="70" width="289"> <!-- Composant : Button --> <mx:Button id="btn" label="Button"/> </mx:VBox> </mx:Application> Dans cet exemple de code, aucune dimension n’a été spécifiée pour le bouton. Le composant Button aura donc les dimensions spécifiées par défaut par Flex (figure 8-1). Figure 8-1 Dimensionnement par défaut =Flex3 FM.book Page 137 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 137 Spécification des dimensions <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Conteneur : VBox --> <mx:VBox x="20" y="27" height="70" width="289"> <!-- Composant : Button --> <mx:Button id="btn" label="Button" width="223" height="35"/> </mx:VBox> </mx:Application> Dans cet exemple, une largeur et une hauteur ont été précisées pour le bouton. Le résultat obtenu est illustré par la figure 8-2. Figure 8-2 Spécification des dimensions Utilisation des pourcentages <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Conteneur : VBox --> <mx:VBox x="20" y="27" height="70" width="289"> <!-- Composant : Button --> <mx:Button id="btn" label="Button" width="50%" height="80%"/> </mx:VBox> </mx:Application> Dans cet exemple de code, nous avons spécifié les dimensions du bouton en fonction de la taille de son conteneur. Ainsi, la largeur du composant est égale à 50 % de la largeur de son conteneur et sa hauteur correspond à 80 % de la hauteur de son conteneur. Pour vous aider dans la compréhension de cette notion parfois difficile à saisir, nous vous invitons à étudier la figure 8-3 présentant le résultat obtenu après exécution du code. =Flex3 FM.book Page 138 Mardi, 2. décembre 2008 3:32 15 138 Comprendre Flex 3 PARTIE I Figure 8-3 Dimensionnement à l’aide des pourcentages À noter que nous aurions également pu utiliser les propriétés percentWidth et percentHeight comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:VBox x="20" y="27" height="70" width="289" borderStyle="inset"> <!-- Composant : Button --> <mx:Button id="btn" label="Button" percentHeight="80" percentWidth="50"/> </mx:VBox> </mx:Application> Cependant, la méthode la plus communément utilisée consiste à spécifier des pourcentages pour les propriétés width et height. Nous savons à présent définir la taille d’un composant selon trois méthodes distinctes. Voyons maintenant comment disposer ce dernier au sein d’une interface. Positionner les composants Pour placer un composant à un endroit précis de l’interface, nous disposons également de trois méthodes : • le positionnement automatique ; • le positionnement absolu ; • le positionnement à l’aide de contraintes (ancrages). Le positionnement automatique Par défaut, Flex place les composants de façon automatique en fonction des règles de positionnement de leur conteneur. Par exemple, un composant intégré dans le conteneur HBox sera automatiquement positionné en haut à gauche, aux coordonnées x = 0 et y = 0. =Flex3 FM.book Page 139 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 139 Nous pouvons néanmoins intervenir sur ce positionnement en modifiant certaines propriétés du conteneur. Le tableau 8-2 présente les propriétés les plus communément modifiées. Tableau 8-2 Propriétés de positionnement automatique Propriété Rôle horizontalAlign Aligne les composants par rapport à l’axe horizontal du conteneur : Center : centre le composant. Left : place le composant à gauche. Right : place le composant à droite. verticalAlign Aligne les composants par rapport à l’axe vertical du conteneur : Bottom : place le composant en bas. Middle : place le composant au centre. Top : place le composant en haut. layout : applicable à l’application et aux composants Panel et Canvas. Permet de modifier la disposition des composants : Absolute : positionne les composants en fonction de leur coordonnées x et y. Vertical : positionne les composants les uns en dessous des autres. Horizontal : positionne les composants côte à côte. paddingBottom Marge inférieure du conteneur. paddingLeft Marge gauche du conteneur. paddingRight Marge droite du conteneur. paddingTop Marge supérieure du conteneur. La propriété horizontalAlign L’exemple de code suivant implémente les trois positions d’alignement horizontal illustrées par la figure 8-4. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- CENTRE --> <mx:Label x="10" y="17" text="Centre" width="250"/> <mx:HBox x="10" y="43" width="250" height="74" horizontalAlign="center"> <mx:Button id="btn1" label="Button"/> </mx:HBox> <!-- DROITE --> <mx:Label x="10" y="129" text="Droite" width="250"/> <mx:HBox x="10" y="153" width="250" height="74" horizontalAlign="right"> <mx:Button id="btn2" label="Button"/> </mx:HBox> <!-- GAUCHE --> <mx:Label x="10" y="247" text="Gauche" width="250"/> =Flex3 FM.book Page 140 Mardi, 2. décembre 2008 3:32 15 140 Comprendre Flex 3 PARTIE I <mx:HBox x="10" y="271" width="250" height="74" horizontalAlign="left"> <mx:Button id="btn3" label="Button"/> </mx:HBox> </mx:Application> Figure 8-4 Positionnement à l’aide de la propriété horizontalAlign La propriété verticalAlign Voici à présent un exemple de code illustrant le positionnement des composants dont la propriété verticalAlign du conteneur a été modifiée. Le résultat obtenu est représenté à la figure 8-5. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- MILIEU --> <mx:Label x="10" y="17" text="Milieu" width="250"/> <mx:HBox x="10" y="43" width="250" height="74" verticalAlign="middle"> <mx:Button id="btn1" label="Button"/> </mx:HBox> <!-- HAUT --> <mx:Label x="10" y="129" text="Haut" width="250"/> <mx:HBox x="10" y="153" width="250" height="74" verticalAlign="top"> <mx:Button id="btn2" label="Button"/> </mx:HBox> =Flex3 FM.book Page 141 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 141 <!-- BAS --> <mx:Label x="10" y="247" text="Bas" width="250"/> <mx:HBox x="10" y="271" width="250" height="74" verticalAlign="bottom"> <mx:Button id="btn3" label="Button"/> </mx:HBox> </mx:Application> Figure 8-5 Positionnement des composants à l’aide de la propriété verticalAlign La propriété layout Dans l’exemple de code suivant, nous voyons que l’application possède une mise en forme de type absolute. Les composants qu’elle contient seront donc placés à l’aide de leurs coordonnées. Nous pouvons observer ce positionnement pour les composants Panel, pour lesquels des valeurs ont été affectées aux propriétés x et y. Le résultat obtenu après exécution de ce code est représenté à la figure 8-6. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- Positionnement de type "absolute" --> <mx:Panel title="Absolute" x="31" y="10" width="250" height="120" layout="absolute" > <mx:Button id="btn" x="10" y="10" label="Button"/> <mx:Button id="btn2" x="133" y="37" label="Button"/> </mx:Panel> <!-- Positionnement de type "vertical" --> <mx:Panel title="Vertical" x="31" y="138" width="250" height="120" layout="vertical" > <mx:Button id="btn3" label="Button"/> =Flex3 FM.book Page 142 Mardi, 2. décembre 2008 3:32 15 142 Comprendre Flex 3 PARTIE I <mx:Button id="btn4" label="Button"/> </mx:Panel> <!-- Positionnement de type "horizontal" --> <mx:Panel title="Horizontal" x="31" y="266" width="250" height="120" ➥layout="horizontal" > <mx:Button id="btn5" label="Button"/> <mx:Button id="btn6" label="Button"/> </mx:Panel> </mx:Application> Figure 8-6 Utilisations de la propriété layout La propriété padding L’exemple de code suivant illustre le positionnement des composants à l’aide des marges. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:HBox x="10" y="10" width="250" height="158" paddingLeft="50" paddingTop="20" > <mx:Button id="btn" label="Button"/> </mx:HBox> </mx:Application> =Flex3 FM.book Page 143 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 143 Les marges gauche et supérieure du conteneur HBox ont été définies, impliquant le positionnement du bouton à une distance de 20 pixels par rapport à la ligne supérieure du conteneur et à 50 pixels de son bord gauche (figure 8-7). Figure 8-7 Utilisation des marges pour le positionnement du composant Le positionnement absolu Ce type de positionnement est appliqué par défaut à l’application ainsi qu’aux composants Panel et Canvas. Comme mentionné précédemment, ce type de positionnement s’effectue en affectant la valeur absolute à la propriété layout des composants concernés. Cette méthode permet de positionner les composants au sein du conteneur selon les axes de coordonnées x et y et, si besoin, d’effectuer des superpositions de composants. Le positionnement à l’aide de contraintes Ce type de positionnement est également appelé positionnement par ancrage. Il peut s’effectuer de deux façons : • en modifiant les propriétés de positionnement par ancrage (voir tableau 8-3) ; • en utilisant la perspective de design et plus particulièrement la vue layout de celle-ci (cette vue est activée lorsqu’on sélectionne un composant et elle se situe en bas à droite de la perspective de design (figure 8-8)). Ancrage du conteneur ou du composant ? Jusqu’à présent, nous avons modifié les propriétés du conteneur afin de positionner les composants à l’intérieur de celui-ci. L’ancrage concerne le composant. C’est donc sur ce dernier que les modifications devront être effectuées. Ceci peut se résumer par : « Le composant est ancré par rapport à son conteneur ». =Flex3 FM.book Page 144 Mardi, 2. décembre 2008 3:32 15 144 Comprendre Flex 3 PARTIE I Tableau 8-3 Propriétés de positionnement par ancrage Propriété Rôle horizontalCenter Distance exprimée en pixels entre le centre de l’axe horizontal du composant et celui de son conteneur. verticalCenter Distance exprimée en pixels entre le centre de l’axe vertical du composant et celui de son conteneur. top Distance exprimée en pixels entre le bord supérieur du composant et celui de son conteneur. bottom Distance exprimée en pixels entre le bord inférieur du composant et celui de son conteneur. left Distance exprimée en pixels entre le bord gauche du composant et celui de son conteneur. right Distance exprimée en pixels entre le bord droit du composant et celui de son conteneur. Figure 8-8 Vue d’ancrage de la perspective design =Flex3 FM.book Page 145 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 145 Exemple d’application Considérons une application servant de conteneur à un composant Panel correspondant au code suivant : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel width="250" layout="absolute" horizontalCenter="0" top="175" bottom="275"> </mx:Panel> </mx:Application> Dans cet exemple de code, nous remarquons que des contraintes de positionnement ont été spécifiées pour le composant Panel : • il doit se situer au centre de l’application : horizontalCenter="0" ; • il doit se situer à 175 pixels du bord supérieur de l’application : top="175" ; • il doit se situer à 275 pixels du bord inférieur de l’application : bottom="275". Ces caractéristiques sont reprises dans la vue de positionnement des contraintes, comme l’illustre la figure 8-9. Figure 8-9 Répercussions du code sur la vue spécifique aux ancrages =Flex3 FM.book Page 146 Mardi, 2. décembre 2008 3:32 15 146 Comprendre Flex 3 PARTIE I Le positionnement des composants à l’aide d’ancrages présente l’avantage de permettre un ajustement de l’interface en fonction de la résolution d’écran de l’utilisateur en adaptant la taille et la disposition des composants (figure 8-10). Figure 8-10 Adaptation de l’interface graphique en fonction de la résolution du navigateur Gestion des ascenseurs Dans certaines configurations (lorsque la taille du composant est sensiblement identique ou supérieure à celle du conteneur), les ascenseurs verticaux et horizontaux du conteneur peuvent s’afficher. Pour pallier cela, il suffit de passer la valeur des propriétés horizontalScrollPolicy et verticalScrollPolicy du conteneur à off (figure 8-11). =Flex3 FM.book Page 147 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 147 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel id="pan" x="10" y="10" width="250" height="86" layout="absolute" horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:Button id="btn" x="0" y="14" label="Button" width="240"/> </mx:Panel> </mx:Application> Figure 8-11 Gestion des ascenseurs horizontaux et verticaux Utiliser les styles Selon les goûts de chacun, le style proposé par défaut dans une application Flex peut parfaitement convenir, alors que d’autres y ajouteraient bien un peu de couleur. Au-delà de cela, il convient de garder à l’esprit qu’une application doit respecter une charte graphique éditée par l’entreprise dont il est très difficile de déroger. C’est pourquoi Flex permet de personnaliser le style d’une application au moyen du langage CSS (Cascading Style Sheet). Le CSS de Flex supporte quelques propriétés du langage CSS standardisé dont voici la liste exhaustive : • color ; • fontFamily ; • fontSize ; • fontStyle ; • fontWeight ; • paddingBottom ; • paddingLeft ; =Flex3 FM.book Page 148 Mardi, 2. décembre 2008 3:32 15 148 Comprendre Flex 3 PARTIE I • paddingRight ; • paddingTop ; • textAlign ; • textDecoration ; • textIndent. Bien entendu, le CSS de Flex ne se limite pas à ces quelques propriétés standardisées, mais englobe un ensemble de propriétés propres à chacun de ses composants. Visualiser les propriétés de style d’un composant Pour visualiser l’ensemble des propriétés de style d’un composant, il suffit de le placer sur l’interface et de le sélectionner. Dans la vue Flex Properties, il est alors possible de cliquer sur le bouton Category view, lequel permet d’afficher la liste des propriétés du composant sous la forme d’un treeview. Dans cette représentation hiérarchique, nous pouvons apercevoir un nœud nommé Style qui reprend l’ensemble des propriétés stylistiques du composant. Étudions en détail l’implémentation de ce langage au sein d’une application Flex. La balise Style La première méthode d’implémentation du langage CSS consiste à utiliser la balise <mx:Style> du langage MXML, comme illustré dans l’exemple de code suivant : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Style> .classePersonnalisee{ fontSize: 10; color:red; } Button { fontSize: 20; } </mx:Style> <mx:Button id="btn" x="10" y="10" label="Button"/> <mx:Label id="lab" x="10" y="53" text="Label" styleName="classePersonnalisee"/> </mx:Application> L’analyse de ces quelques lignes de code permet de comprendre aisément la notion de classes CSS. Le sélecteur Button permet de définir le style de l’ensemble des composants de type bouton de l’interface. La classe personnalisée (classePersonnalisee) ne fait référence à aucune classe de composant et doit donc être appelée à l’aide de la propriété styleName du composant concerné. Cela permet de définir des styles différents pouvant =Flex3 FM.book Page 149 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 149 alors être appliqués pour un même type de composant (un bouton rouge, vert, bleu, etc.). Notez que l’utilisation de styles ne se limite pas au composant de type Button mais peut également être appliquée à l’ensemble de composants du framework. Figure 8-12 Emploi de la balise <mx:Style> Le fichier CSS externe La seconde méthode d’implémentation consiste à faire appel à un fichier CSS externe. Pour ce faire, nous utiliserons de nouveau la balise <mx:Style> mais en lui précisant le chemin d’accès du fichier CSS à utiliser. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Style source="feuilleDeStyle.css"></mx:Style> <mx:Button id="btn" x="10" y="10" label="Button"/> <mx:Label id="lab" x="10" y="53" text="Label" styleName="classePersonnalisee"/> </mx:Application> Le fichier CSS (ici, feuilleDeStyle.css) peut être édité à l’aide de la perspective de développement en choisissant la création d’un nouveau fichier CSS, ou en utilisant l’application Flex Style Explorer développée par l’éditeur. Le Flex Style Explorer vous permet de modifier les propriétés de chaque composant de façon graphique. Le code correspondant est alors automatiquement généré et vous pouvez ensuite l’exporter et l’utiliser dans votre application Flex (figure 8-13). Si vous souhaitez utiliser cette application, rendez-vous sur la page web suivante : http://weblogs.macromedia.com/mc/archives/FlexStyleExplorer.html. Utilisation des images Pour utiliser des images, il convient de faire appel à la méthode Embed(). Dans l’exemple de code suivant, l’image monImage.jpg est employée comme arrière-plan de l’application. backgroundImage : Embed('monImage.jpg') =Flex3 FM.book Page 150 Mardi, 2. décembre 2008 3:32 15 150 Comprendre Flex 3 PARTIE I Figure 8-13 Application Flex Style Explorer CSS et ActionScript La troisième méthode d’implémentation consiste à créer le style CSS à l’aide du langage ActionScript. Ceci est possible grâce à la classe StyleManager qui permet de définir de nouveaux styles et de les appliquer aux composants de l’application. Voyons ceci de plus près à travers un exemple : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="appliquerStyle()" > <mx:Script> <![CDATA[ // Importation de la classe StyleManager import mx.styles.StyleManager; // Définition du style private var styleActionScript:CSSStyleDeclaration; private function appliquerStyle():void{ =Flex3 FM.book Page 151 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 151 // Instanciation de la classe CSSStyleDeclaration; styleActionScript = new CSSStyleDeclaration('styleActionScript'); // Création des propriétés styleActionScript.setStyle('fontSize',20); // Affectation des propriétés à la classe Label StyleManager.setStyleDeclaration("Label",styleActionScript,true); } ]]> </mx:Script> <mx:Label id="lab" x="10" y="10" text="Étiquette"/> </mx:Application> La première étape consiste à instancier la classe CSSStyleDeclaration permettant de déclarer un nouveau style. Nous y ajoutons ensuite des propriétés CSS grâce à la méthode setStyle(). Enfin, nous affectons ce style à la classe Label en employant la méthode setStyleDeclaration(nom de la classe CSS, style, mise à jour (true/false)). À noter que l’ensemble de ces instructions est contenu dans la fonction appliquerStyle(), exécutée à la fin de la création de l’application. Grâce à la classe StyleManager, il devient possible de manipuler le style CSS de notre application. Ceci nous ouvre la voie vers une multitude de possibilités, notamment celle du dynamisme applicatif, c’est-à-dire le changement de style en fonction de l’utilisateur connecté ou lors d’un déclenchement d’événement… Habiller les composants : skinning Une autre particularité de Flex est de permettre l’habillage des composants au moyen d’images, de fichiers SWF (animations Flash) ou de classes contenant des instructions de design. Les habillages (skins) sont généralement appliqués sur les états d’un composant. Ainsi, nous pouvons, par exemple, définir huit skins différents pour les composants de type bouton : • un skin pour l’état relâché : upSkin ; • un skin pour l’état cliqué : downSkin ; • un skin pour l’état survolé : overSkin ; • un skin pour l’état désactivé : disabledSkin ; • un skin pour la prise de focus : focusSkin ; • un skin pour l’état cliqué d’un bouton de type interrupteur : selectedDownSkin ; • un skin pour l’état relâché d’un bouton de type interrupteur : selectedUpSkin ; • un skin pour l’état survolé d’un bouton de type interrupteur : selectedOverSkin. =Flex3 FM.book Page 152 Mardi, 2. décembre 2008 3:32 15 152 Comprendre Flex 3 PARTIE I Utiliser des images Pour implémenter un habillage sur un composant, il est possible d’utiliser la balise <mx:Style>, tout comme nous l’aurions fait pour créer un nouveau style CSS ou pour modifier directement les propriétés souhaitées au sein du composant. L’exemple de code suivant illustre l’utilisation de cette balise : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" > <mx:Style> Button { downSkin: Embed('monImage.jpg'); } </mx:Style> <mx:Button id="btn" x="50" y="42" label="Button"/> </mx:Application> Dans l’exemple suivant, vous notez que l’habillage a été modifié à l’aide des propriétés du composant : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" > <mx:Button id="btn" x="50" y="42" label="Button" downSkin="@Embed(source='monImage.jpg')"/> </mx:Application> Utiliser des fichiers SWF L’habillage des composants est réalisé de la même façon qu’à l’aide d’une image, c’està-dire en utilisant la balise <mx:Style> ou en modifiant les propriétés du composant. Cela est illustré par le code suivant : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" > <mx:Style> Button { downSkin: Embed('monSWF.swf'); } </mx:Style> <mx:Button id="btn" x="50" y="42" label="Button"/> </mx:Application> =Flex3 FM.book Page 153 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 153 Dans l’exemple suivant, les propriétés du composant ont été modifiées : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" > <mx:Button id="btn" x="50" y="42" label="Button" downSkin="Embed(source='monSWF.swf')"/> </mx:Application> L’habillage par programmation Dans cette section, nous allons aborder la programmation de skins à l’aide d’Action Script à travers un exemple d’application, ce qui est le meilleur moyen pour en comprendre les rouages. L’objectif est de créer un habillage pour le composant VBox en redessinant son contour afin d’obtenir le résultat illustré par la figure 8-14. Figure 8-14 Skin personnalisé pour le composant VBox Pour cela, la première étape va consister à créer une classe, dans un package que nous nommerons com.test.skin, qui définira notre skin personnalisé : Package com.test.skin { import mx.skins.RectangularBorder; =Flex3 FM.book Page 154 Mardi, 2. décembre 2008 3:32 15 154 Comprendre Flex 3 PARTIE I public class SkinPersonnalise extends RectangularBorder { // Constructeur public function SkinPersonnalise(){} // Redéfinition de la méthode updateDisplayList override protected function updateDisplayList(unscaledWidth:Number, ➥unscaledHeight:Number):void{ // Récupération de la taille du skin composant super.updateDisplayList(unscaledWidth, unscaledHeight); // Nettoyage de la forme graphics.clear(); // Dessin de la bordure drawRoundRect(0,0,unscaledWidth,unscaledHeight,{tl:50,tr:10,bl:10,br:30} ➥,0xCCCC99,0.8); } } } Analysons un peu ce code. Tout d’abord, nous importons la classe RectangularBorder qui nous permettra de manipuler les bordures du composant. Notons au passage que notre classe SkinPersonnalise hérite de cette classe. Puis, nous spécifions le constructeur et redéfinissons la méthode updateDisplayList. Pour faire très simple, nous dirons que cette méthode permet de gérer l’affichage de tout composant au sein d’une interface graphique (positionnement et dimensionnement des composants ainsi que leur représentation (bordure, couleurs…)). En modifiant quelque peu cette méthode, nous serons en mesure de redessiner les contours de notre VBox. Par ailleurs, nous remarquons la présence des paramètres unscaleWidth et unscaleHeight qui contiennent les valeurs des propriétés width et heigth du composant afin d’en connaître la largeur et la hauteur. Passons à présent aux choses sérieuses. Les contours de notre composant seront redessinés à l’aide de la méthode drawRoundRect qui permet de dessiner un rectangle aux bords arrondis. Les deux premiers paramètres passés à cette méthode correspondent aux coordonnées x et y du composant, les deux suivants à sa largeur et à sa hauteur. Vient ensuite un tableau contenant les dimensions des arcs de cercle redessinant les arrondis de chaque angle du composant : • tl (pour top left) : en haut à gauche ; • tr (pour top right) : en haut à droite ; • bl (pour bottom left) : en bas à gauche ; • br (pour bottom right) : en bas à droite. Enfin, les deux derniers paramètres spécifient la couleur et la transparence du composant. =Flex3 FM.book Page 155 Mardi, 2. décembre 2008 3:32 15 Réaliser le design des interfaces CHAPITRE 8 155 Notre skin est à présent terminé, il est temps de passer à la seconde étape qui consiste à appeler le skin personnalisé en affectant la propriété borderSkin du composant VBox avec le nom de la classe précédemment créée : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:VBox id="vb" x="29" y="20" height="173" width="259" borderSkin="com.test.skin.SkinPersonnalise" > </mx:VBox> </mx:Application> Voilà, c’est terminé ! À noter que dans notre exemple, nous avons utilisé la méthode drawRoundRect, mais il en existe d’autres telles que : • curveTo() qui permet de créer des courbes ; • drawCircle() qui permet de dessiner des cercles ; • drawRect() qui permet de dessiner des rectangles ; • lineTo() qui permet de dessiner une ligne, etc. La création de skins à l’aide du langage ActionScript n’est pas des plus aisées. Néanmoins, tout comme pour la création de styles CSS grâce à ce langage, il nous est maintenant possible de conférer une part de dynamisme aux habillages de nos composants, offrant un réel plus à nos interfaces graphiques. En résumé Au cours de ce chapitre, nous avons abordé les concepts de base utiles à la création d’interfaces graphiques. Nous sommes à présent en mesure de positionner et de dimensionner les composants afin qu’ils répondent à l’ergonomie souhaitée de l’application. Nous savons également personnaliser les interfaces à l’aide du langage CSS et de l’utilisation de skins. Si nous avions pour habitude d’utiliser le langage HTML pour générer nos interfaces web nous pourrions nous contenter de ce qui vient d’être énoncé, mais nous perdrions la notion de richesse des interfaces proposée par Flex. En effet, ce qui différencie Flex du langage HTML, c’est la possibilité d’ajouter un dynamisme visuel aux interfaces. Cette différence se traduit par la mise en place d’effets, de mouvements, de transitions, etc. C’est ce dynamisme que nous allons aborder dans le chapitre suivant en traitant les notions d’états, de transitions et d’effets. =Flex3 FM.book Page 156 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 157 Mardi, 2. décembre 2008 3:32 15 9 Le dynamisme applicatif à l’aide des états, des transitions et des effets Dans le chapitre précédent, nous avons vu comment agencer les composants au sein d’une interface. Nous allons à présent aborder les notions d’états, de transitions et d’effets permettant d’ajouter dynamisme et convivialité à nos applications Flex. Les états ou view states Comme nous le savons, une application Flex est composée d’un fichier MXML décrivant son interface graphique. Sur cette dernière, nous pouvons disposer des composants selon un agencement précis répondant aux besoins d’ergonomie et de fonctionnalité de l’application. Il n’est pas faux d’affirmer qu’une interface graphique doit être « vivante », dans le sens où un événement peut déclencher l’ouverture d’une interface spécifique, cacher certains composants ou parties de l’interface, en modifier totalement l’apparence… En HTML, ceci s’obtient aisément en combinant les langages CSS et JavaScript ou bien en créant une nouvelle page. Néanmoins, n’oublions pas que nous ne possédons qu’un seul fichier de description d’interface, alors comment procéder ? C’est la notion d’état qui va nous apporter la réponse. Cette notion repose sur l’interface de base d’une application Flex, que l’on nommera état de base (base state). Cet état peut par ailleurs donner naissance à des états enfants ayant les mêmes caractéristiques que leur parent, mais pour lesquels il est possible d’ajouter ou de supprimer des composants ou encore de modifier les comportements et événements qui leur sont associés. =Flex3 FM.book Page 158 Mardi, 2. décembre 2008 3:32 15 158 Comprendre Flex 3 PARTIE I La compréhension de la notion d’état n’est pas facile. C’est pourquoi nous allons nous appuyer sur une étude de cas qui va nous permettre de mieux comprendre le mécanisme de ce concept. Vers une première définition Pour introduire la notion d’état, nous pouvons l’assimiler au changement de page d’un site web. Un état correspond alors à une nouvelle page web. Étude de cas Imaginons une interface graphique permettant d’effectuer des recherches sur des patients dans une base de données médicale. Deux types de recherche sont possibles : • la recherche simple contenant quelques critères de base (numéro de patient, prénom et nom) ; • la recherche avancée comportant davantage de critères (numéro de chambre, date d’admission…). La recherche basique sera proposé par défaut à l’utilisateur, mais il lui sera possible de basculer vers la recherche avancée en sélectionnant cette option. Création de l’état de base La première étape va consister à créer l’interface de base proposant la recherche simple : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- GROUPE DE BOUTONS RADIO --> <mx:RadioButtonGroup id="radioBoutons"/> <mx:RadioButton x="34" y="21" label="Recherche simple" groupName="radioBoutons" ➥id="btn_simple" selected="true"/> <mx:RadioButton x="166" y="21" label="Recherche avancée" groupName="radioBoutons" ➥id="btn_avance"/> <!-- CRITÈRES DE RECHERCHE --> <mx:Panel id="panel1" x="34" y="51" width="339" height="198" layout="absolute" ➥title="Critères de recherche" > <mx:Form id="form1"x="10" y="10" height="108" width="302" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="N° patient :"> <mx:TextInput id="numPatient"/> </mx:FormItem> <mx:FormItem label="Prénom :"> <mx:TextInput id="Prenom"/> </mx:FormItem> =Flex3 FM.book Page 159 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 159 <mx:FormItem label="Nom :"> <mx:TextInput id="Nom"/> </mx:FormItem> </mx:Form> <mx:Button id="button1"x="221" y="126" label="Rechercher"/> </mx:Panel> </mx:Application> Cet exemple de code permet de sélectionner le type de recherche souhaité à l’aide du composant RadioButton (figure 9-1). Le bouton radio proposant la recherche simple est sélectionné par défaut (selected="true"). S’en suit la mise en place d’un Panel contenant un formulaire, composé de trois champs correspondant aux trois critères de base. Enfin, un bouton avec un intitulé clair quant à sa fonction est inséré dans le composant Panel. Notre interface de base, ou état de base, est à présent créé. Figure 9-1 Interface de recherche simple Comme le sous-entend le cahier des charges de ce cas pratique, le type de recherche avancée doit inclure les champs de recherche de base tout en proposant des critères supplémentaires. Nous allons donc créer un état enfant qui héritera de l’état de base auquel nous ajouterons d’autres critères. Création de l’état enfant Pour créer ce nouvel état, nous allons ajouter le code suivant dans le fichier MXML de notre application : <mx:states> <mx:State name="rechercheAvancee"/> </mx:states> La balise <mx:states> a pour fonction de lister l’ensemble des états contenus dans l’application. Par ailleurs, une balise <mx:State> y a été ajoutée, cette dernière permettant d’indiquer la création d’un nouvel état nommé rechercheAvancee. Notre état enfant est désormais créé. =Flex3 FM.book Page 160 Mardi, 2. décembre 2008 3:32 15 160 Comprendre Flex 3 PARTIE I Il convient à présent de modifier quelques propriétés afin de proposer les nouveaux critères de recherche : • agrandissement du panel ; • agrandissement du formulaire, occasionnant le déplacement du bouton Rechercher ; • ajout des critères de recherche supplémentaires. Pour cela, nous agrémentons le code précédemment saisi : <mx:states> <mx:State name="rechercheAvancee"> <mx:SetProperty target="{panel1}" name="height" value="267"/> <mx:SetProperty target="{button1}" name="x" value="218"/> <mx:SetProperty target="{button1}" name="y" value="195"/> <mx:SetProperty target="{form1}" name="height" value="177"/> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="N° chambre :"> <mx:TextInput id="num_chambre"/> </mx:FormItem> </mx:AddChild> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="Date admission :"> <mx:DateField id="dateAdmission" /> </mx:FormItem> </mx:AddChild> </mx:State> </mx:states> Quelques explications s’imposent. Grâce à la balise <mx:SetProperty>, il nous est possible de modifier les propriétés du composant dont l’identifiant est précisé dans la propriété target. Ainsi, la première ligne de code consiste à modifier la hauteur (name="height") du composant panel1, en passant la valeur de cette propriété à 267 pixels. Avec ce décryptage en tête, nous vous laissons le soin d’analyser les trois autres lignes de code concernant le déplacement du bouton (lignes 2 et 3) et l’agrandissement du formulaire (ligne 4). Passons à présent à la suite du code : <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="N° chambre :"> <mx:TextInput id="num_chambre"/> </mx:FormItem> </mx:AddChild> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="Date admission :"> <mx:DateField id="dateAdmission" /> </mx:FormItem> </mx:AddChild> =Flex3 FM.book Page 161 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 161 Vous l’avez certainement deviné, ce code permet d’ajouter les nouveaux critères de recherche. Cela est réalisé à l’aide de la balise <mx:AddChild>, qu’il faut comprendre comme suit : « Ajouter à la suite des champs déjà présents (position="lastChild") dans le formulaire form1 (relativeTo="{form1}"), un nouveau champ de formulaire (<mx:FormItem>) dont le label est N° chambre et dont le type est une zone de saisie (<mx:TextInput>) ». Cette traduction est également applicable au champ dateAdmission ajouté à l’aide de la seconde balise <mx:AddChild>. Notre état enfant est à présent terminé. Pour visualiser le résultat obtenu, placez-vous dans la perspective Design de Flex Builder. En haut à droite de cette perspective, vous trouverez la vue States. Si le code a été correctement saisi, vous devriez visualiser le nouvel état héritant de l’état de base (<Base State>), comme l’illustre la figure 9-2. Vous pouvez également naviguer entre les différents états en cliquant dessus, ce qui permet d’en visualiser les différences (figure 9-3). Figure 9-2 Visualisation de l’état rechercheAvancee dans Flex Builder Figure 9-3 Visualisation des états =Flex3 FM.book Page 162 Mardi, 2. décembre 2008 3:32 15 162 Comprendre Flex 3 PARTIE I La dernière tâche qui nous incombe consiste à mettre en place l’aspect dynamique de l’application, c’est-à-dire permettre à l’utilisateur de passer d’un état à un autre en sélectionnant l’option de recherche de son choix. Mise en place de l’interactivité Le passage d’un état à un autre sera effectué lors de la sélection du type de recherche à l’aide des boutons radio. C’est donc sur l’événement click de ceux-ci que nous ferons appel à l’état correspondant à l’option sélectionnée. La sélection d’un état s’effectue grâce à la méthode currentState à laquelle nous passons en paramètre l’état à afficher : <!-- GROUPE DE BOUTONS RADIO --> <mx:RadioButtonGroup id="radioBoutons"/> <mx:RadioButton x="34" y="21" label="Recherche simple" groupName="radioBoutons" ➥id="btn_simple" selected="true" click="currentState=''"/> <mx:RadioButton x="166" y="21" label="Recherche avancée" groupName="radioBoutons" ➥id="btn_avance" click="currentState='rechercheAvancee'"/> Cet exemple de code présente la méthode d’appel de l’état à afficher lors de l’événement click du bouton radio. À noter qu’aucun paramètre n’a été défini pour la méthode currentState du bouton btn_simple, l’état appelé sera donc l’état de base. N’oublions pas que l’état enfant doit hériter de l’état parent, sauf volonté contraire du développeur. Dans notre cas, nous souhaitons que le changement d’état s’effectue également sur l’état enfant. Il convient donc d’ajouter ces deux événements à l’état rechercheAvancee : <mx:SetEventHandler target="{btn_simple}" name="click" handler="currentState=''"/> <mx:SetEventHandler target="{btn_avance}" name="click" handler= ➥"currentState='rechercheAvancee'"/> Vous l’aurez compris, la balise <mx:SetEventHandler> permet d’ajouter des événements sur des composants des états enfants. Pour plus de clarté, voici le code complet de l’état de recherche avancée : <mx:State name="rechercheAvancee"> <mx:SetProperty target="{panel1}" name="height" value="267"/> <mx:SetProperty target="{button1}" name="x" value="218"/> <mx:SetProperty target="{button1}" name="y" value="195"/> <mx:SetProperty target="{form1}" name="height" value="177"/> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="N° chambre :"> <mx:TextInput id="num_chambre"/> </mx:FormItem> </mx:AddChild> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="Date admission :"> <mx:DateField id="dateAdmission"/> </mx:FormItem> =Flex3 FM.book Page 163 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 163 </mx:AddChild> <mx:SetEventHandler target="{btn_simple}" name="click" handler="currentState=''"/> <mx:SetEventHandler target="{btn_avance}" name="click" handler="currentState= ➥'rechercheAvancee'"/> </mx:State> Grâce à cette étude de cas, nous avons pu apprécier la notion d’état. Les états permettent de définir l’architecture de l’application en fonction des actions de l’utilisateur. Vous pouvez ainsi modifier l’apparence de l’interface ou d’un composant en fonction d’un événement déclenché par l’utilisateur. Cette nouvelle notion peut être un peu difficile à assimiler pour celles et ceux habitués à développer des applications web classiques, mais ils en apprécieront pleinement les avantages par la suite. Nous allons à présent aborder la notion de transition qui, comme vous allez le voir, représente une partie très importante de la notion d’interface cliente riche en nous permettant d’ajouter du dynamisme à nos états. Les transitions Un peu à la manière d’un logiciel de montage vidéo, Flex permet d’effectuer des transitions entre chaque changement d’état. Vous pourrez ainsi obtenir des applications à l’aspect visuel très intéressant et attractif. La création d’une transition s’effectue en définissant les quatre paramètres de base suivants : • l’identifiant de la transition ; • l’état de départ ; • l’état d’arrivée ; • l’effet de transition exécuté. En explorant la documentation du package mx.effects , nous pouvons dresser la liste des effets de transition disponibles, repris dans le tableau 9-1, ainsi que leur description. Tableau 9-1 Liste des effets de transition disponibles Effet Description Blur Exécution d’un effet de flouté. Dissolve Passe de l’état transparent à l’état opaque ou inversement. Fade Effet semblable à celui de composant. Glow Applique un effet de surbrillance sur le composant. Iris Utilise un masque rectangulaire centré sur la cible afin de dévoiler petit à petit le contenu de celle-ci. Move Modifie la position d’un composant. Dissolve en jouant sur la valeur de la propriété alpha du =Flex3 FM.book Page 164 Mardi, 2. décembre 2008 3:32 15 164 Comprendre Flex 3 PARTIE I Tableau 9-1 Liste des effets de transition disponibles (suite) Effet Description Rezise Modifie la hauteur et la largeur d’un composant. Rotate Effectue la rotation d’un objet suivant un angle spécifique. WipeDown Effet de « baisser de rideau ». WipeLeft Effet de « tirer de rideau » vers la gauche. WipeUp Effet de « lever de rideau ». WipeRight Effet de « tirer de rideau » vers la droite. Zoom Effet de zoom sur le composant concerné. Voyons à présent comment implémenter une transition à travers l’exemple de code suivant : <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:WipeDown duration="1000" target="{panel1}"> </mx:WipeDown> </mx:Transition> </mx:transitions> La première étape consiste à mettre en place la balise <mx:transitions> qui va contenir l’ensemble des transitions de l’application. Vient ensuite la création de la transition proprement dite qui, comme mentionné précédemment, est définie par : • son identifiant : id="transition" ; • l’état de départ : fromState="*" ; • l’état d’arrivée : toState="*" ; • l’effet : <mx:WipeDown duration="1000" target="{panel1}">. En analysant attentivement les quelques lignes de code précédentes, nous pouvons observer quelques subtilités. La première concerne le nom des états. En effet, leur nom a été remplacé une astérisque (*), signifiant que la transition concerne l’ensemble des changements d’états de l’application. L’expression littérale de notre transition est la suivante : « Pour chaque changement d’état effectué dans l’application, appliquer l’effet WipeDown, ayant une durée de 1000 millisecondes, au composant panel1 ». Si nous avions souhaité créer une transition entre deux états particuliers, nous aurions remplacé les astérisques par l’identifiant de ces états : <mx:transitions> <mx:Transition id="transition" fromState="nomEtat1" toState="nomEtat2"> <mx:WipeDown duration="1000" target="{panel1}"> </mx:WipeDown> </mx:Transition> </mx:transitions> La seconde subtilité concernera l’emploi de la balise <mx:sequence>, dont la signification sera détaillée à la section suivante « Combiner des effets ». =Flex3 FM.book Page 165 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 165 Effet et cible (target) Chaque effet doit être appliqué sur une cible, dont l’identifiant est passé en paramètre de la propriété target de l’effet à l’aide d’accolades ouvrante et fermante. Pour appliquer l’effet à plusieurs cibles, il convient d’utiliser la propriété targets, à laquelle nous passons en paramètre la liste des identifiants des cibles concernées : <mx:WipeDown duration="1000" targets="{[panel1,numPatient]}"> </mx:WipeDown> Combiner des effets Chaque effet a une durée d’exécution déterminée dans le temps. Cette durée, exprimée en millisecondes, est précisée à l’aide de la propriété duration. Pour bien comprendre, revenons sur la notion de transition. Nous avons vu qu’une transition peut comporter un effet, mais elle peut également en comporter plusieurs ! Dans ce cas, comment ordonner leur exécution ? La réponse réside dans l’utilisation des balises <mx:Sequence> et <mx:Parallel> dont nous allons à présent étudier le fonctionnement. Exécution en séquence La balise <mx:Sequence> va nous permettre d’exécuter les effets de façon successive (figure 9-4). Si la transition comporte deux effets, l’effet 1 sera exécuté, puis l’effet 2, à condition que l’exécution du premier effet soit terminée. Figure 9-4 Séquence d’effets <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:Sequence target="{panel1}"> <mx:WipeDown duration="1000"> </mx:WipeDown> <mx:Blur duration="1500"> </mx:Blur> </mx:Sequence> </mx:Transition> </mx:transitions> Dans cet exemple de code, les effets WipeDown et Blur seront exécutés l’un après l’autre. Voyons à présent les particularités de la balise <mx:Parallel>. =Flex3 FM.book Page 166 Mardi, 2. décembre 2008 3:32 15 166 Comprendre Flex 3 PARTIE I Exécution en parallèle Comme vous l’avez sans doute deviné, la balise <mx:Parallel> permet l’exécution d’effets de façon simultanée (figure 9-5). Ainsi, si la transition comporte deux effets, l’effet 1 et l’effet 2 sont exécutés en même temps. <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:Parallel target="{panel1}"> <mx:WipeDown duration="1000"> </mx:WipeDown> <mx:Blur duration="1500"> </mx:Blur> </mx:Parallel> </mx:Transition> </mx:transitions> Dans cet exemple de code, les effets WipeDown et Blur sont exécutés de façon simultanée. Il est temps à présent de mettre en pratique de ce que vous venez d’apprendre sur les transitions et les effets associés. Pour cela, nous vous proposons de reprendre l’étude de cas précédente afin d’y ajouter une transition. Figure 9-5 Effets exécutés en parallèle Mise en pratique La transition que nous souhaitons implémenter sera jouée à chaque changement d’état de l’application. Nous y ajouterons deux effets exécutés de façon simultanée et ayant pour cible commune le composant Panel contenant le formulaire. Les effets choisis sont : • une rotation complète du panneau (figure 9-6) ; • un effet « d’Iris », c’est-à-dire la découverte progressive du panneau (figure 9-7). L’implémentation de la transition se résume à l’ajout des quelques lignes de code suivantes : <!-- TRANSITIONS --> <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:Parallel target="{panel1}"> <mx:Rotate angleFrom="0" angleTo="360" duration="1000"> </mx:Rotate> <mx:Iris duration="1000"> </mx:Iris> </mx:Parallel> </mx:Transition> </mx:transitions> =Flex3 FM.book Page 167 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 Figure 9-6 Effet de rotation Figure 9-7 Effet « d’Iris » 167 =Flex3 FM.book Page 168 Mardi, 2. décembre 2008 3:32 15 168 Comprendre Flex 3 PARTIE I Notre transition est donc jouée à chaque changement d’état grâce à la valeur * affectée aux propriétés fromState et toState. Comme nous souhaitons que l’exécution des effets soit simultanée, nous utilisons la balise <mx:Parallel> ayant pour cible principale le panneau portant l’identifiant panel1. Le premier effet est une rotation complète du panneau (angleFrom="0" angleTo="360") sur une durée de 1000 millisecondes. Quant au second, il s’agit de l’effet Iris ayant une durée équivalente à l’effet précédent. La transition est à présent mise en place. Nous vous laissons le soin de l’apprécier en exécutant le projet. Pour plus de clarté, voici le code complet de l’application qui pourra vous aider en cas d’éventuels dysfonctionnements : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- TRANSITIONS --> <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:Parallel target="{panel1}"> <mx:Rotate angleFrom="0" angleTo="360" duration="1000"> </mx:Rotate> <mx:Iris duration="1000"> </mx:Iris> </mx:Parallel> </mx:Transition> </mx:transitions> <!-- GROUPE DE BOUTONS RADIO --> <mx:RadioButtonGroup id="radioBoutons"/> <mx:RadioButton x="34" y="21" label="Recherche simple" groupName="radioBoutons" ➥id="btn_simple" selected="true" click="currentState=''"/> <mx:RadioButton x="166" y="21" label="Recherche avancée" groupName="radioBoutons" ➥id="btn_avance" click="currentState='rechercheAvancee'"/> <!-- CRITÈRES DE RECHERCHE --> <mx:Panel x="34" y="51" width="339" height="198" layout="absolute" title="Critères de ➥recherche" id="panel1"> <mx:Form x="10" y="10" height="108" width="302" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off" id="form1"> <mx:FormItem label="N° patient :"> <mx:TextInput id="numPatient"/> </mx:FormItem> <mx:FormItem label="Prénom :"> <mx:TextInput id="Prenom"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="Nom"/> </mx:FormItem> </mx:Form> <mx:Button x="221" y="126" label="Rechercher" id="button1"/> </mx:Panel> =Flex3 FM.book Page 169 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 169 <!-- ÉTATS --> <mx:states> <mx:State name="rechercheAvancee"> <mx:SetProperty target="{panel1}" name="height" value="267"/> <mx:SetProperty target="{button1}" name="x" value="218"/> <mx:SetProperty target="{button1}" name="y" value="195"/> <mx:SetProperty target="{form1}" name="height" value="177"/> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="N° chambre :"> <mx:TextInput id="num_chambre"/> </mx:FormItem> </mx:AddChild> <mx:AddChild relativeTo="{form1}" position="lastChild"> <mx:FormItem label="Date admission :"> <mx:DateField id="dateAdmission"/> </mx:FormItem> </mx:AddChild> <mx:SetEventHandler target="{btn_simple}" name="click" ➥handler="currentState=''"/> <mx:SetEventHandler target="{btn_avance}" name="click" ➥handler="currentState='rechercheAvancee'"/> </mx:State> </mx:states> </mx:Application> Écrire des transitions en ActionScript Comme nous l’avons vu au chapitre 2, tout ce qui est réalisé en MXML peut l’être grâce à ActionScript. C’est donc tout naturellement que nous allons recréer l’effet de transition précédent à l’aide du langage ActionScript. Pour cela, il convient tout d’abord d’effacer toute notion de transition dans l’application en supprimant le code suivant : <!-- TRANSITIONS --> <mx:transitions> <mx:Transition id="transition" fromState="*" toState="*"> <mx:Parallel target="{panel1}"> <mx:Rotate angleFrom="0" angleTo="360" duration="1000"> </mx:Rotate> <mx:Iris duration="1000"> </mx:Iris> </mx:Parallel> </mx:Transition> </mx:transitions> Ensuite, nous allons devoir créer un nouveau fichier ActionScript dans le répertoire src du projet, que nous nommerons TransitionAS3.as. Attention à ne pas oublier de créer le lien entre l’application et ce fichier en utilisant la balise <mx:Script> : <mx:Script source="TransitionAS3.as"> </mx:Script> =Flex3 FM.book Page 170 Mardi, 2. décembre 2008 3:32 15 170 Comprendre Flex 3 PARTIE I Passons à présent à l’écriture du code de notre transition : // Importation des classes nécessaires import mx.effects.Iris; import mx.effects.Parallel; import mx.effects.Rotate; import mx.states.Transition; public function creationTransition ():void{ // Création de la transition var transitionAS:Transition = new Transition; transitionAS.fromState = "*"; transitionAS.toState = "*"; // Création de la notion de parallélisme d’effets var parallelisme:Parallel = new Parallel; parallelisme.target = panel1; // Création de l’effet de rotation var rotation:Rotate = new Rotate(); rotation.angleFrom = 0; rotation.angleTo = 360 rotation.duration = 1000; // Création de l’effet d’Iris var iris:Iris = new Iris(); iris.duration = 1000; // Ajout des effets au conteneur d’effets parallelisme.addChild(rotation); parallelisme.addChild(iris); // Ajout du conteneur à la transition transitionAS.effect = parallelisme; // Ajout de la transition à la balise <mx:transitions> de l’application application.transitions = [transitionAS]; } La lecture de ce code parle d’elle-même. Nous importons tout d’abord l’ensemble des classes nécessaires à la réalisation de la transition, puis nous construisons petit à petit l’ensemble des éléments la composant. Le tableau 9-2 présente la correspondance entre le code MXML utilisé précédemment pour la création de la transition et le code ActionScript. Souvenez-vous, les effets de rotation et d’Iris sont dans le conteneur d’effets définissant leur mode d’exécution : <mx:Parallel target="{panel1}"> <mx:Rotate angleFrom="0" angleTo="360" duration="1000"> </mx:Rotate> <mx:Iris duration="1000"> </mx:Iris> </mx:Parallel> =Flex3 FM.book Page 171 Mardi, 2. décembre 2008 3:32 15 Le dynamisme applicatif à l’aide des états, des transitions et des effets CHAPITRE 9 Tableau 9-2 171 Correspondances entre le code MXML et le code ActionScript Étape MXML Actionscript Création de la transition. <mx:Transition id="transition" fromState="*" toState="*"> var transitionAS:Transition = new Transition; transitionAS.fromState = "*"; transitionAS.toState = "*"; Définition du mode d’exécution des effets et de la cible concernée. <mx:Parallel target="{panel1}"> var parallelisme:Parallel = new Parallel; parallelisme.target = panel1; Création de l’effet de rotation. <mx:Rotate angleFrom="0" angleTo="360" duration="1000"> </mx:Rotate> var rotation:Rotate = new Rotate(); rotation.angleFrom = 0; rotation.angleTo = 360 rotation.duration = 1000; Création de l’effet d’Iris. <mx:Iris duration="1000"> </mx:Iris> var iris:Iris = new Iris(); iris.duration = 1000; Bien entendu, MXML étant un langage basé sur XML, la notion d’inclusion d’élément se fait tout naturellement : // L’élément B est contenu dans l’élément A <ElementA> <ElementB> </ElementB> </ElementA> En ActionScript, cela n’est possible que si la classe utilisée permet de réaliser cette inclusion via l’une de ses méthodes. Si nous analysons la classe Parallel, nous constatons la présence de la méthode addChild(childEffect:IEffect) permettant d’ajouter à notre conteneur les deux effets créés : parallelisme.addChild(rotation); parallelisme.addChild(iris); Il convient ensuite d’inclure notre transition dans la propriété transitions (<mx:transitions>) de l’application chargée de contenir dans un tableau l’ensemble des transitions de l’application : application.transitions = [transitionAS]; La dernière étape consiste tout simplement à faire appel à notre procédure creationTransition() dans notre application et à vérifier par l’exécution du projet que le résultat obtenu est identique à celui obtenu par l’usage du langage MXML. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="creationTransition ()"> =Flex3 FM.book Page 172 Mardi, 2. décembre 2008 3:32 15 172 Comprendre Flex 3 PARTIE I En résumé Dans ce chapitre, nous avons vu comment il est possible d’organiser l’interface graphique de nos applications à l’aide des états et comment réaliser des transitions « animées ». Ces dernières permettent de réaliser des interfaces graphiques plus conviviales, avec un pouvoir commercial indéniable : si l’application est agréable à l’œil l’utilisateur aimera s’en servir et en parlera autour de lui. Attention toutefois à ne pas abuser des animations car en trop grand nombre, elles pourraient être gênantes pour les utilisateurs, qui la rejetteraient alors très rapidement, anéantissant ainsi votre dur labeur. Comme nous l’avons vu, Flex offre un éventail de fonctionnalités très large, couvrant la majeure partie de nos besoins. Néanmoins, il peut s’avérer que le composant nécessaire ne soit pas présent dans la bibliothèque de Flex. Nous allons donc voir dans le chapitre suivant comment créer nos propres composants. =Flex3 FM.book Page 173 Mardi, 2. décembre 2008 3:32 15 10 Créer des composants personnalisés Par définition, un composant est un objet faisant partie d’un système. Une application Flex contient un ensemble de composants ayant chacun un rôle précis : • un bouton qui déclenche l’exécution d’une action ; • un DataGrid qui offre la possibilité de présenter les données sous forme tabulaire ; • une zone de saisie, lieu de l’interaction avec l’utilisateur : elle lui offre la possibilité d’alimenter le système d’information, etc. Cependant, ces composants ne sont pas toujours entièrement satisfaisants, car leurs possibilités sont parfois limitées. Fort heureusement, le framework Flex nous permet de remédier à cela en créant nos propres composants. Penser composant Avant d’entrer dans le cœur du sujet, il est souhaitable de bien comprendre la notion de composant. Un composant est un élément autonome offrant un ensemble de fonctionnalités et pouvant être utilisé de façon similaire dans plusieurs applications. Il doit donc être capable de s’adapter à l’environnement applicatif dans lequel il est utilisé, tout en assurant une continuité de ses services. Prenons l’exemple du composant Button. Vous pouvez l’adapter à l’environnement applicatif en changeant son libellé ou son design (couleur, =Flex3 FM.book Page 174 Mardi, 2. décembre 2008 3:32 15 174 Comprendre Flex 3 PARTIE I police…), il assurera toujours sa fonctionnalité principale, qui est le déclenchement d’une action lorsque l’utilisateur clique dessus. Pour pouvoir être considéré comme tel, un composant doit offrir une ou plusieurs fonctionnalités qui pourront être invoquées quelle que soit l’application dans lequel il sera utilisé, ainsi qu’un certain nombre de paramètres lui permettant de s’adapter à son environnement. Tout ceci dans le but d’être réutilisable. Comme mentionné précédemment, une application Flex est constituée d’un ensemble de composants. Par ailleurs, un composant peut lui aussi comprendre d’autres composants. Par exemple, un composant permettant de suivre des flux RSS devra être constitué d’un composant permettant de saisir l’URL du flux à lire et d’un composant DataGrid présentant les articles de ce flux sous forme tabulaire. Un tel composant pourrait être qualifié de complexe mais nous lui préférons le nom de module. Ainsi, une application peut facilement être découpée en modules réutilisables dans d’autres applications. L’intérêt de développer des modules réside dans le fait qu’ils peuvent être développés et maintenus séparément, ne remettant pas en cause la stabilité de l’application dans laquelle ils sont intégrés. Qu’est–ce qu’un composant ? Un composant est un fichier portant l’extension .swc, obtenu grâce à la compilation d’autres fichiers, écrits à l’aide des langages ActionScript et/ou MXML. MXML ou ActionScript ? La première question que nous sommes en droit de nous poser est : faut il créer le composant à l’aide du langage MXML ou ActionScript ? Il n’existe pas de règle réellement établie à ce sujet. Pour les composants simples, c’est-à-dire ayant peu de fonctionnalités (un composant de présentation d’images par exemple), le MXML peut suffire. Pour un composant demandant la mise en place d’une logique complexe, la combinaison des langages ActionScript et MXML est à préférer, mais rien ne vous empêche d’utiliser exclusivement ActionScript. C’est d’ailleurs cette méthode que nous allons privilégier ici afin d’illustrer au mieux la mise en place d’un composant. Libre à vous d’opter pour l’une ou l’autre de ces méthodes en fonction de vos affinités avec les langages ActionScript et MXML, et de la complexité du composant à développer. Le compilateur compc Maintenant que le choix de la méthode de développement a été effectué, nous pouvons passer à la réalisation du composant. Une fois ce dernier créé, il nous faut le compiler afin de le rendre utilisable dans d’autres applications Flex. C’est le rôle du compilateur compc. =Flex3 FM.book Page 175 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 175 Le compilateur de composants compc s’exécute en ligne de commande. Il permet de créer un fichier SWC à partir de fichiers MXML et ActionScript passés en paramètres. Sa syntaxe d’exécution est la suivante : compc [options] -include-classes class [...] compc -o monComposant.swc -root monComposant.mxml Dans cet exemple de code, nous compilons le fichier monComposant.mxml donnant naissance (-o = output) au fichier monComposant.swc. Nous ne nous attarderons pas davantage sur ce compilateur dont le fonctionnement sera détaillé à la section « Compilation avec compc » de ce chapitre. Créer un composant Un exemple valant souvent mieux qu’un long discours, nous vous proposons à présent de créer un composant que vous réutiliserez sans doute dans un grand nombre de vos futures applications Flex, qui vous permettra de filtrer un tableau en fonction d’une donnée saisie dans une zone de texte. Description du composant Le composant que nous allons créer permettra de filtrer le contenu d’un tableau sur une colonne donnée en fonction des informations saisies par l’utilisateur dans un champ prévu à cet effet. Le fonctionnement du composant est synthétisé par la figure 10-1 qui nous permet de définir les étapes suivantes : Étape ➊ : le composant reçoit des données sous la forme d’une collection d’objets (ArrayCollection). Étape ➋ : les données reçues sont affichées dans le DataGrid du composant. Étape ➌ : l’utilisateur saisit son critère de recherche dans la zone de texte prévue à cet effet. Étape ➍ : à chaque modification de la zone de saisie, le filtre est effectué sur la colonne du DataGrid concerné selon la règle suivante : « Afficher les éléments de la colonne contenant la valeur de l’expression saisie dans la zone de texte », ce qui entraîne la mise à jour du DataGrid. Étape ➎ : la sélection d’une ligne du DataGrid permet d’extraire la valeur servant d’identifiant pour la donnée cliquée, valeur qui peut alors être exploitée dans un autre traitement. =Flex3 FM.book Page 176 Mardi, 2. décembre 2008 3:32 15 176 Comprendre Flex 3 PARTIE I Figure 10-1 Fonctionnement du composant Compte tenu de ce que nous venons d’énoncer, les éléments faisant partie intégrante du composant sont donc : • un composant TextInput qui permettra à l’utilisateur de saisir des données ; • un composant Label précédant la zone de saisie et permettant d’indiquer à l’utilisateur la colonne du tableau concernée par le filtre ; • un composant DataGrid représentant les données sous forme tabulaire ; • un composant Canvas servant de conteneur principal. Comme nous l’avons vu précédemment, un composant doit être réutilisable et s’adapter à toutes les situations. Pour que cette adaptation soit effective, certaines propriétés du composant doivent être paramétrables. La plupart des paramétrages sont liés à l’aspect graphique (couleur, libellés…). Pour que notre composant soit réutilisable, nous devons offrir la possibilité de paramétrer les éléments suivants : • le nombre de colonnes du DataGrid ; • les propriétés des colonnes (nom, taille, visibilité…) ; • le texte du composant Label précédant la zone de texte. =Flex3 FM.book Page 177 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 177 Les paramètres liés aux traitements ne peuvent que très rarement être spécifiés car ils obéissent à des règles précises énoncées dans le code du composant. Dans notre cas, nous allons demander à ce que la collection d’objets transmise au composant (ArrayCollection) ait une structure particulière : • le champ sur lequel portera le filtre devra être nommé champFiltre ; • le champ contenant l’identifiant de la donnée devra porter le nom idt. Si l’on considère l’exemple illustré par la figure 10-1, la collection d’objets (ArrayCollection) s’apparente au code suivant : <mx:ArrayCollection id="sourceDonnees"> <mx:Object idt="1" champFiltre="Tucano Flylab"/> <mx:Object idt="2" champFiltre="Pou du ciel"/> <mx:Object idt="3" champFiltre="Skyranger"/> <mx:Object idt="4" champFiltre="A22 Vision"/> <mx:Object idt="5" champFiltre="Storch"/> </mx:ArrayCollection> Le fonctionnement général du composant étant à présent défini, il est temps de se lancer dans sa réalisation. Méthodologie de création La création de notre composant se déroule en six phases que allons découvrir ensemble : 1. création du projet ; 2. création du composant ; 3. mise en place des éléments graphiques du composant ; 4. alimentation du DataGrid (tableau de données) ; 5. gestion des événements ; 6. compilation. Phase 1 – Création du projet Bien que nous allons créer un élément aussi important, il n’existe pas de projet de ce type au sein de Flex Builder. Il faut donc procéder comme si nous allions créer un projet Flex standard. Fichier MXML Component Il est possible de créer un composant au sein d’une application Flex en créant un nouveau fichier MXML Component. 1. Ouvrez Flex Builder et sélectionnez le menu File>New>Flex Project. 2. Dans la fenêtre qui s’ouvre alors, saisissez le nom du projet (compFiltreTableau pour notre exemple) et indiquez que vous souhaitez créer une application de type web (option Web application). =Flex3 FM.book Page 178 Mardi, 2. décembre 2008 3:32 15 178 Comprendre Flex 3 PARTIE I 3. Conservez les options de configuration proposées par défaut et cliquez sur le bouton Finish. Phase 2 − Création du composant La phase suivante consiste à créer la classe ActionScript du composant et à l’insérer dans l’interface graphique du projet afin de pouvoir tester son bon fonctionnement. Dans l’arborescence du projet, nous allons tout d’abord créer un package que l’on nommera com.composants et qui contiendra la classe du composant : 1. Effectuez un clic droit sur le répertoire src et sélectionnez New>Folder. 2. Nommez ce nouveau répertoire com 3. Répétez l’étape 1 avec le répertoire com nouvellement créé et nommez le nouveau sousrépertoire composants. 4. Créez ensuite la classe du composant en effectuant un clic droit sur le répertoire composants et en sélectionnant ActionScript Class>New dans le menu contextuel. 5. Dans la fenêtre qui s’affiche alors, vous constatez que le package com.composants est renseigné de façon automatique. 6. Spécifiez ensuite le nom de la classe, soit FiltreTableau. Le composant étant avant tout un Canvas comportant différents éléments (TextInput, DataGrid), la classe FiltreTableau devra hériter de la classe mx.containers.Canvas. Cet héritage est à spécifier dans le champ Superclass de la fenêtre de configuration (figure 10-2). Convention de nommage Pour respecter la convention de nommage du langage ActionScript, le nom de la classe doit obligatoirement commencer par une majuscule. 7. Cliquez sur le bouton Finish. Si vous observez l’arborescence du projet, vous notez la présence de la classe FiltreTableau créée dans le répertoire composants et contenant le code suivant : package com.composants { import mx.containers.Canvas; public class FiltreTableau extends Canvas { public function FiltreTableau() { super(); } } } =Flex3 FM.book Page 179 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 179 Figure 10-2 Création de la classe FiltreTableau Nous observons que la classe Canvas (import mx.containers.Canvas) a été importée et que notre classe hérite de cette dernière (extends Canvas). Nous notons aussi la présence du constructeur FiltreTableau(), appelé lors de l’instanciation de la classe. À l’intérieur de ce constructeur, on remarque également la présence du mot-clé super. Celui-ci doit être obligatoirement spécifié car notre composant hérite de la classe Canvas et de ce fait, le constructeur de cette classe doit être appelé avant toute autre instruction. Il faut ensuite mettre en place le composant dans l’interface graphique du projet en modifiant le fichier comFiltreTableau.mxml créé lors de la phase d’initialisation du projet. Pour ce faire, activez le mode Source et apportez les modifications suivantes au code déjà présent : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥xmlns:compFT="com.composants.*"> <compFT:FiltreTableau id="ComposantFiltreTableau" width="420" =Flex3 FM.book Page 180 Mardi, 2. décembre 2008 3:32 15 180 Comprendre Flex 3 PARTIE I height="420" x="10" y="10"> </compFT:FiltreTableau> </mx:Application> La première chose à faire est de préciser l’espace de noms du composant à l’aide de xmlns (pour XML Name Space). C’est grâce à cet espace de noms que le compilateur est en mesure de trouver les classes ActionScript correspondant à notre composant. L’espace de noms utilisé est com.composant.* préfixé par la valeur compFT. C’est ce préfixe qui sera utilisé dans l’interface graphique, Flex étant alors en mesure de faire la relation entre le préfixe et la classe spécifiée dans l’espace de noms. Nous pourrons ainsi faire appel aux méthodes du composant. Vient ensuite la mise en place du composant en faisant appel à son constructeur (<compFT:FiltreTableau>). Étant donné qu’il hérite de la classe Canvas, nous pouvons lui affecter les propriétés id, width, height, x et y. À présent, si nous activons le mode Design, nous remarquons la présence de notre composant sous la forme d’un Canvas comme l’illustre la figure 10-3. Figure 10-3 Mise en place du composant Phase 3 − Mise en place des éléments Nous allons à présent modifier la classe FiltreTableau pour que les éléments TextInput, Label et DataGrid soient créés dynamiquement. package com.composants { import mx.containers.Canvas; import mx.controls.DataGrid; =Flex3 FM.book Page 181 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 181 import mx.controls.Label; import mx.controls.TextInput; public class FiltreTableau extends Canvas { private var _libelle:Label = new Label(); private var _zoneTexte:TextInput = new TextInput; private var _datagrid:DataGrid = new DataGrid(); public function FiltreTableau() { super(); // Ajout du libellé _libelle.x=10 _libelle.y=10 _libelle.width = 100; this.addChild(_libelle); // Ajout de la zone de texte _zoneTexte.x = 110; _zoneTexte.y = 10; this.addChild(_zoneTexte); // Ajout du DataGrid _datagrid.x=10; _datagrid.y=40; this.addChild(_datagrid); } } } Après avoir importé les classes relatives à chaque élément, nous devons les instancier en créant les objets _libelle, _zoneTexte et _datagrid. Chaque objet pourra alors être ajouté au Canvas de notre composant grâce à sa méthode addChild(). La figure 10-4 illustre le résultat obtenu après l’ajout de ces quelques lignes de code. Figure 10-4 Mise en place des éléments =Flex3 FM.book Page 182 Mardi, 2. décembre 2008 3:32 15 182 Comprendre Flex 3 PARTIE I Vous aurez sans doute remarqué que le libellé ne semble pas être présent sur l’interface. Cette impression est due au fait que la propriété text du libellé n’a pas été renseignée, mais rassurez-vous, le libellé est bien présent. Nous verrons par la suite comment il est possible de le personnaliser. Phase 4 − Alimentation du DataGrid Le DataGrid du composant sera alimenté via une collection d’objets (ArrayCollection) passée en paramètre. La première étape va donc consister à créer ce paramètre en déclarant un attribut _tableauDonnees de type ArrayCollection ainsi que les méthodes set et get qui lui seront associées. Dans la méthode set, on affectera le dataProvider de l’objet _datagrid avec la valeur reçue en paramètre, permettant l’affichage des données dans le DataGrid. import mx.collections.ArrayCollection; public class FiltreTableau extends Canvas { […] private var _tableauDonnees:ArrayCollection = new ArrayCollection(); public function FiltreTableau() { super(); […] } public function set tableauDonnees(t:ArrayCollection):void{ _datagrid.dataProvider = t; _tableauDonnees = t; } public function get tableauDonnees():ArrayCollection{ return _tableauDonnees; } } Modifions à présent le code du fichier FiltreTableau.mxml en créant une nouvelle collection d’objets (ArrayCollection) qui sera passée en paramètre de notre composant. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥xmlns:compFT="com.composants.*"> <mx:ArrayCollection id="sourceDonnees"> <mx:Object idt="1" champFiltre="Tucano Flylab"/> <mx:Object idt="2" champFiltre="Pou du ciel"/> <mx:Object idt="3" champFiltre="Skyranger"/> <mx:Object idt="4" champFiltre="A22 Vision"/> <mx:Object idt="5" champFiltre="Storch"/> </mx:ArrayCollection> =Flex3 FM.book Page 183 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 183 <compFT:FiltreTableau id="ComposantFiltreTableau" width="420" height="420" x="10" y="10" tableauDonnees="{sourceDonnees}" > </compFT:FiltreTableau> </mx:Application> Exécutons ensuite l’application et vérifions que tout se déroule bien correctement (figure 10-5). Figure 10-5 Alimentation du DataGrid Nous pourrions nous contenter du résultat obtenu, mais n’oublions pas qu’un composant n’est réutilisable que s’il peut s’adapter à une multitude de situations. Dans notre cas, il serait préférable que les colonnes du DataGrid soient paramétrables, c’est-à-dire qu’il soit au moins possible de définir leur libellé, leur taille et leur visibilité. Pour cela, nous allons procéder de la même manière que pour la création du paramètre tableauDonnees. Les colonnes seront décrites dans une ArrayCollection qui sera ensuite analysée, modifiant ainsi les colonnes du DataGrid. import mx.controls.dataGridClasses.DataGridColumn; public class FiltreTableau extends Canvas { […] private var _colonnes:ArrayCollection = new ArrayCollection(); […] public function set colonnes(col:ArrayCollection):void{ _colonnes = col; ajouterColonnes() } =Flex3 FM.book Page 184 Mardi, 2. décembre 2008 3:32 15 184 Comprendre Flex 3 PARTIE I public function get colonnes():ArrayCollection{ return _colonnes; } public function ajouterColonnes():void { var listeColonnes:Array = new Array(); for (var i:int=0; i<_colonnes.length;i++) { var colonne:DataGridColumn = new DataGridColumn(); colonne.headerText = _colonnes[i].entete; colonne.dataField = _colonnes[i].champ; colonne.visible = _colonnes[i].visible; colonne.width = _colonnes[i].longueur; listeColonnes.push(colonne); } _datagrid.columns = listeColonnes; } } Nous devons tout d’abord créer l’objet _colonne et ses méthodes set et get associées. Dans la méthode set, nous faisons appel à la méthode ajouterColonnes() qui, pour chaque élément trouvé dans l’ArrayCollection _colonnes, instancie la classe mx.controls.dataGridClasses.DataGridColumn. Cette instanciation a pour résultat la création d’un objet colonne dont les attributs sont affectés par les données présentes dans l’objet _colonnes. Nous pouvons donc modifier les attributs suivants : • headerText, qui correspond à l’en-tête de la colonne ; • visible, qui indique si la colonne sera visible ou non ; • width, qui permet de spécifier la taille de la colonne ; • DataField, qui correspond au nom de l’attribut présent dans l’objet _tableauDonnees devant être affiché dans cette colonne. Chaque nouvelle colonne est ensuite mise dans un tableau servant à alimenter l’attribut columns de l’objet _datagrid. Voyons à présent comment implémenter tout ceci dans l’interface graphique de notre application. <mx:ArrayCollection id="colonnes"> <mx:Object entete="IDT" champ="idt" visible="false" longueur="10"/> <mx:Object entete="Nom des appareils" champ="champFiltre" visible="true" ➥longueur="300"/> </mx:ArrayCollection> =Flex3 FM.book Page 185 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 185 <compFT:FiltreTableau id="ComposantFiltreTableau" width="420" height="420" x="10" y="10 tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" > </compFT:FiltreTableau> Chaque objet de l’ArrayCollection possède les attributs entete, champ, visible et longueur qui seront repris lors de l’ajout de colonnes dans le DataGrid. Il suffit ensuite de passer cette collection d’objets en paramètre à l’attribut colonnes de notre composant et d’observer le résultat obtenu (figure 10-6). Figure 10-6 Paramétrage des colonnes Le paramétrage de notre composant touche à sa fin, il ne nous reste plus qu’à créer le paramètre servant à afficher le texte dans le label. Pour ce faire, il convient de créer la méthode set de l’objet libelle qui modifie la propriété text de ce dernier : public function set libelle(texte:String):void{ _libelle.text = texte; } L’étape finale consiste à affecter ce nouveau paramètre dans l’interface graphique (figure 10-7) : <compFT:FiltreTableau id="ComposantFiltreTableau" width="420" height="420" x="10" y="10" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" libelle="Appareil ULM :" > =Flex3 FM.book Page 186 Mardi, 2. décembre 2008 3:32 15 186 Comprendre Flex 3 PARTIE I Figure 10-7 Composant paramétré Voici le code complet de la classe FiltreTableau et du fichier compFiltreTableau.mxml, qui vous permettra de vérifier votre bonne compréhension de ce qui vient d’être énoncé et que vous n’avez rien oublié. Classe FiltreTableau package com.composants { import mx.containers.Canvas; import mx.collections.ArrayCollection; import mx.controls.DataGrid; import mx.controls.Label; import mx.controls.TextInput; import mx.controls.dataGridClasses.DataGridColumn; public class FiltreTableau extends Canvas { private var _libelle:Label = new Label(); private var _zoneTexte:TextInput = new TextInput; private var _datagrid:DataGrid = new DataGrid(); private var _tableauDonnees:ArrayCollection = new ArrayCollection(); private var _colonnes:ArrayCollection = new ArrayCollection(); public function FiltreTableau() { super(); // Ajout du libellé _libelle.x=10 _libelle.y=10 _libelle.width = 100; this.addChild(_libelle); =Flex3 FM.book Page 187 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 // Ajout de la zone de texte _zoneTexte.x = 110; _zoneTexte.y = 10; this.addChild(_zoneTexte); // Ajout du DataGrid _datagrid.x=10; _datagrid.y=40; this.addChild(_datagrid); } public function set tableauDonnees(t:ArrayCollection):void{ _datagrid.dataProvider = t; _tableauDonnees = t; } public function get tableauDonnees():ArrayCollection{ return _tableauDonnees; } public function set colonnes(col:ArrayCollection):void{ _colonnes = col; ajouterColonnes() } public function get colonnes():ArrayCollection{ return _colonnes; } public function ajouterColonnes():void { var listeColonnes:Array = new Array(); for (var i:int=0; i<_colonnes.length;i++) { var colonne:DataGridColumn = new DataGridColumn(); colonne.headerText = _colonnes[i].entete; colonne.dataField = _colonnes[i].champ; colonne.visible = _colonnes[i].visible; colonne.width = _colonnes[i].longueur; listeColonnes.push(colonne); } _datagrid.columns = listeColonnes; } public function set libelle(texte:String):void{ _libelle.text = texte; } } } 187 =Flex3 FM.book Page 188 Mardi, 2. décembre 2008 3:32 15 188 Comprendre Flex 3 PARTIE I Fichier compFiltreTableau.mxml <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥xmlns:compFT="com.composants.*"> <mx:ArrayCollection id="sourceDonnees"> <mx:Object idt="1" champFiltre="Tucano Flylab"/> <mx:Object idt="2" champFiltre="Pou du ciel"/> <mx:Object idt="3" champFiltre="Skyranger"/> <mx:Object idt="4" champFiltre="A22 Vision"/> <mx:Object idt="5" champFiltre="Storch"/> </mx:ArrayCollection> <mx:ArrayCollection id="colonnes"> <mx:Object entete="IDT" champ="idt" visible="false" longueur="10"/> <mx:Object entete="Noms des appareils" champ="champFiltre" visible="true" ➥longueur="300"/> </mx:ArrayCollection> <compFT:FiltreTableau id="ComposantFiltreTableau" width="420" height="420" x="10" y="10" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" libelle="Appareil ULM :" > </compFT:FiltreTableau> </mx:Application> Phase 5 − Gestion des événements Nous allons à présent mettre en place toute la logique applicative de notre composant. Nous souhaitons tout d’abord que lorsque l’utilisateur saisit une information dans la zone de texte prévue à cet effet, cela entraîne un filtre sur l’attribut champFiltre de l’objet _tableaudonnee et la mise à jour du DataGrid en fonction du résultat de ce filtre. Ensuite, l’événement déclenché en cliquant sur un item du DataGrid doit permettre de récupérer la valeur de la colonne idt afin que son exploitation soit possible dans un autre traitement. Mise en place du filtre Avant de programmer tout événement, nous devons importer les classes nécessaires : import flash.events.Event; import mx.events.ListEvent; =Flex3 FM.book Page 189 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 189 Par ailleurs, le filtre doit être effectué lors de chaque modification de la zone de saisie, ce qui signifie que nous devons ajouter un écouteur d’événement qui se chargera d’exécuter une méthode lorsque le contenu de la zone de texte sera modifié : _zoneTexte.addEventListener(Event.CHANGE,evenementModification); Voyons à présent le contenu de la méthode evenementModification : public function evenementModification(e:Event):void { var texteSaisi:String = _zoneTexte.text; _tableauDonnees.filterFunction = filtrageDonnees; _tableauDonnees.refresh(); _datagrid.dataProvider = _tableauDonnees; } public function filtrageDonnees(item:Object):Boolean { return !item.champFiltre.length || item.champFiltre.toUpperCase().indexOf ➥(_zoneTexte.text.toUpperCase()) >= 0; } La méthode filterFunction de l’attribut _tableauDonnees est appelée. Cette méthode de la classe ArrayCollection va permettre de filtrer le contenu de l’attribut à l’aide de la fonction filtrageDonnees. Le principe de ce filtre est le suivant : 1. L’utilisateur saisit la première lettre de l’élément recherché. 2. Pour chaque item de l’ArrayCollection, la fonction FiltrageDonnees est exécutée. Si l’item, passé en paramètre de la fonction, correspond aux critères saisis dans la zone de texte, la valeur true est renvoyée, ce qui permet d’indiquer à l’ArrayCollection que l’item pourra être affiché. 3. Le contenu de l’attribut _tableauDonnees est ensuite actualisé. Les données de l’ArrayCollection ne correspondant pas au filtre ne sont pas supprimées mais simplement masquées. 4. L’attribut est ensuite affecté au dataProvider du DataGrid ce qui permet d’afficher les éléments correspondant au filtre saisi par l’utilisateur. Nous pouvons de nouveau exécuter le projet et vérifier que tout fonctionne correctement. Passons à présent à la mise en place de l’événement qui nous permettra de récupérer la valeur du champ idt lorsque l’utilisateur cliquera sur un item du DataGrid. Récupération de la valeur de l’identifiant Pour commencer, nous allons ajouter une zone de texte sur notre interface graphique dans laquelle sera affiché l’identifiant de l’item sélectionné dans le DataGrid. <mx:TextInput x="10" y="457" width="198" id="idITem"/> =Flex3 FM.book Page 190 Mardi, 2. décembre 2008 3:32 15 190 Comprendre Flex 3 PARTIE I Comme nous l’avons fait pour le filtrage des données, nous ajoutons un écouteur d’événement sur le DataGrid qui déclenchera l’exécution d’une méthode à chaque fois que l’utilisateur cliquera sur l’un des items du DataGrid : _datagrid.addEventListener(ListEvent.ITEM_CLICK,renvoyerIdentifiant) L’identifiant sera stocké dans un attribut que l’on nommera _valeurRenvoyee, dont les méthodes set et get devront être spécifiées. Le rôle de la méthode renvoyerIdentifiant sera de récupérer la valeur du champ idt de la ligne du DataGrid sélectionnée et de l’affecter à l’attribut _valeurRenvoyee. public class FiltreTableau extends Canvas { [...] private var _valeurRenvoyee:String; [...] } public function set valeurRenvoyee(valeur:String):void{ _valeurRenvoyee = valeur; } public function get valeurRenvoyee():String { return _valeurRenvoyee; } public function renvoyerIdentifiant(e:Event):void { _valeurRenvoyee = String(e.currentTarget.selectedItem.idt); } Modifions également la zone de texte précédemment créée afin qu’elle affiche le résultat obtenu par la méthode get valeurRenvoyee. <mx:TextInput x="10" y="457" width="198" id="idITem" text="{ComposantFiltreTableau ➥.valeurRenvoyee}"/> Si nous exécutons à présent le projet, nous voyons que cela ne fonctionne pas. Le débogueur de Flex nous indique le message d’alerte suivant : Data Binding will not be able to detect assignments to « ValeurRenvoyee ». Que se passe-t-il ? Tout semblait pourtant être correct ! Souvenez-vous, nous avons vu dans le chapitre 5 que lorsqu’une variable est utilisée à des fins d’association de données (DataBinding), nous devons lui affecter la mention [Bindable]. Ceci est très souvent utilisé lorsqu’une variable sert à alimenter le dataProvider d’un DataGrid ou d’une liste déroulante. Cette mention permet l’exécution d’un événement lors du changement de valeur de la variable, indiquant à Flex que la valeur de la variable a été modifiée et qu’il faut la réassigner. Si on analyse le message affiché dans le débogueur de Flex, il semblerait que la méthode get ValeurRenvoyee ait besoin d’être affectée de la mention [Bindable]. Cela semble tout à fait logique. En effet, nous modifions bien la valeur de l’attribut _valeurRenvoyée grâce à =Flex3 FM.book Page 191 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 191 la méthode set ValeurRetournee(valeur:String) mais Flex nous alerte qu’il n’est pas en mesure d’afficher la nouvelle valeur prise par cet attribut étant donné que la méthode get ValeurRetournee ne possède pas d’événement permettant à Flex de l’appeler. Pour résoudre ce problème, nous allons donc modifier les méthodes set et get de l’attribut _valeurRetournee : public function set valeurRenvoyee(valeur:String):void{ _valeurRenvoyee = valeur; dispatchEvent(new Event("changementValeurRenvoyee")); } [Bindable("changementValeurRenvoyee")] public function get valeurRenvoyee():String{ return _valeurRenvoyee; } La méthode get valeurRenvoyee est affectée de la mention [Bindable("changementValeurRenvoyee")]. Lors de l’exécution de la méthode set ValeurRenvoyee, ceci permet d’effectuer un dispatch (ou appel) à l’événement changementValeurRenvoyee exécutant la méthode get ValeurRenvoyee() et a pour conséquence, dans notre cas, la mise à jour de la zone de texte chargée de contenir l’identifiant de l’élément sélectionné dans le DataGrid. Nous pouvons à présent tester le bon fonctionnement de notre composant en exécutant le projet. Pour plus de clarté, voici le code complet de la classe FiltreTableau et du fichier compFiltreTableau.mxml. Classe FiltreTableau package com.composants { import mx.containers.Canvas; import mx.collections.ArrayCollection; import mx.controls.DataGrid; import mx.controls.Label; import mx.controls.TextInput; import mx.controls.dataGridClasses.DataGridColumn; import flash.events.Event; import mx.events.ListEvent; public class FiltreTableau extends Canvas { private var _tableauDonnees:ArrayCollection = new ArrayCollection(); private var _datagrid:DataGrid = new DataGrid(); private var _libelle:Label = new Label(); private var _zoneTexte:TextInput = new TextInput; private var _colonnes:ArrayCollection = new ArrayCollection(); private var _champRecherche:String; private var _valeurRenvoyee:String; =Flex3 FM.book Page 192 Mardi, 2. décembre 2008 3:32 15 192 Comprendre Flex 3 PARTIE I public function FiltreTableau() { super(); // Ajout d’un libellé _libelle.x=10 _libelle.y=10 _libelle.width = 100; this.addChild(_libelle); // Ajout de la zone de texte _zoneTexte.x = 110; _zoneTexte.y = 10; _zoneTexte.addEventListener(Event.CHANGE,evenementModification); this.addChild(_zoneTexte); //Ajout du DataGrid _datagrid.x=10; _datagrid.y=40; _datagrid.addEventListener(ListEvent.ITEM_CLICK,renvoyerIdentifiant) this.addChild(_datagrid); } // Méthodes Setters (affection de valeur aux attributs) et Getters (récupération ➥des valeurs affectées aux attributs) public function set valeurRenvoyee(valeur:String):void{ _valeurRenvoyee = valeur; dispatchEvent(new Event("changementValeurRenvoyee")); } [Bindable("changementValeurRenvoyee")] public function get valeurRenvoyee():String{ return _valeurRenvoyee; } public function set libelle(texte:String):void{ _libelle.text = texte; } public function get libelle():String{ return _libelle.text; } public function set tableauDonnees(t:ArrayCollection):void{ _datagrid.dataProvider = t; _tableauDonnees = t; } public function get tableauDonnees():ArrayCollection{ return _tableauDonnees; } public function set champRecherche(champ:String):void{ _champRecherche = champ; } =Flex3 FM.book Page 193 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 public function get champRecherche():String{ return _champRecherche; } public function set colonnes(col:ArrayCollection):void{ _colonnes = col; ajouterColonnes() } public function get colonnes():ArrayCollection{ return _colonnes; } // Méthode d’ajout des colonnes public function ajouterColonnes():void { var listeColonnes:Array = new Array(); for (var i:int=0; i<_colonnes.length;i++) { var colonne:DataGridColumn = new DataGridColumn(); colonne.headerText = _colonnes[i].entete; colonne.dataField = _colonnes[i].champ; colonne.visible = _colonnes[i].visible; colonne.width = _colonnes[i].longueur; listeColonnes.push(colonne); } _datagrid.columns = listeColonnes; } public function evenementModification(e:Event):void { var texteSaisi:String = _zoneTexte.text; _tableauDonnees.filterFunction = filtrageDonnees; _tableauDonnees.refresh(); _datagrid.dataProvider = _tableauDonnees; } public function filtrageDonnees(item:Object):Boolean { return !item.champFiltre.length || item.champFiltre.toUpperCase() ➥.indexOf(_zoneTexte.text.toUpperCase()) >= 0; } public function renvoyerIdentifiant(e:Event):void { _valeurRenvoyee = String(e.currentTarget.selectedItem.idt); } } } 193 =Flex3 FM.book Page 194 Mardi, 2. décembre 2008 3:32 15 194 Comprendre Flex 3 PARTIE I Fichier ComFiltreTableau.mxml <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥xmlns:compFT="com.composants.*"> <mx:ArrayCollection id="sourceDonnees"> <mx:Object idt="1" champFiltre="Tucano Flylab"/> <mx:Object idt="2" champFiltre="Pou du ciel"/> <mx:Object idt="3" champFiltre="Skyranger"/> <mx:Object idt="4" champFiltre="A22 Vision"/> <mx:Object idt="5" champFiltre="Storch"/> </mx:ArrayCollection> <mx:ArrayCollection id="colonnes"> <mx:Object entete="IDT" champ="idt" visible="false" longueur="10"/> <mx:Object entete="Nom des appareils" champ="champFiltre" visible="true" ➥longueur="300"/> </mx:ArrayCollection> <compFT:FiltreTableau id="ComposantFiltreTableau" x="10" y="10" width="420" height="320" libelle ="Appareil ULM : " tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" > </compFT:FiltreTableau> <mx:TextInput x="10" y="457" width="198" id="idITem" ➥text="{ComposantFiltreTableau.valeurRenvoyee}"/> </mx:Application> Notre composant est à présent terminé. Nous avons vu qu’il était primordial d’offrir au composant un minimum de possibilités de paramétrage afin qu’il puisse s’adapter à l’application dans lequel il doit être intégré. Cette partie nous a également permis de compléter nos connaissances sur la notion de DataBinding, largement employée dans de nombreuses applications comme celles que nous aurons l’occasion de découvrir dans les chapitres suivants. Voyons à présent comment compiler notre composant et vérifions qu’il est bien possible de le réutiliser dans une autre application. =Flex3 FM.book Page 195 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 195 Phase 6 − Compilation Convention de nommage Afin de faciliter l’ensemble des explications qui vont suivre, nous utiliserons une convention de nommage pour l’ensemble des répertoires qui seront utilisés : RootProjetFlex : répertoire contenant les sources du projet ; RootFlexBuilder : répertoire d’installation de Flex Builder. Nous allons à présent compiler notre composant à l’aide du compilateur compc en mode MS-DOS. Comme nous l’avons vu au chapitre 3, il convient d’utiliser le compilateur compc pour compiler des composants. L’exécutable compc.exe se situe dans le répertoire bin du kit Flex SDK ou dans le répertoire RootFlexBuilder\sdks\3.0.0\bin de Flex Builder. Pour réaliser la compilation, placez-vous dans le répertoire approprié et saisissez la commande suivante : compc -o "c:/librairieComposants/compFiltreTableau.swc" -source-path="RootProjetFlex/ ➥\src" -include-classes="com.composants.FiltreTableau" L’instruction compc fait appel au compilateur compc.exe. L’option –o (output) spécifie le répertoire où sera créé le fichier SWC. Nous vous conseillons d’ailleurs de créer un répertoire sur votre disque dur destiné à accueillir l’ensemble de vos composants, ce qui vous permettra de les retrouver plus rapidement. La seconde option, -source-path, sert à indiquer le chemin d’accès aux sources du projet Flex. Veillez à ne pas oublier le répertoire src car sinon, la classe FiltreTableau ne sera pas trouvée. Enfin, l’option -includeclasses permet de définir le package et la classe de notre composant. Nous pouvons à présent appuyer sur la touche Entrée du clavier pour vérifier la bonne compilation du projet par la création du fichier compFiltreTableau.swc. Réemploi du composant Nous allons à présent voir comment réemployer notre composant dans une autre application. 1. Créez un nouveau projet Flex que vous nommerez orchidees et qui traitera de la gestion des orchidées. 2. Vient ensuite l’étape d’importation du composant dans le projet. Pour ce faire, effectuez un clic droit sur le nom du projet nouvellement créé et sélectionnez Properties. 3. Cliquez ensuite sur Flex Build Path, sélectionnez l’onglet Library path et cliquez sur le bouton Add SWC… 4. Dans la fenêtre qui s’ouvre alors (figure 10-8), sélectionnez le fichier comFiltreTableau .swc se trouvant dans le répertoire de stockage de vos composants (ici, c:\librairie Composants\compFiltreTableau.swc). Cliquez ensuite sur le bouton OK pour terminer la procédure d’importation du composant. =Flex3 FM.book Page 196 Mardi, 2. décembre 2008 3:32 15 196 Comprendre Flex 3 PARTIE I Figure 10-8 Importation du fichier compFiltreTableau.swc Modifions à présent le code du fichier orchidee.mxml. Saisissons les cinq premiers caractères : <comp pour voir apparaître, par le biais de l’autocomplétion, la proposition de notre composant, soit <composants:FiltreTableau>. Notons l’importation automatique de l’espace de noms xmlns:composants="com.composants.*" après validation de la saisie précédente. Nous venons, en quelques instructions, d’importer notre composant au sein de notre application. Voici un exemple d’implémentation de notre composant à travers une collection d’objets listant les orchidées disponibles à la vente sur un site d’une jardinerie : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" ➥layout="absolute" xmlns:composants="com.composants.*"> =Flex3 FM.book Page 197 Mardi, 2. décembre 2008 3:32 15 Créer des composants personnalisés CHAPITRE 10 197 <mx:ArrayCollection id="sourceDonnees"> <mx:Object idt="1" champFiltre="Aerides" couleur="Bleu" prix="19 €"/> <mx:Object idt="2" champFiltre="Bulbophyllum" couleur="Rouge / Blanc" prix="17 €"/> <mx:Object idt="3" champFiltre="Masdevallia" couleur="Rose" prix="40 €"/> <mx:Object idt="4" champFiltre="Miltoniopsis" couleur="Vert / Jaune" prix="6 €"/> <mx:Object idt="5" champFiltre="Phalaenopsis" couleur="Rose" prix="21 €"/> </mx:ArrayCollection> <mx:ArrayCollection id="colonnes"> <mx:Object entete="IDT" champ="idt" visible="false" longueur="10"/> <mx:Object entete="Espèce" champ="champFiltre" visible="true" longueur="100"/> <mx:Object entete="Couleur" champ="couleur" visible="true" longueur="100"/> <mx:Object entete="Prix" champ="prix" visible="true" longueur="60"/> </mx:ArrayCollection> <composants:FiltreTableau id="listeOrchidees" width="480" height="370" libelle="Orchidée :" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}"> </composants:FiltreTableau> </mx:Application> Nous pouvons alors remarquer que des nouvelles colonnes ont été ajoutées et sont parfaitement gérées par notre composant (figure 10-9), ce qui démontre que ce dernier offre un niveau de paramétrage suffisant pour être utilisé dans de nombreuses applications. Figure 10-9 Mise en place du composant Vous constaterez que la méthode de récupération de l’identifiant n’est pas utilisée dans cette application. Libre à vous de l’implémenter en créant une zone de texte dont la propriété text serait affectée de la valeur {listeOrchidees.valeurRenvoyee}. =Flex3 FM.book Page 198 Mardi, 2. décembre 2008 3:32 15 198 Comprendre Flex 3 PARTIE I En résumé Ce chapitre a montré l’intérêt de développer vos applications par composants. Vous pouvez à présent combiner les fonctionnalités de plusieurs composants afin d’en créer un qui corresponde à vos besoins. Il a également mis en valeur le caractère réutilisable des composants. Vous devrez donc toujours veiller à les rendre paramétrables afin qu’ils puissent être utilisés dans de nombreuses applications. Ce chapitre clôt l’étude de la partie graphique du framework Flex. Nous allons à présent nous consacrer à l’étude de l’utilisation des données et découvrir les méthodes d’accès aux services de la couche métier. =Flex3 FM.book Page 199 Mardi, 2. décembre 2008 3:32 15 11 Gérer les données Au cours de ce chapitre, nous allons découvrir les moyens mis à notre disposition par le framework Flex pour assurer la gestion des données. Nous approfondirons la notion de DataBinding, très utilisée dans les applications Flex et déjà mentionnée de nombreuses fois dans cet ouvrage. Nous verrons ensuite comment implémenter le modèle de l’architecture MVC présentée au chapitre 2, puis nous étudierons les méthodes de validation des données permettant de conserver la qualité de ces dernières dans le système d’information mais également d’interagir avec l’utilisateur en lui indiquant les zones de saisie obligatoires et les formats de saisie incorrects. Nous terminerons enfin par le formatage des données. À l’issue de ce chapitre, vous serez en mesure de gérer l’interaction des données entre composants, mais également de vérifier leur validité avant l’exécution de tout traitement. Lier des données La notion de DataBinding est l’une des plus importantes du framework Flex. Son rôle est d’assurer la communication des données entre un objet source et un objet de destination. Ainsi, toute modification des données de l’objet source entraîne la modification des données de l’objet de destination. Illustrons ceci par un exemple : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:NumericStepper x="10" y="22" width="78" id="objet_source"/> <mx:TextInput x="106" y="22" id="objet_destination" text="{objet_source.value}"/> </mx:Application> =Flex3 FM.book Page 200 Mardi, 2. décembre 2008 3:32 15 200 Comprendre Flex 3 PARTIE I Dans cette portion de code, deux composants sont présents : • le composant NumericStepper, qui représente l’objet source ; • le composant TextInput, qui correspond à l’objet de destination. La valeur mentionnée entre les accolades de la propriété text du composant TextInput précise la liaison de données : « pour tout changement de la valeur du NumericStepper, recopier la valeur dans la propriété text du composant TextInput ». Le procédé alors utilisé est le suivant : 1. La valeur du composant NumericStepper est modifiée par l’utilisateur (figure 11-1, ➊). 2. Flex vérifie la présence de la liaison et constate que la valeur de la propriété text de la zone de saisie est liée à la valeur de la propriété value du NumericStepper (figure 11-1, ➋). 3. Dans la mesure où ces deux objets sont liés, la valeur de la propriété text de l’objet de destination s’en trouve modifiée (figure 11-1, ➌). Figure 11-1 Principe du DataBinding Définition Le DataBinding est l’action consistant à copier des données d’un objet source vers un objet de destination lors de l’exécution d’un événement déclenchant l’action de copie. Cet exemple illustre l’une des méthodes d’implémentation du DataBinding mais il en existe d’autres, que nous allons étudier à présent. =Flex3 FM.book Page 201 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 201 Utilisation de la balise <mx:Binding> La balise <mx:Binding> a pour but de remplacer la notation par accolades vue précédemment. Elle permet également de remplir le rôle du contrôleur dans une application ayant un type d’architecture MVC en détachant la vue du modèle et en attribuant plusieurs objets de destination à un seul objet source (nous reviendrons sur ce point un peu plus loin dans ce chapitre). Voyons comment utiliser cette balise dans l’exemple de code précédent : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:NumericStepper x="10" y="22" width="78" id="objet_source"/> <mx:TextInput x="234" y="22" id="objet_destination"/> <mx:Binding source="String(objet_source.value)" destination="objet_destination.text"> </mx:Binding> </mx:Application> Cette balise nous permet, par l’emploi des propriétés source et destination, de mieux comprendre la notion de DataBinding. Une conversion de type numérique vers chaîne a été nécessaire pour que la liaison soit effective. Sans cela, il nous était impossible d’affecter une valeur de type numérique vers une propriété de type chaîne de caractères. Conversion de type Pour convertir un type de données vers un autre type, il suffit de faire appel à la méthode de conversion du type souhaité. Ainsi, pour convertir un numérique en une chaîne de caractères, il convient de saisir le code suivant : String(valeurNumerique) Le DataBinding en ActionScript Grâce au langage ActionScript, il est non seulement possible de programmer nos propres liaisons, mais également de définir des variables en tant que sources de données. Programmation de la liaison La programmation des liaisons de données entre objets passe par l’emploi de la classe BindingUtils. Située dans le package mx.binding.utils, elle met à notre disposition la méthode BindingUtils.bindProperty dont les paramètres sont les suivants : BindingUtils.bindProperty(identifiant de l’objet de destination, propriété de l’objet de destination faisant l’objet de la modification, identifiant de l’objet source, propriété de l’objet source faisant l’objet de la synchronisation). =Flex3 FM.book Page 202 Mardi, 2. décembre 2008 3:32 15 202 Comprendre Flex 3 PARTIE I Reprenons notre exemple précédent et adaptons-le afin d’illustrer ce qui vient d’être énoncé : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="creationLiaison()"> <mx:Script> <![CDATA[ import mx.binding.utils.BindingUtils; public function creationLiaison():void { BindingUtils.bindProperty(objet_destination, "text", objet_source, ➥"value"); } ]]> </mx:Script> <mx:NumericStepper x="10" y="22" width="78" id="objet_source"/> <mx:TextInput x="234" y="22" id="objet_destination"/> </mx:Application> La programmation des liaisons est assez simple. Pour obtenir une résultat concluant, il suffit en effet d’importer la classe nécessaire et de créer une procédure utilisant la méthode bindProperty, dont les paramètres correspondent aux identifiants et propriétés de nos objets. N’oubliez pas d’exécuter cette fonction à la fin de l’initialisation ou de la création de l’application sans quoi l’application ne prendra pas la liaison en compte. Utilisation de l’étiquette [Bindable] Au cours des chapitres précédents, vous avez sans doute remarqué l’utilisation par endroits de l’étiquette [Bindable]. Jusqu’à présent, la liaison de données a été établie entre deux objets MXML. Mais si nous combinons les langages ActionScript et MXML dans notre application, ne serait-il pas intéressant de pouvoir déclarer des variables ActionScript en tant que sources de données pour un objet MXML ? C’est ce que permet de réaliser l’étiquette [Bindable]. Pour permettre à une variable d’être source de données dans une liaison, sa déclaration doit être précédée de l’étiquette [Bindable]. Dans le cas contraire, la liaison souhaitée sera impossible et un avertissement apparaîtra dans la vue Problems de FlexBuilder (figure 11-2). <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> =Flex3 FM.book Page 203 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 203 <mx:Script> <![CDATA[ [Bindable] private var variableSource:String; public function afficherValeur():void { variableSource = "Valeur du NumericStepper : "+ String(numericStepper ➥.value); } ]]> </mx:Script> <mx:NumericStepper x="10" y="22" width="78" id="numericStepper ➥change="afficherValeur()"/> <mx:TextInput x="182" y="22" id="objet_destination" text="{variableSource}" ➥width="360"/> </mx:Application> Figure 11-2 Oubli de l’étiquette [Bindable] La variable variableSource est considérée comme source de données du fait que sa déclaration est précédée de l’étiquette [Bindable]. La procédure afficherValeur() est appelée à chaque modification de la valeur du NumericStepper et a pour fonction de modifier la =Flex3 FM.book Page 204 Mardi, 2. décembre 2008 3:32 15 204 Comprendre Flex 3 PARTIE I variable source. La liaison de données est effectuée sur la propriété text du composant TextInput, ce qui signifie qu’à chaque modification de la variable source, la valeur de la propriété text sera modifiée en conséquence. Pour plus de clarté, la figure 11-3 schématise le principe de ce processus. Figure 11-3 Utilisation de l’étiquette [Bindable] Nous pouvons alors distinguer quatre étapes : ➊ La valeur du composant NumericStepper est modifiée par l’utilisateur, ce qui déclenche l’exécution de la procédure afficherValeur(). ➋ La procédure modifie alors la valeur de la variable variableSource. ➌ Flex vérifie l’existence d’une liaison. ➍ Étant donné qu’une liaison a été établie entre la variable ActionScript et la propriété text du composant TextInput, la valeur de cette propriété est mise à jour. Spécification d’un événement Par défaut, la synchronisation s’effectue sur la modification de la valeur source, mais il est possible de modifier ce comportement en permettant la synchronisation sur le déclenchement d’un événement précis. Pour ce faire, nous devons définir un événement de synchronisation et l’affecter à l’étiquette [Bindable] précédant la variable source. Lorsque le dispatch de l’événement sera exécuté, l’étiquette [Bindable] concernée en sera avertie et procédera à la synchronisation des données. =Flex3 FM.book Page 205 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 205 Dans le code suivant, nous allons faire en sorte que la synchronisation des données ne s’effectue que si la valeur du composant NumericStepper est supérieure ou égale à 5. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable(event="siSupOuEgalA5")] private var variableSource:String; public function afficherValeur():void { if (numericStepper.value >= 5) { variableSource = "Valeur du NumericStepper : "+ String(numericStepper ➥.value); // Déclaration de l’événement var evenement:Event = new Event("siSupOuEgalA5"); // Action de dispatch dispatchEvent(evenement); } } ]]> </mx:Script> <mx:NumericStepper x="10" y="22" width="78" id="numericStepper" ➥change="afficherValeur()"/> <mx:TextInput x="182" y="22" id="objet_destination" text="{variableSource}" ➥width="360"/> </mx:Application> L’expression [Bindable(event="siSupOuEgalA5")] précise que l’action de synchronisation ne peut se produire que lorsque l’événement siSupOuEgalA5 est déclenché. Par ailleurs, cet événement n’est déclaré dans la procédure afficherValeur() que lorsque la valeur du NumericStepper répond aux conditions fixées. Vient ensuite l’envoi de l’ordre de mise à jour de la variable à l’étiquette [Bindable], par l’exécution du dispatch de l’événement. La valeur de variable est alors immédiatement mise à jour et modifiée. Flex 4 et le DataBinding bi-directionnel Le DataBinding consiste à mettre à jour une donnée source, qui répercute cette modification à une donnée destination. Dans l’autre sens, cette action est impossible. Ce problème est résolu dans la version 4 du framework par l’apparition de la notion de DataBinding bi-directionnel. =Flex3 FM.book Page 206 Mardi, 2. décembre 2008 3:32 15 206 Comprendre Flex 3 PARTIE I Stocker des données grâce au modèle Comme nous l’avons vu au chapitre 2, la partie graphique d’une application peut être divisée en trois couches distinctes (modèle, vue et contrôleur) selon l’architecture MVC. Au cours de la section précédente, nous avons également vu que la balise <mx:Binding> peut jouer le rôle du contrôleur. Nous allons maintenant découvrir comment le modèle peut être implémenté à l’aide des langages MXML et ActionScript. Un modèle a pour fonction principale de stocker des données. Ce stockage précède le stockage persistant réalisée par la base de données. L’utilisation d’un modèle permet donc un stockage temporaire des données afin de les manipuler avant leur enregistrement définitif. Dans cette section, nous vous proposons d’étudier les différentes méthodes de déclaration d’un modèle ainsi que son utilité à travers un exemple concret. Implémenter le modèle à l’aide de la balise <mx:Model> Imaginons une petite application dont le but est d’enregistrer les nouvelles admissions dans un centre hospitalier. Une admission consiste à enregistrer les données caractéristiques d’un patient, à savoir son identifiant, son prénom et son nom. La première étape va donc consister à créer un modèle capable de stocker ces informations. Pour cela, nous recourons à la balise <mx:Model> du langage MXML. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- LE MODÈLE --> <mx:Model id="ModelePatient"> <patient> <id/> <prenom/> <nom/> </patient> </mx:Model> </mx:Application> En analysant ce code, nous voyons tout d’abord qu’un modèle se caractérise par un identifiant qui lui est propre. À l’intérieur de ce modèle, nous spécifions ce qui peut être considéré comme la classe patient et ses trois attributs id, prenom et nom. Afin d’étudier l’utilisation du modèle, nous devons ajouter un formulaire de saisie, qui nous permettra d’alimenter le modèle en données <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="315" layout="absolute" title="Patient"> <mx:Form x="10" y="10" height="115" width="295"> <mx:FormItem label="Id :"> <mx:TextInput id="id_txt"/> </mx:FormItem> <mx:FormItem label="Prénom :"> <mx:TextInput id="prenom_txt"/> =Flex3 FM.book Page 207 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 207 </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="nom_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="240" y="145" label="Ajouter" click=”ajouterPatient()”/> </mx:Panel> Il convient ensuite d’implémenter une procédure qui va utiliser notre modèle pour stocker les informations. Cette procédure sera appelée lorsque l’utilisateur cliquera sur le bouton Ajouter. <!-- LE SCRIPT D’AJOUT --> <mx:Script> <![CDATA[ import mx.controls.Alert; public function ajouterPatient():void { ModelePatient.id = id_txt.text; ModelePatient.prenom = prenom_txt.text; ModelePatient.nom = nom_txt.text; Alert.show (ModelePatient.id +" - "+ModelePatient.prenom+" ➥"+ModelePatient.nom); } ]]> </mx:Script> La procédure affecte les attributs du modèle à partir des champs du formulaire pour ensuite afficher la valeur de ces attributs dans une fenêtre d’alerte (figure 11-4). Figure 11-4 Interaction avec le modèle =Flex3 FM.book Page 208 Mardi, 2. décembre 2008 3:32 15 208 Comprendre Flex 3 PARTIE I Pour plus de clarté, voici le code complet de cet exemple : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- LE MODÈLE --> <mx:Model id="ModelePatient"> <patient> <id/> <prenom/> <nom/> </patient> </mx:Model> <!-- LE SCRIPT D’AJOUT --> <mx:Script> <![CDATA[ import mx.controls.Alert; public function ajouterPatient():void { ModelePatient.id = id_txt.text; ModelePatient.prenom = prenom_txt.text; ModelePatient.nom = nom_txt.text; Alert.show (ModelePatient.id +" - "+ModelePatient.prenom+" ➥"+ModelePatient.nom); } ]]> </mx:Script> <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="315" layout="absolute" title="Patient"> <mx:Form x="10" y="10" height="115" width="295"> <mx:FormItem label="Id :"> <mx:TextInput id="id_txt"/> </mx:FormItem> <mx:FormItem label="Prénom :"> <mx:TextInput id="prenom_txt"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="nom_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="240" y="145" label="Button" click="ajouterPatient()"/> </mx:Panel> </mx:Application> Il aurait également été possible d’utiliser le DataBinding. L’objet source de la liaison aurait alors été la zone de saisie et l’objet de destination, l’attribut du modèle correspondant à cette zone de saisie. =Flex3 FM.book Page 209 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 209 <mx:Model id="ModelePatient"> <patient> <id>{id_txt.text} </id> <prenom>{prenom_txt.text} </prenom> <nom>{nom_txt.text} </nom> </patient> </mx:Model> Nous venons de réaliser notre première application faisant usage d’un modèle, nous donnant aussi l’occasion de faire nos premiers pas dans l’architecture MVC à l’aide de Flex. Néanmoins, l’usage de la balise <mx:Model> ne se limite qu’à la description du modèle en lui-même et ne nous permet pas d’y inclure la logique métier. Pour faire cela, nous devrons utiliser le langage ActionScript. Les modèles et ActionScript La première alternative à l’usage de la balise <mx:Model> est son implémentation à l’aide du langage ActionScript : public var ModelePatient:Object={ id:null, // Affecte la valeur nulle à l’identifiant... prenom:null, nom:null } Néanmoins, ceci ne procure guère plus d’avantages que l’emploi de la balise <mx:Model>, car il est toujours impossible d’implémenter la logique métier et d’y typer nos variables. La solution va donc consister à créer des classes ActionScript dont le rôle est de décrire le modèle et de typer les attributs (chaîne, entier…). La figure 11-5 illustre la conceptualisation de la classe Patient. Cette classe comporte les trois attributs id, prenom et nom dont la portée est privée, c’est-à-dire que leur accès est strictement réservé à la classe Patient. Trois méthodes publiques d’affectation de valeur aux attributs sont ensuite créées (set) ainsi que trois méthodes publiques récupérant la valeur des attributs (get). Figure 11-5 La classe Patient =Flex3 FM.book Page 210 Mardi, 2. décembre 2008 3:32 15 210 Comprendre Flex 3 PARTIE I Cette classe sera retranscrite dans un fichier ActionScript distinct du fichier MXML de l’application en créant un fichier de type ActionScript Class (menu File>New de Flex Builder). Le code de la classe est le suivant : package { public class Patient { // Déclaration des attributs private var _id:int; private var _prenom:String; private var _nom:String; // Méthodes d’affectation public function set id(param:int):void{ _id = param; } public function set prenom(param:String):void{ _prenom = param; } public function set nom (param:String):void{ _nom = param; } // Méthodes de récupération des valeurs public function get id():int{ return _id } public function get prenom():String{ return _prenom; } public function get nom():String{ return _nom } } } Passons à présent à l’utilisation de cette classe dans notre application. Commençons par importer notre classe en procédant comme nous l’avons fait pour l’importation des composants personnalisés (chapitre 10), c’est-à-dire en ajoutant la syntaxe suivante au code déclaratif de l’application : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:Modele="*" > =Flex3 FM.book Page 211 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 211 Étant donné que notre classe joue le rôle de modèle, il convient de lui affecter un identifiant afin de pouvoir y faire référence dans les différents scripts qui pourront être développés ultérieurement : <Modele:Patient id="ModelePatient"/> Attention La syntaxe <Modele:Patient> n’est pas fortuite. En effet, Patient correspond au nom de la classe à employer. Notre classe est à présent intégrée dans l’interface graphique. Elle remplit sa fonction de modèle, comme le montrent ces quelques lignes de code : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:Modele="*" > <!-- APPEL DU MODÈLE --> <Modele:Patient id="ModelePatient"/> <!-- LE SCRIPT D’AJOUT --> <mx:Script> <![CDATA[ import mx.controls.Alert; public function ajouterPatient():void { ModelePatient.id = int(id_txt.text); ModelePatient.prenom = prenom_txt.text; ModelePatient.nom = nom_txt.text; Alert.show (ModelePatient.id +" - "+ModelePatient.prenom+" ➥"+ModelePatient.nom); } ]]> </mx:Script> <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="315" layout="absolute" title="Patient"> <mx:Form x="10" y="10" height="115" width="295"> <mx:FormItem label="Id :"> <mx:TextInput id="id_txt"/> </mx:FormItem> <mx:FormItem label="Prénom :"> <mx:TextInput id="prenom_txt"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="nom_txt"/> =Flex3 FM.book Page 212 Mardi, 2. décembre 2008 3:32 15 212 Comprendre Flex 3 PARTIE I </mx:FormItem> </mx:Form> <mx:Button x="240" y="145" label="Ajouter" click="ajouterPatient()" /> </mx:Panel> </mx:Application> Le résultat auquel nous aboutissons est identique à celui obtenu avec la balise <mx:Model> (figure 11-4). Grâce aux classes, nous pouvons implémenter la logique métier en y développant des méthodes spécifiques, ce qui était jusque-là impossible à l’aide des méthodes traditionnelles d’implémentation de modèle. Dans notre exemple, nous aurions pu développer une méthode calculant le nombre de lettres contenues dans le nom de famille saisi, lequel aurait alors été concaténé à ce même nom : […] public function set nom (param:String):void{ _nom = param + " NB Lettres -> "+String(calculNbLettres(param)); } […] // Méthode de calcul du nombre de lettres contenues dans le nom de famille public function calculNbLettres(param:String):int{ return param.length; } Ceci ne présente, certes, que peu d’intérêt ici, mais vous voyez ainsi que l’utilisation des classes nous offre de nombreuses possibilités, notamment celle de manipuler les données stockées dans le modèle avant de les transférer à la couche de persistance de données. Nous pourrions nous arrêter là mais il nous a semblé important de poursuivre avec les méthodes de validation des données. En effet, qui n’a jamais été confronté au codage parfois fastidieux d’une vérification d’une adresse e-mail ? Eh bien ce temps est révolu grâce aux composants Validator qui réalisent ce travail pour vous ! Valider des données Valider les données, c’est s’assurer de la cohérence et de la qualité des informations contenues dans le système. Pour une entreprise de marketing, par exemple, il serait inconcevable que le format des adresses e-mail des clients ne soit pas correct, de même que celui du code postal ou du numéro de carte bancaire. Jusqu’à présent, ces vérifications de format devaient être implémentées par le développeur de l’application. Tout cela est désormais de l’histoire ancienne grâce au composant Validator de Flex. Flex permet de vérifier le format des éléments suivants : • carte de crédit (en fonction du type : Visa, MasterCard…) ; • valeur monétaire ; • date ; • adresse e-mail ; =Flex3 FM.book Page 213 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 • • • • • • 213 nombre ; numéro de téléphone ; numéro de Sécurité sociale ; code postal ; chaîne de caractères ; expression régulière. Nous n’allons pas ici décrire tous ces formats de validation, mais nous nous concentrerons sur un type en particulier, très largement utilisé dans les applications : la validation du format de l’adresse e-mail. Pour commencer, créons un formulaire contenant une zone de texte dédiée à la saisie de l’adresse e-mail : <mx:Panel x="10" y="10" width="344" height="159" layout="absolute" title="E-mail"> <mx:Form x="10" y="10" height="62" width="295"> <mx:FormItem label="Votre e-mail :"> <mx:TextInput id="mail_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="235" y="80" label="Valider" id=”btn_valider” /> </mx:Panel> Rendre la saisie obligatoire Pour cet exemple, le champ mail_txt doit obligatoirement être renseigné. Dans une application web classique (non développée à l’aide d’un framework), il nous faudrait éventuellement développer une fonction JavaScript qui vérifierait la présence ou non de caractères spécifiques dans la zone (point, arobase…). Les choses sont beaucoup plus simples grâce au framework Flex, car il suffit de lui préciser que ce champ est obligatoire grâce à la propriété required du composant FormItem. <mx:FormItem label="Votre e-mail :" required="true"> En passant à true la valeur de la propriété required du composant FormItem, nous indiquons à Flex que la saisie de ce champ est obligatoire. Un astérisque apparaît alors après le libellé du champ (figure 11-6). Figure 11-6 Saisie obligatoire =Flex3 FM.book Page 214 Mardi, 2. décembre 2008 3:32 15 214 Comprendre Flex 3 PARTIE I Il ne nous reste plus qu’à mettre en place le validateur comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- VALIDATION --> <mx:Validator id="validation_saisie" source="{mail_txt}" property="text"> ➥</mx:Validator> <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="159" layout="absolute" title="E-mail"> <mx:Form x="10" y="10" height="62" width="295"> <mx:FormItem label="Votre email :" required="true"> <mx:TextInput id="mail_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="235" y="80" label="Valider" id=”btn_valider” /> </mx:Panel> </mx:Application> Le fonctionnement de la validation est basé sur la notion de DataBinding. La source du Validator est le champ mail_txt. Lorsque sa propriété text est modifiée, l’action de validation est alors déclenchée. Nous vous laissons à présent le soin d’exécuter cette application et de vérifier que lorsque l’on clique sur le bouton Valider sans avoir saisi d’adresse e-mail, le contour du champ devient rouge et un message d’erreur s’affiche (figure 11-7) au survol du champ. Figure 11-7 Contrôle de la saisie obligatoire =Flex3 FM.book Page 215 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 215 Vérification du format Pour qu’une adresse e-mail soit valide, elle doit obligatoirement être composée : • d’un nom d’utilisateur (par exemple, jean.dupont) ; • d’une arobase (@) ; • d’un nom de domaine (par exemple, domaine.fr). La vérification de la présence de ces trois éléments est chose complexe à développer. Grâce à Flex, elle se résume à une simple ligne de code grâce au composant <mx:EmailValidator> qui se charge d’effectuer l’ensemble des vérifications nécessaires. Voyons ceci en détail. Pour commencer, nous devons remplacer le composant de validation présent dans notre application par celui-ci : <mx:EmailValidator id="validation_email" source="{mail_txt}" property="text"> </mx:EmailValidator> Ce composant fonctionne de la même façon que le précédent, à la seule différence qu’il vérifie également, en plus de la saisie obligatoire, la syntaxe de l’adresse e-mail. Si vous testez de nouveau l’application, vous verrez que tous les critères sont correctement vérifiés et ce, grâce à une simple ligne de code. Néanmoins, il reste un petit problème qu’en tant que lecteur attentif vous avez certainement remarqué : les messages d’erreur sont en anglais ! Mais rassurez-vous, il est possible de personnaliser ces messages, ce que nous allons voir à présent. Personnalisation des messages d’erreur Chaque composant de validation possède sa propre bibliothèque de textes à afficher en fonction du type d’erreur rencontré. Il est possible de personnaliser ces messages. Voyons comment procéder pour notre composant : <mx:EmailValidator id="validation_email" source="{mail_txt}" property="text" requiredFieldError="Ce champ est obligatoire" missingAtSignError="Votre adresse e-mail ne comporte pas d’arobase" missingUsernameError="Le nom d’utilisateur n’a pas été spécifié" missingPeriodInDomainError="Le nom de domaine n’a pas été spécifié"> </mx:EmailValidator> En exécutant à nouveau l’application, vous notez que les messages d’erreur affichés correspondent désormais à ceux qui ont été spécifiés suivant le cas de figure concerné. Les événements de validation Par défaut, l’événement de validation de format correspond à la notification de changement de la valeur source du composant de validation. Il nous est possible de modifier ce comportement à l’aide des propriétés trigger et triggerEvent du composant de validation. =Flex3 FM.book Page 216 Mardi, 2. décembre 2008 3:32 15 216 Comprendre Flex 3 PARTIE I La propriété trigger sert à spécifier qu’un composant de l’interface déclenchera l’action de validation. Quant à la propriété triggerEvent, elle précise l’action qui devra être réalisée sur notre composant. Ainsi, si nous souhaitons déclencher la validation d’un champ lorsque l’utilisateur clique sur le bouton btn_verifier de l’interface, la propriété trigger de l’élément de validation devra porter la valeur btn_verifier et il faudra affecter la propriété triggerEvent de la valeur click. Appliquons ceci à notre exemple en définissant la règle suivante : « L’action de validation doit être effectuée à chaque fois que l’utilisateur clique sur le bouton Valider ». <mx:EmailValidator id="validation_email" source="{mail_txt}" property="text" trigger="{btn_valider}" triggerEvent="click"> </mx:EmailValidator> Gestion de la validation en ActionScript Maintenant que nous sommes en mesure de valider le format des données de nos formulaires, il est important d’étudier l’interaction entre la validation et les traitements ActionScript. En effet, il serait bien regrettable que le traitement d’enregistrement ait lieu malgré l’erreur de format détectée par le composant de validation. Pour cela, nous avons recours à la méthode validate() du composant de validation. Grâce à lui, nous vérifierons le résultat des différentes validations et permettrons ou non l’exécution de traitements applicatifs : <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.ValidationResultEvent; public function ajouterAdresseEmail():void{ // Résultat de la validation var resultatValidation:ValidationResultEvent = validation_email.validate() if (resultatValidation.type == ValidationResultEvent.VALID) { Alert.show ("Enregistrement effectué") } } ]]> </mx:Script> Le type de résultat retourné par la méthode validate() est VALID si la validation s’est correctement déroulée, et INVALID si la validation a échoué. Un simple test sur la valeur de la variable resultatValidation permet d’exécuter ou non le traitement d’ajout. =Flex3 FM.book Page 217 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 217 Voici le code de l’exemple dans son intégralité : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- TRAITEMENT --> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.ValidationResultEvent; public function ajouterAdresseEmail():void{ // Résultat de la validation var resultatValidation:ValidationResultEvent = validation_email.validate() if (resultatValidation.type == ValidationResultEvent.VALID) { Alert.show ("Enregistrement effectué") } } ]]> </mx:Script> <!-- VALIDATION --> <mx:EmailValidator id="validation_email" source="{mail_txt}" property="text" trigger="{btn_valider}" triggerEvent="click"> </mx:EmailValidator> <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="159" layout="absolute" title="E-mail"> <mx:Form x="10" y="10" height="62" width="295"> <mx:FormItem label="Votre e-mail :" required="true"> <mx:TextInput id="mail_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="235" y="80" label="Valider" id="btn_valider" ➥click="ajouterAdresseEmail()" /> </mx:Panel> </mx:Application> Ainsi se termine cette section sur la validation des formats de données. Grâce aux composants de validation, vous êtes à présent en mesure de fournir des données cohérentes à votre système d’information. Dans la mesure où nous ne pouvons pas dans cet ouvrage définir toutes les possibilités offertes par ces composants, nous les utiliserons par la suite au travers d’exemples grâce auxquels vous pourrez notamment apprécier les méthodes de création de composant de validation personnalisés. Pour l’heure nous allons aborder un autre sujet tout aussi intéressant : le formatage des données. =Flex3 FM.book Page 218 Mardi, 2. décembre 2008 3:32 15 218 Comprendre Flex 3 PARTIE I Validation complète d’un formulaire Si un formulaire comporte de nombreux champs, la méthode que nous venons de voir deviendra rapidement fastidieuse à implémenter. La classe Validator pallie ce problème grâce à sa méthode validateAll([composants de validation séparés par une virgule]). <mx:Script> <![CDATA[ import mx.validators.Validator; import mx.controls.Alert public function ajouterAdresseEmail():void{ // Stockage des erreurs de validation dans un tableau var tableau_validation:Array = Validator.validateAll([validation_email]); // Si le tableau ne contient aucun élément, le traitement peut être ➥effectué if(tableau_validation.length == 0) { Alert.show ("Enregistrement effectué") } } ]]> </mx:Script> Formater des données Nous ne pouvions pas écrire un chapitre sur la gestion des données sans aborder la notion de formatage. Cette opération consiste à transformer une donnée en une chaîne dont le format aura préalablement été précisé. L’application la plus commune est le formatage du numéro de téléphone, ce que nous allons voir à travers l’exemple suivant. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- SPÉCIFICATION DU FORMAT --> <mx:PhoneFormatter id="formatTelephone" formatString="##.##.##.##.##"> </mx:PhoneFormatter> <!-- LE FORMULAIRE --> <mx:Panel x="10" y="10" width="344" height="210" layout="absolute" title="Formatage"> <mx:Form x="10" y="10" height="62" width="295"> <mx:FormItem label="Téléphone :" > <mx:TextInput id="tel_txt"/> </mx:FormItem> </mx:Form> =Flex3 FM.book Page 219 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 219 <mx:Form x="10" y="97" width="295" height="63"> <mx:FormItem label="Téléphone : "> <mx:TextInput id="telFormate_txt" text="{formatTelephone.format ➥(tel_txt.text)}"/> </mx:FormItem> </mx:Form> </mx:Panel> </mx:Application> Nous commençons l’écriture de l’application par la spécification d’un composant de formatage propre aux données téléphoniques et qui nous permet de formater les données à notre convenance. Nous affectons ainsi la propriété formatString de la valeur ##.##.##.##.##. Vient ensuite l’écriture de l’interface graphique qui sera composée d’un panneau et de deux zones de texte. La première servira à saisir le numéro de téléphone, la seconde affichera le résultat du formatage. Attardons-nous quelques instants sur la propriété text de la seconde zone de texte : text="{formatTelephone.format(tel_txt.text)}" Ces quelques instructions signifient que le formatage est exécuté sur la propriété text de la zone tel_txt lorsque celle-ci est mise à jour (nous retrouvons ici la notion de DataBinding). Le résultat obtenu est illustré par la figure 11-8. Figure 11-8 Formatage de données téléphoniques Les composants de formatage proposés par Flex sont les suivants : • composant de formatage monétaire (<mx:CurrencyFormatter>) ; • composant de formatage de date (<mx:DateFormatter>) ; • composant de formatage de numéro de téléphone (<mx:PhoneFormatter>) ; • composant de formatage de nombre (<mx:NumberFormatter>) ; • Composant de formatage de code postal (<mx:ZipCodeFormatter>). Intéressons-nous à présent au composant de formatage de date dont la particularité est de proposer un système de notation particulier pour le formatage des années, mois, jours… =Flex3 FM.book Page 220 Mardi, 2. décembre 2008 3:32 15 220 Comprendre Flex 3 PARTIE I Le système proprement dit est basé sur une notation par lettres, lesquelles sont présentées dans le tableau 11-1, ainsi que leur signification afin de vous aider dans la manipulation de ce champ très spécial qu’est le champ date : Tableau 11-1 Formatage des différents éléments d’une date Lettre Description Y Permet de formater l’année. Par exemple : YY = 08 YYYY = 2008. M Permet de formater le mois. Par exemple : M = 7 MM = 07 MMM = jul MMMM =july D Permet de formater le jour. Par exemple : D = 1 DD = 01 E Permet de format le jour de la semaine. Par exemple : E = 1 EE = 01 EEE = mon EEEE = monday A Permet d’ajouter l’indicateur Matin/Après midi. J Permet de formater l’heure de 0 à 23. H Permet de formater l’heure de 1 à 24. K Permet de formater l’heure au format AM/PM (0-1). L Permet de formater l’heure au format AM/PM (1-12). N Permet de formater les minutes. S Permet de formater les secondes. Le tableau 11-2 contient quelques exemples de formatage. Tableau 11-2 Exemples de formatage Formatage Résultat obtenu YYYY.MM.DD 2008.05.15 H:NN 9:05 AM EEE, DD MMMM YYYY Thu, 15 May 2008 L’exemple de code suivant montre comment formater la date du jour à l’aide de l’expression EEE, DD MMMM YYYY. =Flex3 FM.book Page 221 Mardi, 2. décembre 2008 3:32 15 Gérer les données CHAPITRE 11 221 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var date:Date = new Date(); //new Date() = date du jour ]]> </mx:Script> <mx:DateFormatter id="formatDate" formatString="EEE, DD MMMM YYYY"> </mx:DateFormatter> <mx:TextInput id="date_txt" text="{formatDate.format(date)}" x="10" y="50"/> </mx:Application> En résumé Grâce à ce chapitre, vous êtes désormais en mesure de créer des liaisons de données grâce à la notion de DataBinding qui permet d’éviter l’écriture de procédures de recopie de données comme c’est le cas dans d’autres langages. Vous avez également pu découvrir les méthodes utilisées afin de mettre en place la notion de modèle de l’architecture MVC qui permet un stockage temporaire des données avant leur enregistrement définitif dans la base de données. Par ailleurs, vous êtes à présent en mesure de vérifier le format des données afin de vous assurer de la qualité des données insérées dans le système d’information, et de formater les données afin de les présenter conformément aux attentes de l’utilisateur. À ce stade, vous savez donc comment faire pour fournir des données de qualité à votre système d’information. La question que nous sommes maintenant en droit de nous poser est la suivante : Comment insérer ces données dans le système d’information ? Le contenu du chapitre 2 nous apporte déjà un élément de réponse en nous indiquant que Flex n’est pas capable de communiquer directement avec la couche de persistance de données. En effet, cette communication est réservée à la couche métier qui, en offrant ses services à l’application Flex, permet la manipulation des données. L’étape suivante va donc consister à étudier les différentes méthodes qui nous permettront de communiquer avec cette couche. =Flex3 FM.book Page 222 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 223 Mardi, 2. décembre 2008 3:32 15 12 Accéder aux services de la couche métier Dans la mesure où Flex ne peut accéder aux informations contenues dans une base de données en raison de son appartenance à la couche graphique, il va demander à un tiers, la couche métier, de réaliser ce travail, exactement comme nous demandons parfois à une personne de notre entourage de nous rendre un service. Pour communiquer avec cette couche, Flex dispose de trois composants RPC (Remote Procedure Call) : • HTTPService, également dénommé REST-Style webservice ; • WebService ; • RemoteObject. Ce chapitre sera donc consacré à l’étude de ces composants Employer les requêtes HTTP avec HTTPService ou REST-Style webservice L’emploi de ce composant dépend du langage utilisé pour la création et le développement des services. Si ce dernier accepte de recevoir des données à l’aide des méthodes POST et GET (ce qui est le cas des langages PHP, JSP, ColdFusion, ASP.NET, Ruby on Rails ou encore Servlet Java), il conviendra alors d’utiliser le composant HTTPService. Le principe est le suivant : 1. Le composant appelle le service grâce à son URL. =Flex3 FM.book Page 224 Mardi, 2. décembre 2008 3:32 15 224 Comprendre Flex 3 PARTIE I 2. Lors de cet appel, des données peuvent être transférées au service via les méthodes POST ou GET. 3. Le service exécute la tâche qui lui a été confiée (connexion à la base de données, exécution de requêtes…). 4. Il renvoie la réponse préalablement formatée au format XML. L’exemple suivant illustre l’interaction d’une application Flex avec un service écrit en PHP. Précisons que pour réaliser cet exemple, vous devez disposer sur votre machine d’un environnement PHP correctement configuré. Environnement PHP Si vous ne connaissez pas du tout le langage PHP, nous vous invitons à consulter son site officiel (http://www.php.net/), qui répondra sans doute à une grande partie des questions que vous pourriez vous poser. Nous vous conseillons d’installer soit EasyPHP qui contient l’ensemble des composants nécessaires à l’utilisation de PHP (http://www.easyphp.org/), soit WampServer (http://www.wampserver.com/). L’interface graphique de l’application sera composée de trois zones de texte. Les deux premières permettront à l’utilisateur de saisir son prénom et son nom, la troisième sera chargée d’afficher le résultat du traitement réalisé par le service PHP. Ce traitement consistera à récupérer les données saisies par l’utilisateur et à les exploiter pour créer la phrase « Bonjour prénom nom ». Le résultat du traitement sera ensuite envoyé à l’application. Pour commencer, il convient donc de créer un formulaire (figure 12-1) : <!-- FORMULAIRE --> <mx:Panel x="10" y="10" width="337" height="220" layout="absolute" ➥title="HTTPService"> <mx:Form x="10" y="10" width="297" height="80" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:FormItem label="Prénom :" width="272"> <mx:TextInput width="200" id="prenom_txt"/> </mx:FormItem> <mx:FormItem label="Nom :" width="272"> <mx:TextInput width="200" id="nom_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="242" y="96" label="Valider" id="btn_valider" ➥click="executerService()"/> <mx:TextInput x="10" y="141" width="297" id="resultat_txt"/> </mx:Panel> =Flex3 FM.book Page 225 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 225 Ce formulaire ressemble en tous points à ceux que vous avez désormais l’habitude de créer. Figure 12-1 Interface de saisie La deuxième étape va consister à implémenter et paramétrer le composant <mx:HTTPService> : <!-- DÉCLARATION DU SERVICE --> <mx:HTTPService id="service" url="http://localhost/PHP/HHTPService/HTTPService.php" result="reponseOK(event)" fault="reponseKO(event)" resultFormat="e4x" method="POST"> <!—AFFECTATION DES PARAMÈTRES --> <mx:request xmlns="*"> <prenom>{prenom_txt.text}</prenom> <nom>{nom_txt.text}</nom> </mx:request> </mx:HTTPService> <mx:HTTPService> étant un composant, il n’échappe pas à la règle de base consistant à lui affecter un identifiant. Vient ensuite la phase de spécification de certains paramètres : • url : adresse web du service ; • result : action à réaliser si le service s’exécute correctement ; • fault : action à réaliser si l’exécution du service échoue ; • resultFormat : format de réception du message de réponse ; • method : méthode de transmission des données. =Flex3 FM.book Page 226 Mardi, 2. décembre 2008 3:32 15 226 Comprendre Flex 3 PARTIE I Pour terminer cette phase de paramétrage, vous devrez ensuite définir les paramètres qui seront envoyés et leurs sources de données via la balise <mx:request>. Le proxy de Flex Le Flash Player dispose d’un espace de sécurité (proxy) qui limite les requêtes d’appels aux services au domaine de chargement du fichier SWF. Pour faire appel à des services web situés en dehors de ce domaine, il convient d’outrepasser cette sécurité en affectant à la propriété useProxy du composant d’accès au service la valeur false (valeur attribuée par défaut si l’attribut useProxy n’est pas utilisé, ce qui est le cas dans l’exemple décrit précédemment). E4X (ECMAScript for XML) E4X est une extension du langage de programmation ECMAScript facilitant l’exploitation des fichiers XML. Considérons le fichier XML suivant stocké dans la variable listeAvions de type XML : var listeAvions = <avions> <appareil id=1>Storch</appareil> <appareil id=2>Cesna</appareil> </avions> Pour accéder à l’identifiant du premier élément, il suffit d’employer la syntaxe suivante : listeAvions.appareil[0].@id En spécifiant le format du résultat du composant HTTPService en tant que E4X dans l’attribut result Format, vous pourrez exploiter le résultat obtenu, tout comme nous venons de le faire. La troisième étape va ensuite consister à écrire service PHP : <?php //--- SERVICE PHP ----// Récupération des paramètres $prenom = $_POST["prenom"]; $nom = $_POST["nom"]; // Traitement $traitement = "Bonjour ".$prenom." ".$nom; // Formatage de la réponse $reponse = "<HTTPService>"; $reponse .= "<reponse>"; $reponse .= "<resultat>".$traitement."</resultat>"; $reponse .= "</reponse>"; $reponse .= "</HTTPService>"; // Envoi de la réponse print $reponse; ?> =Flex3 FM.book Page 227 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 227 Le service ainsi défini récupère les valeurs des paramètres prenom et nom spécifiés dans notre composant <mx:HTTPService>. Ces valeurs sont ensuite stockées dans des variables afin d’être utilisées dans le traitement. Une fois le traitement terminé, la réponse est formatée à l’aide du langage XML afin d’obtenir le format de réponse suivant : <HTTPService> <reponse> <resultat> bonjour prenom nom </resultat> </reponse> <HTTPService> La réponse est ensuite envoyée à l’application Flex : print $reponse; La quatrième étape consistera ensuite à implémenter les procédures ActionScript chargées d’appeler le service et d’interpréter le résultat reçu. <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; // Exécution du service public function executerService():void{ service.send(); } public function reponseOK(event:ResultEvent):void{ var reponseXML:XML = event.result as XML; resultat_txt.text = String(reponseXML.reponse.resultat); } public function reponseKO(event:FaultEvent):void{ Alert.show ("Erreur ! : "+event.fault.message) } ]]> </mx:Script> La procédure executerService() a pour fonction de réaliser la requête d’appel du service (service.send()) lorsque l’utilisateur clique sur le bouton Valider. La procédure reponseOK (event) interprète le résultat reçu et l’affiche dans la zone de texte resultat_txt. Enfin, la procédure reponseKO(event) intercepte l’erreur d’exécution du service et en affiche la cause. Tous nos fichiers sont à présent complets et nous pouvons donc tester notre application. Pour faciliter la compréhension du fonctionnement général, ce dernier est illustré par la figure 12-2. =Flex3 FM.book Page 228 Mardi, 2. décembre 2008 3:32 15 228 Comprendre Flex 3 PARTIE I Figure 12-2 Utilisation du composant HTTPService =Flex3 FM.book Page 229 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 229 Étape ➊ : l’utilisateur saisit les informations demandées, ce qui entraîne la mise à jour des paramètres grâce au DataBinding (voir chapitre 11). Étape ➋ : lorsque l’utilisateur clique sur le bouton Valider, la requête d’exécution du service est déclenchée ainsi que l’envoi des paramètres au service. Étape ➌ : le service récupère les données envoyées via la méthode POST et exécute le traitement. Étape ➍ : le résultat du traitement est formaté en XML. Étape ➎ : le résultat est envoyé à l’application. Étape ➏ : puisque le composant reçoit un résultat, il exécute la procédure reponseOK(event). Étape ➐ : cette procédure extrait le résultat et met à jour l’interface graphique. Nous pouvons ainsi conclure que l’emploi du composant HTTPService est similaire à celui de la majorité des applications web. Il sera donc tout naturellement utilisé dans la plupart des cas. Format des valeurs renvoyées Les valeurs retournées sont au format texte. De ce fait, si la valeur renvoyée comporte des erreurs (par exemple, </message>Bonjour</message>), cela provoquera une erreur de parsing et la valeur ne pourra pas être interprétée et affichée dans l’application Flex. Il est donc préférable d’utiliser des outils tels que SimpleXML proposé par PHP (http://fr.php.net/simplexml), qui vous permettra d’éviter ce genre de désagréments en « échappant » les caractères spéciaux. Le composant WebService Un service web (Web Service dans la langue de Shakespeare) est un mécanisme de communication entre deux applications distantes. La communication est réalisée à l’aide du protocole HTTP dans lequel l’échange des données et l’appel des différentes fonctions sont réalisés à l’aide du langage XML. De nombreux services web sont disponibles sur Internet, tels que : • les services météorologiques ; • les services boursiers ; • les services d’informations, etc. Néanmoins, pour accéder à un service, il faut en connaître l’adresse ainsi que les méthodes d’interrogation. L’implémentation d’un service web s’effectue à l’aide du composant <mx:WebService>. Pour vous permettre de bien appréhender l’utilisation de ce composant, nous allons implémenter un service choisi parmi ceux mis à notre disposition sur le site Internet http://www.web servicex.net. Pour notre exemple, nous avons sélectionné le service permettant de convertir la température exprimée en degrés Celsius en une température exprimée en degrés Fahrenheit. =Flex3 FM.book Page 230 Mardi, 2. décembre 2008 3:32 15 230 Comprendre Flex 3 PARTIE I Le service web en détail Pour commencer, étudions le service web que nous allons utiliser à titre d’exemple. La description du service web est disponible à l’adresse suivante : http://www.webservicex.net /ConvertTemperature.asmx?WSDL. Elle va nous permettre de comprendre le fonctionnement du service : <?xml version="1.0" encoding="utf-8" ?> -<wsdl:definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.webserviceX.NET/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://www.webserviceX.NET/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> - <wsdl:types> - <s:schema elementFormDefault="qualified" targetNamespace= ➥"http://www.webserviceX.NET/"> - <s:element name="ConvertTemp"> - <s:complexType> - <s:sequence> <s:element minOccurs="1" maxOccurs="1" name="Temperature" ➥type="s:double" /> <s:element minOccurs="1" maxOccurs="1" name="FromUnit" ➥type="tns:TemperatureUnit" /> <s:element minOccurs="1" maxOccurs="1" name="ToUnit" ➥type="tns:TemperatureUnit" /> </s:sequence> </s:complexType> </s:element> - <s:simpleType name="TemperatureUnit"> - <s:restriction base="s:string"> <s:enumeration value="degreeCelsius" /> <s:enumeration value="degreeFahrenheit" /> <s:enumeration value="degreeRankine" /> <s:enumeration value="degreeReaumur" /> <s:enumeration value="kelvin" /> </s:restriction> </s:simpleType> - <s:element name="ConvertTempResponse"> - <s:complexType> - <s:sequence> <s:element minOccurs="1" maxOccurs="1" name="ConvertTempResult" ➥type="s:double" /> </s:sequence> </s:complexType> </s:element> =Flex3 FM.book Page 231 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 <s:element name="double" type="s:double" /> </s:schema> </wsdl:types> - <wsdl:message name="ConvertTempSoapIn"> <wsdl:part name="parameters" element="tns:ConvertTemp" /> </wsdl:message> - <wsdl:message name="ConvertTempSoapOut"> <wsdl:part name="parameters" element="tns:ConvertTempResponse" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpGetIn"> <wsdl:part name="Temperature" type="s:string" /> <wsdl:part name="FromUnit" type="s:string" /> <wsdl:part name="ToUnit" type="s:string" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpGetOut"> <wsdl:part name="Body" element="tns:double" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpPostIn"> <wsdl:part name="Temperature" type="s:string" /> <wsdl:part name="FromUnit" type="s:string" /> <wsdl:part name="ToUnit" type="s:string" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpPostOut"> <wsdl:part name="Body" element="tns:double" /> </wsdl:message> - <wsdl:portType name="ConvertTemperatureSoap"> - <wsdl:operation name="ConvertTemp"> <wsdl:input message="tns:ConvertTempSoapIn" /> <wsdl:output message="tns:ConvertTempSoapOut" /> </wsdl:operation> </wsdl:portType> - <wsdl:portType name="ConvertTemperatureHttpGet"> - <wsdl:operation name="ConvertTemp"> <wsdl:input message="tns:ConvertTempHttpGetIn" /> <wsdl:output message="tns:ConvertTempHttpGetOut" /> </wsdl:operation> </wsdl:portType> - <wsdl:portType name="ConvertTemperatureHttpPost"> - <wsdl:operation name="ConvertTemp"> <wsdl:input message="tns:ConvertTempHttpPostIn" /> <wsdl:output message="tns:ConvertTempHttpPostOut" /> </wsdl:operation> </wsdl:portType> - <wsdl:binding name="ConvertTemperatureSoap" type="tns:ConvertTemperatureSoap"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" ➥style="document" /> - <wsdl:operation name="ConvertTemp"> <soap:operation soapAction="http://www.webserviceX.NET/ConvertTemp" ➥style="document" /> - <wsdl:input> <soap:body use="literal" /> 231 =Flex3 FM.book Page 232 Mardi, 2. décembre 2008 3:32 15 232 Comprendre Flex 3 PARTIE I </wsdl:input> - <wsdl:output> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> - <wsdl:binding name="ConvertTemperatureHttpGet" ➥type="tns:ConvertTemperatureHttpGet"> <http:binding verb="GET" /> - <wsdl:operation name="ConvertTemp"> <http:operation location="/ConvertTemp" /> - <wsdl:input> <http:urlEncoded /> </wsdl:input> - <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> - <wsdl:binding name="ConvertTemperatureHttpPost" ➥type="tns:ConvertTemperatureHttpPost"> <http:binding verb="POST" /> - <wsdl:operation name="ConvertTemp"> <http:operation location="/ConvertTemp" /> - <wsdl:input> <mime:content type="application/x-www-form-urlencoded" /> </wsdl:input> - <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> - <wsdl:service name="ConvertTemperature"> - <wsdl:port name="ConvertTemperatureSoap" ➥binding="tns:ConvertTemperatureSoap"> <soap:address location="http://www.webservicex.net/ ➥ConvertTemperature.asmx" /> </wsdl:port> - <wsdl:port name="ConvertTemperatureHttpGet" ➥binding="tns:ConvertTemperatureHttpGet"> <http:address location="http://www.webservicex.net/ ➥ConvertTemperature.asmx" /> </wsdl:port> - <wsdl:port name="ConvertTemperatureHttpPost" ➥binding="tns:ConvertTemperatureHttpPost"> <http:address location="http://www.webservicex.net/ ➥ConvertTemperature.asmx" /> </wsdl:port> </wsdl:service> </wsdl:definitions> =Flex3 FM.book Page 233 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 233 Cela peut paraître très complexe à première vue mais décortiquons ce fichier afin d’en comprendre le fonctionnement. La première étape consiste à définir la méthode d’utilisation de ce service web. Pour cela, nous savons que le protocole HTTP est utilisé pour le transport des données et que les méthodes d’envoi des données via ce protocole sont POST ou GET. En parcourant le fichier, nous remarquons les lignes suivantes : - <wsdl:message name="ConvertTempHttpGetIn"> <wsdl:part name="Temperature" type="s:string" /> <wsdl:part name="FromUnit" type="s:string" /> <wsdl:part name="ToUnit" type="s:string" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpPostIn"> <wsdl:part name="Temperature" type="s:string" /> <wsdl:part name="FromUnit" type="s:string" /> <wsdl:part name="ToUnit" type="s:string" /> </wsdl:message> Cela signifie que notre service attend trois paramètres : • Le premier s’intitule Temperature et reçoit des données numériques (type="s:double"). • Le deuxième, nommé FromUnit, sert à définir l’unité de conversion de base. • Le troisième, nommé ToUnit, permet de définir l’unité de conversion. Il est également important de souligner que ces trois paramètres sont de type chaîne (type="s:string"). Pour faire appel à ce service, nous devons donc lui fournir ces trois paramètres, en respectant cet ordre précis et en veillant au format des données transmises. Nous avons déterminé les paramètres requis et leur type, mais qu’en est-il du format de la réponse fournie par le service ? Continuons notre lecture du fichier et observons les lignes suivantes : <s:element name="double" type="s:double" /> - <wsdl:message name="ConvertTempHttpGetOut"> <wsdl:part name="Body" element="tns:double" /> </wsdl:message> - <wsdl:message name="ConvertTempHttpPostOut"> <wsdl:part name="Body" element="tns:double" /> </wsdl:message> Ces lignes de code indiquent que le format de la réponse sera de type décimal numérique (double). La dernière étape va consister à trouver le nom de la méthode, également appelée opération, qui va être invoquée pour réaliser le traitement. Pour cela, recherchons la balise operation correspondant à notre protocole d’envoi (HTTP). =Flex3 FM.book Page 234 Mardi, 2. décembre 2008 3:32 15 234 Comprendre Flex 3 PARTIE I - <wsdl:portType name="ConvertTemperatureHttpGet"> - <wsdl:operation name="ConvertTemp"> <wsdl:input message="tns:ConvertTempHttpGetIn" /> <wsdl:output message="tns:ConvertTempHttpGetOut" /> </wsdl:operation> </wsdl:portType> - <wsdl:portType name="ConvertTemperatureHttpPost"> - <wsdl:operation name="ConvertTemp"> <wsdl:input message="tns:ConvertTempHttpPostIn" /> <wsdl:output message="tns:ConvertTempHttpPostOut" /> </wsdl:operation> </wsdl:portType> Nous retrouvons les deux éléments propres à notre protocole : ConvertTemperatureHttpGet et ConvertTemperatureHttpPost. Nous remarquons également la présence de la balise operation définissant le nom de la méthode devant être invoquée (ConvertTemp) et l’appel aux paramètres d’entrée (input) et de sortie (output). Ceci termine l’analyse de notre service web qui, avouons-le, n’est pas des plus simples. L’étape suivante va consister à créer une application Flex faisant appel à ce service. Création de l’interface graphique L’interface graphique de notre application comprend seulement deux zones de texte et un bouton permettant l’appel du service web (figure 12-3). Figure 12-3 Interface graphique de conversion de températures <mx:Panel x="10" y="10" width="379" height="183" layout="absolute" title="WebService : Conversion de température"> <mx:Button x="10" y="105" label="Convertir" id="btn_executer" ➥click="executerWebService()" width="339"/> <mx:Form x="10" y="10" width="339" height="87" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:FormItem label="Température en degrés Celsius :"> <mx:TextInput width="79" id="degresC_txt"/> =Flex3 FM.book Page 235 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 235 </mx:FormItem> <mx:FormItem label="Température en degrés Fahrenheit :"> <mx:TextInput width="81" editable="false" enabled="true" id="degresF_txt"/> </mx:FormItem> </mx:Form> </mx:Panel> Appel du service web Le service web sera appelé grâce au composant <mx:WebService>, comme suit : <mx:WebService id="serviceConversion" wsdl="http://www.webservicex.net/ConvertTemperature.asmx?WSDL"> <mx:operation name="ConvertTemp" resultFormat="object" fault="resultatKO(event)" result="resultatOK(event)"/> </mx:WebService> L’URL du service est spécifiée dans la propriété wsdl. Vient ensuite l’appel de l’opération ConvertTemp dont le résultat est ici spécifié comme un objet. On trouve ensuite les procédures resultatOK(event) et resultatKO(event) exécutées en fonction du résultat de l’exécution du service. La configuration de l’appel de notre service web terminée, passons maintenant à l’écriture des procédures d’appel et d’analyse du résultat. <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; // Procédure affichant l’erreur d’exécution public function resultatKO(e:FaultEvent):void{ Alert.show("ERREUR "+e.fault.faultString); } // Récupération du résultat envoyé par le service web public function resultatOK(e:ResultEvent):void { degresF_txt.text=String(e.result); } // Exécution du service public function executerWebService():void { var temperature:String = degresC_txt.text; var uniteSource:String = "degreeCelsius"; =Flex3 FM.book Page 236 Mardi, 2. décembre 2008 3:32 15 236 Comprendre Flex 3 PARTIE I var uniteConversion:String = "degreeFahrenheit"; // Appel du service serviceConversion.ConvertTemp(temperature,uniteSource,uniteConversion); } ]]> </mx:Script> Les commentaires insérés dans cette portion de code parlent d’eux-mêmes. Nous aimerions tout de même attirer votre attention sur la méthode d’appel du service. Cette méthode se résume en l’appel de l’opération appropriée et en la transmission des paramètres requis : serviceConversion.ConvertTemp(temperature,uniteSource,uniteConversion); Soulignons également que l’ordre et le type des paramètres transmis doivent coïncider avec ceux établis en phase d’étude du service web, sous peine d’un dysfonctionnement de celui-ci. Nous pouvons à présent exécuter notre application afin de vérifier qu’elle fonctionne correctement (figure 12-4). Figure 12-4 Appréciation du bon fonctionnement de l’application Analyse du fonctionnement de l’application Au cours de cette section, nous allons analyser le fonctionnement global de notre application afin de synthétiser la notion de service web et son mode d’interaction avec les applications Flex. Sept étapes jalonnent le processus de communication : Étape ➊ : l’utilisateur saisit la température en degrés Celsius et clique sur le bouton Convertir. Étape ➋ : l’action sur le bouton entraîne l’appel du service via son URL et la transmission des paramètres à l’opération de traitement concerné. Étape ➌ : le service reçoit les informations et les transmet à un programme chargé d’exécuter la conversion. À noter que nous n’avons pas accès à ce programme et il nous est impossible d’en déterminer les procédures de calcul. =Flex3 FM.book Page 237 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 Figure 12-5 Fonctionnement du composant WebService 237 =Flex3 FM.book Page 238 Mardi, 2. décembre 2008 3:32 15 238 Comprendre Flex 3 PARTIE I Étape ➍ : le programme retourne le résultat du traitement au service web. Étape ➎ : le service web communique à son tour le résultat à l’application Flex. Étape ➏ : la procédure liée à l’événement de retour positif du service est alors exécutée. Étape ➐ : l’interface graphique est mise à jour. Cet exemple nous a permis de démontrer que l’emploi des services web est assez fastidieux. La phase la plus complexe est sans doute l’analyse du service web, car la méthode d’appel du service reste très simple grâce à l’utilisation du composant <mx:WebService>. Flex nous propose enfin une troisième et dernière méthode de communication que nous allons nous empresser de découvrir au cours de la section suivante. Accéder aux classes distinctes grâce à RemoteObject Comprendre RemoteObject Le composant RemoteObject se distingue des composants HTTPService et WebService par son mode d’accès aux services. En effet, alors que nous devions préciser le mode d’envoi des données avec le composant HTTPService ou choisir l’opération adéquate avec WebService, le composant RemoteObject nous offre la possibilité d’accéder directement à la classe métiers souhaitée. Cette connexion directe n’est possible qu’à l’aide du langage ColdFusion ou de l’applicatif LiveCycle Data Service d’Adobe, souvent utilisé pour les environnements J2EE. Pour les services écrits en PHP et .NET, le composant RemoteObject ne peut accéder directement aux classes métiers, nous devons donc recourir à une passerelle qui effectuera cette connexion. Elle est réalisé au moyen d’applicatifs tels que AMFPHP (http://amfphp.sourceforge.net/), SabreAMF (http://www.osflash.org/sabreamf) ou encore WebORB de Midnight Coders (http://www.themidnightcoders.com/). Nous vous invitons à visiter les sites web de ces outils pour de plus amples informations à leur sujet. Implémentation de RemoteObject L’implémentation du composant RemoteObject à l’aide du langage MXML s’effectue comme suit : <mx:RemoteObject id="identifiant" source="classe à utiliser" endpoint="URL de la classe"> <mx:method name="nom de la méthode de la classe à exécuter" result="procédure à ➥exécuter en cas de succès d’exécution de la méthode" fault="procédure à exécuter en ➥cas d’échec d’exécution de la méthode"></mx:method> </mx:RemoteObject> =Flex3 FM.book Page 239 Mardi, 2. décembre 2008 3:32 15 Accéder aux services de la couche métier CHAPITRE 12 239 Voyons maintenant comment utiliser la classe RemoteObject en ActionScript : import mx.rpc.remoting.mxml.RemoteObject; var service:RemoteObject = new RemoteObject(); service.endpoint = adresse de la classe à utiliser; service.source="classe à utiliser"; service.nom_de_la_methode(); service.nom_de_la_methode.addEventListener("result", procédure à exécuter en cas de ➥succès d’exécution de la méthode); service.nom_de_la_methode.addEventListener("fault", procédure à exécuter en cas ➥d’échec d’exécution de la méthode) À ce stade, nous ne nous attarderons pas d’avantage sur l’utilisation de ce composant, car nous étudierons son application en détail au cours du chapitre suivant. Néanmoins, penchonsnous sur le schéma de son fonctionnement dans le cadre d’une utilisation avec le langage PHP couplé à la passerelle AMFPHP (figure 12-6). Ce schéma nous permet de distinguer les différentes étapes suivantes : Figure 12-6 Fonctionnement du composant RemoteObject avec AMFPHP et PHP =Flex3 FM.book Page 240 Mardi, 2. décembre 2008 3:32 15 240 Comprendre Flex 3 PARTIE I Étape ➊ : le composant établit la connexion avec AMFPHP et lui transmet la classe et la méthode recherchées. Étape ➋ : AMFPHP recherche la classe et la méthode. Étape ➌ : une fois la méthode trouvée, celle-ci est exécutée. Étape ➍ : le résultat de l’exécution de la méthode est transmis à AMFPHP. Étape ➎ : la procédure resultatOK(event) est exécutée afin de présenter le résultat obtenu. En résumé Au cours de ce chapitre, nous avons abordé les différentes méthodes de connexion aux services proposés par la couche métier. La méthode à employer dépend de la nature du service et du type de résultat souhaité (XML ou non). Néanmoins, dans la plupart des cas, le composant HTTPService est le plus communément utilisé car il se rapproche des méthodes de communication traditionnelles. Le chapitre suivant va nous permettre d’approfondir nos connaissances en matière de communication avec la couche métier en détaillant l’interaction avec les services écrits en PHP. =Flex3 FM.book Page 241 Mardi, 2. décembre 2008 3:32 15 13 Flex et PHP L’utilisation du langage PHP est très répandue pour la création de sites web. En effet, il représente aujourd’hui le langage utilisé par 80 % des sites Internet. C’est pourquoi, il est indispensable de comprendre comment il interagit avec le framework Flex. Accès aux services PHP PHP est un langage serveur dont le fonctionnement est basé sur l’interprétation et l’exécution de requêtes HTTP. La transmission des données entre le client et le script PHP s’effectue le plus communément à l’aide des méthodes POST ou GET. À première vue, le composant du framework Flex répondant à ces critères de communication est le composant HTTPService. Néanmoins, ce dernier présente un petit inconvénient : la réponse doit obligatoirement être formatée sous forme de balise XML (voir chapitre 12). Une autre solution consiste alors à utiliser le composant RemoteObject. En effet, grâce à ce composant, il est inutile de formater la réponse, car celle-ci peut être utilisée dans son format originel (chaîne, tableau, entier…). Cependant, RemoteObject ne peut interagir directement avec les objets PHP comme nous aurions pu l’envisager avec le langage ColdFusion. Il va donc falloir utiliser une passerelle capable de réaliser la communication entre l’application Flex et les services PHP. Nous avons ici choisi de vous présenter la passerelle AMFPHP (Action Message Format PHP). Installation et fonctionnement de la passerelle AMFPHP AMFPHP est une bibliothèque PHP sous licence Open Source permettant la communication entre des applications Flash (et par extension Flex) et le langage PHP. Elle joue le rôle de passerelle entre l’application et les services PHP. =Flex3 FM.book Page 242 Mardi, 2. décembre 2008 3:32 15 242 Comprendre Flex 3 PARTIE I Le principal avantage de cette bibliothèque est de ne pas modifier les types des données transmises. Par exemple, si nous transmettons un objet via l’application Flex, PHP reçoit un objet et inversement. Le protocole AMF La libraire AMFPHP utilise le protocole AMF, mis au point par Adobe. Il s’agit d’un protocole binaire de transfert de données entre le client et le serveur, ce qui permet de réduire la taille des paquets échangés entre ces deux entités et, par conséquent, de diminuer la part de la bande passante utilisée par l’application qui le met en œuvre. Il présente également l’avantage d’augmenter la rapidité d’exécution des applications en raison de la diminution des paquets échangés. Pour installer la bibliothèque AMFPHP, il suffit de la télécharger à l’adresse suivante : http://sourceforge.net/project/showfiles.php?group_id=72483#files, et de décompresser l’archive ainsi obtenue à la racine de votre serveur web. Attention Pour que l’interaction avec le composant RemoteObject soit effective, vous devez disposer au minimum de la version amfphp-1.9.beta.20070513. En explorant les différents répertoires de la bibliothèque AMFPHP, nous notons la présence du répertoire services. C’est ici que nous allons déposer l’ensemble de nos services PHP. Rappelons qu’un service PHP est une méthode contenue dans une classe PHP dont le nom doit être rigoureusement identique au nom du fichier PHP qui la contient. En effet, c’est à partir de ce nom de fichier qu’AMFPHP va pouvoir effectuer la corrélation entre la classe et le service appelé. À la racine de la bibliothèque AMFPHP, nous notons également la présence du fichier gateway.php. Ce fichier va être le point d’entrée entre notre application Flex et les services PHP. Les différentes étapes de communication entre une application Flex et les services PHP sont les suivantes (figure 13-1) : Étape 1 : l’application Flex effectue une demande d’exécution de service en se connectant au fichier gateway.php de la bibliothèque AMFPHP et en lui spécifiant la classe et le service (méthode) recherchés. Étapes 2, 3 et 4 : le fichier gateway.php vérifie la présence de la classe, en fonction des noms de fichiers PHP présents dans le répertoire service, et si la méthode demandée est bien implémentée dans la classe. Étape 5 : la méthode renvoie un résultat au fichier gateway.php. Étape 6 : le fichier gateway.php transmet à l’application Flex le résultat fourni par la méthode. Notez que la sérialisation/désérialisation des données est effectuée par AMFPHP, =Flex3 FM.book Page 243 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 243 ce qui permet de ne pas modifier le type de données transmises et reçues. De ce fait, si le service retourne un tableau, c’est un tableau qui sera reçu par l’application Flex et si l’application Flex transmet un tableau au service, c’est sous cette forme qu’il sera réceptionné par le service. Figure 13-1 Processus d’échange entre une application Flex et les services PHP Pour plus de clarté, nous avons choisi d’illustrer l’ensemble des notions abordées jusqu’à présent à travers un exemple dans lequel les composants HTTPService et RemoteObject sont utilisés. =Flex3 FM.book Page 244 Mardi, 2. décembre 2008 3:32 15 244 Comprendre Flex 3 PARTIE I Cas pratique : gestion d’un magasin informatique En guise d’exemple, nous vous proposons de développer une petite application permettant de gérer l’ensemble des produits d’un magasin informatique. Le but n’étant pas ici de développer un cas pratique complet (ceci sera abordé dans la seconde partie de cet ouvrage), nous allons plutôt illustrer l’ensemble des concepts et observer les différences entre les composants HTTPService et RemoteObject. Afin d’observer ces différences, nous réaliserons le listing des produits à l’aide de ces deux composants. Préparation Avant d’entrer dans le vif du sujet, il convient tout d’abord de créer le projet Flex et la base de données qui contiendra les produits du magasin informatique, sans oublier de satisfaire à certains prérequis techniques. Prérequis Pour mener à bien cet exemple, vous devez impérativement disposer d’un environnement PHP correctement installé et configuré sur votre machine. Pour plus de facilité, nous vous conseillons d’utiliser EasyPHP, pack logiciel contenant l’ensemble des éléments requis (PHP, MySQL et le serveur Apache). Vous trouverez toutes les informations nécessaires sur cette application à l’adresse suivante : http://www.easyphp.org/. Création de la base de données Le schéma de la base de données MySQL découle du diagramme de classes représenté à la figure 13-2. La base de données contient donc deux tables : la première synthétise les catégories de produits (carte mère, disque dur, etc.), la seconde permet de stocker les composants informatiques mis en vente. Figure 13-2 Diagramme de classes Voici le script de création de la base de données, issue de la transcription du diagramme précédemment décrit. --- SCHÉMA DE LA BASE DE DONNÉES db_configurateur =Flex3 FM.book Page 245 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 -CREATE DATABASE IF NOT EXISTS db_configurateur; USE db_configurateur; --- CRÉATION DE LA TABLE tb_categorie -CREATE TABLE `tb_categorie` ( `idCategorie` int(10) unsigned NOT NULL auto_increment, `nomCategorie` varchar(45) NOT NULL default '', PRIMARY KEY (`idCategorie`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --- INSERTION DE DONNÉES DANS LA TABLE tb_categorie -INSERT INTO `tb_categorie` (`idCategorie`,`nomCategorie`) VALUES (1,'Disques durs'), (2,'Mémoires'), (3,'Cartes graphiques'), (4,'Processeurs'), (5,'Cartes mères'), (6,'Graveurs & Lecteurs'), (7,'Boîtiers & Alimentations'); --- CRÉATION DE LA TABLE tb_composant liée à la table tb_categorie par le biais de la ➥clé étrangère fkCategorie -CREATE TABLE `tb_composant` ( `idComposant` int(10) unsigned NOT NULL auto_increment, `nomComposant` varchar(45) NOT NULL default '', `prixComposant` float NOT NULL default '0', `fkCategorie` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`idComposant`), KEY `FK_tb_composant` (`fkCategorie`), CONSTRAINT `FK_tb_composant` FOREIGN KEY (`fkCategorie`) REFERENCES `tb_categorie` ➥(`idCategorie`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --- INSERTION DE DONNÉES DANS LA TABLE tb_composant -INSERT INTO `tb_composant` (`idComposant`,`nomComposant`,`prixComposant`, ➥`fkCategorie`) VALUES (1,'SATA - 160 Go, 8 Mo, S-ATA/II, 7200 trs/min',48.99,1), (2,'SATA - 80 Go, 8 Mo, S-ATA/II, 7200 trs/min',38.52,1), (3,'SATA - 400 Go, 16 Mo, S-ATA/II, 7200 trs/min',154.25,1), (4,'IDE - 160 Go, 8 Mo',59,1), (5,'IDE - 320 Go, 8 Mo',72.5,1), (6,'IDE - 400 Go, 16 Mo',150,1), 245 =Flex3 FM.book Page 246 Mardi, 2. décembre 2008 3:32 15 246 Comprendre Flex 3 PARTIE I (7,'1024 Mo, PC3200 (400 MHz)',60.42,2), (8,'512 Mo, PC133',54.12,2), (9,'2048 Mo, PC4200 (533 MHz)',118.99,2), (10,'512 Mo, PC3200 (400 MHz)',32.75,2), (11,'256 Mo, PC133',22.15,2), (12,'512 Mo, PC4200 (533 MHz)',25.89,2), (13,'Radeon X1600 Pro, PCI-Express 16x, 256 Mo',124.52,3), (14,'GeForce 7600 GS, PCI-Express 16x, 256 Mo',98,3), (15,'GeForce 7800 GS, AGP 8x, 256 Mo',300.41,3), (16,'Radeon X1950 Pro, PCI-Express 16x, 256 Mo',174.98,3), (17,'Quadro FX 3500, PCI-Express 16x, 256 Mo',1200.58,3), (18,'GeForce 7300 GS, PCI-Express 16x, 256 Mo',70.25,3), (19,'2,67 GHz, 256 Ko, 533 MHz',35,4), (20,'3,00 GHz, 4 Mo, 800 MHz',125.36,4), (21,'1,86 GHz, 4 Mo, 1066 MHz',41.73,4); INSERT INTO `tb_composant` (`idComposant`,`nomComposant`,`prixComposant`, ➥`fkCategorie`) VALUES (22,'3,33 GHz, 512 Ko, 533 MHz',60.81,4), (23,'2,00 GHz, 2 Mo, 800 MHz',132.84,4), (24,'2,93 GHz, 4 Mo, 1066 MHz',978.68,4), (25,'VIA PT880 Ultra',31.69,5), (26,'NVIDIA nForce Dual PCI-E x 16',254.94,5), (27,'Intel P965',154,5), (28,'NVIDIA nForce 680i SLI',500.84,5), (29,'Intel 946GZ Express',85.24,5), (30,'Intel 975X',100,5), (31,'GRAVEUR DVD - S-ATA, noir',50,6), (32,'GRAVEUR DVD - USB 2.0, aluminium',125.41,6), (33,'LECTEUR DVD - BLANC',19.99,6), (34,'LECTEUR DVD - NOIR',19.99,6), (35,'GRAVEUR DVD - IDE Noir',45,6), (36,'GRAVEUR DVD - IDE Beige',54.26,6), (37,'Digital-B - 480 w',52,7), (38,'NSK6000 - 380 w',98,7), (39,'P160 - 430 w',114.83,7), (40,'Vague 8609B - 500 w',81.23,7), (41,'Nine Hundred - 400 w',100.14,7), (42,'Oxygen 8611B',95.24,7); Passons à présent à la création de l’interface graphique de notre application. Création de l’interface graphique Après avoir créé un nouveau projet Flex, nous vous invitons à saisir les quelques lignes de code suivantes afin d’obtenir l’interface graphique capable de lister l’ensemble des produits de notre magasin (figure 13-3). <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> =Flex3 FM.book Page 247 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 247 <mx:DataGrid id="grilleComposants" x="10" y="10" width="700" rowCount="10"> <mx:columns> <mx:DataGridColumn headerText="Catégorie" dataField="nomCategorie" ➥width="200"/> <mx:DataGridColumn headerText="Composant" dataField="nomComposant" ➥width="400"/> <mx:DataGridColumn headerText="Prix" dataField="prixComposant" width="100"/> </mx:columns> </mx:DataGrid> </mx:Application> Figure 13-3 Interface graphique Nous disposons désormais de l’ensemble des éléments nécessaires au bon déroulement de notre application. Voyons maintenant comment utiliser les composants HTTPService et RemoteObject. Implémentation du composant HTTPService en ActionScript Au cours du chapitre précédent, nous avions vu un exemple mettant en évidence l’utilisation du composant HTTPService pour accéder aux services PHP. Nous allons l’utiliser également dans notre cas pratique, mais cette fois, nous l’implémenterons à l’aide du langage ActionScript. Pour cela, la première étape va consister à créer le service PHP devant se connecter à la base de données et lister les produits qu’elle contient. Il ne faudra pas omettre de transformer le résultat en langage XML, afin qu’il soit exploitable par notre application. Voici le code du fichier listerProduits.php, qui va nous permettre d’obtenir la liste des produits de notre magasin et de la transmettre à l’application Flex sous forme XML : =Flex3 FM.book Page 248 Mardi, 2. décembre 2008 3:32 15 248 Comprendre Flex 3 PARTIE I <?php // Connexion à la base de données MySQL grâce au nom d’hôte, au login et au mot de ➥passe $db = mysql_connect("localhost","root","mysql"); // Sélection de la base de données mysql_select_db("db_configurateur", $db); // Requête $Requete = "select CP.idComposant, CP.nomComposant, CP.prixComposant, ➥CAT.nomCategorie, CAT.idCategorie From tb_composant CP, tb_categorie CAT where CP.fkCategorie = CAT.idCategorie"; // Résultat de la requête $Resultat = mysql_query( $Requete ); // Transformation du résultat en XML $ExportXML = "<composants>"; while ($Composants = mysql_fetch_object ($Resultat)) { $ExportXML .="<composant>"; $ExportXML .="<idComposant>".$Composants->idComposant."</idComposant>"; $ExportXML .="<nomComposant>".$Composants->nomComposant."</nomComposant>"; $ExportXML .="<prixComposant>".$Composants->prixComposant."</prixComposant>"; $ExportXML .="<idCategorie>".$Composants->idCategorie."</idCategorie>"; $ExportXML .="<nomCategorie>".$Composants->nomCategorie."</nomCategorie>"; $ExportXML .="</composant>"; } $ExportXML .= "</composants>"; mysql_free_result($Resultat); print ($ExportXML) ?> Nous devons ensuite créer la procédure alimentant notre tableau. Pour cela, nous vous conseillons de créer un fichier ActionScript nommé httpService.as, que nous lierons par la suite au fichier MXML. Dans la portion de code suivante, nous avons commenté l’ensemble des lignes devant être insérées dans ce fichier afin que vous puissiez apprécier la signification et le rôle de chacune : // Importation des classes nécessaires import mx.controls.Alert; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.http.HTTPService; // Procédure déclenchée à la fin de la création de l’application public function listerComposants():void{ =Flex3 FM.book Page 249 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 249 var serviceHttp:HTTPService = new HTTPService; // Spécification de l’URL serviceHttp.url = "http://localhost/PHP/httpServices/listerProduits.php" // Spécification du format des données reçues serviceHttp.resultFormat = "e4x"; // Type de méthode d’envoi des données serviceHttp.method = "POST"; // Procédure à exécuter en cas de succès serviceHttp.addEventListener(ResultEvent.RESULT,resultatOk) // Procédure a exécuter en cas d’erreur serviceHttp.addEventListener(FaultEvent.FAULT,resultatKo) // Exécution du service serviceHttp.send() } // Procédure exécutée en cas de réception du résultat public function resultatOk(e:ResultEvent):void { // Récupération du résultat var resultatXML:XML = e.result as XML; // Alimentation du dataProvider du DataGrid grilleComposants.dataProvider = resultatXML.composant; } // Procédure exécutée en cas d’erreur public function resultatKo(e:FaultEvent):void { // Message d’erreur Alert.show("Erreur !"); } L’implémentation du composant HTTPService en ActionScript est identique à celle utilisée en MXML (voir chapitre 12) : • spécification de l’URL ; • spécification de la méthode d’envoi des données ; • indication des procédures à exécuter en cas de succès ou d’erreur ; =Flex3 FM.book Page 250 Mardi, 2. décembre 2008 3:32 15 250 Comprendre Flex 3 PARTIE I • indication du format des données récupérées. À présent, il ne nous reste plus qu’à lier notre fichier ActionScript au fichier MXML principal et faire appel à l’exécution de la procédure listerComposants() après la création de l’application : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="listerComposants()"> <mx:Script source="httpService.as"></mx:Script> Nous pouvons maintenant tester notre application et observer que le résultat obtenu est bien concluant (figure 13-4). Figure 13-4 Résultat obtenu à l’aide du composant HTTPService Nous allons réitérer cette procédure, mais en utilisant le composant remoteObject couplé à AMFPHP. RemoteObject en pratique Nous allons à présent voir le couple RemoteObject et AMFPHP en action. Création du service PHP Avant toute chose, il convient de créer le service PHP. Pour cela, nous allons nous placer dans le répertoire services de la bibliothèque AMFPHP et créer un fichier nommé servComposants.php qui va contenir l’ensemble des services accessibles pour notre application : <?php class servComposants { =Flex3 FM.book Page 251 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 function servComposants () { /****************************************** /* LISTE DES SERVICES * /******************************************/ $this->methodTable = array( "serviceListerComposants" => array( "description" => "Liste des composants", "access" => "remote" ) ); } //-------------------------//-SERVICE -//-------------------------function serviceListerComposants () { // Connexion à la base de données MySQL grâce au nom d’hôte, au login et au ➥mot de passe $db = mysql_connect("localhost","root","mysql"); // Sélection de la base de données mysql_select_db("db_configurateur", $db); // Requête $Requete = "select CP.idComposant, CP.nomComposant, CP.prixComposant, ➥CAT.nomCategorie, CAT.idCategorie From tb_composant CP, tb_categorie CAT where CP.fkCategorie = CAT.idCategorie"; // Résultat de la requête $Resultat = mysql_query( $Requete ); // Alimentation d’un tableau avec la liste des composants while ($Composant = mysql_fetch_object ($Resultat)) { $tableauComposants[] = $Composant; } // Envoi du tableau return( $tableauComposants); } } ?> 251 =Flex3 FM.book Page 252 Mardi, 2. décembre 2008 3:32 15 252 Comprendre Flex 3 PARTIE I Ce fichier comporte une classe nommée servComposants. Nous insistons sur le fait que le nom de la classe doit obligatoirement comporter le nom du fichier PHP car ces deux entités sont liées. Le fichier est ensuite découpé en deux parties. La première permet de créer, dans le constructeur de la classe, un tableau contenant la liste des services disponibles : function servComposants () { /****************************************** /* LISTE DES SERVICES * /******************************************/ $this->methodTable = array( "serviceListerComposants" => array( "description" => "Liste des composants", "access" => "remote" ) ); } La seconde partie contient les services proprement dits : function serviceListerComposants () { […] // Alimentation d’un tableau avec la liste des composants while ($Composant = mysql_fetch_object ($Resultat)) { $tableauComposants[] = $Composant; } // Envoi du tableau return( $tableauComposants); } Notre service serviceListerComposants() va donc rechercher les informations dans la base de données et pour chaque ligne trouvée, il va les stocker dans une ligne d’un tableau qui sera ensuite transmis à l’application Flex en suivant les étapes décrites à la section précédente « Installation et fonctionnement » de ce chapitre. Test du service Avant de se lancer dans le codage du fichier MXML de notre application, il convient de s’assurer que notre service fonctionne correctement. Pour cela, nous allons utiliser l’interface prévue à cet effet située dans le répertoire browser de la bibliothèque AMFPHP. Pour tester le service : 1. Dans la partie gauche de l’interface, sélectionnez votre fichier php (ServComposant) contenant la liste des services. =Flex3 FM.book Page 253 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 253 2. Dans la partie droite de l’interface s’affiche alors la liste des services contenus dans ce fichier PHP. Sélectionnez le service serviceListerComposant. 3. Cliquez sur le bouton Call qui déclenche l’appel du service. Vous obtenez alors le résultat illustré à la figure 13-5. Figure 13-5 Test du service dans l’interface Service Browser Première exécution du service browser d’AMFPHP Pour accéder à l’interface de test des services, il faut appeler le fichier index.html du répertoire browser de la bibliothèque AMFPHP via votre navigateur (par exemple, http://localhost/amfphp/browser). Au premier lancement de cette application, une fenêtre vous indique les paramètres utilisés : • le chemin d’accès au fichier gateway.php ; • le type d’encodage : – AMF0 (à utiliser si l’application a été développée à l’aide d’ActionScript 1.0 ou 2.0) ; – AMF3. • les onglets de résultat visibles après l’exécution d’un service : – l’onglet Info, qui permet de visualiser les temps de traitement du service ; – l’onglet Results, qui permet d’afficher le résultat sous forme de trace de log ; – l’onglet Tree view, qui permet de visualiser les résultats sous forme d’arborescence, un nœud étant caractérisé par un objet. =Flex3 FM.book Page 254 Mardi, 2. décembre 2008 3:32 15 254 Comprendre Flex 3 PARTIE I Conseil Pour une prise en main de cette interface, nous vous conseillons de conserver les paramètres spécifiés par défaut, qui sont généralement les plus utilisés. Si vous visualisez la liste des composants informatiques dans l’onglet Results, cela signifie que notre service s’est exécuté correctement. Dans le cas contraire, cela signifie que le fichier PHP contient une erreur. Il est important de noter que seule cette interface vous permettra de déboguer vos services PHP. En effet, dans la mesure où l’application Flex et les services PHP sont séparés par la notion de couche métier, il est impossible de remonter dans l’application les erreurs rencontrées dans les services. Le seul indice nous indiquant un éventuel dysfonctionnement du service est une erreur de connexion au service, ou parfois aucune erreur…, mais dans tous les cas nous n’obtiendrons aucun résultat. Implémentation en MXML Dans un premier temps, nous allons étudier la mise en place du composant RemoteObject à l’aide du langage MXML. Pour cela, analysons les lignes de code suivantes : <mx:RemoteObject id="servRO" source="ServComposants" endpoint="http://localhost/amfphp/gateway.php" ➥destination="amfphp" showBusyCursor="true"> <mx:method name="serviceListerComposants" result="resultatOK(event)" ➥fault="resultatKO(event)"></mx:method> </mx:RemoteObject> Comme nous l’avons vu au chapitre précédent, le composant RemoteObject nécessite quelques paramétrages : • source : sert à spécifier le nom de la classe contenant la méthode à exécuter ; • endPoint : contient l’URL du fichier gateway.php de la bibliothèque AMFPHP ; • destination : permet de faire le lien avec le sous-répertoire amfphp du répertoire services, ce dernier contenant le fichier DiscoveryService.php qui va permettre à AMFPHP de connaître les fichiers PHP contenant l’ensemble des services ; • showBusyCursor : affiche le curseur « Occupé » pendant l’exécution de la méthode ; • method name : précise le nom de la méthode à exécuter ; • result : contient le nom de l’action à réaliser lorsque la méthode retourne un résultat ; • fault : déclare le nom de l’action à réaliser lorsque la méthode a provoqué une erreur. Nous faisons ici appel à la méthode serviceListerComposants de la classe servComposants. Si la méthode retourne un résultat, la procédure resultatOk() est exécutée. Dans le cas contraire, la procédure resultatKO() est exécutée. =Flex3 FM.book Page 255 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 255 Afin de pouvoir réaliser l’appel à notre méthode, nous allons ajouter un bouton comme suit : <mx:Button x="10" y="242" label="Appeler service" id="btn_ro" ➥click="executerService()"/> Notre composant est à présent configuré, il ne reste plus qu’à écrire les procédures ActionScript. <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.controls.Alert; public function executerService():void { servRO.getOperation('serviceListerComposants').send(); } public function resultatOK(e:ResultEvent):void { grilleComposants.dataProvider = e.result as Array; } public function resultatKO(e:FaultEvent):void { Alert.show(e.fault.faultString, e.fault.faultCode.toString()); } ]]> </mx:Script> Observons en détail comment l’appel de l’exécution de la méthode serviceListerComposants est réalisé . En effet, cet appel s’effectue par la combinaison des méthodes getOperation() et send() du composant RemoteObject. La traduction littérale de ceci serait alors : « Recherche l’opération serviceListerComposant(getOperation('serviceListerComposants')) et exécute la méthode send() ». Notre composant est à présent configuré et fonctionnel. Soulignons également le travail réalisé par la bibliothèque AMFPHP : le résultat tabulaire renvoyé par la méthode est directement exploitable sous cette forme par le composant RemoteObject, ce qui facilite ainsi son exploitation ultérieure. =Flex3 FM.book Page 256 Mardi, 2. décembre 2008 3:32 15 256 Comprendre Flex 3 PARTIE I Implémentation en ActionScript Nous allons de nouveau appeler le service serviceListerComposants, mais cette fois-ci avec le langage ActionScript. Pour cela, il convient de modifier quelque peu la procédure executerService() : public function executerService():void { var servRO:RemoteObject = new RemoteObject; // Paramétrage servRO.source = "ServComposants" servRO.destination = "amfphp" servRO.endpoint = "http://localhost/amfphp/gateway.php" // Événements si succès ou erreur servRO.serviceListerComposants.addEventListener("result", resultatOK); servRO.serviceListerComposants.addEventListener("fault", resultatKO) // Exécution de la méthode servRO.serviceListerComposants() } Nous n’utilisons pas ici les méthodes getOperation() et send() pour exécuter le service serviceListerComposants. En effet, nous préférons utiliser la syntaxe servRO.serviceLister Composants (). Pour passer des paramètres au service, il suffit alors de les spécifier à l’intérieur des parenthèses, comme suit : servRO.serviceListerComposants(parametre1, parametre2) Vous pouvez à présent tester l’application afin de vérifier que tout fonctionne correctement (figure 13-6). Figure 13-6 Résultat obtenu à l’aide du composant RemoteObject =Flex3 FM.book Page 257 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 257 Le générateur d’application de Flex Builder L’une des grandes nouveautés de Flex Builder 3 est la possibilité de générer automatiquement l’interface graphique et le service PHP associés à une table d’une base de données. Voici la marche à suivre pour cela : 1. Créez un nouveau projet nommé listerComposant et sélectionnez PHP pour le paramètre Application server type (figure 13-7). Figure 13-7 Création d’un nouveau projet utilisant la technologie PHP 2. Spécifiez le répertoire racine de votre serveur web (pour EasyPHP, il s’agit du chemin d’accès au répertoire www) ainsi que son URL (généralement http://localhost). Cliquez ensuite sur le bouton Validate Configuration (figure 13-8). 3. Le nouveau projet est désormais créé et il faut à présent le connecter à une source de données. Pour cela, sélectionnez le menu Data de Flex Builder et choisissez l’option Create application from database… Dans la fenêtre qui s’ouvre alors, sélectionnez le projet précédemment créé et spécifiez la connexion à la base de données souhaitée à l’aide du champ Connection. Après avoir testé la connexion (en cliquant sur le bouton Test Connexion), renseignez le champ Table en indiquant le nom de la table de la base de données qui fera l’objet du développement. Pour notre exemple, nous avons choisi la table tb_composant (figure 13-9). Le champ Primary key permet de spécifier le champ de la table servant de clé primaire. =Flex3 FM.book Page 258 Mardi, 2. décembre 2008 3:32 15 258 Comprendre Flex 3 PARTIE I Figure 13-8 Configuration des paramètres du serveur web Figure 13-9 Paramétrage de la base de données et sélection de la table =Flex3 FM.book Page 259 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 259 4. Cliquez ensuite sur le bouton Next. Une nouvelle fenêtre apparaît alors, vous permettant de définir le nom et le lieu de stockage du fichier PHP contenant les services nécessaires (figure 13-10). Figure 13-10 Paramétrage du fichier PHP 5. Cliquez à nouveau sur le bouton Next et dans la nouvelle fenêtre qui s’ouvre, spécifiez éventuellement un critère de filtre sur une colonne précise de la table (figure 13-11). 6. Cliquez enfin sur le bouton Finish. Flex Builder va alors générer les interfaces et services nécessaires à la gestion des données contenues dans la table : – Liste des données ; – Ajout ; – Suppression ; – Modification ; – Recherche de données. À première vue, tout semble parfait. Nous disposons d’une interface dans laquelle nous pouvons visualiser la liste des composants et procéder aux opérations de base : ajout, suppression et modification (figure 13-12). =Flex3 FM.book Page 260 Mardi, 2. décembre 2008 3:32 15 260 Comprendre Flex 3 PARTIE I Figure 13-11 Spécification d’un critère de filtre sur une colonne de la table Figure 13-12 Interface générée par Flex Builder =Flex3 FM.book Page 261 Mardi, 2. décembre 2008 3:32 15 Flex et PHP CHAPITRE 13 261 Si nous naviguons dans le composant ViewStack de l’application, nous remarquons la présence d’un formulaire permettant la saisie des informations nécessaires à la création d’un composant informatique (figure 13-13). Figure 13-13 Formulaire d’ajout d’un composant informatique Pour le moment, tout cela est assez satisfaisant. Analysons à présent le code. La première chose que l’on peut remarquer en sélectionnant le mode source pour le fichier MXML, est l’abondance de commentaires au début du fichier, lesquels favorisent une bonne compréhension de ce qui a été réalisé par le générateur. Si nous nous aventurons dans le fichier ActionScript tb_composant.as, nous voyons également de nombreux commentaires expliquant le rôle et le fonctionnement de chaque procédure et fonction. Si le code présenté ici n’est pas très complexe pour les néophytes en ActionScript, il demande tout de même quelques précisions. L’emploi du composant HTTPService permet de réaliser l’appel des services PHP décrits dans le fichier tb_composant.php situé dans le répertoire bin-debug de l’application. C’est à partir d’ici que les choses se compliquent car pour les non-initiés au langage PHP, le fichier tb_composant.php est assez difficile à comprendre. Si nous faisons la synthèse de tout cela, nous pouvons dire que le générateur est assez simple d’utilisation mais que le code généré demande tout de même certaines connaissances et une certaine maîtrise des langages ActionScript et PHP. Cette complexité du code peut dérouter les utilisateurs débutants et c’est l’un des points négatifs que nous pouvons soulever. =Flex3 FM.book Page 262 Mardi, 2. décembre 2008 3:32 15 262 Comprendre Flex 3 PARTIE I Par ailleurs, le résultat final est concluant. Nous disposons en effet d’une application fonctionnelle, réalisée en quelques clics de souris seulement, même si elle ne concerne qu’une seule table de notre base de données. Pour les autres tables, il faudra procéder de la même manière et créer une nouvelle connexion à une source de données en choisissant une autre table de la base. La fusion de plusieurs tables n’est donc pas possible au sein d’une même interface, ce qui est tout de même assez gênant. En résumé Au cours de ce chapitre, nous avons vu qu’il est assez aisé de combiner des services PHP avec une application Flex grâce aux composants HTTPService et RemoteObject. Nous avons ouvert une porte sur la réécriture d’applications PHP existantes vers une application plus dynamique grâce au framework Flex. Flex Builder propose certes un générateur automatique d’interface homme-machine et de services PHP, mais nous vous conseillons de développer vous-même ces éléments. En effet, vous en connaîtrez ainsi les subtilités et cela vous permettra de prévenir tout dysfonctionnement, dont la maîtrise vous échapperait en utilisant la génération automatique. Dans le chapitre suivant, nous allons mettre de côté PHP pour nous consacrer à l’étude du projet BlazeDS d’Adobe, dédié à la communication entre une application Flex et les services Java, ainsi qu’à l’utilisation de données en temps réel (une application de tchat par exemple). =Flex3 FM.book Page 263 Mardi, 2. décembre 2008 3:32 15 14 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications Dans ce chapitre, nous allons faire connaissance avec l’un des produits Open Source d’Adobe : le projet BlazeDS. Grâce à lui, nous pourrons, entre autres, faire appel à des méthodes J2EE de la couche métier et réaliser des échanges de données en temps « réel » entre deux applications Flex. Le projet BlazeDS Pour accéder aux méthodes Java et réaliser l’échange de données en temps « réel » entre deux applications RIA (data push), nous devions jusqu’à présent utiliser la solution serveur LiveCycle Data Service ES d’Adobe dont le prix d’acquisition nécessitait un investissement supplémentaire à l’utilisation de la plate-forme de développement Flex. Il existe certes une version gratuite de cet applicatif, la version LiveCycle Data Service ES Express, mais elle ne peut être utilisée sur un environnement de production. C’est pourquoi le projet BlazeDS a vu le jour, offrant au développeur Flex la possibilité d’utiliser les briques de communication avec les méthodes Java et le push de données du LiveCyle Data Service ES sous licence Open Source (LGPL v3). =Flex3 FM.book Page 264 Mardi, 2. décembre 2008 3:32 15 264 Comprendre Flex 3 PARTIE I La technologie de communication utilisée par le serveur BlazeDS est le protocole AMF (Action Message Format) permettant l’échange de données au format binaire, jugé plus rapide que l’échange de données au format texte (XML). Les différentes versions du serveur BlazeDS Le serveur BlazeDS est disponible sous deux versions : la version BlazeDS Turnkey et une version binaire. La version BlazeDS Turnkey Pour être fonctionnel, BlazeDS doit être déployé sur le serveur web conteneur de servlets bien connu des développeurs J2EE : le serveur Tomcat. La version BlazeDS Turnkey propose aux utilisateurs le téléchargement d’une version « prête à l’emploi » contenant le serveur Tomcat et les services BlazeDS déjà déployés et configurés sur ce serveur. La version binaire Cette version est à privilégier si vous disposez déjà d’un serveur Tomcat sur votre machine. En effet, la version binaire consiste à télécharger l’archive BlazeDS.war pouvant ainsi être déployée sur votre serveur Tomcat. Dans notre cas, nous allons privilégier l’usage de la version BlazeDS Turnkey proposant une facilité d’installation non négligeable et permettant une meilleure approche du serveur BlazeDS. Néanmoins, si vous souhaitez déployer vous-même l’archive du serveur BlazeDS sur votre serveur Tomcat, nous vous conseillons de consulter le lien suivant, qui vous apportera toute les précisions nécessaires pour mener à bien son déploiement : http://opensource.adobe.com/wiki/display/blazeds/Installation+Guide. Installation Avant de procéder à l’installation du serveur BlazeDS, il convient de vérifier certains prérequis. Prérequis Pour que le serveur BlazeDS Turnkey soit fonctionnel, Java SDK (Software Development Kit) doit être installé et correctement configuré sur votre machine. Par ailleurs, la variable d’environnement JAVA_HOME doit être spécifiée. Installation du SDK Pour plus de détails sur l’installation de Java SDK, nous vous invitons à vous reporter au chapitre 3 de cet ouvrage ou à consulter le site web de Sun Microsytems à l’adresse suivante : http://java.sun.com/ javase/downloads/index.jsp. =Flex3 FM.book Page 265 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 265 Afin de nous assurer que notre environnement est correctement configuré, nous allons procéder à la saisie de quelques lignes de commande MS-DOS. Voici celle à saisir pour vérifier la présence de Java : java –version Nous obtenons alors le résultat suivant. Notez que l’affichage de ce résultat peut être différent en fonction de la version de Java installée sur votre système : java version version de java « 1.6.0_05 » Java™ SE Runtime Environnement (build 1.6.0_05-b13) Java HotSpot™ Vlient VM (build 10.0-b19, mixed mode, sharing) Pour vérifier la présence de la variable d’environnement JAVA_HOME, nous saisissons ensuite la ligne de commande suivante : Echo %JAVA_HOME% La valeur spécifiée dans la variable d’environnement doit s’afficher à l’écran. Dans le cas contraire, ajoutez-la comme nous l’avons vu au chapitre 3. Si ces tests sont concluants, vous pouvez passer à l’installation du serveur BlazeDS. L’installation pas à pas L’installation du serveur BlazeDS Turnkey comprend trois phases distinctes : 1. Le téléchargement de l’archive du serveur à partir du site d’Adobe : http://open source.adobe.com/wiki/display/blazeds/Release+Builds. 2. La décompression de l’archive sur votre disque dur. 3. Le renommage du répertoire issu de la décompression en blazeds. Dans la mesure où le répertoire d’installation peut être différent en fonction de la configuration de votre machine, nous nommerons par convention {blazeds} le répertoire racine du serveur BlazeDS correspondant au chemin d’installation que vous avez choisi. Le serveur Tomcat Tomcat est un conteneur d’applications Java également appelées servlets. Souvent associé au serveur web Apache faisant office de serveur de présentation, Tomcat est chargé de gérer la partie dynamique de l’application J2EE par la prise en charge des requêtes effectuées sur les servlets. Nous ne détaillerons pas davantage l’étude de ce serveur dans cet ouvrage. Si vous souhaitez en savoir plus, nous vous conseillons de consulter le site de l’éditeur (http:// jakarta.apache.org/tomcat) ou de vous référer à l’ouvrage Java – (1) Premières applications professionnelles en Java d’Emmanuel Puybaret publié aux éditions Eyrolles. =Flex3 FM.book Page 266 Mardi, 2. décembre 2008 3:32 15 266 Comprendre Flex 3 PARTIE I Configuration Avant de démarrer le serveur Tomcat , il convient de créer une variable d’environnement CATALINA_HOME pointant vers le répertoire racine de Tomcat, c’est-à-dire le répertoire {blazeds}\tomcat. Cette variable d’environnement doit être spécifiée afin d’indiquer au système l’endroit où se situent les fichiers nécessaires à la bonne exécution du serveur Tomcat. Pour cela, suivez les indications fournies au chapitre 3 dans la section des prérequis et saisissez les paramètres suivants (figure 14-1) : • Nom de la variable : CATALINA_HOME ; • Valeur de la variable : répertoire racine de Tomcat. Terminez ensuite en cliquant sur le bouton OK et fermez la fenêtre de propriété du poste de travail. Figure 14-1 Création de la variable d’environnement CATALINA_HOME Démarrage du serveur Avant de lancer le serveur Tomcat, vous devez démarrer le serveur de base de données HSQLDB. Il a été installé avec le serveur BlazeDS, et est indispensable au bon fonctionnement de certaines applications de démonstration livrées avec le serveur BlazeDS Turnkey. Pour cela, placez-vous dans le répertoire sampledb du répertoire racine de BlazeDS et double-cliquez sur le script startdb.bat pour l’exécuter (figure14-2). =Flex3 FM.book Page 267 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 267 Figure 14-2 Démarrage du server HSQLDB Pour exécuter à présent le serveur Tomcat, placez-vous dans le sous-répertoire bin de son répertoire racine et exécutez le script startup.bat (figure 14-3). Figure 14-3 Démarrage du serveur Tomcat Arrêt du serveur Pour arrêter le serveur Tomcat, il faut tout d’abord exécuter le script shutdown.bat situé dans le sous-répertoire bin de Tomcat. Une fois ceci fait, stoppez le serveur de base de données HSQLDB en exécutant le script stopdb.bat situé dans le répertoire {blazeds}/ sampledb. =Flex3 FM.book Page 268 Mardi, 2. décembre 2008 3:32 15 268 Comprendre Flex 3 PARTIE I Test d’installation Après avoir démarré le serveur Tomcat, il est possible de vérifier le bon fonctionnement de BlazeDS en saisissant l’URL suivante dans la barre d’adresse du navigateur web (figure 14-4) : http://localhost:8400/samples/. Cette adresse nous donne accès à une multitude d’applications de tests situées dans le répertoire webapps/samples de Tomcat. Nous vous laissons le soin de les découvrir avant d’entrer dans le détail de l’interaction entre le serveur BlazeDs et les méthodes de classe J2EE. Figure 14-4 Applications de tests Interaction avec les méthodes J2EE Étudions à présent le processus d’exécution d’une méthode J2EE ainsi qu’un exemple d’application qui vous permettra de mieux comprendre l’interaction entre une application Flex et cette classe Java. =Flex3 FM.book Page 269 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 269 Processus d’exécution Pour pouvoir exécuter une méthode J2EE (contenue dans une classe J2EE) à l’aide de BlazeDS, elle doit être connue du serveur. Pour cela, il convient de respecter une certaine organisation : Figure 14-5 Processus d’exécution d’une méthode J2EE =Flex3 FM.book Page 270 Mardi, 2. décembre 2008 3:32 15 270 Comprendre Flex 3 PARTIE I • Les classes J2EE doivent être déployées dans le répertoire {blazeds}\tomcat\webapps\ blazeDS\webapps\classes. • Les classes J2EE doivent ensuite être spécifiées dans le fichier remoting-config.xml, situé dans le répertoire {blazeds}\tomcat\webapps\blazeDS\WEB-INF\flex, qui joue le rôle de routeur vers les classes J2EE. Ce fichier contient ce que l’on appelle des destinations, pointant vers chaque classe présente sur le serveur BlazeDS. Le fichier remoting-config.xml est donc le point d’entrée de chaque requête de demande d’exécution de méthodes. Pour exécuter une méthode, il faut en quelque sorte montrer patte blanche en fournissant le nom de la destination ainsi que le nom de la méthode J2EE à exécuter. La présence de la destination dans le fichier remoting-config.xml est ensuite vérifiée. Si elle est bien détectée, la requête est redirigée vers la classe liée pour permettre la recherche et l’exécution de la méthode. La figure 14-5 résume ce processus. Exemple d’application Illustrons à présent ce concept, en créant notre propre méthode J2EE et en l’appelant dans un projet Flex. Le but de cette méthode sera d’additionner deux entiers et d’en retourner le résultat. Important Avant tout développement, nous vous conseillons d’arrêter les serveurs Tomcat et HSQLDB. En effet, ceci permet de faciliter le déploiement des applications. Même si le serveur est capable de déployer une application alors qu’il est toujours en fonctionnement, il est conseillé de l’arrêter, afin que le déploiement se réalise proprement. Création de la classe J2EE La première étape consiste à créer un fichier Java nommé ClasseJ2ee.java contenant la logique applicative de la méthode. Nous vous suggérons de créer ce fichier à la racine de votre disque dur à l’aide du Bloc-notes de Windows si vous ne disposez pas d’un environnement de développement Java. Néanmoins, si vous désirez utiliser Java et Flex de manière plus poussée, nous vous recommandons fortement d’installer sur votre poste un IDE tel que Eclipse ou NetBeans, car ils contiennent un ensemble de fonctionnalités propres au développement Java. Voici le code du fichier ClasseJ2ee.java : public class ClasseJ2ee{ // Méthode public int calculer (int a, int b) { return (a + b); } } =Flex3 FM.book Page 271 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 271 Une fois ce fichier créé, il convient de le compiler afin d’obtenir un fichier binaire portant l’extension .class, lequel sera ensuite déployé sur le serveur BlazeDS. 1. Ouvrez l’invite de commandes MS-DOS. 2. Placez-vous dans le répertoire du fichier Java précédemment créé. 3. Saisissez ensuite la commande de compilation suivante : javac ClasseJ2ee.java Le résultat de cette compilation est la création du fichier ClasseJ2ee.class. Notre classe créée, nous allons à présent procéder à la configuration du serveur BlazeDS. Configuration du serveur BlazeDS La configuration du serveur se déroule en deux étapes : la configuration du fichier « passerelle » remote-config.xml permettant d’orienter la requête d’exécution d’une méthode J2EE vers la classe Java la contenant, et le déploiement de la classe J2EE. Le fichier remoting-config.xml Comme nous l’avons vu, ce fichier, situé dans le répertoire {blazeds}\tomcat\webapps\ blazeds\WEB-INF\flex, permet de rediriger la requête de demande d’exécution de la méthode J2EE vers la classe qui la contient. <?xml version="1.0" encoding="UTF-8"?> <service id="remoting-service" class="flex.messaging.services.RemotingService"> <adapters> <adapter-definition id="java-object" class="flex.messaging.services ➥.remoting.adapters.JavaAdapter" default="true"/> </adapters> <default-channels> <channel ref="my-amf"/> </default-channels> <destination id="destJ2ee"> <properties> <source>ClasseJ2ee</source> <scope>application</scope> </properties> </destination> </service> Une nouvelle destination (destJ2ee) pointant vers notre classe ClasseJ2ee.class a été créée en spécifiant le nom de la classe dans la balise <source> des propriétés de la destination. =Flex3 FM.book Page 272 Mardi, 2. décembre 2008 3:32 15 272 Comprendre Flex 3 PARTIE I Déploiement de la classe J2EE Le déploiement de la classe J2EE consiste tout simplement à copier le fichier ClasseJ2ee .class dans le répertoire {blazeds}\tomcat\webapps\blazeds\WEB-INF\classes. Vous pouvez à présent redémarrer le serveur Tomcat afin de vous assurer qu’aucune erreur n’est survenue lors du chargement de la classe. Création du projet Flex Nous allons maintenant nous pencher sur la création du projet Flex. Il sera chargé de réaliser le front end de l’application et de faire appel à méthode J2EE : 1. Créez un nouveau projet Flex que vous nommerez BzJ2ee. 2. Dans la fenêtre qui s’ouvre alors (figure 14-6), sélectionnez la technologie serveur J2EE, puisque nous allons faire appel à une méthode J2EE. Activez également l’option LiveCycle Data Services, car BlazeDS se substitue à ce serveur. Cliquez sur le bouton Next. Figure 14-6 Configuration du projet =Flex3 FM.book Page 273 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 273 3. Précisez ensuite le chemin d’installation du serveur BlazeDS. Dans la mesure où nous n’allons pas utiliser LiveCycle Data Services, désactivez l’option Use default location for local LiveCycle Data Services Server et spécifiez les différents paramètres du serveur (figure 14-7) : – Root folder : {blazeds}\tomcat\webapps\blazeds ; – Root URL : http://localhost:8400/blazeds ; – Context root : /blazeds. Répertoire Le répertoire de compilation sera situé dans le répertoire {blazeds}\tomcat\webapps\blazeds et non dans le répertoire de l’application, comme c’est le cas habituellement. Figure 14-7 Configuration du serveur J2EE 4. Cliquez enfin sur le bouton Finish pour terminer la création du projet Flex. Notre projet créé, nous mettons en place l’interface graphique (figure 14-8). =Flex3 FM.book Page 274 Mardi, 2. décembre 2008 3:32 15 274 Comprendre Flex 3 PARTIE I <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel x="10" y="10" width="250" height="200" layout="absolute" title="Addition"> <mx:Form x="10" y="10" height="107" width="210" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:FormItem label="Entier A: "> <mx:TextInput width="78" id="txt_entiera"/> </mx:FormItem> <mx:FormItem label="Entier B:"> <mx:TextInput width="78" id="txt_entierb"/> </mx:FormItem> <mx:FormItem label="Résultat :"> <mx:TextInput width="79" id="txt_resultat"/> </mx:FormItem> </mx:Form> <mx:Button x="10" y="128" label="Calculer" width="210" /> </mx:Panel> </mx:Application> Figure 14-8 Interface graphique du projet La tâche suivante va consister à configurer le composant RemoteObject afin de réaliser l’appel de la méthode J2EE. Exécution de la méthode J2EE Maintenant que notre interface graphique est terminée, la dernière étape va consister à configurer le composant RemoteObject afin d’exécuter la méthode Java : <mx:RemoteObject id="roMethodeJ2ee" destination="destJ2ee" result="resultatOK(event)" fault="resultatKO(event)" showBusyCursor="true"> </mx:RemoteObject> =Flex3 FM.book Page 275 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 275 La propriété destination du composant RemoteObject doit prendre la valeur de la balise destination spécifiée dans le fichier remote-config.xml. En effet, c’est à partir de la concordance des deux propriétés que la méthode Java sera exécutée. La touche finale consiste à écrire les procédures ActionScript permettant de réaliser l’appel de la méthode Java : <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.controls.Alert; public function executerMethodeJ2ee():void { var a:int = int(txt_entiera.text); var b:int = int(txt_entierb.text); roMethodeJ2ee.calculer(a,b); } public function resultatOK(e:ResultEvent):void { txt_resultat.text = e.result.toString(); } public function resultatKO(e:FaultEvent):void { Alert.show(e.fault.faultString); } ]]> </mx:Script> Il convient par ailleurs de ne pas oublier de déclencher la procédure executerMethode J2ee() lorsque l’utilisateur clique sur le bouton Calculer : <mx:Button x="10" y="128" label="Calculer" width="210" click="executerMethodeJ2ee()"/> Test de l’application Pour tester l’application, assurez-vous tout d’abord que le serveur Tomcat est démarré, puis saisissez l’URL suivante dans la barre d’adresse de votre navigateur web : http://localhost:8400/blazeds/BzJ2ee-debug/BzJ2ee.html. Vous constatez que l’application est bien appelée et s’exécute correctement (figure 14-9). Nous venons de réaliser une première application faisant appel à une méthode Java. Le plus compliqué est de créer correctement la classe Java et la méthode et de configurer le serveur BlazeDS. L’appel du service via l’utilisation du composant RemoteObject reste, quant à lui, identique à ce que nous avons pu réaliser au chapitre précédent avec PHP. =Flex3 FM.book Page 276 Mardi, 2. décembre 2008 3:32 15 276 Comprendre Flex 3 PARTIE I Figure 14-9 Test de l’application Nous allons à présent aborder un autre aspect du serveur BlazeDS qui nous permet de créer des applications « communicantes ». Échanger des données en temps réel L’exemple le plus communément développé pour illustrer le mécanisme d’échange de données en temps réel avec le serveur BlazeDS est une application de messagerie instantanée (chat). Pour nous démarquer un peu, nous allons utiliser ce procédé, mais en en détourner l’usage, afin de réaliser une application capable de piloter un « robot » virtuel. Il sera matérialisé par un petit carré rouge au centre de l’interface graphique. L’utilisateur disposera de quatre boutons, représentant les quatre directions, qui lui permettront de déplacer le carré. Comme nous vous l’avons indiqué, nous allons utiliser le procédé de la messagerie instantanée pour piloter notre robot. Pour qu’une communication soit définie comme telle, la présence de deux interlocuteurs est nécessaire. Nous devons donc exécuter deux instances d’applications. Nous allons à nouveau utiliser une destination qui servira ici de point d’échange entre les deux applications. Chaque application sera connectée à cette destination afin d’en être à l’écoute et d’être informée des modifications apportées par chacune d’entre elles. L’échange est donc réalisé selon le principe suivant : 1. Une destination d’échange est créée sur le serveur. 2. Chaque application se connecte à cette destination et se met à son écoute. 3. L’application A envoie un message à la destination. 4. La destination reçoit le message. 5. L’application B, à l’écoute de la destination, est informée de la notification de réception d’un nouveau message et le récupère. 6. L’application B traite le message. C’est sur ce principe que nous allons offrir la possibilité à une application A de piloter le robot d’une application B et inversement. Chaque direction correspondra à une lettre : =Flex3 FM.book Page 277 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 277 • Haut : « H » ; • Bas : « B » ; • Droite : « D » ; • Gauche : « G ». Par ailleurs, nous devrons créer une destination sur le serveur et mettre à l’écoute les deux applications. Bien entendu, chaque application aura également la possibilité d’envoyer un message à la destination afin de faire bouger le robot. Ainsi, si l’application A envoie le message « H » à la destination, l’application B interceptera le message, l’analysera grâce à procédure d’analyse et déterminera que « H » signifie « déplacer le robot vers le haut ». Création du projet Pour commencer, nous allons créer un nouveau projet nommé robot. Nous procéderons de la même manière que pour créer un projet faisant appel à l’exécution d’une méthode J2EE, car nous allons avoir besoin du serveur BlazeDS pour permettre l’échange de données entre les applications. La première étape va consister à créer l’interface graphique : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel x="10" y="10" width="250" height="335" layout="absolute"> <mx:Canvas x="10" y="10" width="210" height="200" backgroundColor="#BFB5B5"> <!-- ROBOT --> <mx:Canvas x="90" y="81" width="30" height="30" backgroundColor="#F90101" ➥cornerRadius="5" borderStyle="solid" id="irobot"> </mx:Canvas> </mx:Canvas> <mx:Button <mx:Button <mx:Button <mx:Button x="82.5" y="218" label="Haut" width="70" id="btn_haut"/> x="82.5" y="263" label="Bas" width="70" id="btn_bas"/> x="153" y="241" label="Droite" width="70" id="btn_droite"/> x="10" y="241" label="Gauche" width="70" id="btn_gauche"/> </mx:Panel> </mx:Application> La composition de cette interface est assez simple (figure 14-10) : • un Canvas définissant le périmètre de déplacement du robot ; • un Canvas représentant le robot ; • quatre boutons représentant les quatre directions. =Flex3 FM.book Page 278 Mardi, 2. décembre 2008 3:32 15 278 Comprendre Flex 3 PARTIE I Figure 14-10 Interface de pilotage du robot Configuration du serveur La configuration du serveur consiste à créer dessus une destination. Pour cela, placez-vous tout d’abord dans le répertoire {blazeds}\tomcat\webapps\blazeds\WEB-INF\flex et ouvrez le fichier service-config.xml, fichier de configuration principal du serveur BlazeDS. Il fait appel au fichier messaging-config.xml : <services> <service-include file-path="remoting-config.xml"/> <service-include file-path="proxy-config.xml"/> <service-include file-path="messaging-config.xml"/> </services> C’est ce fichier qui va particulièrement nous intéresser, car c’est à cet endroit que nous allons créer notre destination. Avant d’en visualiser le contenu, poursuivons notre lecture du fichier service-config.xml et attardons-nous sur les lignes de code suivantes : <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/ ➥amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/> <properties> <polling-enabled>true</polling-enabled> <polling-interval-seconds>4</polling-interval-seconds> </properties> </channel-definition> Vous remarquez la présence du canal my-polling-amf. C’est lui qui sera utilisé pour l’échange de données en temps réel, car il est spécifié comme service par défaut dans le fichier messaging-config.xml. Notons que le temps de consultation de la destination est défini à 4 secondes. Pour plus de réactivité d’échange, il est possible de réduire cette valeur. =Flex3 FM.book Page 279 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 279 Intéressons-nous à présent au fichier messaging-config.xml. Comme nous venons de le spécifier, le canal utilisé par défaut est my-polling-amf. Notre travail va donc se résumer à créer une destination, que nous nommerons bougerrobot, et qui fera appel à ce canal de communication comme suit : <?xml version="1.0" encoding="UTF-8"?> <service id="message-service" class="flex.messaging.services.MessageService"> <adapters> <adapter-definition id="actionscript" class="flex.messaging.services ➥.messaging.adapters.ActionScriptAdapter" default="true" /> <!-- <adapter-definition id="jms" class="flex.messaging.services ➥.messaging.adapters.JMSAdapter"/> --> </adapters> <default-channels> <channel ref="my-polling-amf"/> </default-channels> <destination id="bougerrobot"/> </service> Le serveur est à présent correctement configuré. L’étape suivante consiste à implémenter les méthodes d’écoute et d’échange avec la destination. <mx:Producer> et <mx:Consumer> : les composants émetteurs et récepteurs Le composant <mx:Consumer> permet à l’application de se connecter à une destination afin d’en être à l’écoute et de réceptionner les messages qu’elle reçoit. À l’inverse, le composant <mx:Producer> permet de transmettre des messages à la destination. Nous allons donc utiliser ces composants pour nous connecter à la destination bougerrobot, afin de détecter d’une part tout message qui pourrait nous être transmis via une application distante, et d’autre part de communiquer avec elle. La communication sera donc bidirectionnelle : nous pourrons transmettre et recevoir des informations, ce qui nous permettra de piloter le robot de l’application distante, et l’utilisateur de cette application pourra à son tour piloter notre robot. Voici le code d’implémentation de l’écouteur : <mx:Consumer id="ecouteur" destination="bougerrobot" message="receptionner ➥(event.message)"/> Nous avons spécifié la destination d’écoute et une action à réaliser en cas de réception d’un message. Cette action permettra d’interpréter le message reçu et de déplacer le robot en conséquence. =Flex3 FM.book Page 280 Mardi, 2. décembre 2008 3:32 15 280 Comprendre Flex 3 PARTIE I Il convient également d’initialiser l’écoute dès la fin de la création de l’application en faisant appel à la méthode subscribe() du composant Consumer : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="emetteur.subscribe()"> Voyons à présent la mise en place de l’émetteur qui nous permettra de déplacer le robot de l’application distante : <mx:Producer id="emetteur" destination="bougerrobot"/> Nous avons simplement connecté l’émetteur à la destination bougerrobot. L’envoi du message sera réalisé grâce à la méthode send() du composant Producer dont nous allons voir de suite l’utilisation. Les procédures de communication Nous allons à présent mettre en place les procédures permettant de réaliser l’échange de données et d’interpréter le message reçu. Envoyer un message Comme nous venons de l’évoquer, l’envoi d’un message s’effectue via la méthode send() du composant Producer. Nous allons donc écrire une procédure, que nous nommerons envoyer(), qui transmettra à la destination bougerrobot la lettre correspondant à la direction de déplacement du robot choisi par l’utilisateur : <mx:Script> <![CDATA[ import mx.messaging.messages.AsyncMessage; import mx.messaging.messages.IMessage; private function envoyer(direction:String):void{ var messageAsynchrone:IMessage = new AsyncMessage(); messageAsynchrone.body.chatMessage = direction; emetteur.send(messageAsynchrone); } ]]> </mx:Script> Cette procédure crée un message asynchrone dont la propriété body.chatMessage contient la direction à transmettre à la destination. Cette dernière est alors avertie de la transmission d’un nouveau message. Voyons à présent comment récupérer ce message. Recevoir un message Lors de la mise en place du composant <mx:Consumer>, nous avons spécifié une action à réaliser à chaque réception d’un message de la part de la destination. Le code de cette action est le suivant : =Flex3 FM.book Page 281 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 281 private function receptionner(messageDestination:IMessage):void{ var directionRecue:String = messageDestination.body.chatMessage; switch (directionRecue) { case "G" : gauche(); break; case "D" : droite(); break; case "H" : haut(); break; case "B" : bas(); break; } } Nous récupérons la propriété body.chatMessage du message reçu et nous exécutons une procédure de déplacement en fonction de la lettre reçue. Pour terminer, voici le code des quatre procédures permettant de déplacer le robot : public function gauche():void { irobot.x = irobot.x-5 } public function droite():void { irobot.x = irobot.x+5 } public function haut():void { irobot.y = irobot.y-5 } public function bas():void { irobot.y = irobot.y+5 } Pour chaque destination, nous récupérons la position actuelle à laquelle nous ajoutons ou soustrayons 5 pixels. Libre à vous de modifier cette valeur en fonction de vos préférences. =Flex3 FM.book Page 282 Mardi, 2. décembre 2008 3:32 15 282 Comprendre Flex 3 PARTIE I Test de l’application Le moment est venu de tester notre application. Pour cela, exécutez-la deux fois dans votre navigateur web, afin de créer deux interlocuteurs. En cliquant sur les différents boutons de l’interface, nous voyons que l’échange des données s’effectue correctement (figure 14-11). Figure 14-11 Exécution de l’application En résumé Dans ce chapitre, nous avons abordé les deux principales opérations pouvant être réalisées à l’aide du serveur BlazeDS, à savoir l’appel de méthodes Java et l’échange de données entre plusieurs applications. Adobe mise beaucoup sur ce serveur en nous le proposant en Open Source malgré son offre de distribution du serveur LiveCycle Data Service ES. Néanmoins, BlazeDS ne permet pas d’effectuer l’ensemble des fonctionnalités proposées par son concurrent payant (citons par exemple la génération de fichiers PDF ou la présence d’options de déploiement avancées…). Vous êtes désormais en mesure de créer des applications dynamiques capables d’interagir avec la couche métier développée en Java, ce qui améliorera l’interactivité de vos applications en offrant la possibilité d’interaction entre deux applications Flex. =Flex3 FM.book Page 283 Mardi, 2. décembre 2008 3:32 15 BlazeDS : ouverture Open Source vers le monde J2EE et la communication d’applications CHAPITRE 14 283 Ce chapitre nous également permis d’approfondir notre étude des méthodes de communication avec la couche métier. Nous avons vu au chapitre précédent que pour communiquer avec la couche métier PHP, il convenait d’utiliser le protocole AMF couplé au composant RemoteObject afin d’obtenir des résultats plus concluants (rapidité, sérialisation des données…). Pour accéder aux méthodes Java, nous observons le même mode opératoire. Par conséquent, nous pouvons en déduire que le couple RemoteObject/AMF semble être le mode le plus approprié pour communiquer avec la couche métier à condition que celle-ci le permette. =Flex3 FM.book Page 284 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 285 Mardi, 2. décembre 2008 3:32 15 15 Créer des applications modulaires Au cours de ce chapitre, vous allez utiliser des modules applicatifs afin de les intégrer au sein d’une application Flex. La notion de module Un module est une application (fichier .swf) proposant un certain nombre de fonctionnalités pouvant être intégrées à une autre application. En d’autres termes, si nous considérons qu’une application Flex est un puzzle, un module est une pièce le constituant. Les modules ne sont pas indépendants : ils ont impérativement besoin d’une application pour pouvoir être exécutés. Il existe de nombreux avantages à l’utilisation de modules : • une diminution de la taille de l’application principale ; • une diminution du temps de chargement de l’application ; • un découpage applicatif (module de comptabilité, module de vente en ligne…) ; • une meilleure maintenance de l’application : chaque module étant indépendant, il est possible d’y apporter des modifications sans remettre en cause la stabilité complète de l’application ; • une optimisation de la performance d’exécution de l’application : le module peut être chargé et déchargé à volonté. Un module se crée à partir d’un fichier MXML, tout comme une application Flex standard, à la différence que la balise <mx:Application> est remplacée par la balise <mx:Module>. =Flex3 FM.book Page 286 Mardi, 2. décembre 2008 3:32 15 286 Comprendre Flex 3 PARTIE I C’est le seul élément qui différencie un module d’une application. Il est ensuite possible d’y placer des composants et d’y décrire des procédures ActionScript, tout comme nous le ferions pour une application Flex. Créer un module Afin de mieux comprendre la notion de module, nous vous proposons d’en créer un qui soit capable de déterminer le nombre de caractères d’une chaîne saisie dans une zone de texte. Voici la marche à suivre pour cela : 1. Créez un nouveau projet Flex à l’aide de Flex Builder 3 nommé module. 2. Dans ce projet, créez ensuite un fichier de type MXML Module, que vous nommerez modLettre, en effectuant un clic droit sur le nom du projet et en sélectionnant New. 3. Dans la fenêtre qui s’ouvre alors, assurez-vous que l’option Do not optimize (module can be loaded by multiple applications) est bien cochée afin que le module puisse s’exécuter sur plusieurs applications (figure 15-1). Figure 15-1 Création d’un module =Flex3 FM.book Page 287 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 287 Notre module est désormais créé. Il convient à présent d’implémenter les composants et procédures nécessaires à la réalisation de la tâche demandée (figure 15-2) : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" ➥height="300"> <mx:Panel x="10" y="11" width="380" height="141" layout="absolute" title="Nombre de ➥lettres"> <mx:TextInput x="10" y="10" width="340" id="chaine_txt"/> <mx:TextInput x="190" y="40" id="resultat_txt"/> <mx:Button x="10" y="40" label="Calculer" click="resultat_txt.text = ➥String(chaine_txt.length)" id="btn_calculer"/> </mx:Panel> </mx:Module> Figure 15-2 Interface graphique du module Ainsi, quelques clics de souris et lignes de code suffisent pour créer un module entièrement fonctionnel et prêt à être utilisé. Mais, avant cela, il convient de le compiler et de créer une version de déploiement. 1. Effectuez un clic droit sur le nom du projet et sélectionnez Export. 2. Dans la fenêtre qui s’ouvre alors, indiquez que vous souhaitez réaliser une version de déploiement (build release) en veillant à ne pas modifier les options spécifiées par défaut. =Flex3 FM.book Page 288 Mardi, 2. décembre 2008 3:32 15 288 Comprendre Flex 3 PARTIE I À l’issue de l’exportation, vous pouvez voir qu’un nouveau dossier bin-release est apparu dans l’arborescence du projet. Il contient le fichier modLettre.swf correspondant à la version de déploiement du module. Voyons à présent comment intégrer ce module dans une nouvelle application. Intégrer un module dans une application Nous allons ici créer un nouveau projet puis ajouter, dans son répertoire src, un dossier modules qui contiendra l’ensemble des modules de notre application. Nous copierons ensuite dans ce dossier le module du répertoire bin-release du précédent projet, puis nous l’intégrerons à notre projet. Charger les modules à l’aide du composant ModuleLoader Pour charger un module dans une application, la première méthode consiste à utiliser le composant ModuleLoader comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ModuleLoader id="module" url="modules/modLettre.swf" > </mx:ModuleLoader> </mx:Application> Grâce à la propriété url, nous spécifions le chemin du module permettant de le charger automatiquement. Cependant, il est possible de gérer de façon plus poussée le chargement des modules grâce à ActionScript, ce que nous allons voir dans la section suivante. Gestion des modules avec ActionScript Nous allons ici aborder la gestion du chargement/déchargement de modules à l’aide du langage ActionScript. Charger un module Le chargement d’un module s’effectue très simplement à l’aide de la méthode loadModule() du composant ModuleLoader : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ =Flex3 FM.book Page 289 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 289 import mx.modules.*; public function chargerModule(adresse:String):void{ // Adresse du module chargeurModule.url = adresse; // Chargement du module chargeurModule.loadModule(); } ]]> </mx:Script> <mx:ModuleLoader id="chargeurModule"> </mx:ModuleLoader> <mx:Button x="427" y="10" label="Charger" id="btn_chargerModule" ➥click="chargerModule('modules/modLettre.swf')"/> </mx:Application> Décharger un module Pour décharger un module, il suffit d’utiliser la méthode unload() du composant Module Loader comme suit : public function dechargerModule():void{ // Déchargement du module chargeurModule.unloadModule(); } Gérer les erreurs de chargement La plupart des erreurs surviennent lors du chargement du module. Nous allons voir comment les intercepter afin d’en avertir l’utilisateur et de prévenir tout désagrément. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.modules.*; import mx.events.ModuleEvent; import mx.controls.Alert; public function chargerModule(adresse:String):void{ =Flex3 FM.book Page 290 Mardi, 2. décembre 2008 3:32 15 290 Comprendre Flex 3 PARTIE I // Adresse du module chargeurModule.url = adresse; // Chargement du module chargeurModule.loadModule(); } public function interceptionErreur(e:ModuleEvent):void{ Alert.show ("Erreur lors du chargement du module : "+e.errorText); } ]]> </mx:Script> <mx:ModuleLoader id="chargeurModule" error="interceptionErreur(event)"> </mx:ModuleLoader> <mx:Button x="427" y="10" label="Charger" id="btn_chargerModule" ➥click="chargerModule('modules/modLettres.swf')"/> </mx:Application> L’exécution de la procédure interceptionErreur() n’est déclenchée que lorsque le composant ModuleLoader rencontre une erreur (grâce au paramètre error du ModuleLoader). La procédure reçoit alors en paramètre l’événement qui déclenche l’erreur et nous permet d’en afficher la description (figure 15-3). Figure 15-3 Interception des erreurs de chargement Afficher la progression du chargement Quoi de plus désagréable pour un utilisateur que d’attendre devant une page blanche sans savoir ce qui se passe ? Pour lui éviter cela, il est possible de déterminer l’état d’avancement du chargement du module en se « connectant », par l’usage du terme [Bindable] (voir le chapitre 11), à la propriété progress du composant ModuleLoader : =Flex3 FM.book Page 291 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.modules.*; import mx.events.ModuleEvent; import mx.controls.Alert; public function chargerModule(adresse:String):void{ // Adresse du module chargeurModule.url = adresse; // Chargement du module chargeurModule.loadModule(); } [Bindable] public var texte:String public function afficherProgression(e:ProgressEvent):void { // Taille du module var tailleModule:Number = e.bytesTotal; // Nombre d’octets chargés var nbOctets:Number = e.bytesLoaded; // Calcul du pourcentage de chargement var pourcentage:Number = Math.round((nbOctets/tailleModule)*100) // Affichage du texte texte = String(pourcentage)+"%"; } ]]> </mx:Script> <mx:ModuleLoader id="chargeurModule" progress="afficherProgression(event)"> </mx:ModuleLoader> <mx:Button x="427" y="10" label="Charger" id="btn_chargerModule" ➥click="chargerModule('modules/modLettre.swf')"/> <mx:Panel x="10" y="226" width="401" height="97" layout="absolute" title="Affichage ➥du chargement" id="panel_1"> <mx:Text x="98" y="23" width="222" id="progression_txt" text="{texte}"/> <mx:Label x="10" y="23" text="% Chargé :" width="80"/> </mx:Panel> </mx:Application> 291 =Flex3 FM.book Page 292 Mardi, 2. décembre 2008 3:32 15 292 Comprendre Flex 3 PARTIE I La procédure afficherProgression() est déclenchée à chaque fois que le taux de chargement du module augmente. Par ailleurs, l’événement ProgressEvent nous permet de capturer le nombre d’octets chargés, nous pouvons ainsi déterminer le pourcentage de chargement du module et l’afficher dans une zone de texte (figure 15-4). Figure 15-4 Affichage de la progression du chargement Interagir avec le module Pour pouvoir interagir avec le module depuis l’application, nous devons utiliser une interface qui servira de passerelle permettant l’accès aux méthodes du module. Cet accès est possible car l’interface elle-même connaît l’ensemble des méthodes. La figure 15-5 illustre le processus de communication entre une application et un module : Figure 15-5 Notion d’interface 1. L’application fait appel à une procédure du module. Pour cela elle s’adresse à l’interface qui est liée au module. 2. L’interface recherche l’existence de la procédure parmi celles contenues dans sa liste. Si la procédure est trouvée, l’interface demande son exécution au module. 3. Le module exécute la procédure demandée. Nous allons à présent modifier le module pour y implanter une procédure chargée d’alimenter le champ chaine_txt. Notez que toutes les modifications à apporter devront être effectuées dans le projet module car une nouvelle compilation du module sera nécessaire. =Flex3 FM.book Page 293 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 293 <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" ➥height="300"> <mx:Script> <![CDATA[ [Bindable] public var texte:String public function set chaine(param:String):void { texte = param; } ]]> </mx:Script> <mx:Panel x="10" y="11" width="380" height="141" layout="absolute" title="Nombre de ➥lettres"> <mx:TextInput x="10" y="10" width="340" id="chaine_txt" text="{texte}"/> <mx:TextInput x="190" y="40" id="resultat_txt"/> <mx:Button x="10" y="40" label="Calculer" click="resultat_txt.text = ➥String(chaine_txt.length)" id="btn_calculer"/> </mx:Panel> </mx:Module> La propriété text du champ chaine_txt est liée à la variable texte. Cette dernière est mise à jour à l’aide de la méthode set chaine(param:String):void impliquant une actualisation du champ chaine_txt par la notion de DataBinding reliant la propriété text de ce champ à la variable texte. L’étape suivante consiste à créer l’interface permettant de réaliser la communication entre l’application et le module. Pour cela, il suffit de créer un nouveau fichier ActionScript Interface, nommé InterfaceModule, héritant de la classe IEventDispatcher, et d’y insérer le code suivant : package { import flash.events.IEventDispatcher; public interface InterfaceModule extends IEventDispatcher { function set chaine(param:String):void; } } L’héritage de la classe IEventDispatcher est utile afin d’intercepter les appels aux procédures du module et de les dispatcher correctement. Cette répartition est effectuée parmi les =Flex3 FM.book Page 294 Mardi, 2. décembre 2008 3:32 15 294 Comprendre Flex 3 PARTIE I procédures spécifiées dans l’interface, dont la déclaration doit être identique à celle effectuée dans le module (en excluant leur visibilité publique/privée, figure 15-6). Figure 15-6 Similitude des déclarations de procédure Enfin, il nous reste à établir la liaison entre l’interface et le module en modifiant la propriété implements de ce dernier : <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" ➥height="300" implements="InterfaceModule"> La première étape est terminée, il convient à présent de recompiler le module et d’en réaliser une version de déploiement, comme expliqué précédemment. 1. Créez un nouveau projet Flex. 2. Après avoir copié les fichiers modLettre.swf, modLettre.mxml et interfaceModule.as du projet module dans le répertoire src de notre nouveau projet, éditez le fichier MXML comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; public function chargerModule(module:String):void { chargeurModule.url = module; chargeurModule.loadModule(); } public function finChargementModule(e:ModuleEvent):void { var chargeur:ModuleLoader = e.target as ModuleLoader; var connexionInterface:* = chargeur.child as InterfaceModule; if( connexionInterface != null ) { =Flex3 FM.book Page 295 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 295 connexionInterface.chaine = "Message à afficher"; } } ]]> </mx:Script> <mx:ModuleLoader id="chargeurModule" ready="finChargementModule(event)"> ➥</mx:ModuleLoader> <mx:Button id="btn_charger" x="468" y="10" label="Charger" ➥click="chargerModule('modLettre.swf')"/> </mx:Application> La procédure chargerModule est appelée lorsque l’utilisateur clique sur le bouton Charger. Elle a pour fonction de charger le module modLettre.swf dans le composant ModuleLoader. Une fois celui-ci chargé, la procédure finChargementModule est exécutée, laquelle établit une connexion avec l’interface et fait appel à la procédure chaine() du module en passant en paramètre la chaîne « Message à afficher ». Le résultat obtenu est illustré par la figure 15-7. Figure 15-7 Résultat concluant de la communication avec le module depuis l’application Interagir avec l’application Nous allons à présent voir qu’il est également possible de communiquer avec l’application à partir du module. Pour cela, nous allons quelque peu modifier le code de notre module : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" ➥height="300" implements="InterfaceModule"> <mx:Script> <![CDATA[ [Bindable] public var texte:String public function set chaine(param:String):void =Flex3 FM.book Page 296 Mardi, 2. décembre 2008 3:32 15 296 Comprendre Flex 3 PARTIE I { texte = param; } public function envoyerResultat():void { parentApplication.resultatCalcul(texte.length); } ]]> </mx:Script> <mx:Panel x="10" y="11" width="380" height="141" layout="absolute" title="Nombre de ➥lettres"> <mx:TextInput x="10" y="10" width="340" id="chaine_txt" text="{texte}"/> <mx:TextInput x="190" y="40" id="resultat_txt"/> <mx:Button x="10" y="40" label="Calculer" click="envoyerResultat()" ➥id="btn_calculer"/> </mx:Panel> </mx:Module> Grâce à la propriété parentApplication, il nous est possible de faire appel à une procédure déclarée dans l’application contenant le module. C’est ainsi que nous appellerons la procédure resultatCalcul() de l’application que nous allons à présent implémenter : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; public function chargerModule(module:String):void { chargeurModule.url = module; chargeurModule.loadModule(); } public function finChargementModule(e:ModuleEvent):void { var chargeur:ModuleLoader = e.target as ModuleLoader; var connexionInterface:* = chargeur.child as InterfaceModule; if( connexionInterface != null ) { connexionInterface.chaine = "Message a afficher"; } } [Bindable] =Flex3 FM.book Page 297 Mardi, 2. décembre 2008 3:32 15 Créer des applications modulaires CHAPITRE 15 297 private var resultat:String public function resultatCalcul(param:int):void{ resultat = String(param); } ]]> </mx:Script> <mx:ModuleLoader id="chargeurModule" ready="finChargementModule(event)"> ➥</mx:ModuleLoader> <mx:Button id="btn_charger" x="468" y="10" label="Charger" ➥click="chargerModule('modLettre.swf')"/> <mx:TextInput x="468" y="40" id="resultatCalcul_txt" text="{resultat}"/> </mx:Application> Après avoir recréé une version de déploiement du module et copié les fichiers modLettre .swf et modLettre.mxml dans l’application, nous pouvons la tester afin de vérifier que la communication entre le module et l’application s’effectue correctement (figure 15-8). Figure 15-8 Résultat de la communication entre le module et l’application En résumé La création et l’implémentation d’un module s’effectuent très facilement grâce à l’emploi du composant ModuleLoader. Nous avons également vu qu’il est possible d’interagir avec le module depuis l’application et inversement. En organisant l’architecture de vos applications sous forme de modules, vous allez pouvoir en améliorer la qualité en réduisant leur délai de chargement et en optimisant leur exécution. =Flex3 FM.book Page 298 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 299 Mardi, 2. décembre 2008 3:32 15 16 Interagir avec le conteneur web Jusqu’à présent, nous avons réduit l’espace de communication d’une application Flex à elle-même. Cependant, il n’est pas inconcevable d’imaginer une application Flex intégrée au sein d’une application web statique afin d’offrir des fonctionnalités plus évoluées et de communiquer avec celle-ci. C’est pourquoi, nous avons décidé de consacrer un chapitre à l’étude de cette communication. Nous aborderons tout d’abord la notion de deep linking qui va nous permettre de naviguer au sein de notre application à l’aide des boutons Précédent et Suivant du navigateur, comme nous pourrions le faire avec une application web standard. Nous étudierons ensuite la classe ExternalInterface et la bibliothèque Flex-Ajax Bridge, qui nous permettront de réaliser un canal de communication entre une application Flex et son conteneur web. La notion de deep linking Les applications Flash n’offrent pas la possibilité de se déplacer dans l’application à l’aide du navigateur. En effet, les boutons Précédent et Suivant sont dans ce cas inactifs, ce qui peut dérouter certains utilisateurs habitués à utiliser ce moyen de navigation au sein des applications web classiques. Grâce au deep linking, ce problème est désormais résolu et l’utilisateur peut naviguer au sein de l’application Flex à l’aide de ces boutons. Principe de fonctionnement Le principe de base est assez simple, car il consiste à enregistrer toute action réalisée dans l’application dans l’URL de la page qui la contient. Étant donné que le navigateur =Flex3 FM.book Page 300 Mardi, 2. décembre 2008 3:32 15 300 Comprendre Flex 3 PARTIE I enregistre l’historique des URL utilisées, lorsque l’utilisateur cliquera sur les boutons Précédent ou Suivant, l’URL archivée sera affichée. En analysant cette URL, nous pourrons alors déterminer l’action correspondante et la partie de l’application associée. Voyons ceci à travers un exemple. Imaginons une application composée d’un état principal et d’un état secondaire héritant de l’état principal. Un bouton situé sur l’état de base permet d’accéder à l’état suivant, soit l’état sécondaire. La figure 16-1 illustre le fonctionnement de cette application, que nous pouvons détailler comme suit : Étape ➊ : à l’initialisation de l’application, son URL se termine par le caractère dièse (#), ce qui indique qu’il s’agit de la racine du site. Étape ➋ : lorsque l’utilisateur clique sur le bouton Passer à la vue 2, l’état secondaire s’affiche à l’écran. Étape ➌ : nous ajoutons alors une information dans l’URL de l’application qui nous servira de clé de navigation, à savoir vue2 (le nom attribué à cette clé est à la libre appréciation du développeur). Étape ➍ : si l’utilisateur clique à présent sur le bouton Précédent, l’URL affichée correspond à celle de la racine du site. Figure 16-1 Principe du deep linking =Flex3 FM.book Page 301 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 301 Étape ➎ : dans notre application Flex, nous allons extraire cette information et l’analyser : • si la clé est vide, nous afficherons l’état de base de l’application ; • si la clé est égale à la valeur vue2, nous afficherons l’état secondaire. Comme la clé est vide (DeepLinking.html#), nous affichons l’état de base de l’application. Étape ➏ : si l’utilisateur clique à présent sur le bouton Suivant de son navigateur, l’URL affichée comporte la clé vue2 (DeepLinking.html#vue2). L’analyse de cette clé par l’application Flex aura pour résultat l’affichage de l’état secondaire. Passons à présent à la mise en pratique de ce concept. Navigateurs compatibles Les navigateurs permettant d’utiliser la notion de deep linking sont : • Internet Explorer 6 ; • Internet Explorer 7 ; • Firefox ; • Safari ; • Google Chrome. Mise en pratique du deep linking Nous allons à présent nous pencher sur le concept de deep linking en développant l’application dont nous venons de décrire le fonctionnement, afin de concrétiser cette nouvelle notion. Configuration du projet Pour commencer, il convient de créer un nouveau projet Flex et de vérifier que la navigation à l’aide des boutons Précédent et Suivant du navigateur est activée pour le projet. Pour cela, rendez-vous dans les propriétés de votre projet en réalisant un clic droit sur celui-ci, et dans la rubrique Flex Compiler, activez l’option Enable integration with browser navigation (figure 16-2). En activant cette option, vous indiquez que les fichiers history.css et history.js devront être utilisés lors de la création du conteneur web, dont la fonction principale est de permettre l’exécution du deep linking. // Extrait du fichier HTML généré chargé de contenir l’application <!-- BEGIN Browser History required section --> <link rel="stylesheet" type="text/css" href="history/history.css" /> <!-- END Browser History required section --> <!-- BEGIN Browser History required section --> <script src="history/history.js" language="javascript"></script> <!-- END Browser History required section --> =Flex3 FM.book Page 302 Mardi, 2. décembre 2008 3:32 15 302 Comprendre Flex 3 PARTIE I Figure 16-2 Configuration du projet Création de l’interface graphique Notre projet étant à présent créé et correctement configuré, nous allons créer l’état principal et l’état secondaire de l’application comme suit : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> < !-- Bouton permettant de passer à l’état suivant --> <mx:Button label="Passer à la vue 2" id="button1" click="currentState='vue2'" ➥x="46" y="21"/> <mx:states> < !—- État secondaire --> <mx:State name="vue2"> <mx:RemoveChild target="{button1}"/> <mx:AddChild position="lastChild"> <mx:Label text="vue 2" x="32" y="10" width="81" fontWeight="bold" ➥fontSize="15"/> </mx:AddChild> </mx:State> </mx:states> </mx:Application> =Flex3 FM.book Page 303 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 303 À l’écoute du navigateur Comme nous l’avons vu, la notion de deep linking est essentiellement basée sur l’échange d’informations entre le navigateur et l’application. Pour réaliser cet échange, nous allons utiliser les éléments suivants : • La classe BrowserManager du package mx.manager permettant d’établir la communication avec le navigateur. • L’interface IBrowserManager du package mx.manager, qui va utiliser l’instance de la classe BrowserManager, et permettre de réaliser l’ensemble des opérations sur l’URL de la page affichée dans le navigateur. • La classe BrowserChangeEvent du package mx.events permettant d’intercepter tout événement réalisé à l’aide des méthodes de l’interface IBrowserManager sur l’URL de la page affichée dans le navigateur. Le code suivant illustre l’implémentation de ces éléments : <mx:Script> <![CDATA[ import mx.events.BrowserChangeEvent; import mx.managers.IBrowserManager; import mx.managers.BrowserManager; ]]> </mx:Script> Nous pouvons à présent saisir le code permettant de gérer le deep linking : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" ➥creationComplete="initialiserUrl()" layout="absolute"> <mx:Button label="Passer à la vue 2" id="button1" click="currentState='vue2'; ➥modifierURL('vue2')" x="46" y="21"/> <mx:states> <mx:State name="vue2"> <mx:RemoveChild target="{button1}"/> <mx:AddChild position="lastChild"> <mx:Label text="vue 2" x="32" y="10" width="81" fontWeight="bold" ➥fontSize="15"/> </mx:AddChild> </mx:State> </mx:states> <mx:Script> <![CDATA[ import mx.events.BrowserChangeEvent; import mx.managers.IBrowserManager; import mx.managers.BrowserManager; // Déclaration d’une variable permettant de stocker l’instance // de la classe BrowserManager public var navigateur:IBrowserManager; =Flex3 FM.book Page 304 Mardi, 2. décembre 2008 3:32 15 304 Comprendre Flex 3 PARTIE I // A -- Procédure exécutée à l’initialisation de l’application private function initialiserUrl():void { // Récupération de l’instance du navigateur navigateur = BrowserManager.getInstance(); // Initialisation de l’URL du navigateur navigateur.init(""); // Vide = # // Déclenchement d’un événement à chaque changement de la valeur de l’URL // du navigateur navigateur.addEventListener(BrowserChangeEvent.BROWSER_URL_CHANGE, ➥actionSurUrl); } // B -- Procédure permettant d’ajouter des clés de navigation private function modifierURL(parametre:String):void { navigateur.setFragment(parametre); } // C -- Procédure d’analyse de l’URL du navigateur // déclenchée à chaque modification de l’URL du navigateur private function actionSurUrl(event:Event):void{ // Récupération de la clé de navigation var parametre:String = navigateur.fragment; // En fonction de la clé, on affiche l’état correspondant if (parametre=="") { currentState=""; } else { currentState='vue2'; } } ]]> </mx:Script> </mx:Application> Exécutons à présent notre application et étudions son fonctionnement. La première action réalisée est l’initialisation de l’application par la procédure initialiserUrl(), qui va récupérer l’instance de la classe BrowserManager et l’affecter à la variable navigateur. Cette instance correspond au navigateur utilisé par l’application en cours d’exécution. Nous profitons également de cette initialisation pour placer un écouteur d’événement qui =Flex3 FM.book Page 305 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 305 déclenchera l’action actionSurUrl à chaque changement de la valeur de l’URL du navigateur. Cet écouteur a un rôle primordial dans la notion de deep linking car c’est grâce à lui qu’il nous sera possible d’intercepter les changements d’URL déclenchés par l’utilisation des boutons Précédent et Suivant du navigateur et d’en afficher la vue associée. Enfin, l’initialisation se termine par l’utilisation de la méthode init("")qui va ajouter le caractère dièse (#) à la fin de l’URL de l’application, signifiant que nous sommes à la racine du site. Si nous cliquons sur le bouton Passer à la vue 2, la procédure modifierUrl est exécutée. Cette procédure permet d’ajouter une clé de navigation à l’URL du navigateur (#vue2). Cet ajout est réalisé à l’aide de la procédure setFragment de l’interface IBrowserManager, qui est chargée d’ajouter la valeur qui lui est passée en paramètre à la suite du dièse de l’URL : #cléDeNavigation. Si nous cliquons à présent sur le bouton Précédent de notre navigateur, cela déclenche une modification de l’URL qui est interceptée par l’écouteur que nous avons mis en place. Cet écouteur déclenche alors l’exécution de la procédure actionSurUrl, qui analyse la clé de navigation (via la méthode getFragment() de l’interface IBrowserManager) et affiche l’état correspondant à cette clé. Modifier le titre du navigateur Pour modifier le titre du navigateur, il est possible d’utiliser la méthode setTitle("titreAAfficher") de l’interface IbrowserManager. Déploiement du projet Comme nous l’avons vu lors de la phase de configuration du projet, le deep linking n’est possible que si les fichiers permettant cette fonctionnalité sont présents dans le répertoire de l’application. Par conséquent, lors de la phase de déploiement, il convient de ne pas omettre ces fichiers et de les placer dans le répertoire history (situé par défaut dans le répertoire bin-debug de l’application) à l’endroit où se trouve le conteneur web de l’application Flex. Communiquer avec le conteneur web Jusqu’à présent, nous avons réalisé des applications autonomes, mais il peut arriver qu’une application soit développée à l’aide du framework Flex dans le but de dynamiser l’aspect graphique d’une page statique. Nous vous proposons ici d’étudier une telle application à travers un exemple. L’application Flex sera chargée de lister les produits d’un site marchand dans un composant DataGrid ou autre. Lorsque l’utilisateur sélectionnera l’un des produits, ses caractéristiques devront être communiquées et affichées dans la page contenant l’application. Cet exemple vous permettra de voir comment il est possible d’interagir avec le conteneur de l’application mais aussi comment communiquer avec l’application à partir de ce conteneur. =Flex3 FM.book Page 306 Mardi, 2. décembre 2008 3:32 15 306 Comprendre Flex 3 PARTIE I Ainsi, l’exemple que nous allons mettre en place va consister dans un premier temps à saisir deux nombres dans une application Flex. Ces deux nombres seront ensuite envoyés à une fonction présente dans la page HTML chargée d’en effectuer la somme. Dans un second temps, ce travail sera délégué à l’application Flex qui recevra en paramètres les données saisies dans la page HTML. De l’application Flex vers le conteneur web Comme nous venons de le préciser, l’addition des deux nombres sera effectuée par une fonction JavaScript de la page contenant notre application Flex. La première chose à faire est donc de créer l’application et d’étudier comment il est possible d’appeler cette fonction. Création du projet Flex Pour commencer, créez un nouveau projet Flex que vous nommerez JsFlex. Ajoutez ensuite les lignes de code suivantes à ce projet : <?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥height="374" width="328"> <mx:Script> <![CDATA[ // Importation de la classe ExternalInterface import flash.external.ExternalInterface; // Procédure d’appel de la fonction JavaScript // Passage en paramètres des nombres A et B public function calculJavascript():void{ if (ExternalInterface.available) { var procedureJavascript:String = "calculerSomme" var s:String = ExternalInterface.call(procedureJavascript, ➥Number(txt_a.text), Number(txt_b.text)); } } ]]> </mx:Script> <mx:Panel width="313" height="177" layout="absolute" x="10" y="10" title="Flex -> ➥Conteneur Web" id="pAddition"> <mx:Form x="10" y="10" width="273" height="82" verticalScrollPolicy="off" ➥horizontalScrollPolicy="off"> <mx:FormItem label="Nombre A :"> <mx:TextInput id="txt_a"/> </mx:FormItem> =Flex3 FM.book Page 307 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 307 <mx:FormItem label="Nombre B :"> <mx:TextInput id="txt_b"/> </mx:FormItem> </mx:Form> <mx:Button id="btnCalculer" x="10" y="100" label="Calculer" width="273" ➥click="calculJavascript()"/> </mx:Panel> </mx:Application> La première étape consiste à importer la classe ExternalInterface du package flash.external qui va nous permettre de communiquer avec la page HTML. Nous déclarons ensuite la procédure calculJavascript dont le principe est le suivant : si une communication peut être établie avec la page HTML, nous faisons alors appel à la procédure JavaScript nommée calculerSomme() en prenant soin de lui passer en paramètres les deux nombres A et B nécessaires à sa bonne exécution. Vient ensuite l’écriture de la description de l’interface graphique qui se résume à l’implémentation d’un composant Panel contenant deux zones de saisie ainsi que les libellés de ces dernières au sein d’un formulaire. Enfin, le bouton btnCalculer est inséré afin de permettre l’appel de la procédure calculerSomme lorsque l’utilisateur clique dessus. Pour tester le projet, il convient tout d’abord d’exporter l’application Flex vers une version de déploiement située dans le répertoire bin-release du projet : 1. Effectuez un clic droit sur le nom du projet et sélectionnez Export dans le menu contextuel qui s’affiche alors. 2. Choisissez ensuite Release Build et poursuivez en acceptant les options par défaut. Nous ne nous étendrons pas d’avantage sur la création de la version de déploiement du projet à l’aide de Flex Builder. Pour plus de renseignements à ce sujet, reportez-vous au chapitre 18 de cet ouvrage. Si tout s’est déroulé correctement, vous devriez être en possession d’un fichier SWF nommé JsFlex.swf et situé dans le répertoire bin-release de votre projet. Nous pouvons à présent nous consacrer à la réalisation du fichier HTML qui servira de conteneur à notre application et hébergera la fonction JavaScript qu’il nous faudra également développer. Création de la page HTML Nous allons à présent créer un nouveau fichier HTML dans le répertoire bin-release de notre projet que nous nommerons index.html. Pour ce faire, il suffit d’effectuer un clic droit sur le répertoire bin-release, de sélectionner New>File et de spécifier le nom du fichier HTML à créer, soit index.html. Une fois cela fait, passons à l’écriture du conteneur : <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/1998/REC➥html40-19980424/strict.dtd"> <html> =Flex3 FM.book Page 308 Mardi, 2. décembre 2008 3:32 15 308 Comprendre Flex 3 PARTIE I <head> <title>Calcul de sommes </title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript"> function calculerSomme(a,b) { var nombreA = new Number(a); var nombreB = new Number(b); var total = a+b; document.getElementById("id_total").setAttribute("value",total); } </script> </head> <body> <p> <object id="fichierSWF" type="application/x-shockwave-flash" data="JsFlex.swf" ➥width="328" height="374"> <param name="src" value="JsFlex.swf"> <param name='flashVars' value=''/> </object> </p> <h1>Application Flex -> Conteneur web</h1> <label>Somme des deux nombres : </label> <input type="text" id="id_total" name="id_total" value=""/> </body> </html> Notre fichier est constitué de la procédure JavaScript calculerSomme, dont le rôle est de récupérer les deux nombres passés en paramètres, d’en effectuer la somme et d’afficher le résultat dans la zone de texte id_total. Soulignons également la présence de la balise <object>, qui contient notre application. Tout semble à présent fonctionnel. Pour nous en assurer, il suffit d’appeler la page du conteneur HTML via son URL, par exemple http://localhost/FLEX_3/JsFlex/bin-release/. La figure 16-3 illustre le résultat obtenu. Conseil Notez que cette URL doit être adaptée à votre configuration. Pour cet exemple, FLEX_3 correspond à notre espace de travail Flex Builder et JsFlex représente le nom du projet. Nous allons à présent voir comment réaliser l’opération inverse, c’est-à-dire appeler une fonction ActionScript à partir du conteneur web. =Flex3 FM.book Page 309 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 309 Figure 16-3 Interaction entre l’application Flex et le conteneur web Du conteneur web vers l’application Flex Nous allons quelque peu modifier notre fichier HTML en lui ajoutant un formulaire, deux zones de saisie, une procédure JavaScript faisant appel à une procédure ActionScript de notre application Flex, et un bouton permettant de déclencher l’appel à cette procédure. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/1998/REC➥html40-19980424/strict.dtd"> <html> <head> <title>Calcul de somme !</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript"> function calculerSomme(a,b) { var nombreA = new Number(a); var nombreB = new Number(b); var total = a+b; ‰document.getElementById("id_total").setAttribute("value",total); } =Flex3 FM.book Page 310 Mardi, 2. décembre 2008 3:32 15 310 Comprendre Flex 3 PARTIE I function appelProcedureFlex() { var nombreA = parseInt(document.getElementById("nb_a") ➥.getAttribute("value")); var nombreB = parseInt(document.getElementById("nb_b") ➥.getAttribute("value")); document.getElementById("fichierSWF").calculerSomme(nombreA,nombreB); } </script> </head> <body> <p> <object id="fichierSWF" type="application/x-shockwave-flash" data="JsFlex.swf" ➥width="328" height="374"> <param name="src" value="JsFlex.swf"> <param name='flashVars' value=''/> </object> </p> <h1>Application Flex -> Conteneur web</h1> <label>Somme des deux nombres : </label> <input type="text" id="id_total" name="id_total" value=""/> <hr/> <form onSubmit="return false;"> <div> <label>Nombre A :</label> <input type="text" id="nb_a"> </div> <div> <label>Nombre B :</label> <input type="text" id="nb_b" /> </div> <input type="button" onClick="appelProcedureFlex()" value="Calculer"> </form> </body> </html> En observant la procédure appelProcedureFlex, nous remarquons que la procédure ActionScript permettant de réaliser la somme des deux nombres est appelée via le nom du conteneur SWF qui la contient, soit fichierSWF.calculerSomme(nombreA,nombreB);. Formatage Les paramètres envoyés à la procédure ActionScript doivent être formatés, afin que celle-ci puisse les considérer comme des entiers et en réaliser la somme. Nous pouvons à présent passer à l’écriture de la procédure ActionScript contenue dans notre application Flex : <?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" =Flex3 FM.book Page 311 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 ➥height="374" width="328" creationComplete="aliasProcedure()"> <mx:Script> <![CDATA[ // ---- FLEX -> CONTENEUR WEB --import flash.external.ExternalInterface; public function calculJavascript():void{ if (ExternalInterface.available) { var fonctionJavascript:String = "calculerSomme" var s:String = ExternalInterface.call(fonctionJavascript, ➥Number(txt_a.text), Number(txt_b.text)); } } // Création d’un alias pour la procédure de calcul public function aliasProcedure():void { ExternalInterface.addCallback("calculerSomme",calculActionScript); } // Procédure de calcul public function calculActionScript(a:Number, b:Number):void{ var somme:Number = a + b txt_somme.text = String(somme); } ]]> </mx:Script>‰ <mx:Panel width="313" height="177" layout="absolute" x="10" y="10" title="Flex -> ➥Conteneur Web" id="pAddition"> <mx:Form x="10" y="10" width="273" height="82" verticalScrollPolicy="off" ➥horizontalScrollPolicy="off"> <mx:FormItem label="Nombre A :"> <mx:TextInput id="txt_a"/> </mx:FormItem> <mx:FormItem label="Nombre B :"> <mx:TextInput id="txt_b"/> </mx:FormItem> </mx:Form> <mx:Button id="btnCalculer" x="10" y="100" label="Calculer" width="273" ➥click="calculJavascript()"/> </mx:Panel> <mx:Panel x="10" y="208" width="308" height="156" layout="absolute" title="Conteneur ➥web -> Flex" id="pAdditionConteneur"> <mx:TextInput x="25" y="44" width="235" id="txt_somme"/> </mx:Panel> </mx:Application> 311 =Flex3 FM.book Page 312 Mardi, 2. décembre 2008 3:32 15 312 Comprendre Flex 3 PARTIE I L’appel à la procédure de calcul est réalisé à partir d’un alias qui lui est attribué. Ainsi, lorsque nous faisons appel à la procédure caculerSomme dans notre fichier HTML, nous appelons en réalité la procédure ActionScript calculActionScript. Pour créer un alias, nous utilisons la méthode addCallBack de la classe ExternalInterface, soit ExternalInterface .addCallback("calculerSomme",calculActionScript);. Pour que cet alias soit reconnu et utilisable, il ne faut pas oublier de l’initialiser lors de la création de l’application. Cette initialisation est réalisée par un appel à la procédure aliasProcedure dès la fin de la création de l’application : creationComplete="aliasProcedure()". Vient ensuite la création de la procédure de calcul et la mise en place d’une zone de texte chargée de contenir le résultat obtenu. Pour cela, nous vous laissons le soin d’analyser la procédure calculActionScript et le code MXML ajouté en fin de fichier, dont le contenu vous est maintenant familier. Figure 16-4 Interaction entre le conteneur web et l’application Flex =Flex3 FM.book Page 313 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 313 La dernière étape va consister à créer une nouvelle version de déploiement comme nous l’avons fait pour la première version de ce projet. Une fois cette étape terminée, ouvrez une nouvelle fenêtre dans votre navigateur (afin d’éviter tout problème de cache) et saisissez l’URL de la page HTML du projet dans la barre d’adresse (figure 16-4). Nous venons de voir comment il est possible d’interagir avec une application Flex via l’utilisation de la classe ExternalInterface. Nous allons à présent étudier une autre méthode consistant à utiliser la bibliothèque Flex-Ajax Bridge. La bibliothèque Flex-Ajax Bridge Flex-Ajax Bridge est une bibliothèque qui permet de se passer de la classe External Interface pour communiquer depuis le conteneur HTML vers l’application Flex. Nous allons voir que son implémentation est assez simple et offre de nombreuses possibilités : accès aux composants pour en modifier les propriétés, accès à l’ensemble des procédures… Ajout de la bibliothèque à un projet Pour ajouter la bibliothèque Flex-Ajax Bridge à notre projet, il suffit d’effectuer un clic droit sur le nom de ce dernier et de sélectionner Create Ajax Bridge. Une fenêtre apparaît alors, dans laquelle il suffit d’accepter les options par défaut implémentant les fonctionnalités Flex-Ajax Bridge dans le répertoire src du projet. Si nous nous plaçons ensuite dans le répertoire src du projet, nous notons la présence d’un nouveau répertoire nommé bridge et contenant un fichier ActionScript (FABridge.as) dont le rôle est délivrer les procédures et les fonctions nécessaires à l’implémentation de la bibliothèque Flex-Ajax Bridge. Analysons à présent le fichier MXML de notre application : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥height="374" width="328" xmlns:ns1="bridge.*"> <ns1:FABridge/> Comme nous l’avons vu au chapitre 10 consacré à la création de composants personnalisés, l’importation d’un composant est réalisée à l’aide de la spécification d’un nouvel espace de noms XML. Cet espace de noms est chargé de pointer vers les classes nécessaires à l’utilisation du composant. Pour utiliser les fonctionnalités de Flex-Ajax Bridge au sein d’une application, il convient de procéder de la même manière en définissant un nouvel espace de noms XML (ns1) faisant appel aux classes contenues dans le fichier FABridge.as. Utilisation de la bibliothèque Reprenons l’exemple de la procédure de calcul consistant à saisir les valeurs dans le conteneur et à déléguer le calcul à l’application Flex. Le fichier MXML correspondant est le suivant : =Flex3 FM.book Page 314 Mardi, 2. décembre 2008 3:32 15 314 Comprendre Flex 3 PARTIE I <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="374" width="328" ➥layout="absolute" xmlns:ns1="bridge.*"> <ns1:FABridge/> <mx:Script> <![CDATA[ // Procédure de calcul public function calculActionScript(a:Number, b:Number):void { var somme:Number = a + b; txt_somme.text = String(somme); } ]]> </mx:Script> <mx:Panel x="10" y="10" width="308" height="156" layout="absolute" title="Conteneur ➥web -> Flex" id="pAdditionConteneur"> <mx:TextInput x="25" y="44" width="235" id="txt_somme"/> </mx:Panel> </mx:Application> Jusque là, rien de bien nouveau si ce n’est la disparition de la classe ExternalInterface et de la procédure de création d’alias. La plupart des changements ont été effectués dans le fichier index.html : <html> <head> <title>Calcul de sommes</title> </head> <script src="bridge/FABridge.js" ></script> <SCRIPT LANGUAGE="JavaScript"> function calculerActionscript(){ var nombreA = parseInt(document.getElementById("nb_a").value); var nombreB = parseInt(document.getElementById("nb_b").value); var instanceFlex = FABridge.pontAjax.root(); instanceFlex.calculActionScript(nombreA,nombreB); } </SCRIPT> <object id='fichierSWF' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' ➥codebase='http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab' ➥height='400' width='400'> <param name='src' value='JsFlex.swf'/> <param name='flashVars' value='bridgeName=pontAjax'/> <embed name='fichierSWF' src='JsFlex.swf' pluginspage='http://www.adobe.com/go/ ➥getflashplayer' height='100%' width='100%' flashvars="bridgeName=pontAjax"/> </object> =Flex3 FM.book Page 315 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 315 <br/> <br/> <h1>Flex-Ajax Bridge</h1> <form> <label>Nombre A : </label> <input id="nb_a" /> <br/> <label>Nombre B : </label> <input id="nb_b" /> <br/> <button onClick="calculerActionscript()">Calculer</button> </form> <br/> </body> </html> Pour que Flex-Ajax Bridge fonctionne correctement, nous devons faire appel au fichier FABridge.js contenant l’ensemble des procédures capables de communiquer avec l’application Flex. Ce fichier se trouve dans le répertoire frameworks\javascript\fabridge\src\ bridge du SDK de Flex 3 et doit être copié à l’endroit où se trouve la page index.html. Nous reviendrons plus tard sur la phase de déploiement du projet. Observons à présent la balise <object> permettant d’inclure notre application dans le conteneur HTML. Elle contient le paramètre FlashVars qui va nous permettre de faire le lien avec l’application Flex et les procédures s’y trouvant : bridgeName=pontAjax Par cette instruction, nous définissons un nom pour notre connexion afin que celle-ci puisse être identifiée. Vient ensuite l’appel de la procédure en elle-même à l’aide de l’instruction suivante : var instanceFlex = FABridge.pontAjax.root(); instanceFlex.calculActionScript(nombreA,nombreB); Grâce à ce code, nous créons une variable instanceFlex chargée de stocker l’instance de notre application que nous pouvons récupérer grâce à la connexion que nous avons définie précédemment. À partir de cette instance, il nous est alors possible d’invoquer une fonction, une procédure ou encore un composant de notre application Flex. Déploiement et test Comme nous en avons maintenant l’habitude, il convient tout d’abord de réaliser une version de déploiement du projet Flex. La deuxième étape va ensuite consister à copier le répertoire bridge du kit Flex SDK et son fichier FABridge.js dans le répertoire bin-release de notre projet. Pour ce faire, rendezvous dans le répertoire d’installation de Flex Builder 3 et parcourez l’arborescence pour =Flex3 FM.book Page 316 Mardi, 2. décembre 2008 3:32 15 316 Comprendre Flex 3 PARTIE I retrouver le répertoire devant être copié. Si cette arborescence ne correspond pas à votre installation, n’hésitez pas à utiliser les outils de recherche de votre système d’exploitation à partir du répertoire d’installation de Flex Builder. {répertoire d’installation de Flex Builder 3}\sdks\3.0.0\frameworks\javascript\ ➥fabridge\src\bridge La dernière étape va tout simplement consister à ouvrir la page index.html dans une nouvelle fenêtre de votre navigateur à l’aide de son URL afin de s’assurer de la bonne exécution de la procédure calculActionScript (figure 16-5). Figure 16-5 Utilisation de Flex-Ajax Bridge Il est donc plus simple d’utiliser la bibliothèque Flex-Ajax Bridge que la classe External Interface. En effet, là où nous devions créer des alias de procédures, il nous suffit d’importer la bibliothèque qui se charge de réaliser ce travail pour nous, ce qui représente un gain de temps non négligeable. Notez également que la bibliothèque Flex-Ajax Bridge permet de manipuler l’ensemble des propriétés des composants de l’application Flex ce qui peut s’avérer fort utile dans certaines situations (par exemple, le changement de couleur des zones de texte…). =Flex3 FM.book Page 317 Mardi, 2. décembre 2008 3:32 15 Interagir avec le conteneur web CHAPITRE 16 317 //* //* Modification du texte du champ txt_somme à partir de Javascript /* with(FABridge.pontAjax.root()){ // Récupération du composant getNomDuComposant() var txt = getTxt_somme(); // Affectation de la nouvelle valeur setText() txt.setText("Bonjour!"); } En résumé Au cours de ce chapitre, nous avons qu’une application Flex peut être totalement intégrée à une application web statique et communiquer avec elle. Nous vous avons également présenté les différentes méthodes permettant de réaliser cette communication non seulement de l’application Flex vers le conteneur web mais également du conteneur vers l’application Flex. Nous avons aussi étudié la notion de deep linking qui apporte une fonctionnalité non négligeable aux applications, lesquelles sont désormais comparables aux applications web classiques en termes de navigation. Vous êtes désormais capable d’implémenter des fonctionnalités riches au sein d’applications web statiques existantes, ce qui vous permet d’étendre leurs aspects graphiques et fonctionnels. Dans le chapitre suivant, nous allons aborder un tout autre domaine : le débogage d’une application Flex. =Flex3 FM.book Page 318 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 319 Mardi, 2. décembre 2008 3:32 15 17 Déboguer une application Dans ce chapitre nous allons voir comment déboguer des applications à l’aide du débogueur de Flex Builder. Pour plus de clarté, nous aborderons ce point à travers un exemple comportant volontairement un certain nombre d’erreurs que nous corrigerons au fur et à mesure afin de découvrir les subtilités du débogueur. Création de l’application d’étude Nous allons développer une application simple consistant à calculer l’indice de masse corporelle (IMC) d’un patient. L’IMC est obtenu en effectuant le rapport du poids du patient en kilogrammes par sa taille en mètres élevée au carré, soit : IMC = masse/taille2. Pour cela, nous allons tout d’abord créer l’interface graphique (figure 17-1) : <mx:Panel x="10" y="10" width="330" height="195" layout="absolute" title="IMC"> <mx:Form x="10" y="10" width="281" height="83" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:FormItem label="Taille (m) :"> <mx:TextInput id="taille_txt"/> </mx:FormItem> <mx:FormItem label="Poids (kg) :"> <mx:TextInput id="poids_txt"/> </mx:FormItem> </mx:Form> <mx:Button x="10" y="101" label="Calculer" width="103" id="btn_calculer"/> <mx:TextInput x="121" y="101" width="152" id="imc_txt"/> </mx:Panel> =Flex3 FM.book Page 320 Mardi, 2. décembre 2008 3:32 15 320 Comprendre Flex 3 PARTIE I Figure 17-1 Interface graphique de l’application L’interface créée, nous allons implémenter la procédure de calcul. Pour ce faire, nous avons choisi de la créer dans un fichier ActionScript, dont l’appel s’effectuera dans le fichier MXML de l’application. Ce fichier ActionScript s’intitulera IMC.as et sera situé dans le répertoire src de l’application. Pour le créer, il suffit d’effectuer un clic droit sur le répertoire src et de sélectionner New>ActionScript File dans le menu contextuel qui apparaît alors. Lorsque l’assistant vous demande le nom du fichier à créer, indiquez IMC.as. Une fois le fichier créé, saisissez les lignes de code suivantes : public function calculerIMC() { var taille:Number = Number(taille_txt.text); var poids:Number = Number(poids_txt.text); var imc:Number = (poids)/(taille * taille) imc_txt.text = String(imc); } Calculer la valeur d’un nombre à la puissance n Dans notre exemple, pour élever la taille au carré, nous l’avons multipliée par elle-même. Il est également possible d’utiliser la méthode pow(nombre,puissance) de la classe Math comme suit : var imc:Number = (poids)/ (Math.pow(taille,2)) Nous devons ensuite lier ce fichier ActionScript à notre application et définir l’appel de la procédure calculerIMC() qui sera exécutée lors du clic sur le bouton btn_calculer : <mx:Script source="IMC.as"> </mx:Script> <mx:Button x="10" y="101" label="Calculer" width="103" id="btn_calculer" ➥click="calculerIMC()"/> Notre application est à présent terminée, concentrons-nous sur son exécution et son débogage. =Flex3 FM.book Page 321 Mardi, 2. décembre 2008 3:32 15 Déboguer une application CHAPITRE 17 321 Identifier et corriger les erreurs grâce à la vue Problems Avant d’exécuter l’application, nous vous invitons à consulter les informations présentes dans la vue Problems située en bas de votre écran. Cette vue regroupe les différents avertissements et erreurs produits par la compilation de notre code. Il est important de souligner qu’à la différence d’une erreur (error), un avertissement (warning) ne bloque pas l’exécution de l’application, mais il est tout de même souhaitable de le corriger. Nous constatons donc dans la figure 17-2 la présence de l’avertissement suivant : Figure 17-2 Affichage des avertissements qui nous indique que Flex est incapable de déterminer si calculerIMC() est une procédure ou une fonction. Il convient donc de corriger cet avertissement en ajoutant la mention :void : public function calculerIMC():void Procédure et fonction Une procédure permet d’effectuer un traitement mais ne retourne pas de valeur. Nous spécifions qu’il s’agit d’une procédure via la mention :void. Public function maProcedure():void{ } Dans le cas d’une fonction, nous devons préciser le type de la valeur renvoyée par celle-ci : Public function maFonction():int{ var entier:int = 1; return entier } La vue Problems est l’outil principal permettant de déboguer une application. En effet, grâce à celle-ci, la majeure partie des erreurs peuvent être résolues sans qu’il soit nécessaire de réaliser un débogage avancé. Le débogage avancé Pour illustrer ce point, nous allons mettre en défaut notre application en provoquant une erreur d’exécution. Pour ce faire, exécutons l’application et saisissons les valeurs 0 pour =Flex3 FM.book Page 322 Mardi, 2. décembre 2008 3:32 15 322 Comprendre Flex 3 PARTIE I Taille et 69 pour Poids. Cliquons ensuite sur le bouton Calculer afin d’observer le résultat obtenu dans la zone de texte prévue à cet effet. Nous constatons alors qu’au lieu de nous présenter l’indice de masse corporel attendu, la zone de réponse indique infinity. Que s’est-il passé ? Il n’est pas évident de déterminer avec précision le moment où l’erreur s’est produite. Nous allons donc stopper l’exécution de l’application lors de la phase de calcul afin d’y voir plus clair. Utilisation des points d’arrêt Pour stopper l’exécution d’une application, il suffit de placer un point d’arrêt dans son code. Vous pourrez ainsi exécuter l’application pas à pas et afin de détecter les éventuelles erreurs présentes. Dans notre exemple, nous savons que le problème vient de la procédure calculerIMC(). Il serait donc judicieux de stopper l’application à cet endroit afin d’analyser le fonctionnement de cette procédure. Pour ce faire, il convient de se placer dans le fichier MXML et, au regard de la ligne décrivant le bouton, d’effectuer un clic droit dans la marge et de sélectionner Toogle breakpoint (figure 17-3). Figure 17-3 Positionnement d’un point d’arrêt Notre point d’arrêt est maintenant correctement positionné. Pour l’exploiter, nous devons exécuter l’application en mode Debug en sélectionnant le menu Run>Debug (vous pouvez également appuyer sur la touche F11). À présent, ressaisissons les mêmes valeurs que précédemment (0 pour la taille et 69 pour le poids) et cliquons sur le bouton Valider. Une fenêtre s’ouvre alors dans Flex Builder nous demandant de confirmer l’ouverture de la perspective de débogage. Exécution pas à pas La meilleure façon de déboguer l’application consiste à vérifier le bon déroulement de chaque procédure et fonction. Pour cela, la perspective de débogage met à notre disposition deux icônes : • L’icône Step into permet d’entrer dans la procédure afin d’observer le déroulement de chaque traitement. =Flex3 FM.book Page 323 Mardi, 2. décembre 2008 3:32 15 Déboguer une application CHAPITRE 17 • L’icône Step over 323 permet de poursuivre le traitement sans entrer dans la procédure. Pour illustrer les actions provoquées par l’utilisation de ces icônes, nous vous invitons à exécuter les opérations suivantes : 1. Vérifiez que vous avez bien exécuté l’application en mode Debug et accepté l’ouverture de la perspective de débogage. Appuyez ensuite sur touche F5 (raccourci clavier de Step into) pour entrer dans la procédure. La procédure calculerIMC() s’affiche alors au milieu de l’écran (figure 17-4). Figure 17-4 Entrée dans la procédure calculerIMC() 2. Réitérez cette opération. Le curseur de débogage pointe à présent sur la variable taille. 3. Si vous appuyez à nouveau sur la touche F5, vous entrez cette fois dans le détail de la classe TextInput et pouvez visualiser le code de la méthode get Text() du composant taille_txt. 4. Appuyez ensuite trois fois sur la touche F5 afin de placer le curseur de débogage sur la variable poids. 5. À présent, appuyez sur la touche F6 (raccourci clavier de Step over). Vous constatez alors que vous n’êtes pas entré dans le détail de la méthode Text() du composant poids_txt et que vous êtes directement passé à la variable imc. 6. Pour stopper le débogage, cliquez sur l’icône représentant un petit carré rouge à côté des icônes Step into et Step over. 7. Enfin, pour revenir à la perspective de développement, sélectionnez le menu Windows>Perspective de Flex Builder et choisissez Flex Developpement. Au fur et à mesure que vous naviguez dans le code, observez la vue Variables de la perspective de débogage (figure 17-5). Grâce à cette vue, nous pouvons visualiser les valeurs prises par l’ensemble de nos variables. Après avoir calculé l’indice de masse corporelle, la valeur de la variable imc est Infinity. =Flex3 FM.book Page 324 Mardi, 2. décembre 2008 3:32 15 324 Comprendre Flex 3 PARTIE I Figure 17-5 La vue Variables Étant donné que les variables taille et poids possèdent toutes deux une valeur, le problème ne peut donc provenir que de l’affectation de la variable imc. D’après les valeurs saisies pour la taille (0) et le poids (69), le calcul de l’IMC équivaut à : IMC = 69 / 0 × 0. La division par zéro étant impossible, la valeur Infinity est renvoyée. Le problème est donc identifié. Pour le résoudre, il convient d’ajouter un test de vérification de la saisie utilisateur comme suit : var taille:int = int(taille_txt.text); var poids:Number = Number(poids_txt.text); if (taille != 0) { var imc:Number = (poids)/(taille * taille) imc_txt.text = String(imc); } else { var msg_erreur:String = "Ne peut être calculé"; imc_txt.text = msg_erreur; } Gérer les points d’arrêt La gestion des points d’arrêt s’effectue dans la vue Breakpoints, située à droite de la vue Variables. En effectuant un clic droit sur un ou plusieurs points d’arrêt affichés dans cette vue, il est possible : • d’activer/de désactiver les points d’arrêt (Enable/Disable) ; • de supprimer les points d’arrêt (Remove/Remove All) ; • de se positionner dans le fichier où se trouve les points d’arrêt (Go to file) ; • de passer outre les points d’arrêt (Skip All Breakpoints). Notre application est à présent déboguée et fonctionnelle. Néanmoins, nous sommes loin d’avoir exploité toutes les fonctionnalités du débogueur de Flex Builder. =Flex3 FM.book Page 325 Mardi, 2. décembre 2008 3:32 15 Déboguer une application CHAPITRE 17 325 Modifier la valeur des variables En phase de test, il peut s’avérer intéressant de modifier la valeur des variables afin de vérifier le comportement de la procédure en fonction de ces valeurs. Pour cela, il convient de se placer dans la vue Variables et de double-cliquer sur la valeur de la variable à modifier. Il suffit alors de saisir la valeur souhaitée, à condition que celle-ci soit initialisée. Tracer un parcours Placer un point d’arrêt n’est réellement nécessaire que si un problème survient dans un traitement et qu’une analyse détaillée de ce traitement s’impose. Pour les cas plus simples (vérification de passage dans un test ou une boucle, etc.), la solution consistant à tracer le parcours du traitement peut être envisagée par l’emploi de la méthode trace() : public function calculerIMC():void { var taille:int = int(taille_txt.text); trace ('Taille : ' + taille); var poids:Number = Number(poids_txt.text); trace ('Poids : '+poids); trace ('Debut de test'); if (taille != 0) { trace ('Cas : Taille !=0'); var imc:Number = (poids)/(taille * taille) imc_txt.text = String(imc); } else { trace ('Cas : Taille =0 ->> ERREUR'); var msg_erreur:String = "Ne peut être calculé"; imc_txt.text = msg_erreur; } } Pour bien comprendre l’utilité de cette méthode, nous allons exécuter l’application en mode Debug et visualiser le résultat obtenu dans la vue Console. Nous y trouvons les lignes suivantes : Taille : 0 Poids : 69 Debut de test Cas : Taille =0 ->> ERREUR Nous pouvons alors en déduire que le traitement s’est déroulé correctement, car l’ensemble des traces correspondantes découlent des valeurs saisies. En effet, comme nous avons =Flex3 FM.book Page 326 Mardi, 2. décembre 2008 3:32 15 326 Comprendre Flex 3 PARTIE I saisi la valeur 0 pour la taille, le test if (taille != 0) est faux. Ceci entraîne alors l’affichage de la trace ‘Cas : Taille = 0 ->>Erreur’. Avec cette manipulation, nous vérifions donc que, lorsque la taille est égale à zéro, le traitement de gestion d’erreur s’exécute convenablement. Sélectionner les variables à surveiller Pour sélectionner certaines variables, il suffit de cliquer dessus avec le bouton droit et de choisir Watch nom de la variable. La variable sélectionnée s’affiche alors dans la vue Expressions (figure 17-6) de la perspective de débogage, nous permettant ainsi d’étudier son comportement, tout comme nous pourrions le faire dans la vue Variables. Mais nous allons voir que cette vue offre une fonctionnalité supplémentaire permettant de manipuler les données en modifiant leur expression. Figure 17-6 Sélection de la variable taille dans la vue Expressions La vue Expressions permet de manipuler la valeur des variables en modifiant leur opération. Prenons un exemple : nous souhaitons modifier la valeur de la variable taille afin qu’elle soit égale à deux fois sa valeur (taille = taille ¥ 2). Pour arriver à ce résultat, il suffit de cliquer avec le bouton droit sur la variable taille affichée dans la vue Expressions et de sélectionner Edit Watch Expression. Une nouvelle fenêtre s’ouvre alors, dans laquelle nous pouvons saisir le traitement souhaité (figure 17-7). Figure 17-7 Définition d’une expression pour une variable donnée =Flex3 FM.book Page 327 Mardi, 2. décembre 2008 3:32 15 Déboguer une application CHAPITRE 17 327 À présent, si nous exécutons l’application en mode Debug et que nous observons la variable taille dans la vue Expressions, nous remarquons que sa valeur a été révaluée en fonction de l’opération précédemment saisie (figure 17-8). Figure 17-8 Révaluation de la valeur saisie en fonction de l’expression En résumé Dans ce chapitre, nous avons présenté le fonctionnement du débogueur de Flex Builder, application permettant d’analyser votre code de plusieurs façons différentes. Vous pourrez ainsi observer le comportement de vos fonctions et de vos procédures tout en ayant la possibilité d’interagir avec les données stockées dans les variables. Le débogueur de Flex constitue un outil très performant qui vous sera certainement d’une aide non négligeable si vous rencontrez des difficultés ou si votre code présente des erreurs. Dans le chapitre suivant, nous allons nous pencher sur une autre nouveauté de Flex Builder 3 : le profiling d’application. Ceci consiste à analyser l’ensemble de ses processus afin de détecter les procédures gourmandes en mémoire ou en temps d’exécution. Nous verrons également les bonnes pratiques permettant d’optimiser l’exécution d’une application Flex. =Flex3 FM.book Page 328 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 329 Mardi, 2. décembre 2008 3:32 15 18 Analyser les performances et optimiser l’application Autre grande nouveauté de Flex Builder 3, la fonction d’analyse des performances était attendue avec impatience par les développeurs. Réservé aux utilisateurs de la version professionnelle de Flex Builder 3, cet outil permet d’analyser les moindres détails de vos applications afin d’en améliorer les performances lors de l’exécution. Nous verrons également quelques bonnes pratiques à observer afin d’optimiser l’exécution de vos applications Flex avant de les déployer. Présentation de l’analyseur La version professionnelle de Flex Builder 3 met à notre disposition un outil d’analyse avancé concernant l’exécution des applications, le Profiler. Il nous permettra en effet d’analyser les performances applicatives (taux de mémoire occupée, temps processeur…) et de contrôler les ressources mémoire utilisées en spécifiant le nombre et la taille des objets instanciés, le nombre de procédures exécutées ainsi que leur temps d’exécution. Procéder à l’analyse d’une application permet d’identifier et de comprendre les éléments suivants : • La redondance d’appel des procédures – L’analyseur permet de déterminer combien de fois la procédure est appelée, information qui vous permettra d’optimiser les traitements. • Le temps d’exécution d’une procédure – Si le temps d’exécution d’une procédure est important, nous pourrons nous en rendre compte et procéder à son optimisation. =Flex3 FM.book Page 330 Mardi, 2. décembre 2008 3:32 15 330 Comprendre Flex 3 PARTIE I • Le nombre d’objets instanciés – Grâce à cette fonctionnalité, vous découvrirez qu’un objet est parfois instancié plusieurs fois alors que cela n’est pas nécessaire. Vous pourrez ainsi modifier le code afin de corriger cela. • La taille des objets – En complément de la fonctionnalité précédente, vous pourrez également identifier la taille des objets instanciés afin de visualiser leur occupation mémoire. • Le ramasse-miettes (garbage collector) – Il peut arriver que certains objets devenus obsolètes, ou qui ne sont plus utilisés, soient toujours présents en mémoire. Grâce au Profiler, vous pourrez les identifier et ainsi implémenter les méthodes de destruction d’objet adéquates. Le fonctionnement du Profiler repose sur l’utilisation d’un port de communication permettant d’établir une connexion avec le Flash Player et l’application en cours d’exécution. Une fois la connexion établie, son travail consiste à réaliser à intervalles réguliers des captures des actions réalisées par l’application. L’analyseur en action Étudions à présent son utilisation à travers un exemple concret. Pour cela, nous vous invitons à créer un nouveau projet Flex que vous nommerez Profiler et à y insérer les lignes de code suivantes : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.controls.Alert; public function afficherMessage():void { Alert.show("Message d’information"); } ]]> </mx:Script> <mx:Button x="10" y="10" label="Afficher" id="btn_afficherMessage" ➥click="afficherMessage()"/> </mx:Application> Comme vous pouvez le constater, il s’agit d’une petite application, contenant un bouton qui déclenche l’exécution de la procédure afficherMessage(), affichant un message d’alerte, lorsqu’on clique dessus. =Flex3 FM.book Page 331 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 331 Pare-feu Dans la mesure où la communication s’effectue via un port spécifique du Flash Player, il se peut qu’elle soit bloquée par votre pare-feu. Nous vous conseillons donc de le désactiver temporairement ou d’autoriser l’accès au port 9999. Pour lancer l’analyse de notre application, sélectionnez le menu Run>Profile. Une nouvelle fenêtre apparaît alors, nous demandant l’autorisation d’ouvrir la perspective d’analyse. Vous n’avez alors qu’à confirmer, ce qui déclenche l’exécution de l’application et l’ouverture de la perspective d’analyse. Avant de pouvoir utiliser cette perspective, vous devez indiquer quel type d’analyse vous souhaitez effectuer. Pour une analyse complète, conservez les options cochées par défaut : • analyse de la mémoire (Enable memory profiling) ; • analyse du temps d’exécution des processus (Enable performance profiling). Analyse des performances Nous allons à présent analyser la performance de la procédure afficherMessage(). Pour cela, placez-vous sur l’interface de l’application et cliquez sur le bouton qu’elle contient. Le message d’alerte s’affiche correctement à l’écran. Ne le fermez pas encore et ouvrez la perspective d’analyse de Flex Builder 3. Nous allons procéder à une capture des événements. Pour cela, placez-vous dans la vue Profile située en haut à gauche de l’écran et positionnez-vous sur la ligne commençant par la mention [Running]. Dans la barre d’outils, cliquez ensuite sur l’icône Capture Performance Profile représentée par une paire de lunettes et une horloge . La vue Performance Profile s’ouvre alors, affichant un tableau de données concernant l’ensemble des méthodes et des procédures exécutées (figure 18-1). Nous remarquons que l’une des lignes du tableau concerne l’appel à la procédure profiler .afficherMessage. Le tableau 18-1 présente les informations obtenues en analysant l’exécution de cette procédure, celles-ci pouvant être différentes en fonction des performances de votre ordinateur. Pour entrer dans le détail de son exécution, il suffit de double-cliquer sur la ligne du tableau affichée dans la vue Method Statistic (figure 18-2), afin de voir les statistiques complètes concernant cette procédure. La vue Performance Profile vous permettra donc d’identifier les méthodes pouvant éventuellement poser problème lors de l’exécution de l’application grâce à une analyse attentive de leur temps d’exécution. =Flex3 FM.book Page 332 Mardi, 2. décembre 2008 3:32 15 332 Comprendre Flex 3 PARTIE I Figure 18-1 La vue Performance Profile Tableau 18-1 Tableau d’analyse d’exécution de la procédure profiler.afficherMessage Information Valeur Analyse Method Profiler.afficherMessage -- -- Notre procédure n’appartient à aucun package. 1 La procédure n’a été exécutée qu’une seule fois. 12 (0.78%) Temps d’exécution total : 12 millisecondes. 0 La procédure avait déjà été exécutée lors de la capture. 12 -- 0 -- Nom des méthodes et des procédures Package Nom du package d’appartenance Calls Nombre d’appels d’exécution de la procédure Cumulative time Somme des temps d’exécution de la procédure et des sous-procédures associées Self time Temps d’exécution de la procédure au moment de la capture Avg. Cumulative time Moyenne des temps d’exécution Avg Self Time Moyenne des temps d’exécution au moment de la capture =Flex3 FM.book Page 333 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 333 Figure 18-2 Analyse des statistiques Analyse de l’occupation mémoire Attardons nous à présent sur l’analyse de l’occupation de la mémoire de notre application. Pour cela, comme précédemment, nous devons procéder à une capture d’événement en cliquant cette fois-ci sur l’icône Take Memory Snapshot après nous être positionnés sur la ligne commençant par la mention [Running]. La vue Memory Snapshot s’ouvre alors, nous permettant d’analyser la part d’occupation de la mémoire de chaque processus. Pour ce faire, retournons dans notre application, en cours d’exécution dans le navigateur, et appelons la procédure afficherMessage() en cliquant sur le bouton Afficher, puis retournons dans la perspective d’analyse. Figure 18-3 Analyse de la mémoire Si nous analysons les résultats obtenus (figure 18-3), nous remarquons que l’élément le plus gourmand en ressources mémoire est l’application elle-même (1 572 octets). En double-cliquant sur la ligne profiler, nous visualisons le rapport détaillé le concernant. Nous pouvons alors voir l’ensemble des objets instanciés et leur taux d’occupation de la mémoire, qui expliquent la part importante d’occupation de la mémoire par l’application : nous avons 32 objets instanciés (figure 18-4). =Flex3 FM.book Page 334 Mardi, 2. décembre 2008 3:32 15 334 Comprendre Flex 3 PARTIE I Figure 18-4 Analyse des objets instanciés Méthodes d’analyse Dans cette section, nous allons voir les méthodes d’analyse les plus fréquemment utilisées. Chacune est détaillée en un certain nombre d’étapes que nous vous invitons à suivre. Détecter les allocations mémoire inutiles Pour commencer, nous allons vous présenter la méthode permettant de détecter les allocations de mémoire inutiles. Cela est souvent dû à la présence d’objets toujours instanciés malgré le travail réalisé par le ramasse-miette : 1. Démarrez une session d’analyse en sélectionnant l’option Memory Profiling (voir la section « L’analyseur en action »). 2. Créez deux captures de mémoire à deux moments différents. En cliquant une première fois sur l’icône et en réitérant cette action quelques secondes à quelques minutes plus tard, selon l’analyse souhaitée. =Flex3 FM.book Page 335 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 335 3. Sélectionnez les deux captures effectuées et cliquez sur l’icône d’analyse permettant de détecter les objets chargés en mémoire . 4. Une nouvelle fenêtre s’ouvre alors dans laquelle vous pouvez visualiser l’ensemble des méthodes et des objets toujours instanciés malgré la présence du ramasse-miettes. La solution consistera donc à implémenter les méthodes de destruction d’objet pour les objets concernés via la méthode delete : package com.composants { public class ClMaClasse { public function ClMaClasse() { } //Méthode de destruction public function detruitre():void{ delete this; } } } //Exemple d'utilisation dans un fichier ActionScript : import com.composants.ClMaClasse //Intanciation de la classe public var monObjet:ClMaClasse = new ClMaClasse(); //Destruction de l'objet monObjet.detruitre(); Analyser le temps d’exécution des méthodes « Pourquoi le temps d’exécution de mon application est-il si important ? » Cette question, nous nous la sommes tous posée un jour. Bien souvent, il s’agit d’une procédure demandant un temps de traitement important, mais il nous est parfois difficile de savoir de laquelle il s’agit. Nous allons voir comment, à l’aide d’une méthode simple, il nous est possible de la repérer. 1. Démarrez une session d’analyse en sélectionnant l’option Performance Profiling (voir la section « L’analyseur en action »). 2. Réalisez une capture de performance comme expliqué à la section « Analyse des performances ». =Flex3 FM.book Page 336 Mardi, 2. décembre 2008 3:32 15 336 Comprendre Flex 3 PARTIE I 3. Dans la vue Performance Profile, vous pouvez organiser les résultats par ordre croissant/ décroissant en cliquant sur les titres des colonnes du tableau de résultat. Ainsi, il sera possible de visualiser rapidement (notamment via la colonne Safe time indiquant le temps d’exécution de la procédure) la méthode ayant un temps d’exécution important pouvant cacher un problème (attente de réponse d’un service web, par exemple). Déterminer le nombre d’instances d’une classe Cette méthode va permettre de connaître le nombre d’objets instanciés pour une classe donnée. Chaque instanciation de classe donnant naissance à un objet occupant de la mémoire, il convient de détecter le nombre d’instanciations de classes afin de vérifier qu’il correspond à la quantité d’objets utiles à l’application. 1. Démarrez une session d’analyse en sélectionnant l’option Memory Profiling. 2. Réalisez une capture de mémoire comme expliqué à la section « Analyse de l’occupation mémoire ». 3. Dans la vue Memory Snapshot, classez les noms des classes par ordre alphabétique (en cliquant sur le titre de la colonne Class) afin de repérer facilement la classe souhaitée. 4. Le nombre d’instances de la classe recherchée est indiqué par la valeur de la colonne Instances. Si vous remarquez que ce nombre est supérieur à la quantité d’instanciations réalisées par le code de l’application, il se peut qu’il y reste des instanciations inutiles (parfois réalisées lors de phases de test). Visualiser les allocations d’objets La méthode précédente nous permet de compter le nombre d’objets instanciés. Voyons à présent comment connaître l’occupation mémoire de ceux-ci. 1. Démarrez une session d’analyse en sélectionnant l’option Memory Profiling et en cochant cette fois l’option de visualisation d’allocations d’objets (Generate object allocation stack trace). 2. Réalisez deux captures de mémoire à intervalles séparés, comme nous avons procédé pour la détection d’allocation mémoire. 3. Sélectionnez-les et cliquez sur l’icône View Allocation Trace . 4. La vue Allocation Trace qui s’ouvre alors présente l’ensemble des allocations. (Vous pouvez les classer par ordre croissant/décroissant en cliquant sur les en-têtes des colonnes). Il existe bien entendu beaucoup d’autres méthodes que vous découvrirez à mesure que vous vous familiariserez avec l’outil d’analyse. À vous ensuite de créer vos propres procédures d’analyse en fonction de vos besoins. =Flex3 FM.book Page 337 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 337 Bonnes pratiques d’optimisation L’optimisation d’une application Flex consiste essentiellement à améliorer son exécution et à réduire son temps d’initialisation sur le poste client. Nous allons voir comment, à partir de quelques bonnes pratiques, il est possible d’optimiser nos applications. Calculer les performances applicatives Comme nous l’avons vu, le Profiler de la version professionnelle Flex Builder 3 permet de vérifier les performances d’une application. Cependant, ce dernier n’est présent que dans la version professionnelle ; si vous utilisez Flex SDK pour développer vos application ou Flex Builder dans sa version standard, vous ne pourrez donc pas vous en servir. Nous allons toutefois présenter quelques petites astuces qui vous permettront toutefois d’apprécier les performances de vos applications. Calculer le temps d’initialisation Grâce à la combinaison des méthodes getTimer() et callLater() du package flash.utils, il est possible de calculer le temps d’initialisation d’une application : • getTimer() permet de calculer le temps écoulé en millisecondes depuis l’exécution du Flash Player. • callLater() permet de reporter l’exécution d’une procédure au prochain rafraîchissement de l’écran. Ainsi, en calculant le temps écoulé entre l’exécution de l’application et l’affichage de l’écran principal, nous pouvons déterminer le temps nécessaire à l’initialisation de l’application : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="callLater(afficherTempsInitialisation)"> <mx:Script> <![CDATA[ import flash.utils.Timer; [Bindable] public var tempsInitialisation:String; private function afficherTempsInitialisation():void { tempsInitialisation = "Temps d'initialisation: " + getTimer() + " ms"; } ]]> </mx:Script> <!-- Affichage du temps d’initialisation --> <mx:Label id="l1" text="{tempsInitialisation}"/> </mx:Application> =Flex3 FM.book Page 338 Mardi, 2. décembre 2008 3:32 15 338 Comprendre Flex 3 PARTIE I L’analyse du résultat de cette méthode peut être riche d’enseignements. Si le temps d’initialisation est trop élevé, cela peut être dû à un chargement trop important d’images ou à une procédure lourde en traitement. Calculer l’occupation de la mémoire Pour déterminer la taille de la mémoire occupée par le Flash Player, nous disposons de la propriété totalMemory de la classe System. La portion de code suivante permet de déterminer l’occupation de la mémoire après l’initialisation de l’application : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" ➥initialize="afficherMemoire()"> <mx:Script> <![CDATA[ [Bindable] public var memoireOccupee:String; private function afficherMemoire():void { memoireOccupee= "Mémoire occupée : " + flash.system.System.totalMemory ➥+ " octets"; } ]]> </mx:Script> <!-- Affichage de la taille mémoire occupée --> <mx:Label id="l1" text="{memoireOccupee}"/> </mx:Application> Là encore, l’analyse du résultat permet de tirer une conclusion importante : si le taux d’occupation mémoire est élevé, cela peut allonger le temps d’exécution sur le poste client car la limite mémoire de son environnement peut facilement être atteinte. C’est donc à vous de fixer un taux d’occupation mémoire que l’application ne doit pas dépasser. Pour réussir cela, il convient de respecter quelques règles d’optimisation que nous allons aborder dans la section suivante. Améliorer l’exécution sur les postes clients Comme nous le savons, une application Flex est exécutée sur le poste client. Pour une meilleure performance d’exécution, il faut que notre application soit correctement configurée et respecte quelques règles de base. Prévenir le dépassement du temps d’initialisation (time out) Si l’application est téléchargée sur un poste client à faible capacité de traitement, il se peut qu’un message d’erreur apparaisse, avertissant l’utilisateur que le temps d’initialisation =Flex3 FM.book Page 339 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 339 de l’application a été dépassé (60 secondes par défaut). Pour pallier ce problème, il suffit d’augmenter la valeur de la propriété scriptTimeLimit de l’application comme suit : <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" scriptTimeLimit="120"> </mx:Application> À cause de la performance croissante des ordinateurs, le temps d’initialisation est rarement dépassé et cette fonction peut ne pas être employée. Cependant, vous pouvez tout de même en faire usage si votre application est susceptible d’être utilisée sur des machines intégrées au sein d’un parc informatique ayant déjà quelques années (nous pensons, par exemple, au parc informatique de certains hôpitaux). Attention au cache du navigateur Toute application Flex est téléchargée dans le répertoire des fichiers temporaires d’Internet du poste client. Ce répertoire représente le cache du navigateur permettant de diminuer le nombre de requêtes web effectuées. Ainsi, si vous venez de mettre en ligne une nouvelle version de votre application Flex, il est fort probable que les utilisateurs ne puissent en bénéficier et voir les modifications effectuées. En effet, le cache de leur navigateur va détecter que la page contenant l’application a déjà été visitée et va donc afficher celle enregistrée dans le répertoire de stockage au lieu de la recharger. Pour résoudre ce problème, deux solutions s’offrent à nous. La première consiste à vider le cache de chaque poste client (uniquement pour un déploiement sur site local), la seconde à paramétrer la page web contenant l’application Flex. Attention, cette modification est à apporter après compilation. <!-<meta <!-<meta Ne pas utiliser le cache --> http-equiv=”pragma” content=”no-cache”> Forcer la date d’expiration pour recharger la page --> http-equiv=”EXPIRES” content=” Mon, 22 Jul 2000 11:12:01 GMT”> Dans cet exemple de code, nous avons spécifié une date antérieure à la date du jour. Le navigateur web va donc en déduire que le fichier présent dans le cache est obsolète et va par conséquent procéder au téléchargement de la dernière version de l’application. Réduire la taille des fichiers SWF Un fichier SWF de petite taille permet de réduire le temps de téléchargement et d’initialisation de l’application. Cette réduction de taille peut être effectuée en ne prenant que les éléments vitaux à l’exécution de l’application. Désactiver l’option de débogage Lorsque l’option de débogage est sélectionnée lors de la compilation du projet, les numéros de lignes et les fonctionnalités de débogage sont inclus dans le fichier SWF, ce qui =Flex3 FM.book Page 340 Mardi, 2. décembre 2008 3:32 15 340 Comprendre Flex 3 PARTIE I augmente sa taille. Cette option étant sélectionnée par défaut, il nous est possible de la désactiver en modifiant les paramètres de compilation comme suit : mxmlc -debug=false Application.mxml Soulignons qu’il est impossible de paramétrer cette option dans Flex Builder 3, dans la mesure où l’application contenant toutes les options de débogage est compilée dans le répertoire bin-debug. La version de déploiement destinée aux clients, située quant à elle dans le répertoire bin-release, est ainsi épurée de cette fonctionnalité Compiler en mode Strict Le fait d’utiliser le mode Strict de compilation implique la vérification de l’utilisation effective de tous les packages et classes importés, ainsi que la vérification de la qualité de votre code. Si vous utilisez Flex Builder 3 pour créer et compiler vos applications, ce mode est automatiquement activé. Pour les autres versions de Flex, voici le code permettant d’activer cette option lors de la compilation : mxmlc -strict=true Application.mxml Multiplier les fichiers SWF Une dernière méthode pour réduire la taille d’une application consiste à la décomposer en plusieurs petites applications pouvant alors être chargées à l’aide du composant SWFLoader. Cette méthode présente l’avantage de ne charger que la partie applicative nécessaire, ce qui réduit ainsi la taille du fichier applicatif principal. Nous aborderons cette notion plus en détail dans la seconde partie de cet ouvrage consacrée à la mise en pratique. Améliorer les méthodes de codage Nous allons ici nous pencher sur les éléments auxquels il faudra faire attention lors de la phase de développement de vos applications pour optimiser leur exécution. Instancier les objets ActionScript est un langage orienté objet. Néanmoins, chaque création d’objet entraîne le stockage de données, ce qui provoque une diminution des performances de l’application. Comme en Java, nous disposons cependant dans Flex d’un ramasse-miettes dont le rôle est de supprimer les objets instanciés non utilisés. Par ailleurs, nous vous invitons à suivre la règle de base suivante : instanciez un objet uniquement si vous en avez besoin. Vous augmenterez ainsi les performances applicatives, car un objet instancié non employé occupe inutilement de la mémoire. « Tracer » avec parcimonie Comme nous l’avons vu au chapitre 17 consacré au débogage, « tracer » le parcours d’une application à l’aide de la méthode trace() permet de vérifier le bon fonctionnement d’un =Flex3 FM.book Page 341 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 341 processus. Cependant, chaque trace sera écrite sur le disque dur de l’utilisateur, provoquant alors un ralentissement de l’application et une diminution de l’espace disque du client. Pour pallier ce problème, il convient de désactiver les options de débogage lors de la compilation (voir section précédente « Désactiver l’option de débogage ») ou d’intervenir sur chaque poste client lorsque cela est possible (application intranet) et d’ajouter la ligne de code suivante dans le fichier mm.cfg, situé dans le répertoire Documents and Settings/ nom_utilisateur : TraceOutputFileEnable = 0 Vous désactiverez ainsi l’écriture des traces sur le poste de l’utilisateur et augmenterez la performance de votre application. Concevoir des interfaces graphiques Nous vous conseillons de ne pas abuser des conteneurs (HBox, Panel…) sous peine de réduire considérablement le temps d’initialisation de l’application. En effet, chaque conteneur doit être positionné en fonction de son conteneur parent, ce qui demande des ressources pour le calcul des positions de chacun. En ce qui concerne le positionnement et le dimensionnement des composants, préférez la spécification dans le code des propriétés adéquates (x, y, height et width) à l’utilisation des positionnements et dimensionnements relatifs. De même, utilisez les effets avec parcimonie, car ils nécessitent également un certain nombre de ressources de la part de la machine cliente, ce qui provoque un ralentissement de l’exécution de l’application. Déployer une application Flex Déployer une application peut se résumer à copier les sources situées sur l’environnement de développement vers l’environnement de déploiement accessible aux utilisateurs. Certaines phases sont cependant indispensables et ne peuvent être omises. L’incontournable liste de contrôle Un peu à la manière d’un commandant de bord, nous devons vérifier certains prérequis nécessaires au bon déploiement applicatif (tableau 18-1). Tableau 18-1 Prérequis pour déployer une application Élément à vérifier Description Compilation Assurez-vous d’avoir bien compilé l’ensemble des éléments de votre application à l’aide des compilateurs adéquats : mxmlc et compc. Conteneur applicatif Assurez-vous que vous disposer bien d’une page web contenant le fichier SWF de votre application. =Flex3 FM.book Page 342 Mardi, 2. décembre 2008 3:32 15 342 Comprendre Flex 3 PARTIE I Tableau 18-1 Prérequis pour déployer une application (suite) Élément à vérifier Description Détecteur de la version de Flash Player Pour que la détection du Flash Player soit effective, vous devez disposer du fichier AC_OETags.js. Installation du Flash Player s’il n’est pas détecté sur le poste client Si vous souhaitez que le Flash Player soit installé automatiquement s’il n’est pas présent sur le poste client, assurez-vous que vous disposez bien des fichiers AC_OETags.js et playerProductInstall.swf. Visualisation des sources Déterminez s’il sera possible ou non de consulter les sources de l’application. Images/fichiers externes Assurez-vous de bien déployer les images et fichiers externes nécessaires au bon fonctionnement de votre application Réseau Vérifiez que l’ensemble des serveurs sont accessibles par votre application (couche métier) et que celle-ci est accessible depuis l’extérieur (paramétrage des firewalls) Services web Vérifiez la disponibilité des services web que vous utilisez dans votre application. Tests applicatifs Assurez-vous d’avoir effectué tous les tests applicatifs nécessaires. Si tous les éléments du tableau 18-1 sont vérifiés et fonctionnels, vous pouvez procéder au déploiement de votre application. Mise en ligne de l’application La mise en ligne (ou déploiement) d’une application Flex se réalise tout simplement en copiant les fichiers issus de la compilation sur le serveur que vous avez dédié à l’hébergement de l’application. Si vous décidez de déployer votre application à l’aide de Flex Builder 3, vous devrez néanmoins procéder à une opération supplémentaire consistant à créer une version de déploiement. Voici la marche à suivre pour cela : 1. Effectuez un clic droit sur le nom du projet et choisissez Export. 2. Une nouvelle fenêtre s’ouvre alors, vous demandant de préciser le type d’exportation souhaité, sélectionnez Release Build et cliquez sur le bouton Next. 3. Dans l’interface qui s’affiche, indiquez si vous souhaitez ou non permettre la visualisation des sources de l’application en sélectionnant ou désélectionnant l’option Enable source file. 4. Cliquez sur le bouton Finish pour terminer. Si vous observez à présent l’arborescence de votre projet, vous constatez la présence d’un répertoire nommé bin-release contenant les fichiers prêts à être copiés sur l’environnement de déploiement. =Flex3 FM.book Page 343 Mardi, 2. décembre 2008 3:32 15 Analyser les performances et optimiser l’application CHAPITRE 18 343 Page d’accueil La page HTML contenant le fichier SWF porte le nom du projet. Il est tout à fait possible de la renommer en index.html afin qu’elle soit considérée comme page d’accueil par le serveur web. La figure 18-5 illustre le déploiement et l’utilisation d’une application Flex nous permettant de mesurer l’importance de la phase de validation de chaque élément majeur de l’environnement applicatif. Figure 18-5 Schéma de déploiement et d’utilisation d’une application =Flex3 FM.book Page 344 Mardi, 2. décembre 2008 3:32 15 344 Comprendre Flex 3 PARTIE I Étape 1 : le contenu du répertoire bin-release est copié dans le répertoire racine www du serveur web. Étapes 2 et 3 : l’utilisateur se connecte au serveur web qui lui délivre l’application Flex. À ce stade, le travail du serveur web est terminé (si l’application ne comporte pas de modules devant être téléchargés ultérieurement). Étape 4 : l’application étant entièrement copiée sur le poste client, c’est à partir de celuici qu’elle va pouvoir se connecter au serveur de la couche métier, d’où l’importance du paramétrage des adresses IP dans l’application et la configuration des firewalls permettant l’accès à ces services. Étape 5 : phase de communication entre le serveur contenant les services applicatifs et celui contenant la base de données. Là encore, il convient de vérifier que tous les services sont fonctionnels et que la communication n’est pas entravée. En résumé Au cours de ce chapitre, nous avons présenté les bases de l’utilisation de l’outil d’analyse de Flex Builder Professionnel. Elles vous permettront de détecter les éventuelles erreurs d’exécution ou d’allocation de mémoire de vos applications. Nous vous recommandons d’utiliser le Profiler avant toute phase de déploiement afin d’obtenir une application de qualité, car, ne l’oublions pas, celle-ci sera exécutée sur le poste client qui n’est peut-être pas de la dernière génération. Une saturation de la mémoire peut, en effet, parfois avoir des conséquences désastreuses sur l’utilisation de vos applications. Pour compléter cette notion de qualité applicative, nous avons également consacré une partie de ce chapitre à l’étude de l’optimisation et du processus de déploiement d’une application. Les informations données dans ce chapitre ne sont pas exhaustives, il existe de nombreux points d’optimisation et schémas de déploiement possibles en fonction de l’architecture choisie. Cependant, vous disposez désormais des éléments indispensables au bon déploiement de vos applications, que vous enrichirez par votre expérience. Nous allons à présent sortir du cadre des applications exécutables à l’aide du navigateur pour aborder le développement d’applications s’exécutant sur le poste client à l’aide du runtime Adobe AIR. =Flex3 FM.book Page 345 Mardi, 2. décembre 2008 3:32 15 19 Adobe AIR Pour terminer la première partie de cet ouvrage, penchons-nous sur la machine virtuelle Adobe AIR (Adobe Integrated Runtime). Grâce à elle, vous pourrez utiliser les méthodes de développement d’applications web s’exécutant sans navigateur web, comme le ferait une application développée en Java, Delphi ou C++. Adobe AIR étant basé sur la technologie Flash, il est donc naturel que le framework Flex donne la possibilité de développer ce nouveau type d’applications portant le nom de RDA (Rich Desktop Application). Le projet Adobe AIR Adobe AIR (anciennement appelé Apollo) est une machine virtuelle, un peu à la manière de la machine virtuelle de Java, permettant l’exécution d’applications web écrites en Flash, HTML, JavaScript ou tout autre langage web. Il convient de souligner qu’une application AIR s’exécutera de la même façon sur l’ensemble des systèmes d’exploitation supportés par la machine virtuelle (Windows, Mac, Linux…), ce qui n’est pas le cas pour d’autres langages. Fonctionnement d’une application AIR Le développement d’une application web AIR s’effectue à l’aide des outils proposés par Adobe (Flash, Flex…) ou ses partenaires. Une fois le développement terminé, l’application est exportée au format AIR puis proposée en téléchargement aux utilisateurs. Une fois téléchargée, il suffit de l’installer. Cependant, la machine virtuelle d’Adobe doit être présente sur le poste de l’utilisateur. Après l’installation, une icône apparaîtra sur le Bureau du poste de l’utilisateur, lui permettant d’exécuter l’application téléchargée. Ceci témoigne de la volonté des développeurs d’Abode AIR d’accorder autant d’importance à une =Flex3 FM.book Page 346 Mardi, 2. décembre 2008 3:32 15 346 Comprendre Flex 3 PARTIE I application web qu’à une application standard en ne la cantonnant plus à son exécution dans un navigateur web. Pour vous convaincre de la puissance de ces applications « nouvelle génération », nous vous invitons à visiter le site d’Adobe à l’adresse suivante : http://www.adobe.com/ products/air/showcase/. Vous y trouverez de nombreux exemples d’applications web AIR. Cette technologie est aujourd’hui utilisée par de grandes entreprises telles que eBay, Yahoo! ou encore AOL, ce qui atteste de sa fiabilité et de son intérêt commercial non négligeable. Nouveaux composants Comme nous venons de le voir, Adobe AIR exporte le monde des RIA (Rich Internet Application) directement sur le poste de l’utilisateur (RDA – Rich Desktop Application). Cette innovation va également donner naissance à une nouvelle fonctionnalité fort intéressante : l’accès aux données du disque dur de l’utilisateur à l’aide de composants spécifiques. Le tableau 19-1 présente l’ensemble des composants Adobe AIR et leur implémentation, illustrés page 348 (figures 19-1-a à 19-1-e). Tableau 19-1 Les composants spécifique à Adobe AIR Composant Implémentation FileSystemComboBox <mx:Script> <![CDATA[ Permet d’afficher les répertoires et leur contenu dans une liste déroulante. // Importation de la classe de gestion des fichiers import flash.filesystem.File; ]]> </mx:Script> <!-- Le répertoire parcouru est le Bureau de l’utilisateur: ➥File.desktopDirectory --> <mx:FileSystemComboBox id="listeFichiersListeDeroulante" x="10" ➥y="59" directory="{File.desktopDirectory}" /> FileSystemDataGrid Permet d’afficher les répertoires et leur contenu dans un tableau. FileSystemList Permet d’afficher les répertoires et leur contenu dans une liste. <mx:Script> <![CDATA[ import flash.filesystem.File; ]]> </mx:Script> <mx:FileSystemDataGrid id="listeFichiersTableau" x="10" y="133" ➥directory="{File.desktopDirectory}" /> <mx:Script> <![CDATA[ import flash.filesystem.File; ]]> </mx:Script> <mx:FileSystemList id="listeFichiersListe" x="10" y="328" ➥width="502" height="104" directory="{File.desktopDirectory}" /> =Flex3 FM.book Page 347 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 Tableau 19-1 Les composants spécifique à Adobe AIR (suite) Composant Implémentation FileSystemTree <mx:Script> <![CDATA[ import flash.filesystem.File; ]]> </mx:Script> <mx:FileSystemTree id="listeFichiersArbre" x="10" y="466" ➥width="502" height="102" directory="{File.desktopDirectory}" /> Permet d’afficher les répertoires et leur contenu sous forme d’arborescence. FileSystemHistoryButton Permet de conserver un historique des répertoires visités. Cet exemple met en relation le composant FileSystemList et deux composants FileSystemHistoryButton chargés d’enregistrer la navigation effectuée dans le premier composant. Cet enregistrement permet à l’utilisateur de revenir rapidement à un répertoire déjà visité. Les commentaires ne sont insérés qu’a titre indicatif. Il convient de ne pas les mentionner dans votre code à l’intérieur du composant FileSystemHistoryButon comme nous l’avons fait, sous peine d’être confronté à un problème d’exécution de votre projet. <mx:Script> <![CDATA[ import flash.filesystem.File; ]]> </mx:Script> <mx:HBox x="10" y="576"> <mx:FileSystemHistoryButton label="Precedent" <!-- Stockage des répertoires parcourus --> dataProvider="{listeFichiers.backHistory}" <!-- Activation de la navigation antérieure sur le ➥composant listeFichiers --> enabled="{listeFichiers.canNavigateBack}" <!-- Action de retour en arrière déclenchée lors du ➥clic par l'utilisation --> click="listeFichiers.navigateBack();" <!-- Récupération de l'item sélectionné --> itemClick="listeFichiers.navigateBack(event.index)"/> <mx:FileSystemHistoryButton label="Suivant" dataProvider="{listeFichiers.forwardHistory}" enabled="{listeFichiers.canNavigateForward}" click="listeFichiers.navigateForward();" itemClick="listeFichiers.navigateForward(event.index)"/> </mx:HBox> <mx:FileSystemList id="listeFichiers" x="10" y="606" ➥height="102" width="503"/> 347 =Flex3 FM.book Page 348 Mardi, 2. décembre 2008 3:32 15 348 Comprendre Flex 3 PARTIE I Figure 19-1-a Le nouveau composant FileSystemComboBox Figure 19-1-b Le nouveau composant FileSystemDataGrid Figure 19-1-c Le nouveau composant FileSystemList Figure 19-1-d Le nouveau composant FileSystemTree Figure 19-1-e Le nouveau composant FileSystemHistoryButton =Flex3 FM.book Page 349 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 349 Soulignons également la présence du composant HTML qui permet d’implémenter la visualisation de pages HTML. La portion de code suivante illustre cette fonctionnalité en offrant la possibilité à l’utilisateur d’effectuer des recherches à l’aide de Google : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥height="782"> <mx:HTML id="composantHTML” x="10" y="40" width="608" height="502" location="http://www.google.fr" /> </mx:WindowedApplication> Cet exemple peut également servir de base à la réalisation de votre propre navigateur web, mais pour cela, il convient auparavant de voir comment créer des applications Adobe AIR à l’aide de Flex Builder 3. Première application AIR Grâce à Flex Builder 3, il nous est possible de créer nos propres applications AIR. En guise d’exemple, nous vous proposons de créer une application mettant en œuvre un service web capable de récupérer l’évolution du CAC 40. Vous trouverez ce service web à l’adresse suivante : http://www.webservicex.net/. Création du projet La première étape consiste à créer un nouveau projet Adobe AIR que nous nommerons CAC40. Pour cela, cochez l’option Desktop application (runs in Adobe AIR) située sur la fenêtre de création d’un nouveau projet Flex (figure 19-2). Figure 19-2 Création d’une application Adobe AIR =Flex3 FM.book Page 350 Mardi, 2. décembre 2008 3:32 15 350 Comprendre Flex 3 PARTIE I Procédez ensuite comme vous le feriez pour créer un nouveau projet Flex standard. Une fois la création de l’application terminée, nous pouvons constater que l’arborescence du projet Adobe AIR est identique à celle d’un projet Flex. Nous remarquons également la disparition, dans le répertoire bin-debug, des fichiers permettant la gestion du navigateur web et du Flash Player (AC_OETags.js, History.htm…). En effet, ceux-ci ne sont plus nécessaires étant donné que l’application s’exécute sous la forme d’une application locale. Il est également intéressant de souligner que le fichier principal de l’application est un fichier MXML. Nous emploierons donc les mêmes méthodes de développement qu’auparavant. Si nous nous rendons dans le répertoire contenant les sources de ce fichier, nous constatons la présence d’un élément qui distingue une application Adobe AIR d’une application Flex : le remplacement de la balise <mx:Application> par la balise <mx:WindowedApplication>. Il s’agit là de la seule différence entre un projet Flex standard et un projet Flex Adobe AIR, le terme Windowed (fenêtré) évoquant bien la notion d’application bureautique. Pour preuve, voici le code que nous allons implémenter pour faire appel à notre service : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥width="368" height="310" horizontalScrollPolicy="off" verticalScrollPolicy="off" ➥usePreloader="true"> <mx:WebService id = "serviceCAC40" wsdl="http://www.webservicex.net/stockquote.asmx?WSDL" showBusyCursor="true"> <mx:operation name="GetQuote" resultFormat="object" fault="resultatKO(event)" ➥result="resultatOK(event)"> </mx:operation> </mx:WebService> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; public function resultatKO(e:FaultEvent):void { Alert.show("Erreur "+e.fault.faultString) } =Flex3 FM.book Page 351 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 351 public function resultatOK(e:ResultEvent):void { var resultat:XML = new XML(e.result) txt_entreprise.text = resultat.Stock[0].Name; txt_date.text = resultat.Stock[0].Date; txt_heure.text = resultat.Stock[0].Time; txt_quotation.text = resultat.Stock[0].Last; txt_evolution.text = resultat.Stock[0].Earns; txt_variation.text = resultat.Stock[0].AnnRange; } public function invoquerService():void { serviceCAC40.GetQuote("CAC 40"); } ]]> </mx:Script> <mx:Button x="10" y="10" label="Invoquer le service" width="347" ➥click="invoquerService()"/> <mx:Panel x="10" y="40" width="347" height="254" layout="absolute" ➥title="Quotation"> <mx:Form x="10" y="10" width="307" height="199" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:FormItem label="Entreprise :"> <mx:TextInput width="150" id="txt_entreprise" editable="false"/> </mx:FormItem> <mx:FormItem label="Date :"> <mx:TextInput width="150" id="txt_date" editable="false"/> </mx:FormItem> <mx:FormItem label="Heure :"> <mx:TextInput width="150" id="txt_heure" editable="false"/> </mx:FormItem> <mx:FormItem label="Quotation :"> <mx:TextInput width="150" id="txt_quotation" editable="false"/> </mx:FormItem> <mx:FormItem label="Gain/Perte :"> <mx:TextInput width="150" id="txt_evolution" editable="false"/> </mx:FormItem> <mx:FormItem label="Variation annuelle :"> <mx:TextInput width="150" id="txt_variation" editable="false"/> </mx:FormItem> </mx:Form> </mx:Panel> </mx:WindowedApplication> Le code utilisé ici est identique à celui que nous aurions implémenté pour une application exécutée dans un navigateur. =Flex3 FM.book Page 352 Mardi, 2. décembre 2008 3:32 15 352 Comprendre Flex 3 PARTIE I Exécutons à présent l’application (figure 19-3). Elle semble fonctionner correctement, néanmoins, au lieu de s’exécuter dans le navigateur web, elle se présente sous la forme d’une application standard. Figure 19-3 Exécution de l’application Nous vous laissons donc imaginer les innombrables perspectives qu’offrent ces applications : dynamisme d’une application Flash exécutable sur tout environnement supportant la machine virtuelle d’Adobe AIR, codée comme une application web, mais utilisable comme un logiciel standard. La barrière entre les logiciels et les applications web vient d’être franchie. Déploiement de l’application Le déploiement d’une application AIR à l’aide de Flex Builder 3 s’effectue de la même manière que pour une application Flex standard, c’est-à-dire en exportant le projet vers une version de déploiement (Release Build). Afin de sécuriser vos applications et assurer un gage d’authenticité aux utilisateurs, il est conseillé lors de la phase de déploiement de leur affecter un certificat. Si vous n’en possédez pas encore, il vous est possible d’en créer un en cliquant sur le l’icône Create de la fenêtre de déploiement. Si nous revenons à notre exemple, le fichier issu du déploiement n’est plus un fichier SWF comme nous en avons maintenant l’habitude, mais un fichier AIR : CAC40.air. Format de fichier AIR sans certificat Si vous ne spécifiez aucun certificat pour votre application, le fichier issu de la compilation sera de type AIRI (pour AIR Intermediate). =Flex3 FM.book Page 353 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 353 Pour déployer notre application, il suffit de copier ce fichier sur un serveur web à partir duquel les utilisateurs pourront le télécharger et l’installer sur leur poste. Ils devront cependant installer au préalable la machine virtuelle AIR, disponible à l’adresse suivante : http://get.adobe.com/air/ (figure 19-4). Figure 19-4 Installation de la machine virtuelle Adobe AIR Sur le poste client Le processus d’installation de l’application sur le poste client comprend les trois étapes suivantes (figure 19-5) : Figure 19-5 Processus d’installation de l’application sur le poste client 1. Demande de confirmation et spécification du répertoire d’installation. =Flex3 FM.book Page 354 Mardi, 2. décembre 2008 3:32 15 354 Comprendre Flex 3 PARTIE I 2. Création du raccourci sur le Bureau. 3. Exécution de l’application. Une fois la machine virtuelle Adobe AIR installée, l’utilisateur possède une application web qu’il exécutera sur son poste de la même façon que l’ensemble des applications qu’il utilise quotidiennement. Gestion des données avec la bibliothèque SQLite L’application que nous venons de développer fait appel à un service web, qui nous retourne des informations stockées sur un serveur distant. Comme nous l’avons vu, une application AIR peut être dotée de composants capables d’interagir avec l’ordinateur sur lequel elle est installée (par exemple en accédant aux fichiers stockés sur le disque dur). De la même manière, la bibliothèque SQLite nous permet de stocker des données sur le poste de l’utilisateur, les rendant ainsi exploitables par toute application AIR. La bibliothèque SQLite est un ensemble de fichiers écrits en langage C, permettant d’implémenter un moteur SQL au sein d’une application. Contrairement à une base de données classique (la communication avec l’application est basée sur le schéma client/ serveur), la base de donnée est alors « embarquée » dans l’application elle-même : les données ne sont plus stockées dans des tables mais dans des fichiers textes. Malgré cela, SQLite est basé sur la norme SQL92. Ceci nous permet donc d’utiliser les instructions du langage SQL telles que CREATE TABLE pour la création de table, UPDATE TABLE pour la modification de données, etc. Cependant, il est impossible de gérer les clés étrangères (FOREIGN KEY), de créer des jointures externes (RIGHT/LEFT OUTER JOIN), de gérer les droits des utilisateurs (GRANT/REVOKE) ou encore de supprimer ou de modifier des colonnes d’une table. Cependant, nous disposons tout de même des instructions principales du langage SQL permettant de gérer les données comme nous le ferions dans une base de données classique. Utiliser la bibliothèque SQLite dans une application AIR Il est facile de faire intervenir la bibliothèque SQLite dans une application AIR car elle est déjà intégrée au framework. Pour l’utiliser, il suffit donc de faire appel aux classes détaillées dans le tableau 19-2. Tableau 19-2 Classe Classes nécessaires à l’utilisation de SQLite Description flash.filesystem.File Permet de manipuler des fichiers sur le poste de l’utilisateur de l’application. flash.data.SQLConnection Gère les connexions au moteur de la base de données. flash.data.SQLStatement Permet d’exécuter des requêtes. flash.data.SQLResult Chargé d’accéder aux résultats des requêtes. =Flex3 FM.book Page 355 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 355 Le code ci-dessous, démontre l’usage de ces classes en réalisant la création d’une base de données et d’une table test : import import import import flash.data.SQLResult; flash.filesystem.File; flash.data.SQLStatement; flash.data.SQLConnection; public function utilisationSQLite():void{ //Création du fichier de bases de données sur le disque dur C var fichier:File = new File("C:/baseDeDonnees.db"); //Création d’une nouvelle connexion au moteur de base de données var sqlConnection:SQLConnection= new SQLConnection(); //Ouverture du fichier de la base de données sqlConnection.open(fichier); //Création d’une nouvelle requête var requete:SQLStatement = new SQLStatement(); //Précision sur la connexion devant être utilisée pour l’exécution de la ➥requête requete.sqlConnection = sqlConnection; //Création de la requête à l’aide du langage SQL requete.text = "CREATE TABLE tb_test (id INTEGER PRIMARY KEY AUTOINCREMENT )"; //Exécution de la requête requete.execute(); } SQLite par l’exemple Pour illustrer la mise en place de la librairie SQLite au sein d’une application AIR, développons un carnet d’adresses. Ce projet, somme toute assez simple dans sa composition, stockera les données nominatives des personnes répertoriées dans le carnet d’adresses. L’interface graphique sera composée : • d’un tableau contenant l’ensemble des contacts ; • d’un formulaire permettant de manipuler les données d’un contact ; • d’un bouton d’ajout ; • d’un bouton de modification ; • d’un bouton de suppression ; • d’un bouton d’annulation. =Flex3 FM.book Page 356 Mardi, 2. décembre 2008 3:32 15 356 Comprendre Flex 3 PARTIE I Commençons donc par implémenter cette interface après avoir bien entendu créé un nouveau projet Adode Air que nous nommerons airContact : <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" > <mx:Panel x="10" y="10" width="430" height="375" layout="absolute" ➥title="Carnet d'adresses" id="pan_carnet"> <!-- TABLEAU --> <mx:DataGrid id="dgContacts" x="10" y="10" width="390"> <mx:columns> <mx:DataGridColumn headerText="Id" dataField="col0" ➥width="30"/> <mx:DataGridColumn headerText="Prénom" dataField= ➥"col1"/> <mx:DataGridColumn headerText="Nom" dataField= ➥"col2"/> </mx:columns> </mx:DataGrid> <!-- FORMULAIRE --> <mx:Form x="10" y="177" width="390" height="107" ➥verticalScrollPolicy="off" horizontalScrollPolicy="off"> <mx:FormItem label="Id"> <mx:TextInput id="txt_id" width="52" editable="false" ➥enabled="false"/> </mx:FormItem> <mx:FormItem label="Prénom : "> <mx:TextInput id="txt_prenom"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="txt_nom"/> </mx:FormItem> </mx:Form> <!-- BOUTONS --> <mx:Button id="btn_ajouter" x="330" y="297" label="Ajouter" /> <mx:Button id="btn_modifier" x="169" y="297" label="Modifier" /> <mx:Button id="btn_supprimer" x="73.5" y="297" label="Supprimer" /> <mx:Button x="251" y="297" label="Annuler" id="btn_annuler" /> </mx:Panel> </mx:WindowedApplication> =Flex3 FM.book Page 357 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 357 Vient ensuite la mise en place de la logique d’interface qui, dans notre cas, peut se définir par les règles suivantes : • À l’initialisation de l’interface, seul le bouton Ajouter est actif. • Si l’utilisateur sélectionne un contact dans le datagrid, seuls les boutons Supprimer, Modifier et Annuler seront actifs. Pour traduire ces règles, nous mettons en place les procédures ActionScript suivantes (le résultat obtenu est illustré par la figure 19-06) : Figure 19-06 Création de l’interface graphique <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="initialisationIHM()" > <mx:Script> <![CDATA[ public function initialisationIHM():void { txt_id.text = ""; txt_nom.text=""; txt_prenom.text=""; btn_ajouter.enabled = true; btn_modifier.enabled = false; =Flex3 FM.book Page 358 Mardi, 2. décembre 2008 3:32 15 358 Comprendre Flex 3 PARTIE I btn_supprimer.enabled = false; btn_annuler.enabled = false; } public function modifiationSuppressionIHM():void{ btn_ajouter.enabled = false; btn_modifier.enabled = true; btn_supprimer.enabled = true; btn_annuler.enabled = true; } ]]> </mx :Script> […] </mx:WindowedApplication> La dernière étape consiste à implémenter les procédures d’affichage, d’ajout, de modification et de suppression des données qui seront déclenchées par l’action de l’utilisateur sur les différents éléments de l’interface : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="initialisationIHM();SqliteConnection()"> <mx:Script> <![CDATA[ import mx.events.ListEvent; //Importation des classes nécessaires à SQLite import flash.data.SQLResult; import flash.filesystem.File; import flash.data.SQLStatement; import flash.data.SQLConnection; public function initialisationIHM():void { txt_id.text = ""; txt_nom.text=""; txt_prenom.text=""; btn_ajouter.enabled = true; btn_modifier.enabled = false; btn_supprimer.enabled = false; btn_annuler.enabled = false; } public function modifiationSuppressionIHM():void{ btn_ajouter.enabled = false; btn_modifier.enabled = true; =Flex3 FM.book Page 359 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 btn_supprimer.enabled = true; btn_annuler.enabled = true; } //Création d'une variable de connexion qui sera utilisée dans //l'ensemble des procédures public var sqlConnection:SQLConnection; //Connexion au moteur de base de données public function SqliteConnection():void { //Création du fichier de données nommé "base_Contacts.db" var fichier:File = new File("C:/base_contacts.db");; var fichierExiste:Boolean = fichier.exists; sqlConnection = new SQLConnection(); sqlConnection.open(fichier); //Si le fichier n’existe pas, on crée la table chargée de contenir les ➥enregistrements if (!fichierExiste) { creationTable(); } else { //Sinon on liste des contacts listerContacts(); } } //Script de création de la table tb_contact chargée de contenir les contacts ➥du carnet d’adresses private function creationTable():void { var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = sqlConnection; stmt.text = "CREATE TABLE tb_contact (id INTEGER PRIMARY KEY ➥AUTOINCREMENT , prenom longvarchar, nom longvarchar)"; stmt.execute(); } //Listing des contacts [Bindable] public var tableauContacts:Array = new Array(); 359 =Flex3 FM.book Page 360 Mardi, 2. décembre 2008 3:32 15 360 Comprendre Flex 3 PARTIE I public function listerContacts():void { var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = sqlConnection; stmt.text = "SELECT * FROM tb_contact ORDER BY prenom ASC"; stmt.execute(); tableauContacts = stmt.getResult().data; } //Ajout d’un contact public function ajouterContact():void { var prenom:String = txt_prenom.text; var nom:String = txt_nom.text; var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = sqlConnection; stmt.text = "INSERT INTO tb_contact (prenom,nom) VALUES ➥('"+prenom+"','"+nom+"')"; stmt.execute(); listerContacts(); initialisationIHM(); } //Mise à jour d’un contact private function miseAJourContact():void { var id:String = txt_id.text; var prenom:String = txt_prenom.text; var nom:String = txt_nom.text; var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = sqlConnection; stmt.text = "UPDATE tb_contact SET prenom ='"+prenom+"', nom = '"+nom+"' ➥WHERE id ='"+id+"'" ; stmt.execute(); //Mise à jour du tableau de données listerContacts(); //Initialisation de l’interface graphique initialisationIHM(); } //Suppression d’un contact public function supprimerContact():void { var id:String = txt_id.text; var stmt:SQLStatement = new SQLStatement(); stmt.sqlConnection = sqlConnection; =Flex3 FM.book Page 361 Mardi, 2. décembre 2008 3:32 15 Adobe AIR CHAPITRE 19 361 stmt.text = "delete from tb_contact WHERE id ='"+id+"'"; stmt.execute(); listerContacts(); initialisationIHM(); } //Affichage des données d’un contact après l’avoir sélectionné dans le tableau public function afficherDonneesContact():void { txt_id.text = dgContacts.selectedItem.id; txt_prenom.text = dgContacts.selectedItem.prenom; txt_nom.text = dgContacts.selectedItem.nom; modifiationSuppressionIHM(); } ]]> </mx:Script> <mx:Panel x="10" y="10" width="430" height="375" layout="absolute" title="Carnet ➥d'adresses" id="pan_carnet"> <!-- TABLEAU --> <mx:DataGrid id="dgContacts" x="10" y="10" width="390" dataProvider ➥="{tableauContacts}" itemClick="afficherDonneesContact()"> <mx:columns> <mx:DataGridColumn headerText="Id" dataField="id" ➥width="30"/> <mx:DataGridColumn headerText="Prénom" ➥dataField="prenom"/> <mx:DataGridColumn headerText="Nom" dataField="nom"/> </mx:columns> </mx:DataGrid> <!-- FORMULAIRE --> <mx:Form x="10" y="177" width="390" height="107" ➥verticalScrollPolicy="off" horizontalScrollPolicy="off"> <mx:FormItem label="Id"> <mx:TextInput id="txt_id" width="52" editable="false" ➥enabled="false"/> </mx:FormItem> <mx:FormItem label="Prénom : "> <mx:TextInput id="txt_prenom"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput id="txt_nom"/> </mx:FormItem> =Flex3 FM.book Page 362 Mardi, 2. décembre 2008 3:32 15 362 Comprendre Flex 3 PARTIE I </mx:Form> <!-- BOUTONS --> <mx:Button id="btn_ajouter" x="330" y="297" label="Ajouter" ➥click="ajouterContact()" /> <mx:Button id="btn_modifier" x="169" y="297" label="Modifier" ➥click="miseAJourContact()" /> <mx:Button id="btn_supprimer" x="73.5" y="297" label="Supprimer" ➥click="supprimerContact()" /> <mx:Button x="251" y="297" label="Annuler" id="btn_annuler" ➥click="initialisationIHM()" /> </mx:Panel> </mx:WindowedApplication> En exécutant l’application, vous notez la création du fichier base_contacts.db à la racine de votre disque dur C. Les instructions SQL sont bien réalisées lorsque vous cliquez sur les différents éléments de l’interface. Ce petit exemple nous a permis de voir qu’une application AIR peut facilement rendre les mêmes services qu’une application bureautique classique (les données ne sont certes plus distantes du poste utilisateur comme elles le seraient pour une application web). Adobe AIR constitue donc une solution de développement bureautique intéressante et à surveiller. En résumé Au cours de ce chapitre, nous avons vu les bases du développement d’applications AIR. Désormais, vous êtes en mesure de créer, à partir d’un langage dédié au Web, des applications pouvant être installées et exécutées sur des postes clients, comme c’est le cas les langages Java et C++, pour n’en citer que deux. Ceci sonne-t-il le glas des applications dites standard ? Il serait prématuré d’avancer cela car certaines applications sont optimisées en fonction de l’environnement sur lequel elles sont exécutées, ce qui est actuellement impossible à réaliser pour une application AIR. Toutefois, nous pouvons déjà affirmer que ce type d’application a un avenir prometteur et que cette technologie mérite d’être suivie de très près. =Flex3 FM.book Page 363 Mardi, 2. décembre 2008 3:32 15 Partie II Cas pratiques =Flex3 FM.book Page 364 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 365 Mardi, 2. décembre 2008 3:32 15 20 Création d’un projet de site e-commerce Nous voici à présent dans le premier chapitre consacré à la mise en pratique des connaissances acquises dans la première partie de cet ouvrage. Pour essayer d’être le plus proche des besoins des entreprises en termes de réalisation d’application Internet, nous avons choisi de développer une application de type e-commerce. Pour mener à bien ce projet, nous commencerons par définir les besoins et les concevoir, pour ensuite déterminer l’architecture applicative que nous allons adopter. Viendront enfin la création du projet proprement dite et la configuration du serveur chargé de contenir la couche métier et la couche de persistance des données. Définition des besoins E-Reflex est une société spécialisée dans la vente en ligne d’appareils photo numériques. Pour dynamiser ses ventes et être en adéquation avec son produit de haute technologie, la société souhaite effectuer la refonte de son site actuel avec le framework Flex. Le dirigeant de la société E-Reflex souhaite que le projet puisse conserver son rôle de site vitrine mais désire également dédier une partie du site aux commerciaux et gestionnaires de stocks de l’entreprise. Ils pourront saisir les caractéristiques des produits en ligne mais également avoir une vue d’ensemble sur les stocks de chacun d’eux. Bien sûr, il est important que seuls les commerciaux et les membres de la société aient accès à cette partie du site. Pour la partie « vente en ligne », nous avons interrogé le dirigeant de la société afin qu’il nous en décrive le processus : =Flex3 FM.book Page 366 Mardi, 2. décembre 2008 3:32 15 366 Cas pratiques PARTIE II « Après avoir effectué une recherche sur la page d’accueil du site, l’utilisateur peut visualiser le détail du produit. Si ce produit l’intéresse et convient à ses attentes, il peut alors l’ajouter à son panier d’achat. La règle de gestion de base stipule qu’une commande donne naissance à une et une seule facture. Néanmoins, si l’utilisateur souhaite payer en plusieurs fois, il devra contacter notre service commercial qui pourra échelonner le paiement de sa commande éditant ainsi plusieurs factures. Une autre chose très importante à signaler est que l’échéance de paiement d’une facture est prévue à 30 jours après sa date de création. » Il nous faut maintenant réaliser la conception de toutes ces informations. Conception UML Grâce aux explications du dirigeant, nous savons que l’entreprise propose à la vente des produits achetés chez des fournisseurs. Nous allons donc représenter cette relation via un diagramme de classes UML : Figure 20-1 Diagramme de classe « Fournisseur – Appareil photo » Après nous être renseignés auprès des commerciaux de l’entreprise, nous avons réalisé le diagramme de classes illustré par la figure 20-1. La règle de gestion qui en découle est qu’un appareil n’est disponible que chez un seul fournisseur. Nous avons également décrit les attributs nécessaires à la gestion de stock : • L’attribut stock détermine le nombre d’appareils actuellement en stock pour un appareil donné. • L’attribut stock_minimal fixe le seuil minimal qui, une fois dépassé, informe les commerciaux qu’une commande du produit devra être effectuée chez le fournisseur. • L’attribut stock_maximal sert à déterminer le nombre de produits qui doivent être en stock une fois la commande réalisée. =Flex3 FM.book Page 367 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 367 Attardons-nous à présent sur le processus de commande et de facturation. Figure 20-2 Diagramme de classes complet D’après le diagramme de classes de la figure 20-2, nous pouvons déterminer qu’un utilisateur peut effectuer plusieurs commandes pouvant comporter chacune plusieurs appareils photo. Comme nous l’a indiqué le dirigeant de l’entreprise E-Reflex, cette commande peut donner lieu à plusieurs factures. Si nous observons attentivement la classe utilisateur, nous apercevons l’ensemble des attributs nécessaires à son identification (login, motDePasse) ainsi que l’attribut administrateur_site lui donnant accès ou non à la partie administration du site. Enfin n’oublions pas que toute commande effectuée influe sur la gestion du stock de chaque appareil photo : les informations de stock devront être mises à jour à chaque nouvelle commande d’un produit. Maintenant que nous avons les idées claires sur les souhaits des =Flex3 FM.book Page 368 Mardi, 2. décembre 2008 3:32 15 368 Cas pratiques PARTIE II utilisateurs et que nous en avons réalisé la conception, il est temps de passer à l’étude de l’architecture de notre projet. Architecture du projet Étant donné que le site doit être doté de deux parties distinctes (gestion des produits et vente en ligne), nous devons optimiser l’architecture du projet de telle sorte que le visiteur ne télécharge que la partie du site qui le concerne en fonction de son accréditation. C’est pour cela que le projet sera basé sur une architecture modulaire. En procédant de cette façon, nous découpons le projet en sous-applications, optimisant ainsi son exécution et le temps de chargement. Le site comportera donc deux modules, à savoir le module de gestion de produit et le module de vente en ligne. L’ensemble sera contenu dans une application principale, qui constituera le squelette du site E-Reflex. Le module de gestion des produits permettra aux administrateurs du site de gérer les fournisseurs et les produits associés (ajout, suppression, modification, gestion de stock…). Quant au module de vente en ligne, il permettra aux utilisateurs : • de créer un compte client ; • d’effectuer des recherches sur l’ensemble des produits proposés par la société E-Reflex ; • d’ajouter des articles à leur panier d’achat ; • de réaliser une commande ; • de payer en ligne. Création du projet Voilà, nous y sommes, nous avons identifié les besoins, réalisé la conception et déterminé l’architecture globale de notre projet. Il est temps à présent de passer à sa réalisation. Alors, allons-y ! Qu’allons nous réaliser ? Nous avons souhaité que la partie « Étude de cas » soit à la fois pratique et source d’enseignements. Notre objectif est de vous fournir une méthodologie de travail à adopter pour la réalisation d’applications avec le framework Flex. Nous n’allons donc pas décrire l’ensemble des lignes de code permettant d’obtenir un projet complet et fonctionnel, mais plutôt vous donner les éléments pour le réaliser vous-même, en vous indiquant ce qu’il faut et ne faut pas faire. C’est en prenant conscience de nos erreurs que nous avançons. Il serait donc inutile de décrire par la suite la réalisation complète du projet : beaucoup d’étapes seraient redondantes et n’apporteraient rien. Nous allons donc nous consacrer à certaines parties du projet qui nous paraissent importantes et vous permettront d’appliquer vos connaissances et d’en acquérir de nouvelles. Néanmoins, vous pouvez télécharger une version complète et finalisée de ce projet sur la fiche ouvrage sur le site des éditions Eyrolles : http://www.editions-eyrolles.com. =Flex3 FM.book Page 369 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 369 Le squelette Nous allons commencer par créer le squelette du site. Sa fonction principale sera de contenir les deux modules applicatifs et de servir de point d’entrée des utilisateurs dans l’application. Pour cela, ouvrons Flex Builder et créons un nouveau projet de type web portant le nom eReflex. Ceci fait, nous allons pouvoir réaliser l’interface graphique du site qui sera constituée : • du logo de la société ; • du composant viewStack chargé de contenir les modules ; • d’une barre de navigation comportant une zone d’identification et deux boutons permettant d’accéder à la partie vitrine ou administration du site. Conseil Pour stocker les images du site (logo et autres éléments d’identité graphiques), nous vous conseillons de créer un sous-répertoire images dans le répertoire src du projet. Logo de l’application Le logo de l’application doit avoir les dimensions suivantes : Largeur : 900 pixels Hauteur : 94 pixels Il vous est donc possible d’en créer un à votre convenance ou d’utiliser celui présent dans les sources de l’application. La figure 20-3 illustre le résultat obtenu après avoir saisi (dans le fichier ereflex.mxml du projet) et exécuté le code ci-dessous : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Canvas width="900" height="730" horizontalCenter="0" verticalCenter="0"> <!-- LOGO --> <mx:Image x="0" y="0" height="95" width="900" source="images/logo.jpg"/> <!-- BARRE DE MENUS --> <mx:ApplicationControlBar x="0" y="97" height="30" width="900"> <mx:Button label="Accueil" id="btn_accueil" click="conteneurVues ➥.selectedIndex = 0"/> <mx:Button label="Administration" id="btn_administration" ➥click="conteneurVues.selectedIndex = 1"/> =Flex3 FM.book Page 370 Mardi, 2. décembre 2008 3:32 15 370 Cas pratiques PARTIE II Figure 20-3 Interface graphique du projet <mx:Canvas width="686" height="22"> <mx:Label x="144" y="2" text="Identifiant :" fontWeight="bold" ➥id="lab_identifiant"/> <mx:Label x="365" y="2" text="Mot de passe :" fontWeight="bold" ➥id="lab_motDePasse"/> <mx:TextInput x="226" y="0" width="118" id="txt_identifiant"/> <mx:TextInput x="459" y="0" width="119" displayAsPassword="true" ➥id="txt_motDePasse"/> <mx:Button x="586" y="1" label="Connecter" id="btn_action" /> </mx:Canvas> </mx:ApplicationControlBar> <!-- CONTENEUR DE VUES --> <mx:ViewStack id="conteneurVues" x="0" y="132" width="900" height="590"> <mx:Canvas id="vueAccueil" label="Accueil" width="100%" height="100%"> <mx:Label x="10" y="10" text="ACCUEIL"/> </mx:Canvas> =Flex3 FM.book Page 371 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 371 <mx:Canvas id="vueAdministration" label="Administration" width="100%" ➥height="100%"> <mx:Label x="10" y="10" text="GESTION DES PRODUITS"/> </mx:Canvas> </mx:ViewStack> </mx:Canvas> </mx:Application> La barre de navigation contient les boutons Accueil et Administration, faisant chacun appel à une vue du composant ViewStack. Ainsi le bouton Accueil, affiche la vue portant l’index 0 (correspondant au module de vente en ligne) et le bouton Administration affiche la vue de gestion des produits. Vous pouvez également constater la présence de zones de saisie servant à l’identification de l’utilisateur pour lui permettre d’accéder à la partie administration du site. L’étape suivante va consister à créer nos premières procédures ActionScript permettant de sécuriser l’accès à l’espace d’administration du site. Accès à l’espace d’administration L’idée est de définir un identifiant et un mot de passe qui seront codés dans l’application. Si l’utilisateur saisit correctement ces informations, il aura alors accès à la partie administration du site, sinon un message d’erreur s’affichera à l’écran. Pour réaliser cela, nous devons définir la logique de fonctionnement de l’interface graphique, c’est-à-dire l’état des composants avant et après la connexion. Réalisons le tableau suivant : Tableau 20-1 Logique de fonctionnement de l’interface graphique Action/ composants Bouton Administration Libellés identifiant et mot de passe Zones de texte Bouton de connexion État initial Invisible Visibles Visibles et vides Visible, porte le libellé Connecter Connexion reussie Visible Invisibles Invisibles Visible, porte le libellé Déconnecter À partir de ce tableau, nous pouvons facilement déduire le principe de connexion suivant : lorsque l’utilisateur se connecte, les zones d’identification disparaissent et le bouton Administation devient accessible. Néanmoins, une subtilité réside dans le libellé du bouton de connexion : à l’état initial, il porte le libellé Connecter ; une fois la connexion réalisée, son libellé devient Déconnecter. Cela permettra de réaliser les actions de connexion et de déconnexion avec un seul et même bouton. =Flex3 FM.book Page 372 Mardi, 2. décembre 2008 3:32 15 372 Cas pratiques PARTIE II Voyons comment implémenter ceci : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="initialisationIHM()"> <mx:Script> <![CDATA[ import mx.controls.Alert; //Procédure de connexion private function connexion():void { if (btn_action.label == "Connecter") { if (txt_identifiant.text == 'abc' && txt_motDePasse.text=='1234') { connexionIHM(); } else { Alert.show("Accès refusé") } } else { initialisationIHM() } } //Initialisation de l’interface graphique private function initialisationIHM():void { btn_administration.visible = false; lab_identifiant.visible = true; lab_motDePasse.visible = true; txt_identifiant.visible = true; txt_motDePasse.visible=true; btn_action.label= "Connecter" } //Une fois que l’on est connecté, certains éléments de l’interface sont visibles ➥d’autres sont cachés private function connexionIHM():void { btn_administration.visible = true; lab_identifiant.visible = false; lab_motDePasse.visible = false; txt_identifiant.visible = false; txt_motDePasse.visible=false; txt_identifiant.text = ""; txt_motDePasse.text = ""; =Flex3 FM.book Page 373 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 373 btn_action.label= "Déconnecter" } ]]> </mx:Script> <mx:Canvas width="900" height="730" horizontalCenter="0" verticalCenter="0"> […] <!-- BARRE DE MENUS --> <mx:ApplicationControlBar x="0" y="97" height="30" width="900"> <mx:Button label="Accueil" id="btn_accueil" click="conteneurVues ➥.selectedIndex = 0"/> <mx:Button label="Administration" id="btn_administration" ➥click="conteneurVues.selectedIndex = 1"/> <mx:Canvas width="686" height="22"> <mx:Label x="144" y="2" text="Identifiant :" fontWeight="bold" ➥id="lab_identifiant"/> <mx:Label x="365" y="2" text="Mot de passe :" fontWeight="bold" ➥id="lab_motDePasse"/> <mx:TextInput x="226" y="0" width="118" id="txt_identifiant"/> <mx:TextInput x="459" y="0" width="119" displayAsPassword="true" ➥id="txt_motDePasse"/> <mx:Button x="586" y="1" label="Connecter" id="btn_action" ➥click="connexion()"/> </mx:Canvas> </mx:ApplicationControlBar> […] </mx:Canvas> </mx:Application> Voici l’explication fonctionnelle de ce code : lorsque l’utilisateur clique sur le bouton de connexion, le système vérifie le libellé du bouton. Si ce dernier porte le libellé Connecter, le système procède à la vérification de la concordance de l’identifiant et du mot de passe sinon il réinitialise l’interface de connexion (figures 20-4 et 20-5). Figure 20-4 Interface à l’état initial =Flex3 FM.book Page 374 Mardi, 2. décembre 2008 3:32 15 374 Cas pratiques PARTIE II Figure 20-5 Connexion de l’utilisateur réussie Le squelette est à présent terminé. Il ne reste plus qu’à y greffer les modules. Mais avant de procéder à leur développement, il convient de préparer le serveur applicatif. Préparation du serveur Pour la couche métier et la couche de persistance des données, nous allons utiliser le trio PHP/MySQL et AMFPHP. Prérequis : PHP et AMFPHP Nous vous invitons à vérifier que l’environnement PHP est correctement installé et configuré sur votre ordinateur. Si cet environnement n’est pas présent, nous vous conseillons d’utiliser l’application easyPHP pour la partie PHP/MySQL, disponible à l’adresse suivante : http://www.easyphp .org/, où vous pourrez également obtenir de l’aide concernant son installation. AMFPHP L’installation d’AMFPHP est décrite au chapitre 13 de cet ouvrage. La base de données MySQL Voici le script de création de la base de données de notre projet, découlant du diagramme de classes créé lors de la phase de conception. Afin de minimiser le temps de création de la base de données, vous pouvez télécharger ce script sur la fiche du livre, à l’adresse http://www.editions-eyrolles.com. Vous n’aurez plus qu’à l’exécuter sur votre serveur MySQL. --- CREATION DE LA BASE DE DONNEES REFLEX -CREATE DATABASE IF NOT EXISTS reflex; USE reflex; =Flex3 FM.book Page 375 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 --- TABLE `tb_fournisseur` -DROP TABLE IF EXISTS `tb_fournisseur`; CREATE TABLE `tb_fournisseur` ( `id` int(10) unsigned NOT NULL auto_increment, `nom` varchar(45) NOT NULL, `adresse` text NOT NULL, `cp` varchar(6) NOT NULL, `ville` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; --- DONNEES TABLE `tb_fournisseur` -- INSERT INTO `tb_fournisseur` (`id`,`nom`,`adresse`,`cp`,`ville`) VALUES (1,'Fournisseur_1','25, rue basse','59000','Lille'), (2,'Fournisseur_2','24, avenue de la photo','59100','Roubaix'), (3,'Fournisseur_3','58 Av. jean Jaures\rAppt 44','59100','Roubaix'); --- TABLE `tb_appareilphoto` -DROP TABLE IF EXISTS `tb_appareilphoto`; CREATE TABLE `tb_appareilphoto` ( `id` int(10) unsigned NOT NULL auto_increment, `description` text NOT NULL, `prix` double NOT NULL, `stock` int(10) unsigned NOT NULL, `stockmin` int(10) unsigned NOT NULL, `stockmax` int(10) unsigned NOT NULL, `prixha` double NOT NULL, `fournisseur` int(10) unsigned NOT NULL, `nom` varchar(45) NOT NULL, PRIMARY KEY USING BTREE (`id`), KEY `FK_tb_appareilphoto_1` (`fournisseur`), CONSTRAINT `FK_tb_appareilphoto_1` FOREIGN KEY (`fournisseur`) REFERENCES ➥`tb_fournisseur` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; --- DONNEES TABLE `tb_appareilphoto` 375 =Flex3 FM.book Page 376 Mardi, 2. décembre 2008 3:32 15 376 Cas pratiques PARTIE II -- INSERT INTO `tb_appareilphoto` (`id`,`description`,`prix`,`stock`,`stockmin`, ➥`stockmax`,`prixha`,`fournisseur`,`nom`) VALUES (1,'Description',200,10,5,20,150,1,'Appareil_1'), (2,'Description',50,5,2,20,30,1,'Appareil_2'), (3,'Description',90,50,10,100,40,2,'Appareil_3'), (4,'Description',180,4,1,84,100,2,'Appareil_4'), (5,'description',500,2,0,3,400,2,'Appareil_5'); --- TABLE `tb_utilisateur` -DROP TABLE IF EXISTS `tb_utilisateur`; CREATE TABLE `tb_utilisateur` ( `id` int(10) unsigned NOT NULL auto_increment, `prenom` varchar(20) NOT NULL, `nom` varchar(20) NOT NULL, `login` varchar(10) NOT NULL, `motpasse` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, `adresse` text NOT NULL, `cp` varchar(5) NOT NULL, `ville` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --- TABLE `tb_commande` -DROP TABLE IF EXISTS `tb_commande`; CREATE TABLE `tb_commande` ( `id` int(10) unsigned NOT NULL auto_increment, `date` datetime NOT NULL, `adresse` text NOT NULL, `cp` varchar(5) NOT NULL, `ville` varchar(45) NOT NULL, `traitee` tinyint(1) NOT NULL, `datetraitement` datetime NOT NULL, `utilisateur` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `FK_tb_commande_1` (`utilisateur`), CONSTRAINT `FK_tb_commande_1` FOREIGN KEY (`utilisateur`) REFERENCES =Flex3 FM.book Page 377 Mardi, 2. décembre 2008 3:32 15 Création d’un projet de site e-commerce CHAPITRE 20 377 ➥`tb_utilisateur` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --- TABLE `tb_facture` -DROP TABLE IF EXISTS `tb_facture`; CREATE TABLE `tb_facture` ( `id` int(10) unsigned NOT NULL auto_increment, `commande` int(10) unsigned NOT NULL, `montant` double NOT NULL, PRIMARY KEY (`id`), KEY `FK_tb_facture_1` (`commande`), CONSTRAINT `FK_tb_facture_1` FOREIGN KEY (`commande`) REFERENCES `tb_commande` ➥(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --- TABLE `tb_lignecommande` -DROP TABLE IF EXISTS `tb_lignecommande`; CREATE TABLE `tb_lignecommande` ( `appareilphoto` int(10) unsigned NOT NULL auto_increment, `commande` varchar(45) NOT NULL, PRIMARY KEY (`appareilphoto`,`commande`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; Faisons le point Ainsi s’achève la première partie de notre projet. Nous possédons à présent un squelette applicatif qui va contenir les deux modules de notre site. L’accès sécurisé à la partie d’administration du site a été implémenté de façon basique, certes, mais fonctionnelle. Néanmoins, cette verification d’accès n’est pas réalisée à partir de la base de données, comme cela était prévu dans la phase de conception. Cette fonctionnalité ne sera pas décrite dans le projet, la laissant ainsi à votre charge. Nous allons néanmoins, dans le chapitre suivant, aborder l’ensemble des notions qui vous permettront de la réaliser seul. =Flex3 FM.book Page 378 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 379 Mardi, 2. décembre 2008 3:32 15 21 Module d’administration du site e-commerce Nous allons créer le premier module de notre site E-Reflex, permettant la gestion des fournisseurs et des produits associés, ce qui nous permettra d’aborder les notions suivantes : • l’utilisation du composant RemoteObject (chapitre 12) ; • la notion de modèle (chapitre 2) ; • le databinding (chapitre 11) ; • l’utilisation de la bibliothèque AMFPHP (chapitre 13) ; • la gestion des données (chapitre 11) ; • la création de modules (chapitre 15) ; • la demande de confirmation d’exécution de procédure (nouvelle notion) ; • la lecture d’un fichier XML externe (nouvelle notion) ; • l’alimentation du composant comboBox (chapitre 5) ; • le déploiement et l’intégration d’un module (chapitre 15). Important Avant de poursuivre la lecture de ce chapitre, assurez-vous d’avoir terminé la réalisation du squelette applicatif du chapitre 20, ainsi que la configuration de votre environnement de développement contenant PHP/MySQL et AMFPHP. =Flex3 FM.book Page 380 Mardi, 2. décembre 2008 3:32 15 380 Cas pratiques PARTIE II Création du module Phase préparatoire Nous allons commencer par créer un nouveau projet Flex que nous nommerons module Administration, puis lui ajouterons un module en créant un fichier MXML Module au sein de notre projet avec les caractéristiques suivantes (figure 21-1) : • nom : modAdministration ; • Width (largeur) = 900 pixels (largeur du canevas du composant viewStack chargé de contenir le module) ; • Heigth (hauteur) = 590 pixels ; • non optimisé (utilisable dans toute application Flex). Figure 21-1 Création du module =Flex3 FM.book Page 381 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 381 Pour pouvoir tester le module tout au long de sa phase de développement, nous allons ajouter un composant ModuleLoader dans le fichier MXML du projet faisant appel au module que nous somme en train de créer : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ModuleLoader id="module" url="modAdministration.swf"> </mx:ModuleLoader> </mx:Application> Design de l’interface Ce module va permettre la gestion des fournisseurs et des produits mis en vente. Nous avons donc choisi de distinguer les deux gestions en implémentant un composant tab Navigator comme suit : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590"> <mx:TabNavigator x="0" y="0" width="900" height="590"> <!-- FOURNISSEURS --> <mx:Canvas label="Fournisseurs" width="100%" height="100%"> </mx:Canvas> <!-- PRODUITS --> <mx:Canvas label="Produits" width="100%" height="100%"> </mx:Canvas> </mx:TabNavigator> </mx:Module> Nous allons, dans un premier temps, nous consacrer à la mise en place de la gestion des fournisseurs. Gestion des fournisseurs Créons tout d’abord l’interface graphique. Le code ci-dessous permet de réaliser l’interface graphique illustrée à la figure 21-2 : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590"> <mx:TabNavigator x="0" y="0" width="900" height="590"> =Flex3 FM.book Page 382 Mardi, 2. décembre 2008 3:32 15 382 Cas pratiques PARTIE II <!-- FOURNISSEURS --> <mx:Canvas label="Fournisseur" width="100%" height="100%" > <mx:DataGrid id="dg_fournisseur" x="10" y="10" height="510"> <mx:columns> <mx:DataGridColumn headerText="REF" dataField="id" width="70"/> <mx:DataGridColumn headerText="NOM" dataField="nom" ➥width="250"/> <mx:DataGridColumn headerText="--" dataField="adresse" ➥width="-1" visible="false"/> <mx:DataGridColumn headerText="--" dataField="cp" width="-1" ➥visible="false"/> <mx:DataGridColumn headerText="NOM" dataField="ville" width="-1" ➥visible="false"/> </mx:columns> </mx:DataGrid> <mx:Panel id="pn_fournisseur" x="340" y="10" width="548" height="537" ➥layout="absolute" title="Informations fournisseur"> <mx:Form x="10" y="10" height="217" width="508" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormHeading id="hf_entete"/> <mx:FormItem label="REF :"> <mx:TextInput id="txt_ref" enabled="false" editable="false" ➥text=""/> </mx:FormItem> <mx:FormItem label="Nom :" required="true"> <mx:TextInput width="370" id="txt_nom"/> </mx:FormItem> <mx:FormItem label="Adresse :" required="true"> <mx:TextArea width="370" id="txt_adresse"/> </mx:FormItem> <mx:FormItem label="Code Postal" required="true"> <mx:TextInput width="113" id="txt_codePostal" maxChars="6"/> </mx:FormItem> <mx:FormItem label="Ville :" required="true"> <mx:TextInput width="370" id="txt_ville"/> </mx:FormItem> </mx:Form> <mx:HBox x="10" y="235" width="100%" horizontalAlign="right"> <mx:Button id = "btn_supprimer" label="Supprimer" enabled= ➥"false"/> <mx:Button id = "btn_modifier" label="Modifier" enabled="false"/> <mx:Button id = "btn_ajouter" label="Ajouter" enabled= ➥"false" /> <mx:Button id = "btn_annuler" label="Annuler" enabled="false"/> </mx:HBox> =Flex3 FM.book Page 383 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 383 </mx:Panel> <mx:Button x="10" y="525" label="Nouveau" width="322" id="btn_nouveau" /> </mx:Canvas> <!-- PRODUITS --> <mx:Canvas label="Produits" width="100%" height="100%"> </mx:Canvas> </mx:TabNavigator> </mx:Module> Les fournisseurs seront listés dans le datagrid de gauche tandis que la logique applicative (ajout/suppression/modification) sera assurée par la partie de droite. Figure 21-2 Interface graphique de gestion des fournisseurs Gestion des produits Réalisons à présent l’interface de gestion des produits (figure 21-3) : =Flex3 FM.book Page 384 Mardi, 2. décembre 2008 3:32 15 384 Cas pratiques PARTIE II Figure 21-3 Interface de gestion des produits <!-- PRODUITS --> <mx:Canvas label="Produits" width="100%" height="100%" > <mx:Form x="23" y="5" width="358" height="45" horizontalScrollPolicy ➥="off" verticalScrollPolicy="off"> <mx:FormItem label="Fournisseur :"> <mx:ComboBox width="230" id="cmb_fournisseurs" ></mx:ComboBox> </mx:FormItem> </mx:Form> <mx:AdvancedDataGrid x="23" y="63" id="advdg_produit" ➥designViewDataType="flat" height="168" width="852" > <mx:columns> <mx:AdvancedDataGridColumn headerText="REF" dataField="id" ➥width="50"/> <mx:AdvancedDataGridColumn headerText="NOM" dataField="nom" ➥width="150"/> <mx:AdvancedDataGridColumn headerText="STOCK" dataField="stock" ➥width="50"/> <mx:AdvancedDataGridColumn headerText="--" dataField= =Flex3 FM.book Page 385 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 ➥"description" width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="stockmin" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="stockmax" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="prixha" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField= ➥"fournisseur" width="-1" visible="false"/> </mx:columns> </mx:AdvancedDataGrid> <mx:Button x="755" y="239" label="Nouveau produit" ➥id="btn_nouveauproduit"/> <mx:Panel x="24" y="269" width="852" height="278" layout="absolute" ➥id="panel_produit"> <mx:Form x="10" y="10" height="181" width="526" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="REF :"> <mx:TextInput id="txt_refproduit" width="80" enabled="false" ➥editable="true"/> </mx:FormItem> <mx:FormItem label="Nom :" required="true"> <mx:TextInput width="400" id="txt_nomproduit"/> </mx:FormItem> <mx:FormItem label="Description :" required="true"> <mx:TextArea height="63" width="400" id="txt_description"/> </mx:FormItem> <mx:FormItem label="Prix vente :" required="true"> <mx:TextInput width="80" id="txt_prixvente"/> </mx:FormItem> </mx:Form> <mx:VRule x="567" y="10" width="1" height="181"/> <mx:Form x="592" y="10" height="181" width="230" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="Prix d'achat :" required="true"> <mx:TextInput width="80" id="txt_prixha"/> </mx:FormItem> <mx:FormItem label="Stock min :" required="true"> <mx:TextInput width="80" id="txt_stockmin"/> </mx:FormItem> <mx:FormItem label="Stock max :" required="true"> <mx:TextInput width="80" id="txt_stockmax"/> </mx:FormItem> <mx:FormItem label="Stock :" required="true"> <mx:TextInput width="80" id="txt_stock" editable="false" ➥enabled="false"/> </mx:FormItem> 385 =Flex3 FM.book Page 386 Mardi, 2. décembre 2008 3:32 15 386 Cas pratiques PARTIE II <mx:FormItem label="Ref. fournisseur :"> <mx:TextInput width="80" id="txt_reffournisseur" enabled= ➥"false" editable="false"/> </mx:FormItem> </mx:Form> <mx:HBox x="10" y="208" width="814" height="29" ➥horizontalAlign="right"> <mx:Button label="Supprimer" enabled="false" ➥id="btn_supprimerpt"/> <mx:Button label="Modifier" enabled="false" id="btn_modifierpt"/> <mx:Button label="Ajouter" enabled="false" id="btn_ajouterpt"/> <mx:Button label="Annuler" enabled="false" id="btn_annulerpt"/> </mx:HBox> </mx:Panel> </mx:Canvas> Les fournisseurs sont listés dans une comboBox. Lorsque l’utilisateur en sélectionne un dans la liste déroulante, cela met à jour le tableau contenant la liste des produits liés à ce fournisseur. Nous avons choisi d’implémenter un tableau de type « Avancé » (advancedDatagrid) offrant à l’utilisateur des possibilités de tri avancées. Le panel permet de gérer les données du produit sélectionné dans le tableau : suppression et modification. Il autorise également l’ajout d’un nouveau produit. Gestion des fournisseurs Les différentes étapes du processus d’implémentation de la gestion des fournisseurs sont les suivantes : 1. création des services PHP ; 2. création du modèle (classes ActionScript) ; 3. mise en place de la logique IHM (activation/désactivation des boutons) ; 4. mise en place de la logique applicative ; 5. mise en place de la validation du format et des champs à renseigner impérativement. Création des services PHP La phase initiale va consister à développer les services de la couche métier : le listing et l’ajout/suppression/modification d’un fournisseur. =Flex3 FM.book Page 387 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 387 Création du fichier Nous allons nous positionner dans le répertoire services d’AMFPHP et y créer le fichier servModAdministration.php contenant le code suivant : <?php class ServModAdministration { protected $serveur = 'localhost'; protected $mdp = 'mysql'; protected $utilisateur = 'root'; protected $baseDeDonnees = 'reflex'; protected $connexion = null; protected $methodTable = null; public function construct() { /****************************************** /* LISTE DES SERVICES * /******************************************/ $this->methodTable = array( 'serviceListerFournisseurs'=>array( 'description'=>'Listelesfournisseurs', 'access'=>'remote' ), 'serviceASMFournisseurs' => array( 'description'=>'Ajout Suppression Modification d\'un fournisseur', 'access'=>'remote' ) ); } } ?> Les paramètres de connexion à la base de données sont contenus dans des attributs, suivis de la déclaration des différents services. Il convient donc de les adapter en fonctions de ce que vous avez paramétré lors de l’installation du serveur MySQL. Lister les fournisseurs Le premier service que nous allons implémenter est celui permettant de lister les fournisseurs contenus dans la base de données. Pour cela, après avoir effectué une connexion, nous réaliserons une requête dont le résultat sera contenu dans un tableau et envoyé à notre module : function serviceListerFournisseurs () { //connexion à la base de données MySQL avec nom d'hôte, login et password $db = mysql_connect($this->serveur,$this->utilisateur,$this->mdp); =Flex3 FM.book Page 388 Mardi, 2. décembre 2008 3:32 15 388 Cas pratiques PARTIE II //Sélection de la base de données mysql_select_db($this->baseDeDonnees, $db); //Requête $Requete = "select * from tb_fournisseur"; //Stockage du résultat $Resultat = mysql_query( $Requete ); //Alimentation d'un tableau avec la liste des fournisseurs while ($Fournisseur = mysql_fetch_object ($Resultat)) { $tableauFournisseurs[] = $Fournisseur; } //Envoi du tableau return( $tableauFournisseurs); } Ajouter/supprimer/modifier un fournisseur Ce service va nous permettre d’ajouter, modifier ou supprimer un fournisseur : function serviceASMFournisseurs ($type,$id,$nom,$adresse,$cp,$ville) { //connexion à la base de données MySQL avec nom d'hôte, login et password $db = mysql_connect($this->serveur,$this->utilisateur,$this->mdp); //Sélection de la base de données mysql_select_db($this->baseDeDonnees, $db); //Requête SQL établie en fonction du cas d’ajout, de modification, de ➥suppression switch ($type) { case 'A' : $Requete = "insert into tb_fournisseur (nom,adresse,cp,ville) ➥values ('$nom','$adresse','$cp','$ville') "; break; case 'M' : $Requete = "update tb_fournisseur set nom = '$nom', ➥adresse='$adresse', cp='$cp', ville='$ville' where id = $id "; break; case 'S' : $Requete = "delete from tb_fournisseur where id = $id "; break; } $Resultat = mysql_query( $Requete ); return( "OK"); } =Flex3 FM.book Page 389 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 389 Le service reçoit, en complément, des informations sur le fournisseur et le type d’opération à effectuer : • A = ajout ; • M = modification ; • S = suppression. Une requête est alors créée puis exécutée en fonction de ce paramètre. Grâce à cette méthode, il est inutile de créer trois services différents pour l’ajout, la suppression et la modification de fournisseur ! Test des services PHP Avant de procéder à la programmation de notre module, nous devons nous assurer que les services créés sont fonctionnels. Pour cela, nous vous invitons à vous rendre sur la page du browser d’AMFPHP (http://localhost/amfphp/brower) et de réaliser l’ensemble des tests nécessaires : • exécution du service serviceListerFournisseurs ; • ajout, suppression et modification d’un fournisseur. Création des classes Il est temps à présent d’implémenter le modèle de notre module qui va se charger de stocker temporairement les informations et d’interagir avec les services que nous venons de créer. Commençons par l’arborescence de répertoires nécessaire au stockage de nos classes afin de créer le package. Rendez-vous dans le répertoire src, créez-y un répertoire com. Ajoutez au répertoire nouvellement créé le répertoire ereflex et son sous-répertoire administration. L’arborescence obtenue doit être semblable à celle-ci : + src |------+ com |---------+ereflex |------------- administration La première classe dont nous allons nous occuper est la classe fournisseur. Plaçons-nous dans le répertoire administration et créons un nouveau fichier ActionScript Class nommé Fournisseur et contenant le code suivant : package com.ereflex.administration { import mx.rpc.remoting.mxml.RemoteObject; public class Fournisseur { //Attributs private var _id:int; =Flex3 FM.book Page 390 Mardi, 2. décembre 2008 3:32 15 390 Cas pratiques PARTIE II private private private private var var var var _nom:String; _adresse:String; _cp:String; _ville:String; //Constructeur public function Fournisseur(p_id:int,p_nom:String, p_adresse:String, ➥p_cp:String, p_ville:String ) { _id = p_id; _nom = p_nom; _adresse = p_adresse; _cp=p_cp; _ville = p_ville; } //Getters public function get id():int{ return _id; } public function get nom():String{ return _nom } public function get adresse():String{ return _adresse; } public function get cp():String{ return _cp; } public function get ville():String{ return _ville; } //Setters public function set id(param:int):void{ _id = param; } public function set nom(param:String):void{ _nom = param; =Flex3 FM.book Page 391 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 } public function set adresse(param:String):void{ _adresse = param; } public function set cp(param:String):void{ _cp = param; } public function set ville(param:String):void{ _ville = param; } //METHODES public function ajouter(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMFournisseurs('A',_id,_nom,_adresse,_cp,_ville); } public function modifier(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMFournisseurs('M',_id,_nom,_adresse,_cp,_ville); } public function supprimer(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMFournisseurs('S',_id,_nom,_adresse,_cp,_ville); } } } 391 =Flex3 FM.book Page 392 Mardi, 2. décembre 2008 3:32 15 392 Cas pratiques PARTIE II L’ajout, la suppression et la modification font appel à un objet service issu de l’instanciation de la classe RemoteObject. Le paramètre utilisé par ces méthodes sert à définir l’URL du fichier gateway.php d’AMFPHP, permettant ainsi de réutiliser plus facilement cette classe (nul besoin de la modifier en cas de changement d’URL). Logique IHM Mettre en place la logique IHM consiste à définir l’état des composants en fonction de l’action de l’utilisateur. Par exemple, si l’utilisateur clique sur le bouton Nouveau, il est évident que le bouton Supprimer ne doit pas être actif. Pour réaliser l’exhaustivité des cas, nous allons établir le tableau suivant : Tableau 21-1 État des composants en fonction des actions de l’utilisateur Action\Bouton Nouveau Ajouter Supprimer Modifier Annuler Zones de texte État initial de l’IHM Actif Inactif Inactif Inactif Inactif Vides Action sur le bouton Nouveau – Actif Inactif Inactif Actif Vides En-tête du formulaire : Nouveau Fournisseur Sélection d’une ligne dans le tableau Actif Inactif Actif Actif Inactif Contiennent les informations du fournisseur En-tête du formulaire : Fournisseur : nom_du_fournisseur Il ne nous reste plus qu’à coder tout ceci ! Créons un fichier ActionScript que nous nommerons FournisseurAS3.as, contenant le code suivant : /****************************************************************** * IHM * ****************************************************************/ //Mise à vide des zones de texte public function RAZZonesTextes():void { txt_ref.text = ""; txt_nom.text = ""; txt_adresse.text = ""; txt_codePostal.text = ""; txt_ville.text = ""; hf_entete.label = ""; } //État initial de l'IHM public function initIHM():void =Flex3 FM.book Page 393 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 393 { RAZZonesTextes() btn_modifier.enabled = false; btn_supprimer.enabled = false; btn_ajouter.enabled = false; btn_nouveau.enabled = true; btn_annuler.enabled = false; } //Action sur le bouton Nouveau public function clickBoutonNouveau():void { hf_entete.label = "Nouveau Fournisseur"; RAZZonesTextes(); btn_modifier.enabled = false; btn_supprimer.enabled = false; btn_ajouter.enabled = true; btn_nouveau.enabled = false; btn_annuler.enabled = true; } //Sélection d'une ligne dans le tableau public function selectionLigneTableauIHM():void { btn_modifier.enabled = true; btn_supprimer.enabled = true; btn_ajouter.enabled = false; btn_nouveau.enabled = true; btn_annuler.enabled = false; } Modifions à présent le fichier MXML du module afin de prendre en compte la logique précédemment codée : <!-- Import du script --> <mx:Script source="FournisseurAS3.As"></mx:Script> […] <!-- Initialisation de l’interface --> <mx:Canvas label="Fournisseurs" width="100%" height="100%" creationComplete=" ➥initIHM()"> […] <!-- Action sur le bouton annuler --> <mx:Button id = "btn_annuler" label="Annuler" click="initIHM()" enabled="false"/> […] <!-- Action sur le bouton Nouveau --> <mx:Button x="10" y="525" label="Nouveau" width="322" id="btn_nouveau" ➥click="clickBoutonNouveau()"/> =Flex3 FM.book Page 394 Mardi, 2. décembre 2008 3:32 15 394 Cas pratiques PARTIE II Logique applicative La logique applicative va consister à développer les procédures capables d’interagir avec le modèle afin de satisfaire les règles de gestion. Paramétrage d’AMFPHP Dans l’optique du déploiement, nous allons créer un fichier XML contenant les informations nécessaires pour communiquer avec AMFPHP. Nous devrons en effet certainement modifier l’adresse du serveur AMFPHP, ce qui devient très ardu lorsque celle-ci est spécifiée dans le code de l’application. Créons donc le fichier parametrage_amfphp.xml dans le répertoire src du projet, contenant le code suivant : <?xml version="1.0" encoding="ISO-8859-1" ?> <parametre> <amfphp> <serveur>http://localhost/amfphp/gateway.php</serveur> </amfphp> </parametre> Pour lire ce fichier, nous devons créer une procédure ActionScript capable d’effectuer cela, exécutée après la création du module : Import mx.controls.Alert; /**************************************************** * CHARGEMENT DES PARAMETRES AMFPHP * **************************************************/ public var URL:String; public function chargerParametrageAmfPhp():void { var chargeur:URLLoader = new URLLoader (); var adresse:URLRequest = new URLRequest ("parametrage_amfphp.xml"); chargeur.load(adresse); chargeur.addEventListener(Event.COMPLETE, finDuChargement); chargeur.addEventListener(IOErrorEvent.IO_ERROR, indiquerErreur); } public function finDuChargement ( event:Event ):void { var contenu:XML = new XML(event.target.data); URL = contenu.amfphp.serveur; } public function indiquerErreur( event:Event ):void { Alert.show("Erreur lors du chargement des paramètres amfphp"); } =Flex3 FM.book Page 395 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 395 Le chargement du fichier XML consiste à instancier la classe URLLoader et lui affecter des événements déclenchés selon le résultat du chargement du fichier. Si le chargement s’est correctement déroulé, nous extrayons du fichier XML la valeur de la balise serveur afin d’en affecter la variable publique URL. Cette procédure devant être exécutée au chargement du module, nous allons affecter à sa méthode creationComplete la procédure chargerParametrageAmfPhp() : <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" creationComplete="chargerParametrageAmfPhp()"> Afficher la liste des fournisseurs Pour afficher la liste des fournisseurs, nous allons utiliser la notion de DataBinding. En effet, nous allons créer une variable tableauFournisseur comme source de liaison avec le dataprovider du datagrid. Ainsi, lorsque tableauFournisseur sera mis à jour, datagrid le sera aussi : /**************************************************** * APPEL DU SERVICE DE LISTING DES FOURNISSEURS * **************************************************/ [Bindable] public var tableauFournisseurs:Array; public function listerFournisseurs():void { var service:RemoteObject = new RemoteObject(); service.endpoint = URL; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceListerFournisseurs.addEventListener("result", ➥resultatOKListerFournisseurs); service.serviceListerFournisseurs.addEventListener("fault", resultatKO) service.serviceListerFournisseurs(); } public function resultatOKListerFournisseurs(e:ResultEvent):void { tableauFournisseurs = e.result as Array; } public function resultatKO(e:FaultEvent):void { Alert.show(e.fault.faultString, 'Error'); } Il convient à présent de modifier le fichier MXML du module afin de faire appel à la procédure listerFournisseurs() lorsque le canvas contenant l’interface graphique est affiché =Flex3 FM.book Page 396 Mardi, 2. décembre 2008 3:32 15 396 Cas pratiques PARTIE II à l’écran (événement show), sans oublier de créer la liaison entre le dataprovider du datagrid et la variable tableauFournisseurs : <mx:Canvas label="Fournisseurs" width="100%" height="100%" ➥show="listerFournisseurs();initIHM()"> <mx:DataGrid id="dg_fournisseur" x="10" y="10" height="510" ➥dataProvider="{tableauFournisseurs}"> Afficher les données d’un fournisseur sélectionné Pour afficher les données d’un fournisseur sélectionné dans le datagrid, nous allons faire appel à son événement itemClick() : <mx:DataGrid id="dg_fournisseur" x="10" y="10" height="510" ➥dataProvider="{tableauFournisseurs}" itemClick="selectionnerFournisseur(event)"> Lorsque l’utilisateur sélectionne une ligne du datagrid, la procédure selectionner Fournisseur() est alors exécutée, mettant à jour les zones de texte et exécutant la logique IHM définie pour cette action : /**************************************************** * SELECTION D'UN FOURNISSEUR * **************************************************/ public function selectionnerFournisseur(e:ListEvent):void { txt_ref.text = e.currentTarget.selectedItem.id; txt_nom.text = e.currentTarget.selectedItem.nom; txt_adresse.text = e.currentTarget.selectedItem.adresse; txt_codePostal.text = e.currentTarget.selectedItem.cp; txt_ville.text = e.currentTarget.selectedItem.ville; hf_entete.label = "Fournisseur :"+e.currentTarget.selectedItem.nom; selectionLigneTableauIHM(); } Ajouter, supprimer, modifier un fournisseur Le code ci-dessous décrit les trois procédures faisant appel aux méthodes ajouter, supprimer et modifier de la classe Fournisseur : /****************************************************************** * AJOUT/MODIFICATION/SUPPRESSSION D'UN FOURNISSEUR * ****************************************************************/ public function ajouterFournisseur():void { var identifiant:int = 0; var nom:String = txt_nom.text; var adresse:String = txt_adresse.text; =Flex3 FM.book Page 397 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 var cp:String = txt_codePostal.text; var ville:String = txt_ville.text; //Instanciation de la classe fournisseur var obj_Fournisseur:Fournisseur = new ➥Fournisseur(identifiant,nom,adresse,cp,ville); //Appel de la méthode d'ajout obj_Fournisseur.ajouter(URL); //Mise à jour du tableau des fournisseurs listerFournisseurs(); initIHM() } public function modifierFournisseur():void { var identifiant:int = int(txt_ref.text); var nom:String = txt_nom.text; var adresse:String = txt_adresse.text; var cp:String = txt_codePostal.text; var ville:String = txt_ville.text; //Instanciation de la classe fournisseur var obj_Fournisseur_modif:Fournisseur = new ➥Fournisseur(identifiant,nom,adresse,cp,ville); //Appel de la méthode de modification obj_Fournisseur_modif.modifier(URL); //Mise à jour du tableau des fournisseurs listerFournisseurs(); initIHM() } public function supprimerFournisseur():void { Alert.show("Voulez vous supprimer ce fournisseur ?", "Suppression ➥fournisseur", Alert.OK | Alert.CANCEL, this,confirmerSuppression, null, ➥Alert.OK); } private function confirmerSuppression(eventObj:CloseEvent):void { if (eventObj.detail==Alert.OK) { 397 =Flex3 FM.book Page 398 Mardi, 2. décembre 2008 3:32 15 398 Cas pratiques PARTIE II var var var var var identifiant:int = int(txt_ref.text); nom:String = txt_nom.text; adresse:String = txt_adresse.text; cp:String = txt_codePostal.text; ville:String = txt_ville.text; //Instanciation de la classe fournisseur var obj_Fournisseur_suppr:Fournisseur = new ➥Fournisseur(identifiant,nom,adresse,cp,ville); //Appel de la méthode de suppression obj_Fournisseur_suppr.supprimer(URL); //Mise à jour du tableau des fournisseurs listerFournisseurs(); initIHM(); } } Si nous observons avec attention ces quelques lignes, nous remarquons que la suppression d’un fournisseur n’est exécutée qu’après validation de la part de l’utilisateur. Cette confirmation de suppression est réalisée à l’aide de la classe Alert, en créant une fenêtre de confirmation comme suit : Alert.show("Voulez vous supprimer ce fournisseur ?", "Suppression fournisseur", ➥Alert.OK | Alert.CANCEL, this, confirmerSuppression, null, Alert.OK); Les paramètres utilisés sont les suivants : 1. texte de la demande ; 2. titre de la fenêtre ; 3. boutons présents sur la fenêtre (Ok et Annuler) ; 4. fenêtre parente ; 5. action à réaliser lors du clic sur l’un des boutons de la fenêtre ; 6. bouton cliqué par défaut lorsque l’utilisateur appuie sur la touche Entrée de son clavier. Il nous est alors possible d’intercepter le choix de l’utilisateur et de réaliser une action en fonction de celui-ci: if (eventObj.detail==Alert.OK) { } Vérification des données transmises La dernière étape du processus va être la vérification des données saisies afin de répondre aux attentes du système d’information. =Flex3 FM.book Page 399 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 399 Saisie obligatoire Dans notre formulaire, les champs txt_nom, txt_adresse, txt_codePostal et txt_ville doivent obligatoirement être saisis lors des phases d’ajout et de modification. Nous allons donc commencer par mettre en place le validateur pour chacun de ces champs : <mx:Script source="FournisseurAS3.As"></mx:Script> <!-- VALIDATION DONNÉES --> <mx:StringValidator id="v_nom" required="true" property="text" source="{txt_nom}" ➥requiredFieldError="Ce champ est obligatoire"></mx:StringValidator> <mx:StringValidator id="v_adresse" required="true" property="text" ➥source="{txt_adresse}" requiredFieldError="Ce champ est obligatoire"> ➥</mx:StringValidator> <mx:StringValidator id="v_ville" required="true" property="text" source="{txt_ville}" ➥requiredFieldError="Ce champ est obligatoire"></mx:StringValidator> Nous allons ensuite créer une fonction capable de valider notre formulaire, cette dernière renvoyant la valeur 1 s’il est validé, 0 sinon : /****************************************************************** * VALIDATION DES DONNÉES * ****************************************************************/ import mx.validators.Validator; public function validationFormulaire():int{ var valide:int = 1; //Stockage des erreurs de validation dans un tableau var tableau_validation:Array = Validator.validateAll([v_nom,v_adresse,v_ville]); // Si le tableau ne contient aucun élément, le traitement peut être effectué if(tableau_validation.length != 0) { valide = 0; } return valide; } Il ne nous reste plus qu’à modifier les procédures d’ajout et de modification d’un fournisseur en n’exécutant ces actions que si le formulaire a été validé auparavant : public function ajouterFournisseur():void { if(validationFormulaire() == 1) { var identifiant:int = 0; var nom:String = txt_nom.text; var adresse:String = txt_adresse.text; var cp:String = txt_codePostal.text; =Flex3 FM.book Page 400 Mardi, 2. décembre 2008 3:32 15 400 Cas pratiques PARTIE II var ville:String = txt_ville.text; //Instanciation de la classe fournisseur var obj_Fournisseur:Fournisseur = new ➥Fournisseur(identifiant,nom,adresse,cp,ville); //Appel de la méthode d'ajout obj_Fournisseur.ajouter(URL); //Mise à jour du tableau des fournisseurs listerFournisseurs(); //Réinitialisation des zones de texte initIHM() } } public function modifierFournisseur():void { if(validationFormulaire() == 1) { var identifiant:int = int(txt_ref.text); var nom:String = txt_nom.text; var adresse:String = txt_adresse.text; var cp:String = txt_codePostal.text; var ville:String = txt_ville.text; //Instanciation de la classe fournisseur var obj_Fournisseur_modif:Fournisseur = new ➥Fournisseur(identifiant,nom,adresse,cp,ville); //Appel de la méthode d'ajout obj_Fournisseur_modif.modifier(URL); //Mise à jour du tableau des fournisseurs listerFournisseurs(); //Réinitialisation des zones de texte initIHM() } } Vérifier le format du code postal De la même façon que nous avons vérifié la bonne saisie des champs obligatoires, nous allons employer un validateur (zipCodeValidator) pour vérifier le bon format et la présence de données dans le champ txt_codePostal : <!-- CODE POSTAL --> <mx:ZipCodeValidator property="text" id="v_cp" source="{txt_codePostal}" ➥requiredFieldError="Ce champ est obligatoire" wrongLengthError="Format erroné"> ➥</mx:ZipCodeValidator> =Flex3 FM.book Page 401 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 401 Enfin, modifions la procédure de validation du formulaire afin que ce nouvel élément soit pris en compte : /****************************************************************** * VALIDATION DES DONNÉES ****************************************************************/ import mx.validators.Validator; public function validationFormulaire():int{ var valide:int = 1; //Stockage des erreurs de validation dans un tableau var tableau_validation:Array = Validator.validateAll ➥([v_nom,v_adresse,v_cp,v_ville]); // Si le tableau ne contient aucun élément, le traitement peut être effectué if(tableau_validation.length != 0) { valide = 0; } return valide; } Aspect graphique de la validation Après avoir modifié ou ajouté un fournisseur, les zones de texte se réinitialisent, déclenchant la vérification de la saisie (à cause du DataBinding réalisé sur les validateurs). Elles sont donc entourées de rouge, car leur propriété text contient une chaîne vide. Pour pallier cela, nous allons créer deux procédures permettant d’activer et de désactiver les composants de validation. Ainsi, lorsque nous réinitialiserons le contenu des zones de saisie, nous désactiverons auparavant la validation des champs pour les réactiver une fois la réinitialisation terminée : public function desactiverValidateurs():void { v_nom.enabled = false; v_adresse.enabled = false; v_cp.enabled = false; v_ville.enabled = false; } public function activerValidateurs():void { v_nom.enabled = true; v_adresse.enabled = true; v_cp.enabled = true; v_ville.enabled = true; } =Flex3 FM.book Page 402 Mardi, 2. décembre 2008 3:32 15 402 Cas pratiques PARTIE II //Modification de la procédure initIHM public function initIHM():void { desactiverValidateurs(); RAZZonesTextes(); activerValidateurs(); btn_modifier.enabled = false; btn_supprimer.enabled = false; btn_ajouter.enabled = false; btn_nouveau.enabled = true; btn_annuler.enabled = false; } La première partie du module est à présent terminée. Nous pouvons vérifier son bon fonctionnement en exécutant le projet moduleAdministration (figure 21-4). Figure 21-4 Première partie du module fonctionnel =Flex3 FM.book Page 403 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 403 À vos claviers : la gestion des produits Nous venons de terminer la première partie de notre module consistant à gérer les fournisseurs. Néanmoins, il reste à développer la partie concernant la gestion des produits. Pour y parvenir il est nécessaire de valider les étapes suivantes : • alimenter la liste déroulante contenant les fournisseurs ; • lister les produits correspondants au fournisseur sélectionné dans la liste déroulante ; • afficher les données du produit sélectionné dans les zones de texte correspondantes ; • ajouter, supprimer, modifier un produit pour un fournisseur donné ; • vérifier la qualité des données saisies avant modification et ajout. À vous de jouer ! Quelques pistes de travail Nous vous conseillons d’adopter la même démarche que celle que nous avons suivie pour la partie précédente (création des services PHP, définition de la logique IHM…). De plus, n’oubliez pas que l’alimentation du composant comboBox s’effectue selon un format bien particulier (voir le chapitre 5). Nous vous recommandons de créer un fichier ProduitAS3.as chargé de contenir la logique applicative. Enfin, pour vous aider, nous vous dévoilons le code de base de la classe Appareil Photo : package com.ereflex.administration { public class AppareilPhoto { //Attributs private var _id:int; private var _nom:String; private var _description:String; private var _prix:Number; private private private private private var var var var var _stock:int; _stockMin:int; _stockMax:int; _prixHa:Number; _fournisseur:int; //Constructeur public function AppareilPhoto(p_id:int, p_nom:String, p_description:String, ➥p_prixvente:Number, p_prixha:Number, p_stockmin:int, p_stockmax:int, ➥p_stock:int, p_fournisseur:int) { _id = p_id; _nom = p_nom; =Flex3 FM.book Page 404 Mardi, 2. décembre 2008 3:32 15 404 Cas pratiques PARTIE II _description = p_description; _prix = p_prixvente; _stock = p_stock; _stockMin = p_stockmin; _stockMax = p_stockmax; _prixHa = p_prixha; _fournisseur = p_fournisseur; } //Getters public function get id():int{ return _id; } public function get nom():String{ return _nom; } public function get description():String{ return _description; } public function get prix():Number{ return _prix; } public function get stock():int{ return _stock; } public function get stockMin():int{ return _stockMin; } public function get stockMax():int{ return _stockMax; } public function get prixHa():Number{ return _prixHa; } public function get fournisseur():int{ return _fournisseur; } //Setters public function set id(param:int):void{ _id = param; } public function set nom(param:String):void{ =Flex3 FM.book Page 405 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 405 _nom = param; } public function set description(param:String):void{ _description = param; } public function set prix(param:Number):void{ _prix = param; } public function set stock(param:int):void{ _stockMin = param; } public function set stockMin(param:int):void{ _stockMin = param; } public function set stockMax(param:int):void{ _stockMax = param; } public function set prixHa(param:Number):void{ _prixHa = param; } public function set fournisseur(param:int):void{ _fournisseur = param; } } } Solution Vous avez réussi ? Félicitations ! Dans le cas contraire voici une solution possible, afin que vous puissiez comprendre vos erreurs. Services PHP Il convient tout d’abord d’ajouter les services dans le tableau contenant la liste de ceux-ci dans le fichier servModAdministration.php : function ServModAdministration () { /****************************************** /* LISTE DES SERVICES * /******************************************/ $this->methodTable = array( "serviceListerFournisseurs" => array( =Flex3 FM.book Page 406 Mardi, 2. décembre 2008 3:32 15 406 Cas pratiques PARTIE II "description" => "Liste les fournisseurs", "access" => "remote" ), "serviceASMFournisseurs" => array( "description" => "Ajout Suppression Modification d'un fournisseur", "access" => "remote" ), "serviceComboFournisseurs" => array( "description" => "Liste les fournisseurs dans la combo", "access" => "remote" ), "serviceListerProduitsFournisseurs" => array( "description" => "Liste les produits d'un fournisseur", "access" => "remote" ), "serviceASMProduit" => array( "description" => "Ajout Suppression Modification d'un produit", "access" => "remote" ) ); } Alimentation de la liste déroulante Rappelez-vous, nous avons vu dans le chapitre 5 que le composant comboBox avait besoin de deux arguments lors de son alimentation : • un label servant à afficher la donnée dans la liste ; • un data permettant de stocker l’identifiant de la donnée affichée. La requête permettant l’affichage des fournisseurs dans la liste déroulante devra donc retourner ces deux arguments : function serviceComboFournisseurs (){ //connexion à la base de données MySQL avec nom d'hôte, login et password $db = mysql_connect($this->serveur,$this->utilisateur,$this->mdp); //Sélection de la base de donnée mysql_select_db($this->baseDeDonnees, $db); //Requête $Requete = "select nom as label, id as data from tb_fournisseur order by ➥nom asc"; $Resultat = mysql_query( $Requete ); //Alimentation d'un tableau avec la liste des fournisseurs while ($Fournisseur = mysql_fetch_object ($Resultat)) { $tableauFournisseurs[] = $Fournisseur; } =Flex3 FM.book Page 407 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 407 //Envoi du tableau return( $tableauFournisseurs); } Lister les produits du fournisseur sélectionné Afin de lister les produits du fournisseur sélectionné, créez une méthode ayant pour paramètre l’identifiant du fournisseur sélectionné : function serviceListerProduitsFournisseurs ($idFournisseur){ //connexion à la base de données MySQL avec nom d'hôte, login et password $db = mysql_connect($this->serveur,$this->utilisateur,$this->mdp); //Sélection de la base de donnée mysql_select_db($this->baseDeDonnees, $db); //Requête $Requete = "select * from tb_appareilphoto where fournisseur = ➥$idFournisseur"; $Resultat = mysql_query( $Requete ); //Alimentation d'un tableau avec la liste des appareils photo while ($Appareil = mysql_fetch_object ($Resultat)) { $tableauAppareilsPhoto[] = $Appareil; } //Envoi du tableau return( $tableauAppareilsPhoto); } Ajouter/supprimer/modifier un produit Il suffit d’adapter la méthode utilisée pour l’ajout, la modification et la suppression d’un fournisseur que nous avons développée auparavant : function serviceASMProduit($type,$id,$nom,$description,$prix,$stock,$stockmin, ➥$stockmax,$prixha,$fournisseur){ //connexion à la base de données MySQL avec nom d'hôte, login et password $db = mysql_connect($this->serveur,$this->utilisateur,$this->mdp); //Sélection de la base de données mysql_select_db($this->baseDeDonnees, $db); =Flex3 FM.book Page 408 Mardi, 2. décembre 2008 3:32 15 408 Cas pratiques PARTIE II //Requête SQL établie en fonction du cas d’ajout, de modification, de ➥suppression switch ($type) { case 'A' : $Requete = "insert into tb_appareilphoto ➥(nom,description,prix,stock,stockmin,stockmax,prixha,fournisseur) ➥values ('$nom','$description','$prix','$stock','$stockmin', ➥'$stockmax','$prixha','$fournisseur') "; break; case 'M' : $Requete = "update tb_appareilphoto set nom='$nom', ➥description = '$description', prix='$prix', stock='$stock', ➥stockmin='$stockmin', stockmax='$stockmax', prixha = '$prixha' ➥where id = $id "; break; case 'S' : $Requete = "delete from tb_appareilphoto where id = $id "; break; } $Resultat = mysql_query( $Requete ); //Envoi du résultat return( "OK"); } Classe AppareilPhoto Les modifications que nous devons apporter à la classe AppareilPhoto concernent l’ajout des méthodes ajouter, modifier et supprimer : package com.ereflex.administration { import mx.rpc.remoting.mxml.RemoteObject; public class AppareilPhoto { […] //MÉTHODES public function ajouter(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMProduit('A',_id,_nom,_description,_prix,_stock, ➥_stockMin,_stockMax,_prixHa,_fournisseur); } =Flex3 FM.book Page 409 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 409 public function modifier(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMProduit('M',_id,_nom,_description,_prix, ➥_stock,_stockMin,_stockMax,_prixHa,_fournisseur); } public function supprimer(param:String):void { var service:RemoteObject = new RemoteObject(); service.endpoint = param; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceASMProduit('S',_id,_nom,_description,_prix, ➥_stock,_stockMin,_stockMax,_prixHa,_fournisseur); } } Logique IHM Nous allons, comme pour la partie permettant la gestion des fournisseurs, dresser un tableau des actions de l’utilisateur possibles et indiquer le comportement correspondant des composants de l’interface graphique : Tableau 21-2 État des composants en fonction des actions de l’utilisateur Action/bouton Modifier Nouveau Supprimer Ajouter Annuler Zone de texte stock Zones de texte État initial Inactif Actif Inactif Inactif Inactif Non éditable et non active Vides Action sur le bouton nouveau Inactif Inactif Inactif Actif Actif Éditable et active Vides sauf la zone de texte contenant la référence du fournisseur qui doit contenir la valeur de l’identifiant du fournisseur sélectionné Sélection d’une ligne dans le tableau Actif Actif Actif Inactif Inactif Non éditable et non active Contient les données du produit sélectionné =Flex3 FM.book Page 410 Mardi, 2. décembre 2008 3:32 15 410 Cas pratiques PARTIE II Il convient ensuite d’éditer le fichier ProduitAS3.as en ajoutant ces procédures : /**************************************************** * IHM * **************************************************/ //Mise à vide des zones de texte public function RAZZonesTexteProduit():void { txt_refproduit.text = ""; txt_nomproduit.text = ""; txt_description.text = ""; txt_prixvente.text = ""; txt_prixha.text = ""; txt_stockmin.text = ""; txt_stockmax.text = ""; txt_stock.text = ""; txt_reffournisseur.text = ""; panel_produit.title = ""; } //État initial de l'IHM public function initIHMProduit():void { RAZZonesTexteProduit(); btn_nouveauproduit.enabled = true; btn_supprimerpt.enabled = false; btn_modifierpt.enabled = false; btn_ajouterpt.enabled = false; btn_annulerpt.enabled = false; txt_stock.enabled = false; txt_stock.editable = false; } //Action sur le bouton Nouveau public function clickBoutonNouveauProduit():void { RAZZonesTexteProduit(); panel_produit.title = "Nouveau produit"; btn_nouveauproduit.enabled = false; btn_supprimerpt.enabled = false; btn_modifierpt.enabled = false; btn_ajouterpt.enabled = true; btn_annulerpt.enabled = true; txt_stock.enabled = true; txt_stock.editable = true; //Récupération de l'identifiant du fournisseur txt_reffournisseur.text = cmb_fournisseurs.selectedItem.data; } =Flex3 FM.book Page 411 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 411 //Sélection d'une ligne dans le tableau public function selectionLigneTableauProduitIHM():void { btn_nouveauproduit.enabled = true; btn_supprimerpt.enabled = true; btn_modifierpt.enabled = true; btn_ajouterpt.enabled = false; btn_annulerpt.enabled = false; } Validation des données Il faut, tout d’abord, mettre en place les validateurs adéquats dans le fichier MXML, puis créer la procédure de validation du formulaire dans le fichier ProduitAS3.as : <!-- VALIDATION DES DONNÉES TEXTE --> <mx:StringValidator id="v_description" required="true" property="text" ➥source="{txt_description}" requiredFieldError="Ce champ est obligatoire"> ➥</mx:StringValidator> <mx:StringValidator id="v_nomproduit" required="true" property="text" ➥source="{txt_nomproduit}" requiredFieldError="Ce champ est obligatoire"> ➥</mx:StringValidator> <!-- FORMAT DES DONNÉES NUMÉRIQUES --> <mx:NumberValidator id="v_prixvente" required="true" property="text" ➥source="{txt_prixvente}" requiredFieldError="Ce champ est obligatoire" ➥invalidCharError="Format erroné !" ></mx:NumberValidator> <mx:NumberValidator id="v_prixha" required="true" property="text" ➥source="{txt_prixha}" requiredFieldError="Ce champ est obligatoire" ➥invalidCharError="Format erroné !"></mx:NumberValidator> <mx:NumberValidator id="v_stockmin" required="true" property="text" ➥source="{txt_stockmin}" requiredFieldError="Ce champ est obligatoire" ➥invalidCharError="Format erroné !"></mx:NumberValidator> <mx:NumberValidator id="v_stockmax" required="true" property="text" ➥source="{txt_stockmax}" requiredFieldError="Ce champ est obligatoire" ➥invalidCharError="Format erroné !"></mx:NumberValidator> <mx:NumberValidator id="v_stock" required="true" property="text" source="{txt_stock}" ➥requiredFieldError="Ce champ est obligatoire" invalidCharError="Format erroné !"> ➥</mx:NumberValidator> /****************************************************************** * VALIDATION DES DONNÉES * ****************************************************************/ import mx.validators.Validator; public function validationFormulaireProduit():int{ =Flex3 FM.book Page 412 Mardi, 2. décembre 2008 3:32 15 412 Cas pratiques PARTIE II var valide:int = 1; //Stockage des erreurs de validation dans un tableau var tableau_validation:Array = Validator.validateAll([v_nomproduit, ➥v_description,v_prixvente,v_prixha,v_stockmin,v_stockmax,v_stock]); // Si le tableau ne contient aucun élément, le traitement peut être effectué if(tableau_validation.length != 0) { valide = 0; } return valide; } public function desactiverValidateursProduit():void { v_nomproduit.enabled = false; v_description.enabled = false; v_prixvente.enabled = false; v_prixha.enabled = false; v_stockmin.enabled = false; v_stockmax.enabled = false; v_stock.enabled = false; } public function activerValidateursProduit():void { v_nomproduit.enabled = true; v_description.enabled = true; v_prixvente.enabled = true; v_prixha.enabled = true; v_stockmin.enabled = true; v_stockmax.enabled = true; v_stock.enabled = true; } Nous en profitons également pour modifier la procédure initIHMProduit(), afin de désactiver la vérification des données avant chaque réinitialisation du formulaire : //État initial de l'IHM public function initIHMProduit():void { desactiverValidateursProduit(); RAZZonesTexteProduit(); activerValidateursProduit(); btn_nouveauproduit.enabled = true; btn_supprimerpt.enabled = false; =Flex3 FM.book Page 413 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 btn_modifierpt.enabled = false; btn_ajouterpt.enabled = false; btn_annulerpt.enabled = false; txt_stock.enabled = false; txt_stock.editable = false; } Logique applicative Voici le code des procédures permettant : • d’alimenter la liste déroulante ; • de lister les produits d’un fournisseur sélectionné ; • de visualiser les données d’un produit sélectionné dans le tableau ; • d’ajouter, supprimer et modifier un produit. /**************************************************** * ALIMENTATION DE LA COMBOBOX * **************************************************/ public function alimenterComboFournisseurs():void { var service:RemoteObject = new RemoteObject(); service.endpoint = URL; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceComboFournisseurs.addEventListener("result", ➥resultatOKComboFournisseurs); service.serviceComboFournisseurs.addEventListener("fault", resultatKO) service.serviceComboFournisseurs(); } public function resultatOKComboFournisseurs(e:ResultEvent):void { cmb_fournisseurs.dataProvider = e.result as Array; //>> ON SÉLECTIONNE LE PREMIER ENREGISTREMENT DE LA LISTE DÉROULANTE cmb_fournisseurs.selectedIndex = 0; //>> ON AFFICHE LES DONNÉES DU FOURNISSEUR SÉLECTIONNÉ listerAppareils(); } /********************************************************* * LISTING DES PRODUITS POUR LE FOURNISSEUR SÉLECTIONNÉ * *******************************************************/ [Bindable] public var tableauProduits:Array; 413 =Flex3 FM.book Page 414 Mardi, 2. décembre 2008 3:32 15 414 Cas pratiques PARTIE II public function listerAppareils():void { var service:RemoteObject = new RemoteObject(); service.endpoint = URL; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModAdministration"; service.serviceListerProduitsFournisseurs.addEventListener("result", ➥resultatOKListerAppareils ); service.serviceListerProduitsFournisseurs.addEventListener("fault", resultatKO) //Récupération de la valeur sélectionnée dans la comboBox service.serviceListerProduitsFournisseurs(cmb_fournisseurs.selectedItem.data); } public function resultatOKListerAppareils (e:ResultEvent):void { tableauProduits = e.result as Array } public function resultatOKListerAppareils (e:ResultEvent):void { advdg_produit.dataProvider = e.result as Array } /**************************************************** * SÉLECTION D'UN PRODUIT * **************************************************/ Import mx.events.ListEvent; public function selectionnerProduit(e:ListEvent):void { txt_refproduit.text = e.currentTarget.selectedItem.id; txt_nomproduit.text = e.currentTarget.selectedItem.nom; txt_description.text = e.currentTarget.selectedItem.description; txt_prixvente.text = e.currentTarget.selectedItem.prix; txt_prixha.text = e.currentTarget.selectedItem.prixha; txt_stockmin.text = e.currentTarget.selectedItem.stockmin; txt_stockmax.text = e.currentTarget.selectedItem.stockmax; txt_stock.text = e.currentTarget.selectedItem.stock; txt_reffournisseur.text = e.currentTarget.selectedItem.fournisseur; panel_produit.title = e.currentTarget.selectedItem.nom; selectionLigneTableauProduitIHM() } /****************************************************************** * AJOUT/MODIFICATION/SUPPRESSION D'UN PRODUIT *****************************************************************/ public function ajouterProduit():void =Flex3 FM.book Page 415 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 { if(validationFormulaireProduit() == 1) { var identifiant:int = 0; var nom:String = txt_nomproduit.text; var description:String = txt_description.text; var prix:Number = Number(txt_prixvente.text); var stock:int = int(txt_stock.text); var stockMin:int = int(txt_stockmin.text); var stockMax:int = int(txt_stockmax.text); var prixHa:Number = Number(txt_prixha.text); var fournisseur:int = int(txt_reffournisseur.text); //Instanciation de la classe AppareilPhoto var obj_Produit:AppareilPhoto = new AppareilPhoto(identifiant,nom, ➥description,prix,prixHa,stockMin,stockMax,stock,fournisseur); //Appel de la méthode d'ajout obj_Produit.ajouter(URL); //Mise à jour du tableau des produits listerAppareils(); //Réinitialisation des zones de texte initIHMProduit() } } public function modifierProduit():void { if(validationFormulaireProduit() == 1) { var identifiant:int = int(txt_refproduit.text); var nom:String = txt_nomproduit.text; var description:String = txt_description.text; var prix:Number = Number(txt_prixvente.text); var stock:int = int(txt_stock.text); var stockMin:int = int(txt_stockmin.text); var stockMax:int = int(txt_stockmax.text); var prixHa:Number = Number(txt_prixha.text); var fournisseur:int = int(txt_reffournisseur.text); //Instanciation de la classe AppareilPhoto var obj_Produit_modifier:AppareilPhoto = new AppareilPhoto(identifiant,nom, ➥description,prix,prixHa,stockMin,stockMax,stock,fournisseur); //Appel de la méthode de modification obj_Produit_modifier.modifier(URL); //Mise à jour du tableau des produits listerAppareils(); //Réinitialisation des zones de texte initIHMProduit() } } 415 =Flex3 FM.book Page 416 Mardi, 2. décembre 2008 3:32 15 416 Cas pratiques PARTIE II public function supprimerProduit():void { Alert.show("Voulez vous supprimer ce produit ?", "Suppression produit", ➥Alert.OK | Alert.CANCEL, this,confirmerSuppressionproduit, null, Alert.OK); } private function confirmerSuppressionproduit(eventObj:CloseEvent):void { if (eventObj.detail==Alert.OK) { var identifiant:int = int(txt_refproduit.text); var nom:String = txt_nomproduit.text; var description:String = txt_description.text; var prix:Number = Number(txt_prixvente.text); var stock:int = int(txt_stock.text); var stockMin:int = int(txt_stockmin.text); var stockMax:int = int(txt_stockmax.text); var prixHa:Number = Number(txt_prixha.text); var fournisseur:int = int(txt_reffournisseur.text); //Instanciation de la classe AppareilPhoto var obj_Produit_supprimer:AppareilPhoto = new AppareilPhoto(identifiant, ➥nom,description,prix,prixHa,stockMin,stockMax,stock,fournisseur); //Appel de la méthode de suppression obj_Produit_supprimer.supprimer(URL); //Mise à jour du tableau des produits listerAppareils(); //Réinitialisation des zones de texte initIHMProduit() } } Fichier MXML La dernière étape consiste à implémenter les logiques IHM et applicative dans le fichier MXML : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" creationComplete="chargerParametrageAmfPhp()"> <mx:Script source="FournisseurAS3.As"></mx:Script> <mx:Script source="ProduitAS3.as"> </mx:Script> […] <mx:TabNavigator> […] <!-- PRODUITS --> <mx:Canvas label="Produits" width="100%" height="100%" ➥show="alimenterComboFournisseurs();initIHMProduit()"> =Flex3 FM.book Page 417 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 <mx:Form x="23" y="5" width="358" height="45" horizontalScrollPolicy= ➥"off"verticalScrollPolicy="off"> <mx:FormItem label="Fournisseur :"> <mx:ComboBox width="230" id="cmb_fournisseurs" ➥change="listerAppareils()"></mx:ComboBox> </mx:FormItem> </mx:Form> <mx:AdvancedDataGrid x="23" y="63" id="advdg_produit" ➥dataProvider="{tableauProduits}" designViewDataType="flat" ➥height="168" width="852" itemClick="selectionnerProduit(event)"> <mx:columns> <mx:AdvancedDataGridColumn headerText="REF" dataField="id" ➥width="50"/> <mx:AdvancedDataGridColumn headerText="NOM" dataField="nom" ➥width="150"/> <mx:AdvancedDataGridColumn headerText="STOCK" dataField="stock" ➥width="50"/> <mx:AdvancedDataGridColumn headerText="--" dataField= ➥"description" width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="stockmin" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="stockmax" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField="prixha" ➥width="-1" visible="false"/> <mx:AdvancedDataGridColumn headerText="--" dataField= ➥"fournisseur" width="-1" visible="false"/> </mx:columns> </mx:AdvancedDataGrid> <mx:Button x="755" y="239" label="Nouveau produit" ➥id="btn_nouveauproduit" click="clickBoutonNouveauProduit()"/> <mx:Panel x="24" y="269" width="852" height="278" layout="absolute" ➥id="panel_produit"> <mx:Form x="10" y="10" height="181" width="526" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="REF :"> <mx:TextInput id="txt_refproduit" width="80" enabled="false" ➥editable="true"/> </mx:FormItem> <mx:FormItem label="Nom :" required="true"> <mx:TextInput width="400" id="txt_nomproduit"/> </mx:FormItem> <mx:FormItem label="Description :" required="true"> <mx:TextArea height="63" width="400" id="txt_description"/> </mx:FormItem> <mx:FormItem label="Prix vente :" required="true"> <mx:TextInput width="80" id="txt_prixvente"/> 417 =Flex3 FM.book Page 418 Mardi, 2. décembre 2008 3:32 15 418 Cas pratiques PARTIE II </mx:FormItem> </mx:Form> <mx:VRule x="567" y="10" width="1" height="181"/> <mx:Form x="592" y="10" height="181" width="230" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="Prix d'achat :" required="true"> <mx:TextInput width="80" id="txt_prixha"/> </mx:FormItem> <mx:FormItem label="Stock min :" required="true"> <mx:TextInput width="80" id="txt_stockmin"/> </mx:FormItem> <mx:FormItem label="Stock max :" required="true"> <mx:TextInput width="80" id="txt_stockmax"/> </mx:FormItem> <mx:FormItem label="Stock :" required="true"> <mx:TextInput width="80" id="txt_stock" editable="false" ➥enabled="false"/> </mx:FormItem> <mx:FormItem label="Ref. fournisseur :"> <mx:TextInput width="80" id="txt_reffournisseur" enabled ➥="false" editable="false"/> </mx:FormItem> </mx:Form> <mx:HBox x="10" y="208" width="814" height="29" ➥horizontalAlign="right"> <mx:Button label="Supprimer" enabled="false" ➥id="btn_supprimerpt" click="supprimerProduit()"/> <mx:Button label="Modifier" enabled="false" ➥id="btn_modifierpt" click="modifierProduit()"/> <mx:Button label="Ajouter" enabled="false" ➥id="btn_ajouterpt" click="ajouterProduit()"/> <mx:Button label="Annuler" enabled="false" ➥id="btn_annulerpt" click="initIHMProduit()"/> </mx:HBox> </mx:Panel> </mx:Canvas> </mx:TabNavigator> </mx:Module> Voilà, c’est terminé ! Nous disposons à présent d’un module fonctionnel prêt à être déployé et intégré dans notre application finale (figure 21-5). =Flex3 FM.book Page 419 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 419 Figure 21-5 Seconde partie du module fonctionnel Version de déploiement du module Pour déployer un module, il est nécessaire d’en créer une version de déploiement. Pour cela, placez-vous sur le nom du projet (moduleAdministration), cliquez droit puis choisissez l’option export dans le menu contextuel. Dans la fenêtre qui s’ouvre, sélectionnez l’option Release-build puis cliquez sur Next et terminez en cliquant sur le bouton Finish. Si tout s’est déroulé correctement, un nouveau répertoire bin-release contenant l’ensemble des fichiers issus de la compilation a été ajouté à la racine du projet. Intégration du module dans l’application principale Le module étant indépendant, nous n’avons nul besoin de créer une interface pour interagir avec l’application. Par conséquent, l’intégration du module dans l’application eReflex se résume à copier les fichiers modAdministration.swf et parametrage-amfphp.xml, présents dans répertoire bin-release de l’application moduleAdministration, vers le répertoire src de l’application eReflex (figure 21-6). =Flex3 FM.book Page 420 Mardi, 2. décembre 2008 3:32 15 420 Cas pratiques PARTIE II Figure 21-6 Intégration du module dans l’application principale Nous n’avons plus maintenant qu’à appeler le module dans le Canvas de la vue administration en implémentant un composant ModuleLoader : <mx:Canvas id="vueAdministration" label="Administration" width="100%" height="100%"> <mx:ModuleLoader id="moduleAdministration" url="modAdministration.swf"> ➥</mx:ModuleLoader> </mx:Canvas> Nous pouvons à présent visualiser notre travail en exécutant le projet E-Reflex et en nous connectant au module d’administration. Figure 21-7 Chargement du module d’administration dans l’application principale =Flex3 FM.book Page 421 Mardi, 2. décembre 2008 3:32 15 Module d’administration du site e-commerce CHAPITRE 21 421 En résumé Grâce à ce premier module, nous avons pu mettre en pratique les connaissances de base utliles pour tout développement de projet Flex. Nous vous invitons à recréer ce module sans l’aide de l’ouvrage afin de vérifier vos connaissances et vos aptitudes à créer des services PHP, établir la connexion de ces services avec l’application Flex, mettre en place un modèle et vérifier la saisie de l’utilisateur. Dans le chapitre suivant, nous allons nous consacrer au module « Site » du projet, où nous mettrons en pratique nos connaissances sur les composants et aborderons une nouvelle notion : les ItemRenderer. =Flex3 FM.book Page 422 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 423 Mardi, 2. décembre 2008 3:32 15 22 Module de vente en ligne : le panier d’achat Nous allons à présent nous consacrer au développement de la première partie du module constituant le cœur du site E-Reflex, dans laquelle nous implémenterons le composant de filtrage de données développé dans le chapitre 10, pour ensuite se consacrer à la gestion du panier d’achat. À travers ce module, nous aborderons les notions suivantes : • état et transition (chapitre 9) ; • utilisation d’un composant (chapitre 10) ; • ItemRenderer (nouvelle notion) ; • formater des données (chapitre 11) ; • lier des données (chapitre 11). Important Dans ce chapitre, nous allons utiliser le composant développé dans le chapitre 10 de cet ouvrage. Pour profiter pleinement de ce cas pratique nous vous conseillons donc d’avoir lu ce chapitre et réalisé le composant qui y est décrit. Création du module Nous allons, comme pour le module précédent, créer un nouveau projet que nous nommerons cette fois-ci moduleSite, dans lequel nous créerons un nouveau module avec les paramètres suivants : =Flex3 FM.book Page 424 Mardi, 2. décembre 2008 3:32 15 424 Cas pratiques PARTIE II • nom : modSite ; • width (largeur) = 900 pixels ; • heigth (hauteur) = 590 pixels ; • non optimisé (utilisable dans toute application Flex). Là encore, pour pouvoir tester le module tout au long de sa phase de développement, nous allons ajouter, dans le fichier MXML du projet, un composant ModuleLoader faisant appel au module que nous sommes en train de créer : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ModuleLoader id="module" url="modSite.swf"> </mx:ModuleLoader> </mx:Application> Design de l’interface L’interface va être notre page d’accueil du site E-Reflex, elle permettra à l’utilisateur de rechercher un appareil photo et en visualiser le détail. Si l’appareil lui convient, il pourra alors l’ajouter à son panier et passer commande. Les états Nous allons créer deux états. Le premier, l’état de base, comportera trois panneaux (figure 22-1) : • un panneau de recherche ; • un panneau représentant le panier du client ; • un panneau inactif contenant le détail de l’appareil photo choisi. Le second état, que nous nommerons etat_visualisationarticle, héritant de l’état de base, il comportera les mêmes panneaux mais, cette fois-ci, le panneau de recherche sera désactivé (figure 22-2). Voici le code de ces états : <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" > <mx:Script source="SiteAS3.as"> </mx:Script> =Flex3 FM.book Page 425 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 Figure 22-1 État de base <!-- ***************** ÉTAT PRINCIPAL ******************** --> <!-- PANNEAU DE RECHERCHE --> <mx:Panel x="10" y="10" width="618" height="560" layout="absolute" title="Recherche" ➥id="panel_recherche" horizontalScrollPolicy="off" verticalScrollPolicy="off"> </mx:Panel> <!-- PANIER D’ACHAT --> <mx:Panel x="636" y="10" width="250" height="452" layout="absolute" title="Mon ➥panier" id="panel_panier"> <mx:DataGrid x="10" y="10" height="367" id="dg_panier" width="210"> <mx:columns> <mx:DataGridColumn headerText="Appareils" dataField="col1"/> </mx:columns> </mx:DataGrid> <mx:Button x="10" y="380" label="Vider" width="107" id="btn_viderpanier"/> <mx:Button x="125" y="380" label="Commander" id="btn_commander"/> </mx:Panel> 425 =Flex3 FM.book Page 426 Mardi, 2. décembre 2008 3:32 15 426 Cas pratiques PARTIE II Figure 22-2 État de visualisation du détail d’un appareil photo <!-- PANNEAU DE DÉTAIL D’ARTICLE --> <mx:Panel x="636" y="470" width="250" height="100" layout="absolute" ➥title="Détail Article" id="panel_detail" verticalScrollPolicy="off" ➥horizontalScrollPolicy="off"> <mx:Form x="10" y="10" width="13" height="40" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off" id="form_detail"> <mx:FormItem label="Référence :" id="lab_reference"> <mx:TextInput width="70" id="txt_ref" editable="false"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput width="402" id="txt_nom" editable="false"/> </mx:FormItem> <mx:FormItem label="Description :"> <mx:TextArea width="402" height="84" id="txt_description" ➥editable="false"/> </mx:FormItem> <mx:FormItem label="Prix TTC :"> <mx:TextInput width="76" id="txt_prix" editable="false"/> </mx:FormItem> <mx:FormItem label="Qté en stock :"> =Flex3 FM.book Page 427 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 427 <mx:TextInput width="76" id="txt_qte" editable="false"/> </mx:FormItem> </mx:Form> </mx:Panel> <!-- ***************** ÉTAT SECONDAIRE******************** --> <mx:states> <mx:State name="etat_visualisationarticle"> <mx:SetProperty target="{panel_recherche}" name="height" value="107"/> <mx:SetProperty target="{panel_detail}" name="x" value="10"/> <mx:SetProperty target="{panel_detail}" name="y" value="10"/> <mx:SetProperty target="{panel_recherche}" name="y" value="470"/> <mx:SetProperty target="{panel_recherche}" name="width" value="250"/> <mx:SetProperty target="{panel_recherche}" name="x" value="636"/> <mx:SetProperty target="{panel_detail}" name="height" value="570"/> <mx:SetProperty target="{panel_detail}" name="width" value="618"/> <mx:SetProperty target="{form_detail}" name="width" value="578"/> <mx:SetProperty target="{form_detail}" name="height" value="510"/> <mx:AddChild relativeTo="{form_detail}" position="lastChild"> <mx:FormItem> <mx:HBox width="444" horizontalAlign="right"> <mx:Button label="Ajouter au panier" id="button1"/> <mx:Button label="Fermer" width="125"/> </mx:HBox> </mx:FormItem> </mx:AddChild> </mx:State> </mx:states> </mx:Module> Comme nous vous l’avons indiqué en introduction de ce chapitre nous allons employer le composant développé dans le chapitre 10 qui va offrir à l’utilisateur un outil de recherche. C’est par son implémentation que nous allons commencer le développement de ce module. Voyons comment implémenter le composant de recherche. La première chose à faire est de récupérer le fichier swc issu de la compilation du composant et de l’insérer dans notre module. Si vous l’avez supprimé de votre disque, référez-vous au chapitre 10 afin de le recompiler. Pour insérer un composant dans la bibliothèque de notre module Flex, il convient de procéder comme suit : 1. positionnez-vous dans les propriétés du projet ; =Flex3 FM.book Page 428 Mardi, 2. décembre 2008 3:32 15 428 Cas pratiques PARTIE II 2. dans le menu de gauche de la fenêtre, choisissez l’option Flex Build Path puis sélectionnez l’onglet library path ; 3. sur la partie droite de l’écran, cliquez sur le bouton add swc, ce qui nous permet d’importer le fichier swc de notre composant. Maintenant que le composant est ajouté à la bibliothèque, nous pouvons l’implémenter dans notre état principal, et plus particulièrement dans le panneau de recherche : <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" xmlns:composant="com.composants.*"> Implémentation du composant Voici le code réalisant l’insertion du composant dans l’interface graphique du module : <!-- Création des colonnes du tableau de notre composant --> <mx:ArrayCollection id="colonnes"> <mx:Object entete="FOURNISSEUR" champ="nomF" visible="true" longueur="150"/> <mx:Object entete="NOM" champ="champFiltre" visible="true" longueur="300"/> <mx:Object entete="PRIX (¤)" champ="prixA" visible="true" longueur="60"/> <mx:Object entete="STOCK" champ="stockA" visible="true" longueur="50"/> <mx:Object entete="--" champ="idt" visible="false" longueur="-1"/> <mx:Object entete="--" champ="descriptionA" visible="false" longueur="-1"/> <mx:Object entete="--" champ="prixA" visible="false" longueur="-1"/> </mx:ArrayCollection> <mx:Panel x="10" y="10" width="618" height="560" layout="absolute" ➥title="Recherche" id="panel_recherche" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <composant:FiltreTableau id="listeAppareilsPhotos" height="500" width="578" libelle="Nom :" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" x="10" y="10" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> </composant:FiltreTableau> </mx:Panel> Comme vous pouvez le constater, notre composant comportera quatre colonnes visibles et le filtrage sera effectuée sur le nom de l’appareil photo. L’étape suivante va consister à alimenter le composant avec la liste des appareils photo. Pour cela, nous allons créer un service PHP que nous exécuterons, comme nous l’avons fait dans le module précédent, à l’aide du composant RemoteObject. Pour le détail de la création du service et de son exécution, reportez-vous au chapitre précédent. Voici la liste des fichiers à créer et le code qui les compose. =Flex3 FM.book Page 429 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 Fichier de service PHP servModSite.php : <?php class ServModSite { protected $_serveur = 'localhost'; protected $_methodTable = array(); protected $_mdp = ''; protected $_utilisateur = 'root'; protected $_baseDeDonnees = 'reflex'; protected $_connexion = null; public function __construct() { /****************************************** /* LISTE DES SERVICES * /******************************************/ $this->_methodTable = array( 'serviceListerAppareils' => array( 'description' => 'Liste les appareils photo', 'access' => 'remote', ) ); } /* Permet la connexion au serveur de base de données */ protected function _connect() { $this->_connexion = mysql_connect($this->_serveur,$this->_utilisateur, ➥$this->_mdp); $selectDb = mysql_select_db($this->_baseDeDonnees,$this->_connexion); } /* Permet la fermeture de la connexion au serveur de base de données */ protected function _disconnect() { if(null !== $this->_connexion) mysql_close(); } public function serviceListerAppareils () { $this->_connect(); $requete = "select f.id as idF, f.nom as nomF, a.id as idt, a.nom as champFiltre, a.description as descriptionA, a.prix as prixA, a.stock as stockA, a.stockmin as stockminA, a.stockmax as stockmaxA, a.prixha as prixhaA from tb_fournisseur f, 429 =Flex3 FM.book Page 430 Mardi, 2. décembre 2008 3:32 15 430 Cas pratiques PARTIE II tb_appareilphoto a where a.fournisseur = f.id order by f.nom asc"; $resultat = mysql_query($requete); //Alimentation d'un tableau avec la liste des appareils $tableauAppareils = array(); while ($appareil = mysql_fetch_object($resultat)) { $tableauAppareils[] = $appareil; } $this->_disconnect(); return $tableauAppareils; } ?> Fichier parametrage-amfphp.xml : <?xml version="1.0" encoding="ISO-8859-1" ?> <parametre> <amfphp> <serveur>http://localhost/amfphp/gateway.php</serveur> </amfphp> </parametre> Fichier ActionScript SiteAS3.as : import import import import mx.controls.Alert; mx.rpc.events.FaultEvent; mx.rpc.events.ResultEvent; mx.rpc.remoting.mxml.RemoteObject; /**************************************************** * CHARGEMENT DES PARAMÈTRES AMFPHP * **************************************************/ public var URL:String public function chargerParametrageAmfPhp():void { var chargeur:URLLoader = new URLLoader (); var adresse:URLRequest = new URLRequest ("parametrage_amfphp.xml"); chargeur.load(adresse); chargeur.addEventListener(Event.COMPLETE, finDuChargement); chargeur.addEventListener(IOErrorEvent.IO_ERROR, indiquerErreur); } public function finDuChargement ( event:Event ):void { var contenu:XML = new XML(event.target.data); URL = contenu.amfphp.serveur; listerAppareils(); } =Flex3 FM.book Page 431 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 431 public function indiquerErreur( event:Event ):void { Alert.show("Erreur lors du chargement des paramètres amfphp"); } Modification du fichier modSite.mxml (ajout de l’attribut creationComplete() qui appellera la procédure chargerParametrageAmfPhp()) : <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" xmlns:composant="com.composants.*" creationComplete= ➥"chargerParametrageAmfPhp()"> <mx:Script source="SiteAS3.as"> </mx:Script> Procédure d’alimentation du composant : /**************************************************** * ALIMENTATION DU COMPOSANT * **************************************************/ [Bindable] public var sourceDonnees:ArrayCollection; public function listerAppareils():void { var service:RemoteObject = new RemoteObject(); service.endpoint = URL; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModSite"; service.serviceListerAppareils.addEventListener("result", ➥resultatOKListerAppareils); service.serviceListerAppareils.addEventListener("fault", resultatKO) service.serviceListerAppareils(); } public function resultatOKListerAppareils(e:ResultEvent):void { var resultat:Array = e.result as Array; //Transformation du Array en ArrayCollection nécessaire à l'alimentation du ➥tableau sourceDonnees = new ArrayCollection(resultat) } public function resultatKO(e:FaultEvent):void { Alert.show(e.fault.faultString, 'Error'); } =Flex3 FM.book Page 432 Mardi, 2. décembre 2008 3:32 15 432 Cas pratiques PARTIE II Voilà, c’est terminé ! Si nous exécutons l’application, nous constatons que le tableau est correctement alimenté et que la fonction de filtrage du tableau est fonctionnelle (figure 22-3). Cela prouve, une fois de plus, que le composant que nous avons créé est digne de ce nom car il peut s’adapter à l’application dans laquelle il est implémenté ! Figure 22-3 Composant fonctionnel Lorsque l’utilisateur va sélectionner un produit dans le tableau, nous allons afficher l’état etat_visualisationarticle qui va offrir à l’utilisateur une vision du détail du produit sélectionné. Avant de mettre en place la cinématique de ce changement d’état, il convient auparavant de vous fournir le code complet de l’IHM à des fins de vérifications. <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="900" ➥height="590" xmlns:composant="com.composants.*" creationComplete ➥="chargerParametrageAmfPhp()"> <mx:Script source="SiteAS3.as"> </mx:Script> <!-- Création des colonnes du tableau de notre composant --> <mx:ArrayCollection id="colonnes"> <mx:Object entete="FOURNISSEUR" champ="nomF" visible="true" longueur="150"/> <mx:Object entete="NOM" champ="champFiltre" visible="true" longueur="300"/> <mx:Object entete="PRIX (¤)" champ="prixA" visible="true" longueur="60"/> <mx:Object entete="STOCK" champ="stockA" visible="true" longueur="50"/> <mx:Object entete="--" champ="idt" visible="false" longueur="-1"/> <mx:Object entete="--" champ="descriptionA" visible="false" longueur="-1"/> <mx:Object entete="--" champ="prixA" visible="false" longueur="-1"/> </mx:ArrayCollection> =Flex3 FM.book Page 433 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 <!-- ***************** ÉTAT PRINCIPAL ******************** --> <mx:Panel x="10" y="10" width="618" height="560" layout="absolute" ➥title="Recherche" id="panel_recherche" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <composant:FiltreTableau id="listeAppareilsPhotos" height="500" width="578" libelle="Nom :" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" x="10" y="10" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> </composant:FiltreTableau > </mx:Panel> <mx:Panel x="636" y="10" width="250" height="452" layout="absolute" ➥title="Mon panier" id="panel_panier"> <mx:DataGrid x="10" y="10" height="367" id="dg_panier" width="210"> <mx:columns> <mx:DataGridColumn headerText="Appareils" dataField="col1"/> </mx:columns> </mx:DataGrid> <mx:Button x="10" y="380" label="Vider" width="107" id="btn_viderpanier"/> <mx:Button x="125" y="380" label="Commander" id="btn_commander"/> </mx:Panel> <mx:Panel x="636" y="470" width="250" height="100" layout="absolute" ➥title="Détail Article" id="panel_detail" verticalScrollPolicy="off" ➥horizontalScrollPolicy="off"> <mx:Form x="10" y="10" width="13" height="40" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off" id="form_detail"> <mx:FormItem label="Référence :" id="lab_reference"> <mx:TextInput width="70" id="txt_ref" editable="false"/> </mx:FormItem> <mx:FormItem label="Nom :"> <mx:TextInput width="402" id="txt_nom" editable="false"/> </mx:FormItem> <mx:FormItem label="Description :"> <mx:TextArea width="402" height="84" id="txt_description" ➥editable="false"/> </mx:FormItem> <mx:FormItem label="Prix TTC :"> <mx:TextInput width="76" id="txt_prix" editable="false"/> </mx:FormItem> <mx:FormItem label="Qté en stock :"> <mx:TextInput width="76" id="txt_qte" editable="false"/> </mx:FormItem> </mx:Form> </mx:Panel> 433 =Flex3 FM.book Page 434 Mardi, 2. décembre 2008 3:32 15 434 Cas pratiques PARTIE II <!-- ***************** ÉTAT SECONDAIRE******************** --> <mx:states> <mx:State name="etat_visualisationarticle"> <mx:SetProperty target="{panel_recherche}" name="height" value="107"/> <mx:SetProperty target="{panel_detail}" name="x" value="10"/> <mx:SetProperty target="{panel_detail}" name="y" value="10"/> <mx:SetProperty target="{panel_recherche}" name="y" value="470"/> <mx:SetProperty target="{panel_recherche}" name="width" value="250"/> <mx:SetProperty target="{panel_recherche}" name="x" value="636"/> <mx:SetProperty target="{panel_detail}" name="height" value="570"/> <mx:SetProperty target="{panel_detail}" name="width" value="618"/> <mx:SetProperty target="{form_detail}" name="width" value="578"/> <mx:SetProperty target="{form_detail}" name="height" value="510"/> <mx:AddChild relativeTo="{form_detail}" position="lastChild"> <mx:FormItem> <mx:HBox width="444" horizontalAlign="right"> <mx:Button label="Ajouter au panier" id="button1"/> < !-- Fermeture de l’état et ouverture de l’état de base --> <mx:Button label="Fermer" click="currentState=''" ➥width="125"/> </mx:HBox> </mx:FormItem> </mx:AddChild> </mx:State> </mx:states> </mx:Module> Nous pouvons à présent coder les changements d’état lorsque l’utilisateur effectue sa sélection de produit dans le tableau du composant. Rappelez-vous, lors du développement du composant nous avons prévu une procédure permettant de récupérer la valeur de la variable valeurRenvoyee correspondant à la valeur du champ idt (identifiant) de la ligne sélectionnée par l’utilisateur. Nous allons donc insérer un champ de type textinput dans notre interface, dont la propriété text sera liée à la valeur de la variable valeurRenvoyee. Ce champ ne servant pas aux utilisateurs de notre site, nous le rendrons invisible. Lorsque la valeur du champ invisible sera modifiée (à chaque sélection d’une ligne dans le tableau du composant), cela déclenchera une procédure qui exécutera un service capable de récupérer les informations du produit sélectionné (grâce à l’identifiant transmis) et d’ouvrir l’état de visualisation du détail. =Flex3 FM.book Page 435 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 435 Modifions donc notre fichier modSite.mxml afin d’y insérer la zone de texte invisible : <composant:FiltreTableau id="listeAppareilsPhotos" height="500" width="578" libelle="Nom :" tableauDonnees="{sourceDonnees}" colonnes="{colonnes}" x="10" y="10" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> </composant:FiltreTableau> <mx:TextInput x="10" y="408" text="{listeAppareilsPhotos.valeurRenvoyee}" ➥updateComplete="selectionAppareil()" visible="false"/> et créons la procédure selectionAppareil() permettant l’ouverture de l’état etat _visualisationarticle : /**************************************************** * SÉLECTION D'UN APPAREIL DANS LA LISTE * **************************************************/ public function selectionAppareil():void{ if (listeAppareilsPhotos.valeurRenvoyee != null) { //Ouverture de l'état permettant la visualisation du détail de l'appareil ➥sélectionné currentState = 'etat_visualisationarticle' //Envoi de l'identifiant au champ txt_ref dans l'état ➥etat_visualisationproduit txt_ref.text = listeAppareilsPhotos.valeurRenvoyee } } Les transitions Afin de mettre un peu de mouvement dans cette interface, nous allons utiliser des transitions pour passer d’un état à un autre. Cette partie n’étant pas des plus aisées à décrire dans un livre, nous vous conseillons de lire ce qui suit et de mettre en place les transitions afin de vous rendre compte de leur fonctionnement. Voici la transition que nous allons employer lorsque nous passerons de l’état de base vers l’état de visualisation du détail de l’appareil photo sélectionné : 1. le composant situé dans le panneau de recherche est réduit ; 2. le panneau recherche est réduit à son tour pour prendre la taille du panneau affichant le détail ; =Flex3 FM.book Page 436 Mardi, 2. décembre 2008 3:32 15 436 Cas pratiques PARTIE II 3. le panneau de détail est déplacé vers la gauche pour laisser la place au panneau de recherche ; 4. le panneau de recherche est déplacé et prend la place du panneau de détail ; 5. le panneau de détail est positionné aux anciennes coordonnées du panneau de recherche ; 6. le panneau de détail est agrandi pour prendre la taille qu’occupait le panneau de recherche ; 7. le formulaire que contient le panneau de détail est agrandi, permettant d’afficher l’ensemble des informations sur l’appareil photo sélectionné. Ajoutons donc cette transition à notre fichier modSite.mxml : <!-- ***************** TRANSITIONS ******************** --> <mx:transitions> <mx:Transition id="ouvertureDetail" fromState="" ➥toState="etat_visualisationarticle"> <mx:Sequence> <mx:Resize target="{listeAppareilsPhotos}" heightTo="0" widthTo="0" ➥duration="1000"></mx:Resize> <mx:Resize target="{panel_recherche}" heightTo="100" widthTo="250" ➥duration="1000"> </mx:Resize> <mx:Move target="{panel_detail}" xTo="378" yTo="470" duration="1000"> ➥</mx:Move> <mx:Move target="{panel_recherche}" xTo="636" yTo="470" ➥duration="1000"></mx:Move> <mx:Move target="{panel_detail}" xTo="10" yTo="10" duration="1000"> ➥</mx:Move> <mx:Resize target="{panel_detail}" heightTo="560" widthTo="618" ➥duration="1000" > </mx:Resize> <mx:Resize target="{form_detail}" heightTo="510" widthTo="578" ➥duration="1000" > </mx:Resize> </mx:Sequence> </mx:Transition> </mx:transitions> La transition vers l’état de base sera, quant à elle, la suivante : 1. le formulaire situé dans le panneau de détail est réduit ; 2. le panneau de détail est réduit à son tour pour prendre la taille du panneau de recherche ; 3. le panneau de recherche est déplacé vers la gauche pour laisser la place au panneau de détail ; 4. le panneau de détail est déplacé et prend la place du panneau de recherche ; 5. le panneau de recherche est positionné aux anciennes coordonnées du panneau de détail ; 6. le panneau de recherche est agrandi pour prendre la taille qu’occupait le panneau de détail ; =Flex3 FM.book Page 437 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 437 7. le composant que contient le panneau de recherche est agrandi afin d’afficher la liste des appareils que nous proposons à la vente. <!-- ***************** TRANSITIONS ******************** --> <mx:transitions> […] <mx:Transition id="ouvertureRecherche" fromState="etat_visualisationarticle" ➥toState=""> <mx:Sequence> <mx:Resize target="{form_detail}" heightTo="40" widthTo="10" ➥duration="1000"> </mx:Resize> <mx:Resize target="{panel_detail}" heightTo="100" widthTo="250" ➥duration="1000"> </mx:Resize> <mx:Move target="{panel_recherche}" xTo="378" yTo="470" ➥duration="1000"></mx:Move> <mx:Move target="{panel_detail}" xTo="636" yTo="470" duration="1000"> ➥</mx:Move> <mx:Move target="{panel_recherche}" xTo="10" yTo="10" ➥duration="1000"></mx:Move> <mx:Resize target="{panel_recherche}" heightTo="560" widthTo="618" ➥duration="1000" > </mx:Resize> <mx:Resize target="{listeAppareilsPhotos}" heightTo="500" ➥widthTo="578" duration="1000"></mx:Resize> </mx:Sequence> </mx:Transition> </mx:transitions> Voyons à présent comment alimenter les zones de texte de l’état présentant le détail de l’appareil photo sélectionné. Affichage du détail d’un produit Comme vous devez vous en douter, il s’agit là de créer un nouveau service dont voici le code : public function servideDetailAppareil($idAppareil){ $this->_connect(); $requete = 'SELECT * FROM tb_appareilphoto WHERE id='.(int)$idAppareil. ➥' LIMIT 1'; $resultat = mysql_query($requete); $tableauAppareil = array(); while ($appareil = mysql_fetch_object($resultat)) { $tableauAppareil[] = $appareil; } $this->_disconnect(); return $tableauAppareil; } =Flex3 FM.book Page 438 Mardi, 2. décembre 2008 3:32 15 438 Cas pratiques PARTIE II Modifions à présent la procédure selectionAppareil() afin d’exécuter ce service : /**************************************************** * SÉLECTION D'UN APPAREIL DANS LA LISTE * **************************************************/ public function selectionAppareil():void{ if (listeAppareilsPhotos.valeurRenvoyee != null) { var service:RemoteObject = new RemoteObject(); service.endpoint = URL; service.showBusyCursor = true; service.destination="amfphp"; service.source="ServModSite"; service.servideDetailAppareil.addEventListener("result", ➥resultatOKDetailAppareil); service.servideDetailAppareil.addEventListener("fault", resultatKO) //Appel du service et passage de l’identifiant de l’appareil en paramètre service.servideDetailAppareil(listeAppareilsPhotos.valeurRenvoyee); } } public function resultatOKDetailAppareil(e:ResultEvent):void { var resultat:Array = e.result as Array; //Transformation du résultat en ArrayCollection var tableau:ArrayCollection = new ArrayCollection(resultat) //Analyse du tableau reçu en paramètre et récupération des données du premier ➥enregistrement if (tableau.length != 0) { txt_ref.text = tableau[0].id; txt_description.text = tableau[0].description; txt_nom.text = tableau[0].nom; txt_prix.text = tableau[0].prix; txt_qte.text = tableau[0].stock; //On a déplacé l'ouverture de l'état dans cette procédure currentState = 'etat_visualisationarticle' } } =Flex3 FM.book Page 439 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 439 La première partie du module est à présent terminée. Nous allons maintenant nous atteler au développement du panier d’achat. Gestion du panier d’achat Dans cette partie, nous allons aborder le design du panier pour ensuite nous concentrer sur son alimentation. Design du panier avec ItemRenderer L’objectif est de présenter, pour chaque ligne de produit présent dans le panier, sa référence, son nom et son prix. Nous avons utilisé le composant Datagrid pour afficher l’ensemble des produits ajoutés au panier. Cependant, il ne permet pas la présentation multi-ligne des données, c’est pourquoi nous allons devoir utiliser un composant de type conteneur, qui servira à mettre en forme chaque ligne du Datagrid. Le principe réside en la création d’un composant MXML où il nous sera possible de réaliser la mise en forme souhaitée. Ce composant sera ensuite utilisé dans la propriété itemRenderer de la ligne du datagrid (figure 22-4), ce qui créera un masque de mise en forme pour chaque ligne du datagrid. Figure 22-4 Principe de mise en forme avec la propriété ItemRenderer =Flex3 FM.book Page 440 Mardi, 2. décembre 2008 3:32 15 440 Cas pratiques PARTIE II Créons le composant de mise en forme. La première étape consiste à ajouter un nouveau fichier MXML Component à notre projet ayant les caractéristiques suivantes : • nom : ItemRenderer_Panier ; • type : Canvas ; • hauteur (height) : 70 px ; • largeur (width) : 210 px (correspond à la largeur d’une ligne du DataGrid). Les données affichées dans le datagrid seront issue de son dataprovider, qui sera alimenté par un tableau d’objets contenant les attributs suivants : • refProduit, stockant la référence du produit ; • nomProduit, stockant le nom du produit ; • prixProduit, stockant le prix du produit. Néanmoins, le dataprovider ne sert qu’à alimenter les lignes du datagrid et non notre composant de mise en forme. Pour cela nous ferons appel, dans notre composant de mise en forme, à la propriété data qui effectuera une connexion avec la ligne du datagrid concernée par la mise en forme et permettra d’en extraire les données. Voici le code de notre composant : <?xml version="1.0" encoding="utf-8"?> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="210" height="70" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:CurrencyFormatter id="formatEuros" currencySymbol="¤" alignSymbol="right" /> <mx:Label x="13" y="10" text="Réf :" id="lab_referenceProduit"/> <mx:Text x="46" y="10" text="{data.refProduit}" width="78" id="txt_refpanier" ➥fontStyle="italic" height="18"/> <mx:Text x="10" y="36" text="{data.nomProduit}" width="117" id="txt_nompanier" ➥fontWeight="bold"/> <!-- Ajout d’une ligne verticale de séparation --> <mx:VRule x="132" y="0" width="11" height="70" strokeWidth="1"/> <mx:Text x="139" y="25" id="txt_prixpanier" text="{formatEuros.format(data.prixProduit)}" width="66" height="29" fontWeight="bold" textAlign="center" fontSize="14" /> </mx:Canvas> Nous avons désactivé l’affichage des barres de défilement horizontal et vertical du Canvas, évitant ainsi tout défaut d’affichage. Nous avons ensuite implémenté le composant currencyFormater qui nous permettra d’afficher le prix du produit ajouté au panier =Flex3 FM.book Page 441 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 441 sous le format Euros. On observe enfin que chaque zone de texte récupère la valeur qui lui est propre grâce à la propriété data et que la valeur contenue dans la zone de texte txt_prixpanier fait appel au composant currencyFormater afin de mettre en forme la donnée qu’il contient. Nous terminons en appelant le masque de mise en forme dans le tableau représentant le panier d’achat situé dans le fichier modSite.mxml, sans oublier d’ajuster la hauteur des lignes du datagrid à 70 pixels afin d’afficher notre composant dans son intégralité : <mx:DataGrid x="10" y="10" height="367" id="dg_panier" width="210" rowHeight="70"/> <mx:columns> <mx:DataGridColumn headerText="Appareils" ➥itemRenderer="ItemRenderer_Panier"/> </mx:columns> </mx:DataGrid> Ajouter un produit au panier L’ajout d’un produit au panier s’effectue à l’aide d’une procédure mettant à jour une collection d’objets. Notez que le dataProvider du datagrid représentant le panier d’achat est lié par la notion de databinding à la collection d’objets. De ce fait, lorsque la collection d’objets est mise à jour, les données affichées dans le panier le sont aussi. Il convient donc d’ajouter cette procédure au fichier SiteAS3.as : [Bindable] public var panierAchat:ArrayCollection = new ArrayCollection(); public function ajouterPanier():void { var reference:String = txt_ref.text var prix:Number = Number(txt_prix.text) var nom:String = txt_nom.text panierAchat.addItem({refProduit:reference, nomProduit:nom, prixProduit:prix}) } puis de créer la liaison entre la variable panierAchat et le dataProvider du panier d’achat : <mx:DataGrid x="10" y="10" height="367" id="dg_panier" width="210" rowHeight="70" dataProvider="{panierAchat}" /> L’appel de la procédure ajouterPanier() sera effectué lorsque l’utilisateur cliquera sur le bouton Ajouter situé dans l’état etat_visualisationarticle. Il faut donc spécifier cet appel comme suit : <!-- ***************** ÉTAT SECONDAIRE ******************** --> <mx:states> <mx:State name="etat_visualisationarticle"> <mx:SetProperty target="{panel_recherche}" name="height" value="107"/> =Flex3 FM.book Page 442 Mardi, 2. décembre 2008 3:32 15 442 Cas pratiques PARTIE II <mx:SetProperty target="{panel_detail}" name="x" value="10"/> <mx:SetProperty target="{panel_detail}" name="y" value="10"/> <mx:SetProperty target="{panel_recherche}" name="y" value="470"/> <mx:SetProperty target="{panel_recherche}" name="width" value="250"/> <mx:SetProperty target="{panel_recherche}" name="x" value="636"/> <mx:SetProperty target="{panel_detail}" name="height" value="570"/> <mx:SetProperty target="{panel_detail}" name="width" value="618"/> <mx:SetProperty target="{form_detail}" name="width" value="578"/> <mx:SetProperty target="{form_detail}" name="height" value="510"/> <mx:AddChild relativeTo="{form_detail}" position="lastChild"> <mx:FormItem> <mx:HBox width="444" horizontalAlign="right"> <mx:Button label="Ajouter au panier" id="button1" ➥click="ajouterPanier()"/> <mx:Button label="Fermer" click="currentState=''" ➥width="125"/> </mx:HBox> </mx:FormItem> </mx:AddChild> </mx:State> </mx:states> Vider le panier Pour vider le panier, nous allons employer la méthode removeAll() de la classe Array Collection. Pour cela, créons une procédure viderPanier() contenant le code suivant : public function viderPanier():void { panierAchat.removeAll(); } Comme une liaison entre le dataProvider du panier et la variable panierAchat a été effectuée, l’utilisateur verra disparaître l’ensemble des éléments de son panier. Mais cela n’est possible que si nous appelons notre nouvelle procédure lors du clic sur le bouton Vider situé dans le Panel contenant notre panier. Placez-vous bien sur l’état de base lors de l’implémentation de cet appel, sous peine de ne voir s’exécuter la procédure de suppression d’éléments que lorsque l’utilisateur se situera sur l’état etat_visualisatioarticle ! <mx:Button x="10" y="380" label="Vider" width="107" id="btn_viderpanier" ➥click="viderPanier()"/> Nous pouvons à présent tester le bon fonctionnement de notre panier en y ajoutant des produits et en vidant son contenu. =Flex3 FM.book Page 443 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 443 À vos claviers : création de l’interface graphique Votre travail va consister à préparer l’interface graphique qui nous servira de base de travail pour le chapitre suivant. L’objectif est de créer l’interface graphique de passage d’une commande présenté à la figure 22-5. Figure 22-5 État « etat_commande » Ce qu’il faut réaliser Il faut créer un nouvel état que nous nommerons etat_commande, héritant de l’état de base, dont l’appel sera effectué en cliquant sur le bouton Commander situé dans le Panel du panier. Dans cet état, nous vous demanderons d’y placer les éléments suivants : • Un formulaire de saisie d’informations sur le client (figure 22-6). =Flex3 FM.book Page 444 Mardi, 2. décembre 2008 3:32 15 444 Cas pratiques PARTIE II Figure 22-6 Informations sur le client • Un composant TileList, contenant l’ensemble des produits présents dans le panier. Vous devez y ajouter une fonctionnalité permettant de choisir la quantité voulue et recalculant le total à payer par produit (figure 22-7). Figure 22-7 Mise en place du composant TileList • Un tableau nommé dg_commande contenant les colonnes Ref, Produit, Prix, Quantité, Total. L’alimentation de ce tableau ne nous intéresse pas pour le moment. Ajoutez-y également un label contenant le texte « Total à payer » et une zone de texte (figure 22-8). Figure 22-8 Tableau de commande =Flex3 FM.book Page 445 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 445 • Un bouton portant le libellé « Valider Commande » dont l’action sur celui-ci déclenchera la validation du formulaire de saisie d’information et, selon le résultat de la validation, affichera le texte « Commande Validée ». • Un bouton Retour permettant à l’utilisateur d’annuler sa commande et de revenir au détail de l’article. Avant de vous laisser réaliser cette interface, nous allons modifier le code d’ajout d’un produit dans le panier en ajoutant les champs quantiteProduit, servant à stocker la quantité commandée, et totalProduit, servant à stocker le montant total à payer pour chaque produit. public function ajouterPanier():void { var reference:String = txt_ref.text var prix:Number = Number(txt_prix.text) var nom:String = txt_nom.text panierAchat.addItem({refProduit:reference, nomProduit:nom, prixProduit:prix, ➥quantiteProduit:1, totalProduit:prix}) } La partie la plus complexe de l’exercice réside dans la mise en place du composant TileList. La solution, comme vous devez vous en douter, consiste à créer un ItemRenderer permettant la mise en forme de chaque cellule du composant TileList. N’oubliez pas de modifier les valeurs des champs totalPrix et quantitePrix du dataProvider du composant TileList (la propriété data.nomduchamp sert à récupérer la valeur de la ligne en cours de lecture mais permet aussi de modifier la valeur du dataProvider de la ligne lue). Solution Création de l’interface La difficulté résidait essentiellement dans l’alimentation du composant TileList : <!-- ***************** ÉTAT COMMANDE ******************** --> <mx:State name="etat_commande"> <mx:RemoveChild target="{panel_recherche}"/> <mx:RemoveChild target="{panel_panier}"/> <mx:RemoveChild target="{panel_detail}"/> <mx:AddChild position="lastChild"> <mx:Panel x="10" y="10" width="880" height="570" layout="absolute" ➥title="Passer votre commande" id="panel_commande"> <!-- FORMULAIRE DE SAISIE --> <mx:Label x="10" y="12" text="Adresse de livraison :" ➥fontWeight="bold" id="lab_adresseLivraison"/> <mx:Form x="10" y="38" width="288" height="186" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:FormItem label="Prénom :" required="true"> <mx:TextInput id="txt_prenomCommande"/> =Flex3 FM.book Page 446 Mardi, 2. décembre 2008 3:32 15 446 Cas pratiques PARTIE II </mx:FormItem> <mx:FormItem label="Nom :" required="true"> <mx:TextInput id="txt_nomCommande"/> </mx:FormItem> <mx:FormItem label="Adresse :" required="true"> <mx:TextArea id="txt_adresseCommande"/> </mx:FormItem> <mx:FormItem label="Code Postal :" required="true"> <mx:TextInput id="txt_cpCommande"/> </mx:FormItem> <mx:FormItem label="Ville :" required="true"> <mx:TextInput id="txt_villeCommande"/> </mx:FormItem> </mx:Form> <!-- MISE EN PLACE DU COMPOSANT TITLELIST --> <mx:Label x="366" y="12" text="Votre panier :" fontWeight="bold" ➥id="lab_VotrePanier"/> <mx:TileList itemRenderer="ItemRenderer_PreCommande" x="366" y="38" height="228" ➥dataProvider="{panierAchat}" rowHeight="98" columnWidth="400" width="400" ➥id="tl_Panier"></mx:TileList> <mx:HRule x="10" y="274" width="840" height="14" strokeWidth="1"/> <!-- LE TABLEAU --> <mx:Label x="10" y="308" text="Votre commande :" ➥fontWeight="bold" id="lab_VotreCommande"/> <mx:DataGrid x="10" y="334" width="840" height="84" ➥id="dg_commande"> <mx:columns> <mx:DataGridColumn headerText="Ref" dataField=" "/> <mx:DataGridColumn headerText="Produit" dataField=" "/> <mx:DataGridColumn headerText="Prix (¤)" dataField=" "/> <mx:DataGridColumn headerText="Quantité" dataField=" "/> <mx:DataGridColumn headerText="Total (¤)" dataField=" "/> </mx:columns> </mx:DataGrid> <mx:Label x="602" y="431" text="Total à payer :" ➥id="lab_TotalAPayer"/> <mx:Text x="681" y="426" text="Text" width="169" height="27" ➥fontWeight="bold" fontSize="16" textAlign="center" ➥id="txt_totalCommande"/> <mx:HRule x="10" y="457" width="840" height="14" strokeWidth="1"/> <!-- LE BOUTON DE VALIDATION --> =Flex3 FM.book Page 447 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 447 <mx:Button x="705" y="483" label="Valider la commande" ➥id="btn_validerCommande" click="validerCommande()"/> <!-- LE BOUTON DE RETOUR --> <mx:Button x="10" y="483" label="Retour" click= ➥"currentState='etat_visualisationarticle'" id="btn_retour"/> </mx:Panel> </mx:AddChild> </mx:State> N’oublions pas de faire appel à cet état lorsque l’utilisateur cliquera sur le bouton Commander présent sur l’interface du panier : <mx:Panel x="636" y="10" width="250" height="452" layout="absolute" title="Mon ➥panier" id="panel_panier"> <mx:DataGrid x="10" y="10" height="367" id="dg_panier" width="210" ➥rowHeight="70" dataProvider="{panierAchat}" > <mx:columns> <mx:DataGridColumn headerText="Appareils" ➥itemRenderer="ItemRenderer_Panier"/> </mx:columns> </mx:DataGrid> <mx:Button x="10" y="380" label="Vider" width="107" id="btn_viderpanier" ➥click="viderPanier()"/> <mx:Button x="125" y="380" label="Commander" id="btn_commander" ➥click="currentState='etat_commande'"/> </mx:Panel> Création de l’ItemRenderer Nous avons choisi de nommer notre ItemRenderer ItemRenderer_PreCommande.mxml. Nous l’avons créé à partir du composant HBox qui permet d’aligner automatiquement sur le plan horizontal les composants qui y sont insérés. <?xml version="1.0" encoding="utf-8"?> <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="98" ➥horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:Script> <![CDATA[ //Calcul du prix total public function calculerPrix():void { //Mise à jour du DataProvider data.quantiteProduit = num_quantite.value; data.totalProduit = num_quantite.value * (Number(data.prixProduit)); //Mise à jour de la zone de texte txt_prixTotal txt_prixTotal.text = formatEuros.format(data.totalProduit) } =Flex3 FM.book Page 448 Mardi, 2. décembre 2008 3:32 15 448 Cas pratiques PARTIE II ]]> </mx:Script> <!-- FORMAT EUROS --> <mx:CurrencyFormatter id="formatEuros" alignSymbol="right" currencySymbol="¤" /> <!-- DÉTAIL DU PRODUIT --> <mx:Canvas width="227" height="97" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:Text x="0" y="5" text="PRODUIT" width="227" fontWeight="bold" ➥textAlign="center"/> <mx:HRule x="0" y="26" strokeWidth="1" width="227"/> <mx:Label x="10" y="31" text="Ref :" id="lab_ref"/> <mx:Text x="61" y="31" text="{data.refProduit}" width="156" id="txt_ref" ➥textAlign="left" fontWeight="bold"/> <mx:Label x="10" y="51" text="Nom :" id="lab_nom"/> <mx:Text x="61" y="52" text="{data.nomProduit}" width="156" id="txt_nom" ➥textAlign="left" fontWeight="bold"/> <mx:Label x="10" y="71" text="Prix :" id="lab_prix"/> <mx:Text x="61" y="71" text="{formatEuros.format(data.prixProduit)}" ➥width="156" id="txt_prix" textAlign="left" fontWeight="bold"/> </mx:Canvas> <!-- SAISIE DE LA QUANTITÉ --> <mx:Canvas width="58" height="97" verticalScrollPolicy="off" ➥horizontalScrollPolicy="off"> <mx:Text x="0" y="5" text="QTE" fontWeight="bold" textAlign="center" ➥width="58"/> <mx:NumericStepper x="12" y="46" height="23" width="38" id="num_quantite" ➥minimum="1" stepSize="1" value="{data.quantiteProduit}" ➥change="calculerPrix()"/> <mx:HRule x="0" y="26" strokeWidth="1" width="58" height="1"/> </mx:Canvas> <!-- AFFICHAGE DU PRIX TOTAL --> <mx:Canvas width="98" height="99" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:Text x="0" y="5" text="PRIX TOTAL" width="98" textAlign="center" ➥fontWeight="bold"/> <mx:HRule x="-1" y="26" strokeWidth="1"/> <mx:Text x="10" y="47" text="{formatEuros.format(data.totalProduit)}" ➥fontSize="14" fontWeight="bold" width="78" textAlign="center" ➥id="txt_prixTotal"/> </mx:Canvas> </mx:HBox> =Flex3 FM.book Page 449 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : le panier d’achat CHAPITRE 22 449 Mise en place de la validation du formulaire La première étape consiste à créer les éléments de validation dans le fichier modSite.mxml (placez-les en dessous des transitions déjà présentes) : <!-- ***************** VALIDATEURS COMMANDES ******************** --> <mx:StringValidator id="val_prenom" property="text" source="{txt_prenomCommande}" ➥required="true" requiredFieldError="Ce champ est obligatoire" /> <mx:StringValidator id="val_nom" property="text" source="{txt_nomCommande}" ➥required="true" requiredFieldError="Ce champ est obligatoire" /> <mx:StringValidator id="val_adresse" property="text" source=" ➥{txt_adresseCommande}" required="true" requiredFieldError="Ce champ est ➥obligatoire" /> <mx:StringValidator id="val_ville" property="text" source="{txt_villeCommande}" ➥required="true" requiredFieldError="Ce champ est obligatoire" /> <mx:ZipCodeValidator id="val_codePostal" property="text" ➥source="{txt_cpCommande}" required="true" requiredFieldError="Ce champ est ➥obligatoire" wrongLengthError="Format erroné !!" /> Terminez par la création des procédures de validation du formulaire dans le fichier SiteAS3.as : /**************************************************** * CRÉATION COMMANDE * **************************************************/ import mx.validators.Validator; //Procédure de validation des champs public function validerSaisie():int { var valide:int = 1; var tableau_validation:Array = Validator.validateAll ➥([val_prenom,val_nom,val_adresse,val_ville,val_codePostal]); if (tableau_validation.length != 0) { valide = 0; } return valide; } //Procédure de validation de la commande public function validerCommande():void { if (validerSaisie()==1) { Alert.show("La commande est validée") } } =Flex3 FM.book Page 450 Mardi, 2. décembre 2008 3:32 15 450 Cas pratiques PARTIE II Cela ne présente pas de grandes difficultés, étant donné que nous avions abordé la validation de formulaire dans le chapitre précédent. En résumé Dans ce chapitre, traitant de la première partie de la vente en ligne, nous avons pu mettre en pratique nos connaissances sur la création d’états et de transitions et l’utilisation de composants personnalisés. Nous avons également abordé la notion d’ItemRenderer, outil permettant de réaliser des masques de mise en forme applicables à tout composant, et pratiqué la création de services PHP, la validation de données et le databinding. Dans le chapitre suivant, nous allons terminer le module concernant le cœur du site E-Reflex en étudiant la notion de glisser-déposer et en appliquant nos connaissances sur la gestion des pop-ups, acquises dans le chapitre 6. =Flex3 FM.book Page 451 Mardi, 2. décembre 2008 3:32 15 23 Module de vente en ligne : commande et facturation Dans cette deuxième partie du module de vente en ligne, nous allons nous concentrer sur la création de la commande et de sa facturation (édition et impression). Enfin, nous terminerons par la création d’une interface qui rendra possible la réalisation du paiement en ligne. Dans cette partie, nous allons travailler sur les nouvelles notions suivantes : • le glisser-déposer (drag and drop) ; • l’impression ; • la manipulation de dates ; • l’utilisation du composant <mx:repeater>. Important Avant de poursuivre la lecture de ce chapitre, il convient d’avoir réalisé l’ensemble des tâches demandées dans le chapitre précédent. Si vous n’avez pas réalisé ce travail, vous pouvez télécharger les sources sur la fiche de l’ouvrage : www.editions-eyrolles.com Création de la commande Nous allons dans un premier temps nous consacrer à la mise en place du processus de commande. Pour passer sa commande, l’utilisateur prendra les éléments de son panier qu’il souhaite commander et viendra les déposer dans le tableau de commande que vous avez créé dans le chapitre précédent. =Flex3 FM.book Page 452 Mardi, 2. décembre 2008 3:32 15 452 Cas pratiques PARTIE II Implémenter le glisser-déposer dans le tableau de commander Pour implémenter l’opération de glisser-déposer (drag and drop), nous devons définir l’objet source et l’objet de destination. Notre objet source est le panier à partir duquel nous allons effectuer le glissé (drag). Notre objet de destination est le tableau de commande dans lequel nous allons déposer (drop) les produits. La première étape va donc consister à mettre définir les actions sur chaque objet : Le panier : <mx:TileList dragEnabled="true" itemRenderer="ItemRenderer_PreCommande" x="366" y="38" height="228" dataProvider="{panierAchat}" rowHeight="98" columnWidth="400" width="400" id="tl_Panier"> </mx:TileList> Le tableau de commande : <mx:DataGrid dropEnabled="true" x="10" y="334" width="840" height="84" id="dg_commande"> <mx:columns> <mx:DataGridColumn headerText="Ref" ➥dataField="refProduit"/> <mx:DataGridColumn headerText="Produit" ➥dataField="nomProduit"/> <mx:DataGridColumn headerText="Prix" ➥dataField="prixProduit"/> <mx:DataGridColumn headerText="Quantité" ➥dataField="quantiteProduit"/> <mx:DataGridColumn headerText="Total" ➥dataField="totalProduit"/> </mx:columns> </mx:DataGrid> Lorsque l’utilisateur déposera le produit dans le tableau de commandes, les données contenues dans ce tableau seront une copie des données présentes dans le panier. Par conséquent, les champs alimentant le tableau de commande doivent être identiques à ceux contenus dans le dataProvider du panier. Nous pouvons à présent tester notre application et vérifier le bon fonctionnement du glisser-déposer mis en place. =Flex3 FM.book Page 453 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 453 Supprimer l’article du panier Lorsque l’utilisateur a sélectionné son article et l’a déposé dans le tableau de commande, celui-ci ne doit plus être présent dans son panier. Pour réaliser cette suppression, nous devons activer la propriété dragMoveEnabled du composant source : <mx:TileList dragEnabled="true" dragMoveEnabled="true" itemRenderer="ItemRenderer_PreCommande" x="366" y="38" height="228" dataProvider="{panierAchat}" rowHeight="98" columnWidth="400" width="400" id="tl_Panier"> </mx:TileList> Si nous exécutons notre module, nous voyons qu’il est possible de sélectionner un produit, de le placer dans le tableau de commande et de le voir disparaître de notre panier. L’objectif est donc atteint (figure 23-1). Figure 23-1 Ajout d’un produit dans le tableau de commande =Flex3 FM.book Page 454 Mardi, 2. décembre 2008 3:32 15 454 Cas pratiques PARTIE II Implémenter l’inverse Nous sommes en mesure de déplacer un produit du panier vers le tableau de commande. Néanmoins, il se peut que l’utilisateur se trompe et souhaite remettre le produit dans son panier. Les objets source et destination étant inversés, il suffit d’activer les propriétés dragEnabled et dragMove Enabled du tableau de commande, et permettre la possibilité de redéposer un produit dans le panier en activant la propriété dropEnabled. Le tableau de commande : <mx:DataGrid dropEnabled="true" dragEnabled="true" dragMoveEnabled="true" x="10" y="334" width="840" height="84" id="dg_commande"> <mx:columns> <mx:DataGridColumn headerText="Ref" ➥dataField="refProduit"/> <mx:DataGridColumn headerText="Produit" ➥dataField="nomProduit"/> <mx:DataGridColumn headerText="Prix" ➥dataField="prixProduit"/> <mx:DataGridColumn headerText="Quantité" ➥dataField="quantiteProduit"/> <mx:DataGridColumn headerText="Total" ➥dataField="totalProduit"/> </mx:columns> </mx:DataGrid> Le panier : <mx:TileList dragEnabled="true" dragMoveEnabled="true" dropEnabled="true" itemRenderer="ItemRenderer_PreCommande" x="366" y="38" height="228" dataProvider="{panierAchat}" rowHeight="98" columnWidth="400" width="400" id="tl_Panier"> </mx:TileList> Il est à présent possible de remettre un produit dans le panier, annulant ainsi la commande de ce dernier (figure 23-2). =Flex3 FM.book Page 455 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 455 Figure 23-2 Remise du produit dans le panier d’achat Calcul du prix total de la commande Le prix total de la commande est calculé en réalisant la somme des prix de chaque produit situé dans le tableau de commande. Ce calcul est effectué à chaque mise à jour du contenu de ce tableau, c’est-à-dire à chaque fois que l’utilisateur dépose ou retire un élément dans le tableau. On peut traduire ce processus comme suit : • Lorsque l’utilisateur déplace un produit du panier vers le tableau, le prix de ce produit est ajouté au total de la commande. • Lorsque l’utilisateur déplace un produit de tableau de commande vers le panier d’achat, le prix de ce produit est déduit du total de la commande. Si nous analysons bien ces deux phrases, nous souhaitons que le calcul soit effectué après déplacement complet du produit. Pour réaliser cela, nous allons utiliser le déclencheur d’événement dragComplete() des deux composants : <mx:TileList dragEnabled="true" dragMoveEnabled="true" dropEnabled="true" =Flex3 FM.book Page 456 Mardi, 2. décembre 2008 3:32 15 456 Cas pratiques PARTIE II dragComplete="calculerTotalCommande(event)" name="listePanier"> </mx:TileList> <mx:DataGrid dropEnabled="true" dragMoveEnabled="true" dragEnabled="true" dragComplete="calculerTotalCommande(event)" ➥name="tableauCommande" Ainsi, lorsque le produit est déplacé, la procédure calculerTotalCommande() est exécutée. La propriété name a également été ajoutée, permettant de déterminer le composant étant à l’origine du déplacement (dragInitiator) et de déterminer ainsi, l’ajout ou la diminution du prix total du produit sélectionné au total de la commande. Voyons à présent le code de la procédure calculerTotalCommande() : /**************************************************** * CALCUL DU TOTAL DE LA COMMANDE * **************************************************/ [Bindable] public var totalCommande:int = 0 public function calculerTotalCommande(e:DragEvent):void { if (e.dragInitiator.name == "listePanier") { totalCommande += e.currentTarget.selectedItem.totalProduit } else { totalCommande -= e.currentTarget.selectedItem.totalProduit } } Comme nous venons de l’indiquer, en fonction du nom de composant étant à l’origine du déplacement du produit, la valeur du champ totalProduit est ajoutée ou soustraite à la variable totalCommande. Enfin, pour que cela soit entièrement fonctionnel, il convient de lier la propriété text du composant txt_totalCommande chargé d’afficher le total de la commande en prenant soin de formater le résultat, via le composant CurrencyFormatter, afin que celui-ci soit présenté sous forme monétaire (figure 23-3) : =Flex3 FM.book Page 457 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 457 <!-- FORMAT EURO (A PLACER AU DESSUS DE L'ETAT PRINCIPAL) --> <mx:CurrencyFormatter id="formatEuros" alignSymbol="right" currencySymbol="€" /> <!-- composant txt_totalCommande de l’état etat_commande --> <mx:Text x="681" y="426" text="{formatEuros.format(totalCommande)}" width="169" ➥height="27" fontWeight="bold" fontSize="16" textAlign="center" ➥id="txt_totalCommande"/> Figure 23-3 Calcul du total de la commande Création de la facture Nous souhaitons proposer la visualisation de la facture à l’aide d’un pop-up. Dans ce pop-up, nous disposerons un bouton permettant d’imprimer la facture. Implémentation du pop-up de facturation Comme nous l’avons vu dans le chapitre 6, pour créer un pop-up, il faut créer un nouveau fichier MXML Component basé sur le composant TitleWindow. Nous le nommerons pop Facture.mxml et il accueillera le code permettant de réaliser la facture illustrée par la figure 23-4 : =Flex3 FM.book Page 458 Mardi, 2. décembre 2008 3:32 15 458 Cas pratiques PARTIE II Figure 23-4 Pop-up de facturation <?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow close="fermerPopUp()" xmlns:mx="http://www.adobe.com/2006/mxml" ➥layout="absolute" width="544" height="570" title="Votre Facture" ➥showCloseButton="true"> <mx:Script> <![CDATA[ //Procédure de fermeture import mx.managers.PopUpManager; public function fermerPopUp():void { PopUpManager.removePopUp(this) } =Flex3 FM.book Page 459 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 459 //Impression de la Facture import mx.printing.* public function imprimerFacture():void { var impression:FlexPrintJob = new FlexPrintJob() impression.start(); impression.addObject(this,FlexPrintJobScaleType.NONE) impression.send(); } ]]> </mx:Script> <!-- TITRE --> <mx:Label x="10" y="10" text="EReflex" width="165" fontWeight="bold" ➥fontSize="24"/> <mx:HRule x="10" y="42" width="496" height="8" strokeWidth="1"/> <!-- ADRESSE CLIENT --> <mx:Canvas x="10" y="58" width="265" height="171" borderStyle="solid" ➥cornerRadius="20"> <mx:Label x="10" y="10" text="Adresse de livraison / Destinataire" ➥fontWeight="bold" id="lab_adresse" textDecoration="underline"/> <mx:Text x="10" y="36" text="prenom" width="89" id="txt_prenomFacture"/> <mx:Text x="107" y="36" text="nom" id="txt_nomFacture" width="146"/> <mx:TextArea x="10" y="62" width="243" id="txt_adresseFacture" ➥text="adresse" height="67"/> <mx:Text x="10" y="137" text="cp" id="txt_cpFacture" width="59"/> <mx:Text x="69" y="137" text="ville" width="184" id="txt_villeFacture"/> </mx:Canvas> <!-- INFORMATIONS FACTURE --> <mx:Canvas x="283" y="58" width="223" height="171" borderStyle="solid" ➥cornerRadius="20"> <mx:Label x="10" y="10" text="Facture" fontWeight="bold" id="lab_facture" ➥textDecoration="underline"/> <mx:Label x="10" y="38" text="Numéro :" fontWeight="bold"/> <mx:Text x="97" y="38" text="12345679" width="114" id="txt_numFacture"/> <mx:Label x="10" y="64" text="Date : " id="lab_date" fontWeight="bold"/> <mx:Text x="97" y="64" text="date" width="114" id="txt_dateFacture"/> <mx:Label x="10" y="90" text="Echéance :" fontWeight="bold" ➥id="lab_echeance"/> <mx:Text x="97" y="90" text="echeance" width="114" id="txt_echeanceFacture"/> <mx:Label x="10" y="116" text="Montant (¤) :" fontWeight="bold" ➥id="lab_montant"/> <mx:Text x="97" y="116" text="montant" width="114" id="txt_montantFacture"/> </mx:Canvas> =Flex3 FM.book Page 460 Mardi, 2. décembre 2008 3:32 15 460 Cas pratiques PARTIE II <!-- PRODUITS --> <mx:Canvas x="10" y="237" width="496" height="207"> <mx:DataGrid x="10" y="10" width="476" height="174" editable="false" ➥id="dg_facture"> <mx:columns> <mx:DataGridColumn headerText="Produit" dataField="nomProduit"/> <mx:DataGridColumn headerText="Quantite" dataField="quantiteProduit" ➥width="100"/> <mx:DataGridColumn headerText="Prix (¤)" dataField="totalProduit" ➥width="100"/> </mx:columns> </mx:DataGrid> </mx:Canvas> <mx:Label x="273" y="452" text="Nous vous remercions de votre confiance"/> <mx:Button id="btn_imprimer" x="433" y="492" label="Imprimer" /> </mx:TitleWindow>x Créons à présent la procédure qui ouvrira le pop-up tout en lui transmettant les données de la facturation. Pour cela, éditons le fichier SiteAS3.as en lui ajoutant ces quelques lignes : /**************************************************** * FACTURE * **************************************************/ import mx.managers.PopUpManager public function ouvertureFacture():void { //Création d'un objet PopUp créé en instanciant la classe popFacture //Cela permet de pouvoir accéder à l'ensemble de ses objets et de leurs //transmettre des données var objetPopUp:popFacture = popFacture ➥(PopUpManager.createPopUp(this,popFacture,true)); objetPopUp.txt_prenomFacture.text = txt_prenomCommande.text objetPopUp.txt_nomFacture.text = txt_nomCommande.text objetPopUp.txt_adresseFacture.text = txt_adresseCommande.text objetPopUp.txt_cpFacture.text = txt_cpCommande.text objetPopUp.txt_villeFacture.text = txt_villeCommande.text objetPopUp.dg_facture.dataProvider = dg_commande.dataProvider; objetPopUp.txt_montantFacture.text = txt_totalCommande.text; //Calcul des dates //Date du jour : var dateDuJour:Date = new Date(); objetPopUp.txt_dateFacture.text = String(dateDuJour.getDate()+'/' ➥+(dateDuJour.getMonth()+1)+"/"+dateDuJour.getFullYear()); =Flex3 FM.book Page 461 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 461 //Date d'échéance = 30 jours plus tard soit dans 30*24*60*60*1000 Millisecondes ! var dateEcheance:Date = new Date(dateDuJour.getTime()+(30*24*60*60*1000)) objetPopUp.txt_echeanceFacture.text = String(dateEcheance.getDate()+'/' ➥+(dateEcheance.getMonth()+1)+"/"+dateEcheance.getFullYear()); } Regardons de plus près la méthode utilisée pour l’ajout ou la soustraction de temps à une date. Pour ajouter ou soustraire du temps à une date, il convient de calculer le nombre de millisecondes que ce temps représente. Les règles énoncées ci-dessous pourront vous servir de bases de calcul : • Une seconde représente 1 000 millisecondes. • Une minute représente 60 ¥ 1 000 millisecondes = 60 000 ms. • Une heure représente 60 ¥ 60 ¥ 1 000 = 3 600 000 ms. • Une journée représente 24 ¥ 60 ¥ 60 ¥ 1 000 = 86 400 000 ms. Une fois le nombre de millisecondes déterminé, il faut ensuite extraire le nombre de millisecondes écoulées entre la date, faisant l’objet d’ajout ou de soustraction de temps, et le 1er janvier 1970 (cette extraction est réalisée à l’aide de la méthode getTime()). Une fois ce calcul réalisé, nous lui ajoutons ou soustrayons le nombre de millisecondes que représente le temps à ajouter ou soustraire : //Détermination de la date d’échéance fixée 30 jours plus tard de la date du jour: var dateDuJour:Date = new Date(); var dateEcheance:Date = new Date(dateDuJour.getTime()+(30*24*60*60*1000)) Tout semblant en place, nous allons à présent faire appel à ce pop-up. Le pop-up de facturation ne peut s’ouvrir que si l’ensemble de la commande est validée, c’est-à-dire si la procédure validerSaisie() retourne 1 et si le dataprovider mis en place précédemment contient au moins un élément. Pour cela, modifions la procédure comme suit : public function validerCommande():void { if (validerSaisie()==1 && dg_commande.dataProvider.length != 0) { ouvertureFacture(); } } Nous avons ajouté la vérification de la présence d’au moins un produit dans la commande, car sans cela, il est bien inutile de créer une facture. Si nous exécutons notre module, le pop-up s’ouvre bien lors de la validation de la commande et que les données de la facture y sont reprises et affichées correctement. Il ne nous reste plus qu’a imprimer la facture ! =Flex3 FM.book Page 462 Mardi, 2. décembre 2008 3:32 15 462 Cas pratiques PARTIE II Impression de la facture Pour réaliser des impressions à l’aide du framework Flex, nous avons à notre disposition la classe FlexPrintJob située dans le package mx.printing. Cette classe permet l’impression d’objets présents dans une interface graphique. Ainsi, nous avons la possibilité d’imprimer un Panel et l’ensemble de champs qu’il contient, un datagrid, une zone de texte, etc. La réalisation de la tâche d’impression se réalise en quatre temps : 1. Instanciation de la classe FlexPrintJob permettant de créer un travail d’impression. 2. Démarrage du travail d’impression. 3. Ajout de l’objet à imprimer dans le travail d’impression avec la spécification de l’échelle à utiliser. 4. Exécution de l’impression. La spécification de l’échelle s’effectue en utilisant la classe FlexPrintJobScale en choisissant l’une de ces méthodes : Méthode Description MATCH_WIDTH Méthode utilisée par défaut. Elle adapte la longueur de l’objet à imprimer à celle de la page. MATCH_HEIGHT Adapte la hauteur de l’objet à imprimer à celle de la page. Dans certains cas, cela entraîne l’impression de plusieurs pages si l’objet ne peut être adapté. SHOW_ALL Adapte les dimensions de l’objet afin qu’il soit imprimé sur une seule page. FILL_PAGE Adapte les dimensions de l’objet afin que sa hauteur soit égale à la hauteur de la page. NONE N’effectue aucune modification sur les dimensions de l’objet à imprimer. Il sera imprimé avec les dimensions spécifiées dans l’application Flex. Mettons ceci en pratique en ajoutant le code suivant à notre pop-up : //Impression de la Facture import mx.printing.* public function imprimerFacture():void { //Création du travail d'impression : var travailImpression:FlexPrintJob = new FlexPrintJob() //Debut du travail d'impression travailImpression.start(); //Ajout de l'ojet à imprimer (This = le pop-up entier) travailImpression.addObject(this,FlexPrintJobScaleType.NONE) //Execution de l'impression travailImpression.send(); } =Flex3 FM.book Page 463 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 463 Ajoutons à présent l’appel de cette procédure au bouton btn_imprimer : <mx:Button id="btn_imprimer" x="433" y="492" label="Imprimer" ➥click="imprimerFacture()" Enfin, exécutons le module pour vérifier que l’impression se réalise correctement. À vos claviers : création d’un pop-up de paiement et de validation de la commande Votre contribution, dans ce chapitre, va consister à créer un autre pop-up où l’utilisateur pourra saisir le numéro de sa carte bancaire et valider sa commande. Ce pop-up (que nous nommerons popPaiement.mxml) sera appelé à partir du pop-up de facturation à l’aide d’un bouton portant le libellé Paiement en ligne. L’interface graphique du pop-up sera constituée d’un clavier numérique ainsi que d’une liste déroulante offrant à l’utilisateur la possibilité de choisir le type de carte de paiement souhaité (figure 23-5), sans oublier un bouton permettant de valider le paiement. Bien entendu, le format de validation de la donnée saisie diffère selon le type de carte sélectionnée ! Il convient donc de s’assurer que la donnée saisie par l’utilisateur (à l’aide uniquement du clavier numérique) soit correctement formatée. Figure 23-5 Pop-up de réalisation du paiement =Flex3 FM.book Page 464 Mardi, 2. décembre 2008 3:32 15 464 Cas pratiques PARTIE II Les types de cartes disponibles sont : • American Express • MasterCard • Visa Nous allons concentrer nos explications sur l’utilisation du composant <mx:Repeater> avec qui nous allons de suite faire connaissance. Répétition de composants : <mx:Repeater> Vous conviendrez certainement que la création du pavé numérique n’est pas des plus sympathique : 10 chiffres, 10 boutons, 10 identifiants différents…. Mais grâce au composant <mx:repeater>, ce travail est terminé ! Voyons ceci en détail : <mx:Script> <![CDATA[ [Bindable] public var listeBoutons:Array=[1,2,3,4,5,6,7,8,9,0]; ]]> </mx:Script> <mx:ArrayCollection id="boutons" source="{listeBoutons}"/> <mx:Tile x="0" y="65" direction="horizontal" id="tl_boutons"> <mx:Repeater id="clavierSaisie" dataProvider="{boutons}"> <mx:Button id="btn_clavier" label="{clavierSaisie.currentItem}" width="60" ➥height="35"/> </mx:Repeater> </mx:Tile> Nous avons d’abord créé un tableau contenant les 10 chiffres du clavier numérique. Ensuite, nous avons transformé ce tableau en collection d’objet afin qu’il puisse être exploité par le dataProvider du composant <mx:repeater>. Figure 23-6 Utilisation du composant <mx :Repeater> =Flex3 FM.book Page 465 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 465 L’objectif de notre composant <mx :repeater> est de créer autant de bouton qu’il y a de données dans son dataProvider. Couplé au composant <mx:Tile>, qui est capable d’agencer automatiquement les composants dans une grille en fonction de leur nombre (10 composants = 2 lignes de 4 composants et 1 ligne de 2, comme vous pouvez le voir sur la figure 23-6), le clavier numérique se construit en quelques lignes de code seulement ! Pour connaître la valeur du bouton cliqué, il suffit de récupérer la valeur de l’item affecté au bouton. Pour cela, nous utilisons la méthode getRepeaterItem() du bouton : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var listeBoutons:Array=[1,2,3,4,5,6,7,8,9,0]; import mx.controls.Alert public function valeurBouton(valeur:String):void { Alert.show(valeur); } ]]> </mx:Script> <mx:ArrayCollection id="boutons" source="{listeBoutons}"/> <mx:Tile x="0" y="65" direction="horizontal" id="tl_boutons"> <mx:Repeater id="clavierSaisie" dataProvider="{boutons}"> <mx:Button id="btn_clavier" label="{clavierSaisie.currentItem}" width="60" ➥height="35" click="valeurBouton(String(event.currentTarget ➥.getRepeaterItem()))"/> </mx:Repeater> </mx:Tile> </mx:Application> À présent, à vous de travailler sur la mise en place du pop-up de paiement en ligne. Solution Vous avez peut-être consulté l’aide de Flex Builder et avez sans doute trouvé la solution. Sinon, c’est dommage, car la solution y figurait : saisir credicardvalidator dans la zone =Flex3 FM.book Page 466 Mardi, 2. décembre 2008 3:32 15 466 Cas pratiques PARTIE II de recherche de l’aide. Cet exemple, a en effet pour but de vous montrer que l’aide de Flex Builder est extrêmement riche en contenu et au moindre souci ou doute, il ne faut pas hésiter à la consulter. La solution au problème s’y trouve certainement ! Avez-vous pensé à implémenter un bouton pour effacer la zone de saisie en cas d’erreur ? Car n’oublions pas que seul le clavier numérique devait être utilisé pour la saisie du numéro de carte bancaire : <?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow close="fermerPopUp()" xmlns:mx="http://www.adobe.com/2006/mxml" ➥layout="absolute" width="400" height="378" showCloseButton="true" ➥title="Réalisation du paiement"> <mx:Script> <![CDATA[ [Bindable] public var listeBoutons:Array=[1,2,3,4,5,6,7,8,9,0,'C']; import mx.controls.Alert public function valeurBouton(valeur:String):void { if (valeur != 'C') { txt_numeroCarte.text += valeur; } else { txt_numeroCarte.text = ''; } } import mx.managers.PopUpManager; public function fermerPopUp():void { PopUpManager.removePopUp(this) } ]]> </mx:Script> <mx:ArrayCollection id="boutons" source="{listeBoutons}"/> <!-- MODELE STOCKANT LA LISTE DES CARTES DE PAIEMENT ET LEUR FORMAT --> <mx:Model id="cartesPaiement"> <carte> <type>{cmb_cartes.selectedItem.data}</type> =Flex3 FM.book Page 467 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 467 <format>{txt_numeroCarte.text}</format> </carte> </mx:Model> <!--- VALIDATION DU FORMAT EN FONCTION DE LA CARTE PAIEMENT --> <mx:CreditCardValidator id="val_cartePaiement" cardTypeSource="{cartesPaiement}" cardTypeProperty="type" cardNumberSource="{cartesPaiement}" cardNumberProperty="format" trigger="{btn_valider}" triggerEvent="click" cardTypeListener="{cmb_cartes}" cardNumberListener="{txt_numeroCarte}" wrongLengthError="Format erroné !" wrongTypeError="Format erroné !" valid="Alert.show('Paiement accepté');"/> <mx:Panel title="Validez votre paiement" layout="absolute" height="299" ➥horizontalCenter="0" verticalCenter="0"> <!--- FORMULAIRE DE SAISIE --> <mx:Form id="frm_saisie" x="0" y="0"> <mx:FormItem label="Choix de la carte :"> <mx:ComboBox id="cmb_cartes"> <mx:dataProvider> <mx:Object label="American Express" data="American Express"/> <mx:Object label="MasterCard" data="MasterCard"/> <mx:Object label="Visa" data="Visa"/> </mx:dataProvider> </mx:ComboBox> </mx:FormItem> <mx:FormItem label="Numéro de la carte :"> <mx:TextInput id="txt_numeroCarte" editable="false"/> </mx:FormItem> </mx:Form> <!--- CLAVIER NUMERIQUE --> <mx:Tile x="10" y="90" direction="horizontal" id="tl_boutons" > <mx:Repeater id="clavierSaisie" dataProvider="{boutons}"> <mx:Button id="btn_clavier" label="{clavierSaisie.currentItem}" width="60" ➥height="35" click="valeurBouton(String(event.currentTarget ➥.getRepeaterItem()))"/> </mx:Repeater> </mx:Tile> <!--- BOUTON DE VALIDATION --> <mx:Button id="btn_valider" label="Effectuer le paiement" x="10" y="227" ➥width="306"/> =Flex3 FM.book Page 468 Mardi, 2. décembre 2008 3:32 15 468 Cas pratiques PARTIE II </mx:Panel> </mx:TitleWindow> Nous pouvons à présent tester notre pop-up (figure 23-7), phase qui achève la réalisation de notre module. Figure 23-7 Pop-up de paiement en ligne Déploiement du module Notre module terminé, il est maintenant temps de passer à la phase de déploiement et d’intégration au site E-Reflex. Pour cela, nous allons procéder de façon identique au module d’administration en réalisant une exportation dite « Release Build » du projet : 1. Positionnez-vous sur le nom du projet (moduleSite). 2. Cliquez avec le bouton droit de la souris et choisissez l’option Export. 3. Choisissez l’option Release Build. 4. Cliquez sur Next et enfin sur Finish. 5. Placez-vous dans le répertoire bin-debug du projet et copiez les fichiers modSite.swf et popFacture.swf dans le répertoire src du projet eReflex. =Flex3 FM.book Page 469 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 469 6. Éditons ensuite le fichier eReflex.mxml en important le module modSite dans le canvas vueAccueil : <!-- CONTENEUR DE VUES --> <mx:ViewStack id="conteneurVues" x="0" y="132" width="900" height="590"> <mx:Canvas id="vueAccueil" label="Accueil" width="100%" height="100%"> <mx:ModuleLoader id="moduleSite" url="modSite.swf"> ➥</mx:ModuleLoader> </mx:Canvas> <mx:Canvas id="vueAdministration" label="Administration" width="100%" ➥height="100%"> <mx:ModuleLoader id="moduleAdministration" ➥url="modAdministration.swf"></mx:ModuleLoader> </mx:Canvas> </mx:ViewStack> Il ne nous reste plus qu’à tester l’ensemble de notre projet (figure 23-8). Figure 23-8 Intégration du module de vente en ligne au site E-Reflex =Flex3 FM.book Page 470 Mardi, 2. décembre 2008 3:32 15 470 Cas pratiques PARTIE II Optimisation et déploiement Dans cette partie, qui clôt la réalisation de notre premier cas pratique, nous allons voir comment optimiser notre application et comment la déployer. Optimiser le temps de chargement Comme il nous l’a été spécifié dans le cahier des charges du projet, seuls les administrateurs du site ont accès à la partie administration. Une fois connectés à cette partie de l’application, ils ne peuvent visualiser la partie vitrine du site. Dans ce cas, il est inutile de charger l’ensemble des modules de l’application lors de l’initialisation de l’application ! Ceci nous permettra de gagner du temps lors du chargement de l’application. Pour ce faire, éditons le fichier MXML du projet eReflex en lui ajoutant ces quelques lignes : <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="initialisationIHM()"> <mx:Script> <![CDATA[ import mx.controls.Alert; private function connexion():void { if (btn_action.label == "Connecter") { if (txt_identifiant.text == 'abc' && txt_motDePasse.text=='1234') { connexionIHM(); } else { Alert.show("Accès refusé") } } else { initialisationIHM() } } private function initialisationIHM():void { btn_administration.visible = false; lab_identifiant.visible = true; lab_motDePasse.visible = true; txt_identifiant.visible = true; txt_motDePasse.visible=true; =Flex3 FM.book Page 471 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 btn_action.label= "Connecter" //Chargement du module Site chargerModuleSite(); conteneurVues.selectedIndex = 0; } private function connexionIHM():void { btn_administration.visible = true; lab_identifiant.visible = false; lab_motDePasse.visible = false; txt_identifiant.visible = false; txt_motDePasse.visible=false; txt_identifiant.text = ""; txt_motDePasse.text = ""; btn_action.label= "Déconnecter" //Chargement du module d'administration chargerModuleAdministration(); conteneurVues.selectedIndex = 1; } //Procédure de chargement/déchargement de modules private function dechargerModuleAdministration():void { moduleAdministration.unloadModule(); } private function dechargerModuleSite():void { moduleSite.unloadModule(); } private function chargerModuleSite():void { dechargerModuleAdministration() moduleSite.loadModule(); } private function chargerModuleAdministration():void { dechargerModuleSite() moduleAdministration.loadModule(); } ]]> 471 =Flex3 FM.book Page 472 Mardi, 2. décembre 2008 3:32 15 472 Cas pratiques PARTIE II </mx:Script> <mx:Canvas width="900" height="730" horizontalCenter="0" verticalCenter="0"> <!-- LOGO --> <mx:Image x="0" y="0" height="95" width="900" source="images/logo.jpg"/> <!-- BARRE DE MENUS --> <mx:ApplicationControlBar x="0" y="97" height="30" width="900"> <mx:Button label="Accueil" id="btn_accueil" ➥click="conteneurVues.selectedIndex = 0;chargerModuleSite()"/> <mx:Button label="Administration" id="btn_administration" ➥click="conteneurVues.selectedIndex = 1;chargerModuleAdministration()"/> <mx:Canvas width="686" height="22"> <mx:Label x="144" y="2" text="Identifiant :" fontWeight="bold" ➥id="lab_identifiant"/> <mx:Label x="365" y="2" text="Mot de passe :" fontWeight="bold" ➥id="lab_motDePasse"/> <mx:TextInput x="226" y="0" width="118" id="txt_identifiant"/> <mx:TextInput x="459" y="0" width="119" displayAsPassword="true" ➥id="txt_motDePasse"/> <mx:Button x="586" y="1" label="Connecter" id="btn_action" ➥click="connexion()"/> </mx:Canvas> </mx:ApplicationControlBar> <!-- CONTENEUR DE VUES --> <mx:ViewStack id="conteneurVues" x="0" y="132" width="900" height="590"> <mx:Canvas id="vueAccueil" label="Accueil" width="100%" height="100%"> <mx:ModuleLoader id="moduleSite" url="modSite.swf"> ➥</mx:ModuleLoader> </mx:Canvas> <mx:Canvas id="vueAdministration" label="Administration" width="100%" ➥height="100%"> <mx:ModuleLoader id="moduleAdministration" ➥url="modAdministration.swf"></mx:ModuleLoader> </mx:Canvas> </mx:ViewStack> </mx:Canvas> </mx:Application> =Flex3 FM.book Page 473 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 473 Lors de l’initialisation de l’application, seul le module Site est chargé. À chaque fois que l’utilisateur change de module, cela a pour conséquence de décharger le module affiché pour charger le module souhaité. En faisant cela, nous avons réduit le temps de chargement de notre application. Certes, sur un petit projet comme le nôtre, cela ne se ressent pas forcément, mais sur un projet de grande envergure, cette méthode est payante. Faire patienter l’utilisateur Comme nous venons de l’évoquer, le chargement d’un module peut parfois prendre du temps. Lors de cette phase, l’utilisateur a devant lui un écran vide, qu’il s’empresse de fermer ou affirme que le projet n’est pas fonctionnel. Pour pallier ce problème, nous allons informer l’utilisateur que le chargement de ces modules est en cours grâce à une zone de texte, qui affichera le pourcentage de chargement effectué. Pour commencer, nous allons agrandir de quelques pixels notre canvas applicatif afin d’y insérer la zone de texte : <mx:Canvas width="900" height="754" horizontalCenter="0" verticalCenter="0"> <!-- LOGO --> <mx:Image x="0" y="0" height="95" width="900" source="images/logo.jpg"/> Plaçons ensuite la zone de texte en bas à gauche de l’application : <mx :ViewStack> […] </mx:ViewStack> <!—AFFICHAGE DE LA PROGRESSION DU CHARGEMENT --> <mx:Label text="{texte}" fontWeight="bold" fontSize="14" x="10" y="727" width="325" id="txt_progression" visible="false"> </mx:Label> Par défaut, la zone de texte est invisible. Elle sera affichée à chaque nouveau chargement d’un module via la procédure afficherProgression que voici : //Procédure d'affichage de progression de chargement [Bindable] public var texte:String public function afficherProgression(e:ProgressEvent):void { //Affichage de la zone de progression txt_progression.visible = true; //Taille du module var tailleModule:Number = e.bytesTotal; =Flex3 FM.book Page 474 Mardi, 2. décembre 2008 3:32 15 474 Cas pratiques PARTIE II //Nombre d'octet chargés: var nbOctets:Number = e.bytesLoaded; //Calcul du pourcentage de chargement var pourcentage:Number = Math.round((nbOctets/tailleModule)*100) //Affichage du texte texte = "Chargement du module : "+ String(pourcentage)+"%"; if (nbOctets == tailleModule) { txt_progression.visible = false; } } Rappel Si vous souhaitez revoir les détails de cette portion de code, reportez-vous au chapitre 15 traitant des applications modulaires. Dans cette procédure, nous attirons votre attention sur la présence de la variable texte. Elle est chargée de contenir le résultat calculé et de transmettre ce résultat à la zone de texte par le biais du DataBinding. Il ne nous reste plus qu’à faire appel à cette procédure lors du chargement de chaque module comme suit : <!-- CONTENEUR DE VUES --> <mx:ViewStack id="conteneurVues" x="0" y="132" width="900" height="590"> <mx:Canvas id="vueAccueil" label="Accueil" width="100%" height="100%"> <mx:ModuleLoader id="moduleSite" url="modSite.swf" progress="afficherProgression(event)" ></mx:ModuleLoader> </mx:Canvas> <mx:Canvas id="vueAdministration" label="Administration" width="100%" ➥height="100%"> <mx:ModuleLoader id="moduleAdministration" progress= ➥"afficherProgression(event)" url="modAdministration.swf"> ➥</mx:ModuleLoader> </mx:Canvas> </mx:ViewStack> Voilà, c’est à présent terminé. Le résultat obtenu n’est peut être pas visible si vous exécutez l’application sur votre réseau local, car le chargement est quasi instantané. Néanmoins, la figure 23-9 illustre ce résultat obtenu sur un serveur distant. =Flex3 FM.book Page 475 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 475 Figure 23-9 Indication du pourcentage de chargement du module Déploiement de l’application Maintenant que notre application est davantage optimisée, nous allons pouvoir la déployer. Création de la version de déploiement La première étape va consister à créer une version de déploiement du projet. 1. Cliquez avec le bouton droit sur le projet eReflex et sélectionnez le menu Export. 2. Dans la fenêtre qui se présente à l’écran, choisissez l’option release-build. 3. Terminons ce processus en cliquant respectivement sur les boutons Next puis Finish de la fenêtre. =Flex3 FM.book Page 476 Mardi, 2. décembre 2008 3:32 15 476 Cas pratiques PARTIE II Ceci a pour conséquence la création du répertoire bin-release dans l’arborescence du projet contenant la version de déploiement de ce dernier. Dans ce répertoire, nous y trouvons les fichiers et répertoires suivants (tableau 23-1) : Tableau 23-1 Fichiers contenus dans le répertoire bin-release Nom du répertoire Rôle History Permet de gérer le deep linking. Image Contient l’ensemble des images du projet. AC_OETags.js Permet de détecter la présence du Flash Player et d’en proposer l’installation le cas échéant. eReflex.html Chargé de contenir le fichier eReflex.swf. eReflex.swf Issu de la compilation du fichier MXML du projet. modAdministration.swf Module d’administration. modSite.swf Module du site vitrine. parametrage_amfphp.xml Contenant les paramètres de connexion à AMF php. playerProducInstall.swf Permet de télécharger et d’installer le Flash Player si ce dernier n’est pas présent sur le poste de l’utilisateur. popFacture.swf Pop-up de facturation. L’ensemble de ces fichiers doit ensuite être copié sur le serveur web chargé d’accueillir l’application. À cet étape, libre à vous de copier le répertoire bin-release ou de créer un répertoire sur le serveur web qui contiendra l’ensemble de ces fichiers. Paramétrage de l’application La dernière étape consiste à paramétrer l’application en fonction de son nouvel environnement. Il convient tout d’abord de procéder à l’édition du fichier parametrage_amfphp.xml. Souvenez-vous, dans le chapitre 2, nous avions insisté sur le mécanisme client/serveur d’une application Flex. En effet, l’application étant chargée sur le poste client, l’ensemble des références vers les serveurs de base de données ou ceux de la couche métier doivent être adaptés en conséquence. Ainsi, si notre serveur contenant la couche métier de notre application a l’adresse 192.168.2.1 sur notre réseau local, celle-ci n’est nullement utilisable via l’Internet. Pour que les services soient accessibles, il faut utiliser l’adresse web publique du serveur. Voici un exemple de configuration pour le fichier de paramétrage d’amfphp : PARAMETRAGE DU FICHIER SUR LE POSTE DE DEVELOPPEMENT <?xml version="1.0" encoding="ISO-8859-1" ?> <parametre> <amfphp> <serveur>http://localhost/amfphp/gateway.php</serveur> </amfphp> =Flex3 FM.book Page 477 Mardi, 2. décembre 2008 3:32 15 Module de vente en ligne : commande et facturation CHAPITRE 23 477 </parametre> PARAMETRAGE DU FICHIER SUR LE SERVEUR ACCESSIBLE VIA INTERNET <parametre> <amfphp> <serveur>http://82.127.X.X/amfphpv19/gateway.php</serveur> </amfphp> </parametre> Ainsi lorsque l’application sera chargée sur le poste de l’utilisateur, les requêtes d’exécution de services seront redirigées vers le serveur 82.127.x.x qui contient la passerelle AMFPHP et les services associés. Enfin n’oublions pas un point de détail important : il faut installer la base de données MySQL ainsi qu’AMFPHP et l’ensemble des services PHP associés sur le ou les serveurs qui leur seront dédiés ! Conseil Pour votre premier déploiement, nous vous conseillons de ne pas séparer les couches graphique, métier et persistance de données sur deux voire trois serveurs différents. Il suffit donc d’installer tout ceci sur un seul serveur ou mieux encore, de faire en sorte que votre poste de développement fasse office de serveur accessible via l’Internet ! Ceci vous permettra de résoudre plus facilement les problèmes que vous seriez susceptible de rencontrer. Le point crucial du déploiement et les problèmes les plus fréquemment rencontrés sont issus du paramétrage du fichier parametrage_amfphp.xml. Fin du site E-Reflex ? Si nous faisons le point sur ce projet, voici ce que nous avons réalisé : • la mise en place de la partie de gestion des produits ; • l’implémentation de la partie vente en ligne. À première vue tout semble terminé, mais détrompez vous ! Si nous savons créer une commande, il nous est toujours impossible de la stocker dans notre base de données. Ceci implique donc la création de services PHP, la mise en place d’un modèle au sein de notre application Flex, sans oublier la gestion automatique des commandes de stocks, la création d’une interface permettant la création d’un compte client, etc. De plus, que se passe-t-il si l’un des modules fait défaut lors du chargement ? Actuellement… rien, car nous n’avons pas implémenté cette fonctionnalité (mais nous l’avons détaillée au chapitre 15). Donc, il reste encore beaucoup de choses à faire… Si nous avons choisi de ne pas aborder ces notions, c’est que nous souhaitions nous concentrer sur l’apport de nouvelles connaissances telles que l’implémentation du glisserdéposer, l’utilisation de pop-up, la manipulation de dates et l’utilisation du composant <mx :Renderer> dont l’intérêt est sans doute plus grand que la description de longs services PHP, de classes ActionScript ou d’interfaces graphiques. =Flex3 FM.book Page 478 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 479 Mardi, 2. décembre 2008 3:32 15 24 Créer un lecteur MP3 avec Adobe AIR Dans ce cas pratique, nous allons créer une application multimédia exécutable à l’aide de la machine virtuelle d’Adobe AIR : un lecteur MP3. Cette application vous permettra de concrétiser la notion d’application bureautique riche (RDA, Rich Desktop Application) qui est une autre facette du framework Flex. Après avoir abordé l’utilisation du composant FileSystemTree et la description des méthodes de lecture d’un fichier audio, nous nous attarderons sur les fonctionnalités de notre application pour ensuite terminer par sa réalisation et son déploiement. Dans ce cas pratique nous aborderons notamment les notions suivantes : • l’utilisation du composant FileSystemTree ; • l’étude des méthodes de lecture d’un fichier audio à l’aide d’ActionScript ; • l’utilisation du composant PopMenuButton. Rechercher des MP3 à l’aide de <mx :FileSystemTree> L’avantage d’une application Adobe AIR est qu’elle s’exécute sur le poste de l’utilisateur tout en étant réalisée à l’aide de langage web. Le principal privilège de ce type d’exécution réside dans l’utilisation de composants spécifiques interagissant avec le poste de travail. Le composant FileSystemTree fait partie de ceux-ci en permettant le parcours du disque dur, ce qui va nous être très utile pour rechercher les MP3 situés sur le disque dur de l’utilisateur. =Flex3 FM.book Page 480 Mardi, 2. décembre 2008 3:32 15 480 Cas pratiques PARTIE II Comme nous l’avons fait dans le chapitre 5 pour les composants utilisés dans une application web, nous allons décrire l’usage du composant FileSystemTree du point de vue du développeur, en étudiant son implémentation et son interaction avec l’utilisateur. Implémentation Pour commencer, nous allons créer un nouveau projet (File > new Flex projet>Desktop application) que nous appellerons Lecteur_mp3. Le composant FileSystemTree n’est disponible que pour les applications Adobe AIR. Son rôle est de représenter l’ensemble des dossiers et fichiers du disque dur de l’utilisateur sous forme d’arborescence. Son implémentation est semblable au composant Tree, à la seule exception que l’alimentation en données s’effectue automatiquement à partir des informations contenues sur le disque dur de l’utilisateur (figure 24-1). <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:FileSystemTree x="10" y="25" width="300" height="363" id="fs_disqueDur" showHidden="true" showExtensions="true" directory="{new File('h:\\Flex_3')}"/> </mx:WindowedApplication> Figure 24-1 Composant FileSystemTree =Flex3 FM.book Page 481 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 481 Par défaut, notre composant liste l’ensemble des lecteurs des partitions du disque ou des lecteurs externes présents sur le poste de travail. Il nous est cependant possible de lui spécifier un répertoire par défaut via sa propriété directory. Vous pouvez également activer d’autres options comme la visualisation des fichiers cachés (showHidden) ou l’affichage des extensions de chaque fichiers (showExtension). Interaction avec l’utilisateur Grâce à ce composant, l’utilisateur peut sélectionner des fichiers ou des dossiers de son disque dur, afin de les utiliser dans diverses tâches comme l’envoi par e-mail, l’ouverture du fichier à des fins d’édition, etc. Le code ci-dessous dévoile une petite partie du cas pratique en décrivant la méthode utilisée pour détecter si le fichier sélectionné porte l’extension mp3 ou non : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.controls.Alert public function typeFichier(e:Event):void { var fichier:File = e.currentTarget.selectedItem as File; if(!fichier.isDirectory) { if (fichier.extension.toLowerCase()=="mp3") { Alert.show("C'est un mp3 !"); } } } ]]> </mx:Script> <mx:FileSystemTree x="10" y="25" width="300" height="363" id="fs_disqueDur" showHidden="true" showExtensions="true" itemClick="typeFichier(event)" /> </mx:WindowedApplication> =Flex3 FM.book Page 482 Mardi, 2. décembre 2008 3:32 15 482 Cas pratiques PARTIE II Nous déclarons tout d’abord une variable de type fichier capable de stocker les informations sur le fichier sélectionné. À partir de cet instant il nous est possible de déterminer s’il s’agit d’un dossier (fichier.isDirectory) ou, dans le cas contraire, d’en extraire l’extension (fichier.extension.toLowerCase), afin de déterminer s’il s’agit d’un fichier de type MP3 ou non. Maintenant que nous savons rechercher les fichiers MP3 sur le disque dur de l’utilisateur, nous allons découvrir comment les lire. Lire un fichier MP3 avec ActionScript Pour lire un fichier MP3 à l’aide d’ActionScript, nous devons faire appel aux classes suivantes • flash.media.Sound qui permet le chargement ; la lecture et l’obtention d’information sur le fichier MP3 ; • flash.media.SoundChannel qui offre la possibilité de connaître la progression de la lecture, de stopper celle-ci, de connaître le volume des canaux droit et gauche de la musique et de lui appliquer des transformations. Voici comment les utiliser à travers les étapes du processus de lecture : 1. Instanciation de la classe flash.media.Sound pour la création d’un nouvel objet : var mp3:Sound = new Sound(); 2. Chargement du fichier MP3 et exécution d’un traitement lorsque celui-ci est terminé : // Veiller à utiliser les \\ !! var p_chemin:String = "c:\\fichier.mp3" var requete:URLRequest = new URLRequest(p_chemin); mp3.load(requete) mp3.addEventListener( Event.COMPLETE, finChargement ); 3. Extraction des informations et lecture du fichier : public function finChargement(event:Event):void { //Création d’un objet Sound à partir du fichier chargé var mp3:Sound = Sound(event.target); //Extraction des Id3 var p_artiste:String var p_album:String = var p_annee:String = var p_titre:String = Tags = mp3.id3.artist; mp3.id3.album; mp3.id3.year; mp3.id3.songName; //Extraction de la durée en millisecondes var p_duree:Number = mp3.length; //Création d’un nouvel objet SoundChannel =Flex3 FM.book Page 483 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 483 var chanson:SoundChannel = new SoundChannel(); //Lecture du fichier MP3 au début (position 0) //en l'affectant à l'objet Chanson ce qui va nous //permettre de déclencher un événement lors de la fin //de la lecture, ou durant celle-ci chanson = mp3.play(0) 4. Déclenchement d’événements lors de certaines étapes de la lecture (ici à la fin) : //Déclenchement d'un événement lors de la fin de la lecture chanson.addEventListener(Event.SOUND_COMPLETE, finChanson) public function finChanson(e:Event):void { Alert.show("Fin de la lecture"); } Voici le code complet vous permettant de lire un fichier MP3 situé sur votre disque dur et affichant le message « Fin de lecture » lorsque la lecture de celui-ci est terminée : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.controls.Alert import flash.media.Sound; import flash.media.SoundChannel; public function lireMp3():void { var mp3:Sound = new Sound(); var p_chemin:String = "L:\\Fichier.mp3" var requete:URLRequest = new URLRequest(p_chemin); mp3.load(requete) mp3.addEventListener( Event.COMPLETE, finChargement ); } public function finChargement(e:Event):void { var var var var var var var mp3:Sound = Sound(e.target) p_artiste:String = mp3.id3.artist; p_album:String = mp3.id3.album; p_annee:String = mp3.id3.year; p_titre:String = mp3.id3.songName; p_duree:Number = mp3.length; chanson:SoundChannel = new SoundChannel(); =Flex3 FM.book Page 484 Mardi, 2. décembre 2008 3:32 15 484 Cas pratiques PARTIE II chanson = mp3.play(0) chanson.addEventListener(Event.SOUND_COMPLETE, ➥finChanson) } public function finChanson(e:Event):void { Alert.show("Fin de la lecture"); } ]]> </mx:Script> <mx:Button x="28" y="19" label="Button" id="btn_lire" click="lireMp3()"/> </mx:WindowedApplication> Nous avons extrait les données contenues dans les tags ID3 pouvant alors être exploitées pour afficher, en cours de lecture, le titre du morceau, le nom de l’artiste, le numéro de piste dans l’album, etc. La durée est exprimée en millisecondes. Pour l’afficher au format standard (minutes: secondes), il convient de créer une variable de type Date à partir de cette donnée et d’en extraire les secondes et les minutes : var p_duree:Number = mp3.length; //Transformation de la durée var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); minutes = String(temps.getMinutes()); //Si les secondes sont inférieures à 10 on ajoute un 0 avant la valeur, par ➥exemple : 6 = 06 if (temps.getSeconds() < 10 ){secondes = "0"+String ➥(temps.getSeconds())}else{secondes=String(temps.getSeconds())}; Alert.show (minutes+":"+secondes) Nous allons à présent voir les différentes méthodes qui vont nous permettre de manipuler la lecture du fichier MP3. Les tags ID3 Les balises (tags) ID3 sont insérées dans le fichier MP3 et permettent de stocker des informations sur celuici (artiste, titre, album…). Attention cependant, ces informations ne sont pas systématiquement précisées. =Flex3 FM.book Page 485 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 485 Principales fonctions de lecture d’un fichier audio Lorsque nous lisons un fichier MP3, il est parfois nécessaire de le mettre en pause pour ensuite en reprendre la lecture ou de le stopper ou encore de connaître la progression de la lecture. Ce sont ces actions que nous allons aborder dans cette partie. Stopper et mettre en pause Il n’existe pas de fonction pause à proprement parler, mais la classe SoundChannel dispose d’une propriété forte intéressante : la propriété position. Cette propriété indique la position du curseur de lecture, c’est-à-dire le temps écoulé depuis le début de la lecture du MP3, exprimé en millisecondes. En stockant cette propriété dans une variable, il nous est possible de stopper la lecture et de la reprendre à la position préalablement stockée : //Enregistrement de la position var position:Number = chanson.position; //Arrêt de la lecture chanson.stop(); //Reprise de la lecture chanson = mp3.play(position) Connaître la progression de la lecture Pour connaître la progression de la lecture d’un fichier MP3, nous allons utiliser la classe flash.utils.timer qui permet de créer un minuteur déclenchant la répétition d’un événement suivant un certain délai exprimé en milliseconde. Ainsi, pour récupérer le temps de lecture écoulé, il nous suffit de récupérer la position de lecture toutes les x millisecondes et d’en afficher le résultat : //Création du minuteur (Déclenchement de l’événement toutes les 50 millisecondes var positionTimer:Timer = new Timer(50); //Indication de l’événement à déclencher positionTimer.addEventListener(TimerEvent.TIMER, progressionLecture); //Démarrage du minuteur positionTimer.start(); //PROGRESSION DE LA LECTURE private function progressionLecture(e:Event):void{ var p_duree:Number = chanson.position; var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); minutes = String(temps.getMinutes()); =Flex3 FM.book Page 486 Mardi, 2. décembre 2008 3:32 15 486 Cas pratiques PARTIE II if (temps.getSeconds() < 10 ){secondes = "0"+String ➥(temps.getSeconds())}else{secondes=String(temps.getSeconds())}; var progression :String = minutes+":"+secondes } Exemple complet Voici à présent le code permettant de lire, d’afficher le temps de lecture, de mettre en pause, de reprendre la lecture et de stopper un fichier MP3 (figure 24-2) : Figure 24-2 Fonctions de bases <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥creationComplete="chargerMp3()"> <mx:Script> <![CDATA[ import mx.controls.Alert import flash.media.Sound; import flash.media.SoundChannel; public var public var public var [Bindable] public var mp3:Sound = new Sound(); chanson:SoundChannel = new SoundChannel(); position:Number = 0; progression:String; public function chargerMp3():void { var p_chemin:String = "C:\\Fichier.mp3" var requete:URLRequest = new URLRequest(p_chemin); mp3.load(requete) mp3.addEventListener( Event.COMPLETE, finChargement ); } public function lire():void { chanson = mp3.play(position); var positionTimer:Timer = new Timer(50); positionTimer.addEventListener(TimerEvent.TIMER, progressionLecture); positionTimer.start(); =Flex3 FM.book Page 487 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 } private function progressionLecture(e:Event):void{ var p_duree:Number = chanson.position; var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); minutes = String(temps.getMinutes()); if (temps.getSeconds() < 10 ){secondes = "0"+String(temps ➥.getSeconds())}else{secondes=String(temps.getSeconds())}; progression = minutes+":"+secondes } public function stopper():void { chanson.stop(); position = 0; } public function mettreEnPause():void { position = chanson.position; chanson.stop(); } public function finChargement(e:Event):void { Alert.show ("Chargement MP3 Terminé") } ]]> </mx:Script> <mx:Button x="10" y="19" label="Lire" id="btn_lire" click="lire()" width="65"/> <mx:Button x="83" y="19" label="Pause" width="65" id="btn_pause" ➥click="mettreEnPause()"/> <mx:Button x="156" y="19" label="Stop" width="65" id="btn_stop" ➥click="stopper()"/> <mx:TextInput x="10" y="49" width="211" id="txt_progression" ➥text="{progression}"/> </mx:WindowedApplication> 487 =Flex3 FM.book Page 488 Mardi, 2. décembre 2008 3:32 15 488 Cas pratiques PARTIE II Définition des fonctionnalités de notre application Maintenant que nous connaissons les différentes méthodes qui interviennent dans la lecture d’un fichier MP3, nous pouvons nous consacrer pleinement à notre étude de cas. L’objectif du projet est de créer un lecteur MP3 sous forme d’une application Adobe AIR où l’utilisateur aurait la possibilité de parcourir les dossiers de son disque dur et d’y sélectionner les fichiers MP3 qu’il souhaite écouter. La figure 24-3 illustre les différentes parties de l’interface graphique de notre lecteur MP3 dont nous allons décrire les fonctionnalités. Figure 24-3 Interface graphique du lecteur MP3 =Flex3 FM.book Page 489 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 489 Gestion de la liste de lecture La liste de lecture (playlist) affiche l’ensemble des fichiers MP3 que l’utilisateur a sélectionnés et qu’il souhaite lire (figure 24-4). Figure 24-4 Liste de lecture Son mode de fonctionnement est le suivant : • l’utilisateur sélectionne un fichier MP3 dans le composant FileSystemTree ; • ce fichier est analysé puis ajouté à la liste de lecture. Les informations affichées dans la liste de lecture sont le titre du fichier MP3 (issu des tags ID3) et sa durée. Pour chaque ajout de fichier MP3, le temps total de lecture de la liste est calculé. Notons également la présence des boutons Supprimer et Vider permettant de supprimer un fichier de la liste de lecture ou de la vider intégralement. Il est également intéressant d’offrir à l’utilisateur la possibilité d’écouter sa liste de lecture en boucle. Pour assurer cette fonctionnalité, le composant PopUpMenuButton sera utilisé en proposant les valeurs « En boucle » ou « Lecture simple ». =Flex3 FM.book Page 490 Mardi, 2. décembre 2008 3:32 15 490 Cas pratiques PARTIE II Règles de gestion Voici à présent les règles de gestion de la liste de lecture : • pour chaque ajout ou suppression de fichier MP3, le temps de lecture total doit être recalculé ; • le mode de lecture proposé par défaut est « En boucle » ; • lorsque la lecture d’un fichier MP3 est terminée, celle du morceau suivant démarre automatiquement. Le composant PopUpMenuButton Ce composant permet de créer des menus dont le fonctionnement et la présentation sont identiques au composant ComboBox (figure 24-5). Figure 24-5 Composant PopUpMenuButton Implémentation et alimentation en données Son implémentation est assez simple et se résume à créer un tableau de libellés (Label) venant alimenter le dataProvider du composant : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var menus:Array = [{label:"Menu_1"},{label:"Menu_2"}]; ]]> </mx:Script> <mx:PopUpMenuButton x="32" y="44" id="popMenu" dataProvider="{menus}"/> </mx:WindowedApplication> Interaction avec l’utilisateur Pour connaître, l’option de menu sélectionnée par l’utilisateur, nous devons déclencher un événement lors de la sélection d’un item (itemClick) afin d’un récupérer le libellé : =Flex3 FM.book Page 491 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 491 <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ [Bindable] public var menus:Array = [{label:"Menu_1"},{label:"Menu_2"}]; //Import de la classe permettant de gérer les événements sur les menus import mx.events.MenuEvent; import mx.controls.Alert; public function choixMenu(e:MenuEvent):void { Alert.show(e.currentTarget.label) } ]]> </mx:Script> <mx:PopUpMenuButton x="32" y="44" id="popMenu" dataProvider="{menus}" ➥itemClick="choixMenu(event)"/> </mx:WindowedApplication> Comme vous pouvez le constater, ce composant est assez simple à implémenter et peut également nous permettre de créer des menus avancés comme le démontre l’exemple cidessous (figure 24-6) : <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- CRÉATION DE MENU AVEC SOUS MENUS --> <mx:XMLList id="menuAvance"> <node label="Menu_1"> <node label="SousMenu_1"> <node label="SousMenu_2"/> <node label="SousMenu_3"/> </node> </node> </mx:XMLList> <mx:PopUpMenuButton x="32" y="44" labelField="@label" id="popMenu" ➥dataProvider="{menuAvance}"/> </mx:WindowedApplication> =Flex3 FM.book Page 492 Mardi, 2. décembre 2008 3:32 15 492 Cas pratiques PARTIE II Figure 24-6 Menu avancé Interface de lecture Commune à tout lecteur MP3, cette interface permet de : • lire un fichier MP3 ; • mettre en pause et reprendre la lecture ; • passer au fichier MP3 suivant ; • revenir au début du fichier MP3 en cours de lecture ; • revenir au fichier MP3 précédent. Cette interface nous permet également d’obtenir des informations sur la progression de la lecture et de connaître le titre du fichier MP3 accompagné de son temps total de lecture (figure 24-7). Figure 24-7 Interface de lecture =Flex3 FM.book Page 493 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 493 Il est temps à présent de passer au codage du projet. À vos claviers : création d’un lecteur MP3 L’ensemble des fonctionnalités du projet étant à présent décrites, vous disposez des éléments nécessaires à la création de l’application. Ce cas pratique étant le dernier de l’ouvrage, il nous a semblé important de vous laisser une autonomie complète dans sa réalisation en vous laissant maître de vos choix de conception et de réalisation. En effet, cela vous permettra de vérifier l’acquisition des connaissances présentées tout au long de cet ouvrage et de déterminer ainsi votre capacité à développer des applications à l’aide du Framework Flex. Nous ne doutons pas de votre succès dans la réalisation de ce cas pratique. Néanmoins, nous vous proposons la solution suivante. Nous avons organisé notre application en quatre fichiers distincts : • ClassesLecteurMp3.as : la classe de notre lecteur MP3 et ses méthodes associées (lecture, affichage de la progression de lecture…) ; • LecteurMP3AS3.as : diverses procédures faisant appel aux méthodes de la classe Classes LecteurMP3, mais aussi à la gestion des composants de l’IHM ; • LecteurMP3.mxml : fichier principal de l’application ; • Bleu_lagon.css : feuille de styles CSS donnant un aspect plus sympathique à notre application. Ce fichier est optionnel. Voici donc le code de chacun de ces fichiers. Fichier de styles CSS Nous avons choisi de créer un style de type « Bleu lagon », mais libre à vous de l’adapter en fonction de vos envies : /* CSS file */ Button { cornerRadius: 11; highlightAlphas: 0.22, 0.43; fillAlphas: 0.27, 0.39, 0.27, 1; color: #003366; textSelectedColor: #0b333c; borderColor: #000033; themeColor: #000033; fontFamily: Arial; } Application { backgroundColor: #003366; =Flex3 FM.book Page 494 Mardi, 2. décembre 2008 3:32 15 494 Cas pratiques PARTIE II backgroundGradientColors: #006699, #68808c; themeColor: #006699; color: #ffffff; } Tree { backgroundAlpha: 0.41; color: #000000; openDuration: 551; dropShadowEnabled: true; shadowDistance: 4; shadowDirection: right; fontFamily: Arial; cornerRadius: 9; } DataGrid { backgroundColor: #006699; alternatingItemColors: #006699, #006699; headerColors: #006699, #e6eeee; verticalGridLines: false; useRollOver: true; color: #ffffff; headerStyleName: "mydataGridHeaderStyle"; } .mydataGridHeaderStyle { color: #000099; } Canvas{ borderStyle: solid; borderThickness: 1; cornerRadius: 9; borderColor: #084570; } .tempsMP3{ fontFamily: Arial; fontSize: 16; color: #ffffcc; textAlign: right; } .arrierePlanDeLecture{ backgroundAlpha: 0.92; backgroundColor: #000000; cornerRadius: 14; =Flex3 FM.book Page 495 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 495 dropShadowEnabled: true; shadowDirection: right; shadowDistance: 4; } .titre{ color: #0099cc; fontSize: 16; } .tempsTotalPlayList{ fontSize: 12; fontWeight:bold; textAlign: right; } Code de la classe ClassesLecteurMp3 Remarquez l’usage du DataBinding pour certains attributs de la classe, permettant d’intercepter la modification de leur valeur et d’afficher celle-ci dans l’interface graphique (afin d’obtenir la progression de lecture par exemple). //Création préalable du package com.lecteurMP3 package com.lecteurMp3 { import mx.collections.ArrayCollection; public class ClasseLecteurMP3 { import import import import import import flash.media.Sound; flash.media.SoundChannel; flash.net.URLRequest; mx.controls.Alert; flash.events.* flash.utils.Timer; /******************************** * ATTRIBUTS PRIVÉS * ********************************/ private var _listeFichiersMP3:ArrayCollection; //Liste des MP3 de la playlist private var _mp3:Sound; //Fichier MP3 private var _chanson:SoundChannel; //Chanson en cours de lecture private var _lectureEnBoucle:Boolean = true; // Lecture en boucle de la ➥playlist private var _lectureEnCours:Boolean = false; //Indique si une lecture est en ➥cours ou non =Flex3 FM.book Page 496 Mardi, 2. décembre 2008 3:32 15 496 Cas pratiques PARTIE II private var _positionDePause:int = 0; //Position de pause de la chanson //Information ID3 Tag private var _artiste:String; private var _album:String; private var _annee:String; private var _duree:Number; /********************************************* * ATTRIBUTS PUBLIC LIÉS A l'IHM * *********************************************/ [Bindable] public var indexDeLecture:int = 0; //Index de selection du fichier Mp3 dans ➥la playlist [Bindable] public var titre:String; // Titre de la chanson [Bindable] public var progression:String //Progression de la lecture /************************** * CONSTRUCTEUR * **************************/ public function ClasseLecteurMP3() { } /******************************* * GETTERS / SETTERS * *******************************/ //---- CRÉATION DE LA LISTE DE MP3 --public function set listeFichiersMP3 (liste:ArrayCollection):void { _listeFichiersMP3 = liste } //--- INFORMATIONS ID3 TAGS --public function get artiste():String { return _artiste; } public function get album():String =Flex3 FM.book Page 497 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 { return _album; } public function get annee():String { return _annee; } public function get duree():Number { return _duree; } //--- POSITION DE PAUSE public function set positionDePause (index:int):void { _positionDePause = index; } /******************************* * MÉTHODES * *******************************/ public function modeLecture(mode:String):void { if (mode == "En boucle") { _lectureEnBoucle = true; } else { _lectureEnBoucle = false; } } //---- DÉBUT LECTURE ---public function lire():void { if (_lectureEnCours == 1 && _positionDePause == 0) { _chanson.stop(); } var request:URLRequest = new URLRequest ➥(_listeFichiersMP3[indexDeLecture].chemin); _mp3 = new Sound(); 497 =Flex3 FM.book Page 498 Mardi, 2. décembre 2008 3:32 15 498 Cas pratiques PARTIE II _mp3.load(request); titre = _listeFichiersMP3[indexDeLecture].titre + " ➥["+_listeFichiersMP3[indexDeLecture].dureeAffichee+"]"; _artiste = _listeFichiersMP3[indexDeLecture].artiste; _album = _listeFichiersMP3[indexDeLecture].album; _annee = _listeFichiersMP3[indexDeLecture].annee; _duree = _listeFichiersMP3[indexDeLecture].duree; _chanson = _mp3.play(_positionDePause) _chanson.addEventListener(Event.SOUND_COMPLETE, ➥passageAutomatiqueSuivant); var positionTimer:Timer = new Timer(50); positionTimer.addEventListener(TimerEvent.TIMER, progressionLecture); positionTimer.start(); _lectureEnCours = true; } //--- AFFICHAGE DE LA PROGRESSION DE LA LECTURE --private function progressionLecture(e:Event):void{ var p_duree:Number = _chanson.position; var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); minutes = String(temps.getMinutes()); if (temps.getSeconds() < 10 ){secondes = "0"+String ➥(temps.getSeconds())}else{secondes=String(temps.getSeconds())}; progression = minutes+":"+secondes } //---- PASSAGE AUTOMATIQUE AU SUIVANT ---public function passageAutomatiqueSuivant(e:Event):void { var indice:int = indexDeLecture; indice++; _positionDePause = 0 if (indice > (_listeFichiersMP3.length -1)) { if (_lectureEnBoucle == true) { indexDeLecture = 0; lire(); } =Flex3 FM.book Page 499 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 else { stopper(); } } else { indexDeLecture++; lire(); } } //---- PASSAGE MANUEL AU SUIVANT ---public function passageManuelSuivant():void { var indice:int = indexDeLecture; indice++; _positionDePause = 0 if (indice > (_listeFichiersMP3.length -1)) { if (_lectureEnBoucle == true) { indexDeLecture = 0; lire(); } } else { indexDeLecture++; lire(); } } //---- PASSAGE MANUEL AU PRÉCÉDENT ---public function passageManuelPrecedent():void { var indice:int = indexDeLecture; indice--; _positionDePause = 0 if (indice < 0) 499 =Flex3 FM.book Page 500 Mardi, 2. décembre 2008 3:32 15 500 Cas pratiques PARTIE II { indexDeLecture = 0; } lire() } //---- STOPPER ---public function stopper():void { _chanson.stop(); _lectureEnCours = false; progression = "00:00"; } //---- METTRE EN PAUSE ---public function mettreEnPause():void { _positionDePause = _chanson.position; stopper(); } //---- REVENIR AU DÉBUT ---public function revenirDebut():void { stopper(); lire(); } } } Fichier LecteurMP3AS3.as Dans ce fichier, nous avons créé des procédures liées aux différents composants de l’interface graphique : démarrage de la lecture, alimentation de la liste de lecture, etc. /***************************************** * INSTANCIATION DE LA CLASSE LECTEUR MP3 ******************************************/ import com.lecteurMp3.ClasseLecteurMP3; [Bindable] =Flex3 FM.book Page 501 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 public var lecteur:ClasseLecteurMP3 = new ClasseLecteurMP3; /***************************************** * SELECTION D'UN MP3 ******************************************/ //SELECTION DES MP3 public function choixFichier(e:Event):void { var fichier:File = e.currentTarget.selectedItem as File; if(!fichier.isDirectory) { if (fichier.extension.toLowerCase()=="mp3") { analyserFichierMP3(fichier) } } } /***************************************** * ANALYSE DU FICHIER MP3 ******************************************/ import com.lecteurMp3.ClasseLecteurMP3; import flash.media.Sound; import flash.net.URLRequest; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.events.ListEvent; import mx.events.MenuEvent; [Bindable] public var tableauFichiersMP3:ArrayCollection = new ArrayCollection(); public var p_nomFichier:String public function analyserFichierMP3(fichierMP3:File):void { //Analyse du fichier var p_chemin:String = fichierMP3.url; 501 =Flex3 FM.book Page 502 Mardi, 2. décembre 2008 3:32 15 502 Cas pratiques PARTIE II p_nomFichier = fichierMP3.name //Chargement du MP3 et extraction des ID3 tags var request:URLRequest = new URLRequest(p_chemin); var mp3:Sound = new Sound(); mp3.load(request) mp3.addEventListener( Event.COMPLETE, finChargement ); } public function finChargement(event:Event):void { var var var var var var var mp3:Sound = Sound(event.target); p_chemin:String = String(event.target.url); p_artiste:String = mp3.id3.artist; p_album:String = mp3.id3.album; p_annee:String = mp3.id3.year; p_titre:String = mp3.id3.songName; p_duree:Number = mp3.length; //Transformation de la durée var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); minutes = String(temps.getMinutes()); if (temps.getSeconds() < 10 ){secondes = "0"+String ➥(temps.getSeconds())}else{secondes=String(temps.getSeconds())}; var p_dureeAffichee:String = minutes+":"+secondes //Vérification de la présence du titre du morceau if (p_artiste == null) {p_artiste = p_nomFichier}; mp3.close(); //Stockage dans le tableau des MP3 tableauFichiersMP3.addItem({chemin:p_chemin, nom:p_nomFichier, artiste:p_artiste, album:p_album, annee:p_annee, titre:p_titre, duree:p_duree, dureeAffichee:p_dureeAffichee}) //Mise à jour de l'attribut listeFichierMP3 de la classe ClasseLecteurMP3 lecteur.listeFichiersMP3 = tableauFichiersMP3; //Calcul du temps total de lecture de la playlist =Flex3 FM.book Page 503 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 calculerTempsTotal(); } /***************************************** * LECTURE D'UN FICHIER ******************************************/ public function boutonPlay():void { var index:int = dg_titres.selectedIndex; lecteur.indexDeLecture = index; lecteur.lire(); txt_progression.visible = true; } public function doubleClickPlayList(e:ListEvent):void { var index:int = e.currentTarget.selectedIndex; lecteur.indexDeLecture = index; lecteur.lire() txt_titreEcoute.text = lecteur.titre; txt_progression.visible = true; } public function boutonStop():void { lecteur.stopper() txt_progression.visible = false; } public function boutonPause():void { lecteur.mettreEnPause(); } public function boutonSuivant():void { lecteur.passageManuelSuivant() } public function boutonPrecedent():void { lecteur.passageManuelPrecedent() } 503 =Flex3 FM.book Page 504 Mardi, 2. décembre 2008 3:32 15 504 Cas pratiques PARTIE II public function boutonDebut():void { lecteur.revenirDebut(); } /***************************************** * GESTION DE LA PLAYLIST ******************************************/ public function supprimerMp3():void { var index:int = dg_titres.selectedIndex; tableauFichiersMP3.removeItemAt(index); lecteur.listeFichiersMP3 = tableauFichiersMP3; calculerTempsTotal(); } public function viderPlayList():void { lecteur.stopper(); tableauFichiersMP3.removeAll(); lecteur.listeFichiersMP3 = tableauFichiersMP3; txt_titreEcoute.text = ""; txt_progression.visible = false; tempsTotal = "Temps : 00:00"; } [Bindable] public var tempsTotal:String = "Temps : 00:00"; public function calculerTempsTotal():void{ var p_duree:Number =0; for (var i:int=0; i<tableauFichiersMP3.length; i++) { p_duree += tableauFichiersMP3[i].duree; } var minutes:String; var secondes:String; var temps:Date = new Date(0,0,0,0,0,0,p_duree); =Flex3 FM.book Page 505 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 505 minutes = String(temps.getMinutes()); if (temps.getSeconds() < 10 ){secondes = "0"+String ➥(temps.getSeconds())}else{secondes=String(temps.getSeconds())}; tempsTotal= "Temps : "+minutes+":"+secondes } /***************************************** * CHOIX DU MODE DE LECTURE ******************************************/ [Bindable] public var modeLecture:Array = [{label:"En boucle"},{label:"Lecture simple"}]; public function choixModeLecture(e:MenuEvent):void { lecteur.modeLecture(e.currentTarget.label) } Fichier principal Voici enfin, le code du fichier principal de l’application où nous avons utilisé les propriétés maxHeight, maxWidth, minHeight et maxHeight afin d’empêcher le redimensionnement de la fenêtre par l’utilisateur. <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" ➥height="544" width="799" horizontalScrollPolicy="off" verticalScrollPolicy="off" ➥maxHeight="544" maxWidth="799" minHeight="544" minWidth="799"> <mx:Style source="bleu_lagon.css"> </mx:Style> <mx:Script source = "LecteurMP3AS3.as"> </mx:Script> <!-- FILESYSTEMTREE --> <mx:Canvas x="10" y="133" width="450" height="386" horizontalScrollPolicy="off" ➥verticalScrollPolicy="off"> <mx:Label x="10" y="10" text="Vos MP3 :" fontWeight="bold" width="218" ➥textAlign="left"/> <mx:FileSystemTree x="10" y="36" height="326" width="430" id="arbre_mp3" ➥itemClick="choixFichier(event)"/> </mx:Canvas> <!-- INTERFACE DE LECTURE --> <mx:Canvas x="10" y="10" width="450" height="115"> <mx:HBox x="6" y="71" width="100%"> =Flex3 FM.book Page 506 Mardi, 2. décembre 2008 3:32 15 506 Cas pratiques PARTIE II <mx:Button <mx:Button <mx:Button <mx:Button <mx:Button <mx:Button </mx:HBox> label="<<" width="65" click="boutonPrecedent()"/> label="<" width="65" click="boutonDebut()"/> label=">" width="65" id="btn_lire" click="boutonPlay()"/> label=">>" width="65" click="boutonSuivant()"/> label="||" width="65" click="boutonPause()" id="btn_pause"/> label="Stop" width="65" click="boutonStop()"/> <mx:Canvas x="5" y="7" width="433" height="56" ➥styleName="arrierePlanDeLecture"> <mx:Label x="10" y="16" text="{lecteur.titre}" width="319" height="24" ➥fontWeight="bold" fontSize="12" id="txt_titreEcoute" styleName="titre"/> <!-- Databinding avec l’attribut progression de la classe --> <mx:Text x="348" y="14" text="{lecteur.progression}" width="72" height="27" ➥id="txt_progression" styleName="tempsMP3" visible="false"/> </mx:Canvas> </mx:Canvas> <!-- LISTE DE LECTURE --> <mx:DataGrid doubleClickEnabled="true" x="468" y="10" width="319" height="458" ➥id="dg_titres" dataProvider="{tableauFichiersMP3}" selectedIndex= ➥"{lecteur.indexDeLecture}" itemDoubleClick="doubleClickPlayList(event)"> <mx:columns> <mx:DataGridColumn headerText="Play List" dataField="titre"/> <mx:DataGridColumn headerText="Temps" dataField="dureeAffichee" ➥width="50"/> </mx:columns> </mx:DataGrid> <mx:Button x="575" y="497" label="Supprimer" id="btn_supprimer" ➥click="supprimerMp3()" width="102"/> <mx:Button x="685" y="497" label="Vider la playlist" click="viderPlayList()" ➥id="btn_viderplaylist"/> <mx:PopUpMenuButton x="468" y="497" dataProvider="{modeLecture}" ➥selectedField="0" itemClick="choixModeLecture(event)" width="102"/> <mx:Text x="632" y="471" text="{tempsTotal}" id="txt_tempTotal" ➥styleName="tempsTotalPlayList" width="155" height="18"/> </mx:WindowedApplication> Déploiement du projet Comme nous en avons maintenant l’habitude, pour déployer le projet, il convient de l’exporter vers une version de type Release-build. Néanmoins, pour que le déploiement soit complet, il convient de créer un certificat de sécurité assurant l’authenticité de votre application à ses utilisateurs. Sur ce point, nous vous renvoyons au chapitre 18 de cet ouvrage. =Flex3 FM.book Page 507 Mardi, 2. décembre 2008 3:32 15 Créer un lecteur MP3 avec Adobe AIR CHAPITRE 24 507 En résumé Ce chapitre clôt la partie purement pratique de cet ouvrage où nous avons souhaité vous présenter des cas couvrant les fonctionnalités majeures du framework Flex. Néanmoins, pour parfaire vos connaissances, la meilleur méthode consiste à créer vous-même des applications diverses et variées. Comme nous l’avons vu dans le chapitre 1, le framework Flex ne cesse de se perfectionner, et de nouvelles versions sortent régulièrement. Durant l’écriture de cet ouvrage, nous avons appris la sortie, courant 2009 (vraisemblablement dans la seconde moitié de l’année) de Flex 4. C’est donc tout naturellement que nous allons terminer cet ouvrage par les nouveautés proposées dans cette version. =Flex3 FM.book Page 508 Mardi, 2. décembre 2008 3:32 15 =Flex3 FM.book Page 509 Mardi, 2. décembre 2008 3:32 15 25 Flex 4 Gumbo Nous n’aurions pu terminer cet ouvrage sans y mentionner le successeur de Flex 3 : le projet Gumbo (Flex 4). À l’heure où nous écrivons ces lignes, la version disponible en téléchargement est la bêta 4.0.0.3957. Vous conviendrez donc que nous n’avons pas pu étudier l’ensemble des détails de la future version du framework Flex, car celle-ci n’est pas encore finalisée. Néanmoins nous pouvons d’ores et déjà dévoiler les nouveautés majeures qu’elle apporte. Les nouveautés de Flex 4 La nouvelle version du framework Flex s’oriente selon les trois axes suivants: • améliorer la collaboration entre les développeurs et les designers ; • améliorer les performances du compilateur ; • exploiter au mieux les fonctionnalités du Flash Player 10 sur lequel les applications Flex seront exclusivement exécutées. Le premier axe est de loin le plus important, et se concrétise par l’apparition d’un nouveau format graphique nommé FXG basé, une fois encore, sur la syntaxe XML. Ce format va permettre au designer utilisant le produit Thermo d’Adobe d’exporter leurs créations dans ce nouveau format. =Flex3 FM.book Page 510 Mardi, 2. décembre 2008 3:32 15 510 Cas pratiques PARTIE II Projet Thermo Ce projet a pour vocation de réaliser une scission entre le design et développement d’une application Flex. En effet, le projet Thermo permettra aux designers de réaliser la partie graphique de l’application dont le rendu sera ensuite transformé au format FXG, intégrable dans une application Flex. Pour plus d’informations sur ce projet, nous vous recommandons de consulter la page suivante : http://labs.adobe.com/ wiki/index.php/Thermo. Dans cette nouvelle version, nous soulignons également la disparition de MXML 2006 au profit de MXML 2009. Ceci implique l’utilisation d’un nouvel espace de noms (namespace), l’apparition de nouvelles balises et la redéfinition de certains composants de Flex 3. Bien entendu, nous aurons l’occasion dans ce chapitre de rentrer dans le détail de chacune de ces modifications. Pour lors, nous vous proposons de découvrir l’outil permettant d’exécuter nos futures applications : le Flash Player 10. Installer le Flash Player 10 Comme nous l’avons évoqué en début de chapitre, les applications développées à l’aide de la version 4 du framework ne seront exécutables qu’avec le Flash Player 10. En version bêta (disponible depuis le 15 mai 2008), la nouvelle version du Flash Player (nommée Astro) apporte également son lot de nouveautés : • gestion native des effets 3D (zoom, rotation...) ; • création d’effets personnalisés à l’aide du langage Adobe Pixel Blender (successeur du langage Hydra) ; • diminution de l’allocation mémoire et du temps processeur à son exécution. Au vu de ces quelques lignes, nous pouvons d’ores et déjà imaginer l’impact sur nos applications Flex. Pour nous donner un avant-goût de ces nouvelles possibilités, Adobe met à notre disposition une application de démonstration. Avant cela, il convient de configurer notre environnement de travail en installant la nouvelle version du Flash Player. Avant d’installer la version bêta du Flash Player 10, il convient de désinstaller la version 9 de votre environnement. Pour cela, rendez-vous sur la page Labs du site d’Adobe http:// labs.adobe.com/technologies/flashplayer10/releasenotes.html#install et téléchargez-y le logiciel de désinstallation correspondant à votre système d’exploitation. Exécutez-le. Une fois cette étape terminée, il ne nous reste plus qu’à télécharger et installer la version beta du plug-in Flash Player 10 librement téléchargeable à cette adresse : http://labs .adobe.com/downloads/flashplayer10.html. Afin de vérifier le bon déroulement de cette installation, exécutez l’application de démonstration disponible à cette adresse : http://labs.adobe.com/technologies/flashplayer10/ demos/ (figure 25-1), et observez au passage les nouvelles fonctionnalités du Flash Player. =Flex3 FM.book Page 511 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 511 Figure 25-1 Application de démonstration du Flash Player 10 FXG 1.0, nouveau format graphique Comme nous l’avons vu, l’axe principal de la nouvelle version du framework est d’améliorer la collaboration entre le développeur et le designer. Un développeur n’étant pas forcément designer dans l’âme (et vise-versa), Flex 3 imposait aux développeurs de mettre à disposition leur sources aux équipes graphiques, afin qu’elles réalisent les interfaces de l’application. Avec le framework Flex 4, ce temps est révolu ! En effet, grâce au nouveau format graphique FXG, interprétable par le nouveau framework, et au projet Thermo, il est désormais possible pour les designers de créer l’interface graphique de l’application, puis de l’intégrer au sein du framework. Les spécifications techniques de ce nouveau format étant très nombreuses, nous ne le décrirons pas en détail, les spécifications étant disponibles à l’adresse suivante : http:// opensource.adobe.com/wiki/display/flexsdk/FXG+1.0+Specification. Un exemple valant mieux qu’un long discours, penchons-nous sur le code suivant, qui permet de dessiner un petit personnage, certes basique (figure 25-2) : <Group> <!-- TETE --> <Ellipse x="80" y="10" width="40" height="40" id="tete"> =Flex3 FM.book Page 512 Mardi, 2. décembre 2008 3:32 15 512 Cas pratiques PARTIE II <fill> <SolidColor color="#000000"/> </fill> </Ellipse> <!-- BRAS --> <Rect width="100" height="30" x="50" y="50" id="bras"> <fill> <SolidColor color="#000000"/> </fill> </Rect> <!-- CORPS --> <Rect width="30" height="45" x="85" y="70" id="corps"> <fill> <SolidColor color="#000000"/> </fill> </Rect> <!-- HANCHES --> <Rect width="60" height="25" x="70" y="115" id="hanche"> <fill> <SolidColor color="#000000"/> </fill> </Rect> <!-- JAMBE DROITE --> <Rect width="20" height="20" x="110" y="140" id="jambeDroite"> <fill> <SolidColor color="#000000"/> </fill> </Rect> <!-- JAMBE GAUCHE --> <Rect width="20" height="20" x="70" y="140" id="jambeGauche"> <fill> <SolidColor color="#000000"> </fill> </Rect> </Group> =Flex3 FM.book Page 513 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 513 Figure 25-2 Création d’un personnage à l’aide de FXG La balise <Group> a pour fonction première de créer un groupement d’éléments qui sont ici représentés par les rectangles (<rec>) et l’ellipse (<ellipse>). Grâce aux balises <fill> et <solidColor>, nous colorons l’ensemble des éléments. Comme FXG est intégré au framework Flex, nous pouvons utiliser ces mêmes balises au sein d’un fichier MXML, c’est d’ailleurs ce que nous verrons un peu plus loin dans ce chapitre. MXML 2009 L’une des principales nouveautés apportées par la version 4 de Flex est la disparition du langage MXML 2006 au profit MXML 2009. Dans sa version 2009, le langage MXML nous apporte les nouveautés suivantes : • l’utilisation d’un nouvel espace de noms ; • l’apparition de nouvelles balises ; • la notion de DataBinding bi-directionnel ; • la modification de certains composants. Voici tout ceci en détail. Un nouvel espace de noms La première question que l’on est en droit de poser est l’utilité d’utiliser un nouvel espace de noms. Comme nous l’avons vu au début de cet ouvrage, un espace de noms permet de définir les balises utilisées par le langage MXML. Étant donné que certains composants ont de nouvelles propriétés, et que le langage MXML s’est enrichi, l’ancien espace de noms n’est plus utilisable. C’est la raison pour laquelle nous devons en utiliser un nouveau. Il se présente maintenant sous cette forme : xmlns= « http://ns.adobe.com/mxml/2009 » =Flex3 FM.book Page 514 Mardi, 2. décembre 2008 3:32 15 514 Cas pratiques PARTIE II Notons qu’aucun préfixe n’a été spécifié, contrairement à celui utilisé dans Flex 3 (xmlns :mx= http://www.adobe.com/2006/mxml). Ceci signifie que la méthode d’appel des balises du langage MXML est également modifiée. Par exemple, si on écrivait dans Flex 3 <mx :Model>, cela deviendra <Model> dans Flex 4. Ce nouvel espace de noms ne sert que pour appeler les balises spécifiques du langage MXML 2009. Il faut donc lui adjoindre un espace de noms utilisant les composants graphiques de Flex 4, que l’on préfixera à notre convenance (ici cpflex4) : xmlns:cpflex4="library:adobe/flex/gumbo" Enfin, si nous souhaitons faire appel à l’espace de noms Halo de Flex 3 qui sert à réaliser l’habillage de composants (cf. chapitre 8), il convient d’ajouter ceci : xmlns:mx="library:adobe/flex/halo" Pour résumer, la déclaration d’une application à l’aide de MXML 2009, se présente à présent sous cette forme : <Application xmlns="http://ns.adobe.com/mxml/2009" xmlns:mx="library:adobe/flex/halo" xmlns:cpflex4="library:adobe/flex/gumbo" > </Application> Voyons à présent quelques nouveautés présentes dans le langage MXML 2009. La balise <private> La première petite nouveauté de cette version 2009 de MXML est l’apparition de la balise <private>. Avant toute chose, il est important de signaler que le contenu de cette balise sera exclu lors de la compilation du projet. À quoi sert-elle ? Eh bien tout simplement à insérer un commentaire sur le fichier : <Private> <Commentaire>Commentaire sur l'application</Commentaire> </Private> Attention à l’implémentation La balise <private> ne peut être insérée qu’en fin de fichier MXML avant la fermeture de la balise <application>. Le couple de balises <library> et <description> Issus du format FXG, le couple de balise <library> et <description> permet de créer des bibliothèques graphiques réutilisables au sein de l’application, évitant ainsi la redondance de code. =Flex3 FM.book Page 515 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 515 En guise d’exemple, reprenons notre dessin de personnage (figure 25-2). Si nous l’observons à nouveau, nous voyons que nous avons dessiné cinq rectangles définis sous le même format graphique et dont seuls le nom, la disposition et les dimensions diffèrent. Tout ceci aurait pu être écrit bien plus simplement grâce aux balises <library> et <definition> : <?xml version="1.0" encoding="utf-8"?> <Application xmlns="http://ns.adobe.com/mxml/2009" xmlns:cpflex4="library:adobe/flex/gumbo" > <!-- CREATION DE LA BIBLIOTHÈQUE GRAPHIQUE --> <Library> <Definition name="Tete" > <Ellipse x="80" y="10" width="40" height="40"> <fill> <SolidColor color="#000000"/> </fill> </Ellipse> </Definition> <Definition name="Membre" > <Rect > <fill> <SolidColor color="#000000"/> </fill> </Rect> </Definition> </Library> <!-- UTILISATION DE BIBLIOTHÈQUE GRAPHIQUE --> <!-- Tete --> <Tete> </Tete> <!-- Bras --> <Membre width="100" height="30" x="50" y="50"/> <!-- Corps --> <Membre width="30" height="45" x="85" y="70" ></Membre> <!-- Hanches --> <Membre width="60" height="25" x="70" y="115" ></Membre> <!-- Jambe droite --> =Flex3 FM.book Page 516 Mardi, 2. décembre 2008 3:32 15 516 Cas pratiques PARTIE II <Membre width="20" height="20" x="110" y="140" ></Membre> <!-- Jambe Gauche --> <Membre width="20" height="20" x="70" y="140" ></Membre> </Application> Dans cet exemple, nous avons créé une bibliothèque graphique contenant une ellipse et un rectangle. Ces éléments graphiques sont décrits dans la balise <definition> qui sera ensuite appelée dans le code de l’application affichant l’élément graphique correspondant. On constate donc que l’usage d’une bibliothèque graphique comporte l’avantage de diminuer le nombre de lignes de code et permet de modifier facilement le design de l’élément, qui, lui, est décrit en un seul et unique point de l’application. Attention La balise <library> doit obligatoirement être déclarée en début de document. Il ne peut donc y voir d’autre déclaration avant celle-ci. Le DataBinding bi-directionnel Voici une nouveauté attendue, permettant de réaliser le DataBinding bi-directionnel. Rappelez vous, dans Flex 3, le DataBinding consistait à mettre à jour une donnée A qui répercutait cette mise à jour dans la donnée B. Avec Flex 4, la donnée B pourra, à son tour, mettre à jour la donnée A. Voyons ceci en détail : <cpflex4:TextInput widthInChars="2" x="10" y="70" id="txtValeur_1"> </cpflex4:TextInput> <cpflex4:TextInput widthInChars="2" x="10" y="100" id="txtValeur_2" text="@{txtValeur_1.text}"> </cpflex4:TextInput> Analysons tout ceci. À première vue, de par la présence des accolades dans la propriété text de la zone de texte txtValeur_2, celle-ci est liée à la propriété text de la zone de saisie txtValeur_1. Ceci ne nous étonne que très peu car nous avons l’habitude de cette notation fréquemment utilisée dans la version 3 du framework. Néanmoins, si nous regardons de plus prêt, nous notons la présence d’une arobase. C’est elle qui va permettre de définir la notion de DataBinding bi-directionnel. En voici le fonctionnement: =Flex3 FM.book Page 517 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 517 • Lorsque le contenu de la première zone de saisie est modifié, le contenu de la seconde l’est également. • Lorsque le contenu de la seconde zone de saisie est modifié, le contenu de la première s’en trouve également modifié. Amélioration de certains composants de Flex 3 Là encore, nous ne verrons pas les apports de cette nouvelle version du framework de manière exhaustive, car la version que nous testons est loin d’être finalisée. Voici donc à l’heure où nous écrivons ces lignes, les principales modifications. Remplacement du composant <mx:Label> Tout d’abord, le composant <mx:Label> est remplacé par le composant <TextBox> dont voici la syntaxe : <cpflex4:TextBox text="Composant TextBox " id="labelX" x="10" y="10" /> Le composant <TextInput> Jusqu’à présent, il n’existait pas de propriété portant sur les zones de saisie permettant d’en dimensionner automatiquement la longueur en fonction du nombre maximum de caractères. C’est maintenant chose faite grâce à la propriété widthInChars applicable notamment au composant <TextInput> : <cpflex4:TextInput widthInChars="5" /> La figure 25-3, illustre cela : la longueur du composant s’est adaptée pour n’afficher que cinq caractères. Figure 25-3 Le composant TextInput Le composant <TextArea> Comme nous le savons, le composant <TextArea> permet de saisir plusieurs lignes de texte. La nouveauté apportée à ce composant est la possibilité de limiter le nombre de caractères affichés sur une ligne et le nombre de lignes visibles à l’écran. Si nous souhaitons limiter à 20 le nombre de caractères par ligne, nous aurons recours à la propriété widthInChars. Pour ne proposer que trois lignes à l’écran, nous emploierons la propriété heightInLine. Ces deux propriétés permettent donc de dimensionner automatiquement le composant : <cpflex4:TextArea widthInChars="20" heightInLines="3" /> =Flex3 FM.book Page 518 Mardi, 2. décembre 2008 3:32 15 518 Cas pratiques PARTIE II Figure 25-4 Le composant TextArea D’autres composants apportent également leur lot de nouveautés. Citons par exemple <HSlider> ou son homologue <VSlider>, ainsi que <NumericStepper>, mais la documentation sur les nouveautés de Flex 4 n’est actuellement pas encore assez fournie pour pouvoir les illustrer à l’aide d’exemple. Néanmoins, il vous est possible de consulter cette documentation en perpétuelle évolution sur le site de l’éditeur en vous rendant à cette adresse : http://opensource.adobe.com/wiki/display/flexsdk/Gumbo ou bien en consultant la documentation du langage MXML consultable à partir de ce lien : http://livedocs.adobe.com/ flex/gumbo/langref/ Installation de l’environnement de développement À présent, franchissons le pas et installons la nouvelle version du SDK de Flex 4. Pour cela, nous allons tout d’abord le télécharger sur le site d’Adobe. Rendez-vous à l’adresse : http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4 et téléchargez l’archive de la dernière version bêta du SDK d’Adobe disponible. Décompressez cette archive téléchargée sur votre environnement de travail. Passons ensuite à la configuration du Flex Builder pour qu’il puisse utiliser cette nouvelle version et faire usage du Flash Player 10 (qui, rappelons-le, est indispensable à l’exécution des applications Flex 4). Étant donné que nous allons créer un nouvel environnement de développement propre à Flex 4, il faut éviter que les projets Flex 4 soient mélangés avec les projets Flex 3, développés jusqu’à présent. Pour cela, nous allons créer un nouvel espace de travail (workspace) dans le Flex Builder qui sera dédié exclusivement aux applications Flex 4. Espace de travail Un espace de travail, ou workspace, est un répertoire contenant les sources de vos projets et l’ensemble de leurs fichiers de configuration utilisés par Eclipse. Pour créer ce nouvel espace de travail, il suffit de procéder comme suit : 1. Exécutez l’application Flex Builder. 2. Ouvrez le menu File. 3. Positionnez-vous sur le sous-menu Switch Workspace. 4. Cliquez sur le sous-menu Other. =Flex3 FM.book Page 519 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 519 5. Une fenêtre de configuration s’ouvre alors (figure 25-5), où nous devons spécifier le répertoire de stockage des projets Flex 4, que vous aurez au préalable créé sur notre disque dur. 6. Cliquez ensuite sur le bouton OK. Flex Builder redémarre pour prendre en compte ce nouveau paramétrage. Revenir à l’espace de travail de Flex 3 Pour réutiliser l’espace de travail précédent, il suffit d’ouvrir le menu File, de se positionner à nouveau sur le sous-menu Switch Workspace et de sélectionner l’espace de travail correspondant aux projets Flex 3. Figure 25-5 Création d’un nouvel espace de travail L’étape suivante consiste à indiquer à Flex Builder l’endroit où se situe le nouveau SDK : 1. Ouvrez le menu Windows de Flex Builder. 2. Choisissez le sous-menu Preferences. 3. Dans la fenêtre qui s’ouvre, parcourez l’arborescence et sélectionnez sur le nœud Flex. 4. Sélectionnez ensuite le nœud Installed SDK. 5. Dans la partie de droite de l’écran, nous avons l’ensemble des SDK installés. Pour ajouter le SDK de Flex 4, il suffit de cliquer sur le bouton Add situé à droite de l’écran. Ceci ouvre d’un pop-up, où nous cliquons sur le bouton Browse et choisissons le répertoire de l’archive décompressée du SDK. 6. Nous terminons ensuite en cliquant sur le bouton OK et cochons ensuite Flex 4 afin d’indiquer à Flex Builder son nouveau SDK de référence (figure 25-6). =Flex3 FM.book Page 520 Mardi, 2. décembre 2008 3:32 15 520 Cas pratiques PARTIE II Figure 25-6 Installation du SDK 4 Le SDK de Flex 4 est à présent installé, mais vérifions son bon fonctionnement en créant une première application Flex 4. Première application 3D avec Flex 4 Création et configuration du projet Avant toute chose, il convient de créer un nouveau projet que nous nommerons 3dFlex4. Ensuite, indiquons au Flex Builder que notre projet doit s’exécuter à l’aide du Flash Player 10. Pour cela, il suffit de suivre ce cheminement : 1. Cliquez-droit sur le projet et choisissez le sous-menu Properties. 2. Dans la partie gauche de la fenêtre qui se présente à l’écran, sélectionnez l’élément Flex Compiler. 3. Dans la partie droite de la fenêtre, assurez-vous que le SDK utilisé est bien Flex 4.0. 4. Enfin, modifiez la version du Flash Player requis (10.0.0). 5. Terminez en cliquant sur le bouton OK (figure 25-7). =Flex3 FM.book Page 521 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 521 Figure 25-7 Configuration du projet Mise à jour automatique du Flash Player et erreur de compilation Il arrive que la mise à jour automatique du Flash Player entraîne une erreur de compilation de vos projets Flex. Pour remédier à cela, il suffit de modifier la version du Flash Player comme nous venons de le faire. Maintenant que notre projet est configuré, nous pouvons passer au codage. Création de l’interface Nous vous proposons de découvrir comment utiliser la fonctionnalité 3D en réalisant une petite application permettant d’effectuer la rotation d’un rectangle autour de ses axes X, Y et Z. Commençons tout d’abord par utiliser les espaces de noms nécessaires, c’est-à-dire l’espace de noms de MXML 2009 et celui des composants de Flex 4 : cpflex4 : <Application xmlns="http://ns.adobe.com/mxml/2009" xmlns:cpflex4="library:adobe/flex/gumbo" > =Flex3 FM.book Page 522 Mardi, 2. décembre 2008 3:32 15 522 Cas pratiques PARTIE II Nous implémentons ensuite trois composants <HSLider> qui nous serviront à faire varier l’angle de rotation de chacun de axes, ainsi que leur libellés associés : <cpflex4:TextBox text="X : " id="labelX" x="10" y="10" /> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderX" x="30" y="10"> ➥</cpflex4:HSlider> <cpflex4:TextBox text="Y : " id="labelY" x="10" y="40"/> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderY" x="30" y="40"> ➥</cpflex4:HSlider> <cpflex4:TextBox text="Z : " id="labelZ" x="10" y="70"/> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderZ" x="30" y="70" > ➥</cpflex4:HSlider> Chaque composant <HSlider> est définit sur la plage [-360;360] correspondant à une rotation complète sur chacun des axes. Pour que notre interface soit complète, il nous manque l’élément essentiel : le rectangle qui va faire l’objet des rotations. Pour le dessiner, nous allons utiliser le composant <Rect> issu du format FXG vu précédemment : <cpflex4:Rect width="200" height="100" x="100" y="200" id="rectangle" > <cpflex4:fill> <cpflex4:SolidColor color="#FF45EDF"/> </cpflex4:fill> </cpflex4:Rect> Notre interface est à présent terminée. Si vous avez scrupuleusement suivi les étapes de configuration du projet, vous devriez être en mesure de l’exécuter et de visualiser le résultat qui doit être semblable à la figure 25-8. Figure 25-8 Interface graphique du projet =Flex3 FM.book Page 523 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 523 Codage de l’application Passons maintenant à l’implémentation des rotations. Si nous observons les propriétés du composant <Rect>, nous remarquons la présence de trois nouvelles propriétés, jusque-là inconnues dans le framework Flex 3 : • rotationX : définissant l’angle de rotation par rapport à l’axe X ; • rotationY : définissant l’angle de rotation par rapport à l’axe Y ; • rotationZ : définissant l’angle de rotation par rapport à l’axe Z. Comme vous l’avez sans doute deviné, nous allons exploiter ces nouvelles fonctionnalités afin de réaliser les rotations souhaitées. Pour ce faire, ajoutons ces trois procédures : <Script> public function axeX():void{ rectangle.rotationX = sliderX.value; } public function axeY():void{ rectangle.rotationY = sliderY.value; } public function axeZ():void{ rectangle.rotationZ = sliderZ.value; } </Script> La première chose que nous remarquons est que la balise <script> n’est pas précédée du préfixe cpflex4. Cela est dû au fait que cette balise n’est pas un composant, mais fait partie du langage MXML. Sa définition est donc située dans l’espace de noms xmlns=http:// ns.adobe.com/mxml/2009. Analysons à présent la procédure axeX(). Elle récupère la valeur du composant <HSlider> portant l’identifiant sliderX et l’affecte à la propriété rotationX du composant Rectangle. Cette affectation a pour conséquence de modifier l’angle de rotation de l’axe X du rectangle et de le faire tourner autour de cet axe. Les procédure axeY() et axeZ() ont le même fonctionnement mais modifient l’angle de rotation respectivement autour des axes Y et Z, en fonction des valeur sélectionnées à l’aide des composants sliderY et sliderZ. Pour que l’ensemble soit fonctionnel, il ne nous reste qu’à faire appel à ces procédures lors du changement de valeur sur les composants <HSlider> : <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderX" x="30" y="10" ➥change="axeX()"></cpflex4:HSlider> =Flex3 FM.book Page 524 Mardi, 2. décembre 2008 3:32 15 524 Cas pratiques PARTIE II <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderY" x="30" y="40" ➥change="axeY()"></cpflex4:HSlider> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderZ" x="30" y="70" ➥change="axeZ()" ></cpflex4:HSlider> Pour plus de clarté, voici le code complet de cet exemple dont le résultat est illustré par la figure 25-9. Notez également la présence d’un commentaire spécifié à l’aide de la balise <private> : <?xml version="1.0" encoding="utf-8"?> <Application xmlns="http://ns.adobe.com/mxml/2009" xmlns:cpflex4="library:adobe/flex/gumbo" > <Script> public function axeX():void{ rectangle.rotationX = sliderX.value ; } public function axeY():void{ rectangle.rotationY = sliderY.value ; } public function axeZ():void{ rectangle.rotationZ = sliderZ.value ; } </Script> <cpflex4:TextBox text="X : " id="labelX" x="10" y="10" /> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderX" x="30" y="10" ➥change="axeX()"></cpflex4:HSlider> <cpflex4:TextBox text="Y : " id="labelY" x="10" y="40"/> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderY" x="30" y="40" ➥change="axeY()"></cpflex4:HSlider> =Flex3 FM.book Page 525 Mardi, 2. décembre 2008 3:32 15 Flex 4 Gumbo CHAPITRE 25 <cpflex4:TextBox text="Z : " id="labelZ" x="10" y="70"/> <cpflex4:HSlider minimum="-360" maximum="360" value="0" id="sliderZ" x="30" y="70" ➥change="axeZ()" ></cpflex4:HSlider> <!-- Rectangle --> <cpflex4:Rect width="200" height="100" x="100" y="200" id="rectangle" <cpflex4:fill> <cpflex4:SolidColor color="#FF45EDF"/> </cpflex4:fill> </cpflex4:Rect> <Private> <Commentaire> Premiere application 3D avec Flex 4 </Commentaire> </Private> </Application> Figure 25-9 Utilisation des propriétés de rotation 3D > 525 =Flex3 FM.book Page 526 Mardi, 2. décembre 2008 3:32 15 526 Cas pratiques PARTIE II En conclusion Ce dernier chapitre nous a permis de nous rendre compte que le projet Flex est en perpétuelle évolution, proposant à chaque version de nouvelles fonctionnalités plus étonnantes les unes que les autres. Cette inventivité permet de contrecarrer la concurrence que représente notamment le projet Silverlight de Microsoft (qui a annoncé sa portabilité sur Eclipse le 13 octobre 2008). L’aventure Flex est loin d’être terminée ! Nous espérons vous avoir donné envie de la poursuivre… =Flex3 FM.book Page 527 Mardi, 2. décembre 2008 3:32 15 Index A AC_OETags.js 342 accès aux données HTTPService 223 RemoteObject 223 WebService 223 accordéon 126 ActionScript 16, 18, 174, 286, 310, 482 algorithme de boucle 19 boucle 19 condition 19, 20 fonction 21 implémenter HTTPService 247 MXML 171 opération booléenne 20 procédure 21 programmation objet 22 variable 18, 19 Adobe AIR 67, 345 composant 346 FileSystemComboBox 346 FileSystemDataGrid 346 FileSystemHistoryButton 347 FileSystemList 346 FileSystemTree 347 HTML 349 déploiement 352 Desktop Application 349 fonctionnement 345 mx:WindowedApplication 350 SQLite 354 AdvancedDataGrid, mode de tri Expert 90 afficherLabel 110 agencement des composants 135 AIR 12 AIRI 352 Ajax 8 algorithme de boucle 19 alias 314 AMF (protocole) 242 AMFPHP (Action Message Format PHP) 241, 374, 387, 389, 394 browser 252 test du service 252 analyse de performances 329 Ant 39, 40 antivirus et Flash Player 331 Apollo 345 application déploiement 39 intégrer un module 288 modulaire 285 architecture modulaire 368 n-tiers 13 Array 107 ArrayCollection 78, 85, 107 ascenseur 146 attribut déclaration 23 icon 107 label 107 autoLoad 100 autonome (mode) 48 avertissement 321 Avg. Cumulative time 332 Avg. Self Time 332 B balise mx:Module 285 object 315 Style 148 SWF 152 base de données 13, 14, 374 Bindable 202 dispacthEvent 205 bin-debug 340 bin-release 342, 476 BlazeDS 263 data push 263 échange de données 276 J2EE 263 remote_config.xml 270 borderSkin 155 bottom 144 bouton 17 C cache du navigateur (désactiver) 339 callLater 337 Calls 332 canal, my-polling-amf 278 Canvas 124, 125, 277 capture d’événement 331, 333 des actions de l’application 330 certificat 352 AIRI 352 champFiltre 177 chargement, afficher la progression 290 classe 15, 22 ActionScript 22 Alert 398 ArrayCollection 442 BrowserChangeEvent 303 Canvas 179 ExternalInterface 313, 314, 316 instancier 23 Math 320 =Flex3 FM.book Page 528 Mardi, 2. décembre 2008 3:32 15 528 Programmation Flex 3 classe (suite) nombre d’instances 336 servComposants 252, 254 Validator 218 VideoDisplay 101 ColdFusion 52 colonne regrouper 88, 90 trier 88 commentaire, private 514 communication entre application et module 293 compc 174, 195 compilateur 30, 174 compc 31, 341 mxmlc 30, 341 compilation 36 automatisation 39 créer un script 40 html-wrapper 42 manuelle 39 mode Strict 340 Tomcat 273 composant 31, 173 Adobe AIR, FileSystemTree 479 ArrayCollection 175 Button 34 Canvas 176 comboBox 406 compc 175, 195 conteneur ApplicationControlBar 111 Canvas 112 Form 115 FormHeading 115 FormItem 115 Grid 116 HBox 113 HDividedBox 113 Panel 117 TitleWindow 118 VBox 113 VDividedBox 113 contrôle AdvancedDataGrid 88, 386 Button 76 CheckBox 76 ColorPicker 103 ComboBox 77 DataGrid 85 DateChooser 104 DateFiled 104 HorizontalList 106 HSlider 105, 132 Image 100 Label 82 LinkButton 107 List 77 ListBox 77 NumericStepper 106 OLAPDataGrid 92 radioButton 80 radioButtonGroup 80 RichTextEditor 83 SWFLoader 100 Text 82 TextArea 82 TextInput 82 TileList 106 ToogleButton 76 Tree 108 VideoDisplay 101 VSlider 105 créer 175 DataGrid 175, 176, 439 dimensionner 135 émetteur, mx:Producer 279 graphique AreaChart 128 BarChart 128 BubbeChart 128 CandlestickChart 128 ColumnChart 128 HLOCChart 128 LineChart 128 PieChart 128 PlotChart 128 HBox 447 HTTPService 17, 225 Label 176 ModuleLoader 288, 290, 295, 424 mx:Label 517 navigation Accordion 126 PopUpMenuButton 490 TabNavigator 123 tabNavigator 381 ViewStack 124 Panel 34 positionner 138, 143 récepteur, mx:Consumer 279 RemoteObject 238, 241, 274 spécification des dimensions 137 taille 136 TextArea 517 TextBox 517 TextInput 176, 517 ToggleButtonBar 125 WebService 17, 235 xmlns 180 conception UML 366 constructeur 23 conteneur 17 HTML 315 optimisation 341 web 305, 309 intégration 38 couche 13 métier 223 création de projet 365 creationComplete 84 CSS (Cascading Style Sheet) 147, 493 ActionScript 150 color 147 fontFamily 147 fontSize 147 fontStyle 147 fontWeight 147 paddingBottom 147 paddingLeft 147 paddingRight 148 paddingTop 148 textAlign 148 textDecoration 148 textIdent 148 CSSStyleDeclaration 151 Cumulative time 332 currencyFormater 440 curseur de lecture 485 curveTo 155 CVS (Concurrent Versions System) 68 D data push 263 DataBinding 16, 79, 190, 199, 200, 395, 495 ActionScript 201 bi-directionnel 205, 516 Bindable 202 BindingUtils 201 mx:Binding 201 =Flex3 FM.book Page 529 Mardi, 2. décembre 2008 3:32 15 Index DataGrid 85, 175, 188, 190 alimenter 182 dataProvider 78, 90, 104, 107, 109, 125, 132, 190, 442 date calcul 461 format 104 formatage, mx:DateFormatter 219 débogage 319 exécution pas à pas 322 mode avancé 321 modifier la valeur des variables 325 point d’arrêt 322 profiling 329 trace 325 deep linking 11, 299, 301, 476 BrowserChangeEvent (classe) 303 BrowserManager (classe) 303 history.css 301 history.js 301 déploiement 315, 341 Adobe AIR 352 bin-release 342 check list 341 Release Build 342 version 419 design pattern 16 designViewDataType 90 diagramme de classes UML 366 dimensionner composant 135 par défaut 136 pourcentage 137 données DataBinding 199 formatage 218 hiérarchie 108 mx:EmailValidator 215 présentation hiérarchique 88 saisie obligatoire 213 validation 212 vérification 215, 398 visualisation 90 drawCircle 155 drawRect 155 E E4X (ECMAScript for XML) 226 easyPHP 374 échange de données BlazeDS 276 mx:Consumer 279 mx:Producer 279 Eclipse 47, 48 espace de travail 518 IDE Open Source Eclipse 54 Linux 49 ECMAScript 18 effet blur 163 combinaison 165 Dissolve 163 Fade 163 Glow 163 Iris 163 Move 163 Rezise 164 Rotate 164 sequence 165 target (cible) 165 transition 163, 166 WipeDown 164 WipeLeft 164 WipeRight 164 WipeUp 164 zoom 164 erreur compilation Flash Player 521 corriger avec la vue Problems 321 espace de noms 17, 510 XML 313 de travail 519 état 157 currentState 162 de base 157 mx:AddChild 161 mx:SetProperty 160 mx:states 159 target 160 transition 163, 423 événement 188 executerService 256 extends 22 F fenêtre, redimensionner 505 FileSystemTree 480, 489 filtre 188 Firefox 301 Flash 299 référencement 11 Flash Player 8, 10, 342 AC_OETags.js 342 antivirus 331 désinstaller la version 9 510 getTimer 337 installation automatique 342 mémoire occupée 338 mise à jour 29, 521 totalMemory 338 version 10 510 flash.media.Sound 482 flash.media.SoundChannel 482 flash.utils 337 flash.utils.timer 485 Flex Builder 47 installation 49 mode Autonome 48 Plug-in 48 perspective 56 travail collaboratif 68 Flex SDK 27 Flex-Ajax Bridge 299, 313 flv 101 fonction, alimenterDatagrid 85 format Date 484 de données, zipCodeValidator 400 FXG 510 format de données credicardvalidator 465 currencyFormater 440 formatage 220 ActionScript 310 code postal mx:ZipCodeFormatter 219 date mx:DateFormatter 219 monétaire 219 nombre mx:NumberFormatter 219 numéro de téléphone mx:PhoneFormatter 219 formulaire (validation) 218, 449 front end 13 FXG 18, 509, 511 Rect 522 529 =Flex3 FM.book Page 530 Mardi, 2. décembre 2008 3:32 15 530 Programmation Flex 3 G gateway.php 242, 392 getOperation 255 getTimer 337 glisser-déposer 451 dragComplete 455 dragEnabled 454 dragInitiator 456 dragMoveEnabled 453 Google Chrome 301 Web Toolkit 4 H habillage (skin) 153 Height 136 heightInLine 517 héritage 22 HierarchicalData 90 horizontalAlign 139 horizontalCenter 144 horizontalScrollPolicy 146 HSlider 518, 522, 523 HSQLDB 270 html-wrapper 42 HTTPService 14, 223, 261 implémentation ActionScript 247 mx:HTTPService 227 PHP 241 I IDE 270 Eclipse 4, 7, 270 Flex Builder 8 NetBeans 270 identifiant, récupérer valeur 189 idt 177 IHM 15, 392 impression 451, 462 FlexPrintJobScale 462 initialisation, calculer le temps d’ 337 installation, Flex Builder 49 instance d’une classe 336 interface graphique 135, 381 agencement des composants 135 Internet Explorer 301 item 81 itemClick 110, 396, 490 ItemClickEvent 81 ItemRenderer 423, 439, 447 J J2EE 263 classe création 270 déploiement 272 RemoteObject 274 Tomcat 264 Java J2EE 268 SDK 264 JDK (Java Developpement Kit) 28 JRE (Java Runtime Environment) 28 JSEclipse 52 L label 109 labelField 109 layout 139 left 144 liaison des données 199 librairie ajouter à un projet 313 AMFPHP 242 Flex-Ajax Bridge 299, 313, 316 graphique déclaration 516 description 514 library 514 licence 27 lineTo 155 Linux plug-in Flex Builder 49 Silverlight 10 liste déroulante 190 ListeEvent 110 listerComposants 250 LiveCycle Data Services ES 64, 263 logique applicative 394 IHM 392 M machine virtuelle 345 maxHeight 136, 505 maxWidth 136, 505 mémoire allocution inutile 334 occupation 333, 338 menu, accordéon 127 message d’erreur 215 Method 332 méthode ActionScript 22 init 305 J2EE 268 exécution 274 pow 320 setTitle 305 temps d’exécution 335 trace 325 minHeight 136, 505 minWidth 136 mise en forme ItemRenderer 423 mx:repeater 451 mm.cfg 341 mode Debug 322 MODEL 16 modèle, classe 389 module 285 ActionScript 288 charger 288 compiler 287 créer 286 implémenter un composant 287 intégrer dans une application 288 interaction 292 avec l’application 295 loadModule() 288 ModuleLoader 381 mx:ModuleLoader 288 parentApplication 296 progression du chargement 290, 473 version de déploiement 297 MP3 482 multithreading 62 MVC (modèle-vue-contrôleur) 15, 206 ActionScript 209 balise 209 gestion des données 201 mx:Model 206 mx:Application 17 =Flex3 FM.book Page 531 Mardi, 2. décembre 2008 3:32 15 Index MXML (Macromedia fleX Markup Language) 16, 17, 174, 313, 510, 513 2009 18 ActionScript 171 appel des balises 514 Component 177 espace de noms 513 mx:RemoteObject 238 RemoteObject 254 my-polling-amf 278 MySQL 374 N navigateur 305 deep linking 299 ExternalInterface 307 Flex-Ajax Bridge 313 JavaScript 307 nœud, récupérer valeur 109 NumericStepper 518 O object 107 objet allocation 336 instancié 330 taille 330 OLAP (OnLine Analytical Processing) 92 onglet 123, 124 opérateur booléen 20 comparaison 20 optimisation 337 cache du navigateur 339 compilation mode Strict 340 occupation mémoire 338 temps d’initialisation 337, 338 P package 22, 332 paddingBottom 139 paddingLeft 139 paddingRight 139 paddingTop 139 page d’accueil 343 panier 439 vider 442 paramètre, FlashVars 315 parentApplication, module 296 passerelle, remote-config.xml 271 percentHeigth 136 percentWidth 136 performances analyse 331 applicatives 337 PHP (Hypertext Preprocessor) 241 environnement 224 générateur d’application 257 Pixel Blender 510 Play 101 plug-in 49 Eclipse 55 Linux 49 mode 48 point d’arrêt 62, 322, 324 pop-up 118, 457 createPopUp 119 parentApplication 122 PopUpManager 119 removePopUp 119 TitleWindow 457, 458, 460 PopUpMenuButton 489 positionnement absolu 143 automatique 138 par contraintes 143 poste client 338 AIR 345, 353 cache du navigateur 339 mm.cfg 341 temps d’initialisation 338 private 514, 524 procédure 315 afficherProgression() 292 appelProcedureFlex 310 chargerModule 295 initialiserUrl() 304 interceptionErreur() 290 redondance d’appel 329 reporter l’exécution 337 temps d’exécution 329 Profiler 330 ligne 333 profiling 329 allocation d’objet 336 occupation de la mémoire 333 temps d’exécution 335 projet, création 365 propriété autoPlay 101 implements 294 531 itemRenderer 439 position 485 selectedDate 105 source 101 url 288 protocole, AMF 242 proxy 226 R ramasse-miettes 330, 340 RDA (Rich Desktop Application) 12 Release-build 506 RemoteObject 14, 223, 392 AMFPHP 250 implémentation ActionScript 256 MXML 254 PHP 250 send 255 removeAll() 442 répétition de mise en forme mx:Repeater 464 RIA (Rich Internet Application) 14 right 144 RPC (Remote Procedure Call) 223 S Safari 301 scaleContent 100 script 523 balise 35 compilation 40 scriptTimeLimit 339 selectedIndex 126 selectedItem 104 Self time 332 sérialisation des données 242 servComposants 252, 254 servComposants.php 250 serveur 270 BlazeDS, configuration 271 configuration 278 Tomcat 265 service PHP 387 web fonctionnement 236 mx:WebService 229 serviceListerComposants 254, 255, 256 =Flex3 FM.book Page 532 Mardi, 2. décembre 2008 3:32 15 532 Programmation Flex 3 services (répertoire) 242 servRO.serviceListerComposants 256 setStyleDeclaration 151 Silverlight 10 SimpleXML 229 skin 151 disabledSkin 151 downSkin 151 focusSkin 151 overSkin 151 programmation 153 selectedDownSkin 151 selectedOverSkin 151 selectedUpSkin 151 upSkin 151 snapInterval 106 SoundChannel 485 stepSize 106 style ActionScript 150 CSS 147 CSS externe 149 image 152 visualiser les propriétés d’un composant 148 Style (balise) 148 StyleManager 150 styleName 148 swc 174 SWC (Shockwave Component) 32 SWF (ShockWave Flash) 23, 30, 152, 341, 343 balise Style 152 exclure les lignes et fonctionnalités de débogage 339 taille 339 SWFLoader 340 System 338 T tableau, trier 90 TabNavigator 124 tb_composant 261 temps d’initialisation 338 text 83 Thermo 510, 511 tickInterval 106 TileList 444 time line 6 Tomcat 265, 270 répertoire de compilation 273 top 144 totalMemory 338 trace 62, 325, 326 optimiser 340 transition 163, 435 ActionScript 169 effet 163 fromState 168 mx.effects 163 mx:Parallel 166 mx:Sequence 165 mx:transitions 164 toState 168 verticalCenter 144 VerticalScrollPolicy 146 vidéo, progression du chargement 102 view state 157 base state 157 currentState 162 état 157 mx:AddChild 161 mx:SetProperty 160 mx:states 159 target 160 transition 163 ViewStack 125, 261 visible 86 VSlider 518 vue Expressions 326 Memory Snapshot 333 Problems 321 Variables 325 W U UML conception 366 diagramme de classes 366 unscaleHeight 154 unscaleWidth 154 updateDisplayList 154 URLLoader 395 V value 80, 81, 106 variable critique 62 déclarer 19 non affectée 62 surveiller 326 vérification des données 398 version de déploiement 419 verticalAlign 139 W3C (World Wide Web Consortium) 3 warning 321 WebService 223 Width 136 widthInChars 83, 517 X XAML 10 xmlns 180 Z zone de saisie 17, 371 redimensionnement 517 de texte redimensionnement automatique 83 Flex 3, framework de référence pour le développement Flash Open Source, le SDK de Flex offre un véritable environnement en phase avec les bonnes pratiques de génie logiciel (MVC…) et de gestion de projet (travail collaboratif…). Il propose des bibliothèques de composants graphiques et des fonctions pour dialoguer avec le serveur, et s’interfacer avec des bases de données via des serveurs PHP/J2EE. Une bible avec de nombreux cas pratiques et retours d’expérience Programmation Flex 3 explique aux développeurs web, qu’ils soient ou non rompus à Flash et ActionScript, comment utiliser le framework Flex pour concevoir et créer des applications web dites « riches » (RIA), à l’instar des applications Ajax ou Silverlight. Tout en rappelant les langages sur lesquels s’adosse cette technologie (ActionScript, MXML), l’ouvrage passe en revue l’intégralité des techniques de développement Flex : maîtrise de l’environnement de travail, création d’interfaces interactives et évoluées avec les vues, transitions et thèmes, gestion des données et échanges avec le serveur via RPC, mais aussi gestion et création des composants, débogage et optimisation. Il les met ensuite en situation avec deux études de cas détaillant la création d’un site e-commerce puis d’un lecteur MP3 tournant sur Adobe Air. Au sommaire Pourquoi utiliser Flex ? • Flex dans une architecture trois tiers • Flex et MVC • MXML et Actionscript • Procédures et fonctions • Programmation objet • Mécanisme client/serveur • Flex SDK et Flex Builder • Gestion d’un projet • Arborescence d’un projet Flex Builder • Exécution et test • Travail collaboratif • Export et import • Création d’interfaces graphiques • Composants de contrôles • Boutons • Listes • Zones de texte • Tableaux • Animations et vidéos Flash • Composants de navigation • Autres contrôles • Dimensionner et positionner • ApplicationControlBar • Canvas • Hbox • Grid • Panel • TitleWindow • Styles • CSS et ActionScript • Skinning • Utilisation d’images et de fichiers SWF • États, transitions et effets • Créer ses composants • MXML ou ActionScript ? • compc • Gestion des données • DataBinding • Validation des données • Accès aux services de la couche métier • HTTPService ou REST • RemoteObject • Flex et PHP • AMFPHP • HTTPService et ActionScript • Le générateur de Flex Builder • Flex et J2EE avec BlazeDS • Composants émetteurs et récepteurs • Créer des applications modulaires • Interagir avec le conteneur web • Deep linking • Flex-Ajax Bridge • Débogage d’une application • Points d’arrêt et exécution pas à pas • Analyse des performances • Optimisation et déploiement • Réduire la taille des fichiers SWF • Adobe AIR • Flex 4 Gumbo. A.Vannieuwenhuyze Ingénieur concepteur dans une SSII et responsable d’applications pour l’association Outcomerea, spécialisée dans le domaine de la recherche médicale, Aurélien Vannieuwenhuyze s’est d’abord investi dans la conception et la réalisation d’applications J2EE. Pour créer des applications Internet riches, il a étudié les frameworks alliant richesse et rapidité de réalisation. Son choix s’est porté sur Flex, avec lequel il a réalisé des applicatifs à vocation médicale et des extranets pour de grandes entreprises. R. Pouclet Passionné de développement multimédia depuis plusieurs années, Romain Pouclet se tourne aujourd’hui vers le développement d’interfaces riches et de solutions pour supports mobiles. À qui s’adresse cet ouvrage ? @ Sur le site www.editions-eyrolles.com – Téléchargez le code source des exemples et cas pratiques du livre Conception : Nord Compo – À toute la communauté des concepteurs et développeurs web 2.0 (Flash, PHP, Java, Ajax, XHTML/CSS) qui désirent développer des applications Internet riches. – Aux webmestres et développeurs connaissant Flash et ActionScript, qui recherchent un framework pour industrialiser la création d’interfaces graphiques pour leurs applications. – Aux développeurs amenés à créer des applications autonomes exécutables avec ou sans navigateur web. Flex 3 Applications Internet riches avec Flash ActionScript 3, MXML et Flex Builder A. Vannieuwenhuyze Flex 3 Programmation Programmation Programmation e Couvr tés uveau o n s le x 4 de Fle Flex 3 Applications Internet riches avec Flash ActionScript 3, MXML et Flex Builder Aurélien Vannieuwenhuyze