<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>La Fabrick &#187; Tutoriels</title>
	<atom:link href="http://www.lafabrick.com/blog/tag/tutoriels/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lafabrick.com/blog</link>
	<description>Laboratoire d&#039;interfaces riches (Flex, Flash, Air ...)</description>
	<lastBuildDate>Mon, 28 Nov 2011 22:02:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Object to XML to Object : conversion XSD</title>
		<link>http://www.lafabrick.com/blog/2009/12/14/1492-object-to-xml-to-object-conversion-xsd/</link>
		<comments>http://www.lafabrick.com/blog/2009/12/14/1492-object-to-xml-to-object-conversion-xsd/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 21:38:47 +0000</pubDate>
		<dc:creator>Fabien</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=1492</guid>
		<description><![CDATA[Utiliser les schéma de déclaration XSD, s’avère souvent fort utile. Plus que l’autocompletion sur vos fichiers XML, l’apport des XSD se trouve avant tout dans le fait de qualifier et de valider vos fichiers. Dans Flex, bien que caché au fin fond du package rpc, la mécanique de lecture et de conversion XSD est bien [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/back.png" alt="back" title="back" width="520" height="120" class="aligncenter size-full wp-image-1507" /></center><br />
Utiliser les schéma de déclaration XSD, s’avère souvent fort utile. Plus que l’autocompletion sur vos fichiers XML, l’apport des XSD se trouve avant tout dans le fait de qualifier et de valider vos fichiers. Dans Flex, bien que caché au fin fond du package rpc, la mécanique de lecture et de conversion XSD est bien là. Nous allons voir comment l’utiliser, et convertir vos objets AS3 vers XML (et vice versa), en suivant ces schémas de définition.<br />
<span id="more-1492"></span></p>
<h2>Pourquoi utiliser une XSD?</h2>
<p>Pour ma part, ces quelques raisons (et pour vous certainement plein d’autres raisons) </p>
<ul>
<li>Elle valide vos XML : parce que vous définissez en amont la structure de vos fichiers, une définition XSD permet de les valider;</li>
<li>Parce que vous avez besoin de plusieurs écritures différentes d’un même jeu de donnés;</li>
<li>Parce que, comme tout bon dèv, vous êtes fainéant&#8230;</li>
<li>&#8230;et le fait que le programme valide tout et fait tout, tout seul, en suivant des règles normées ça vous va bien.</li>
<li>Ca fait toujours bien d’avoir des fichiers XSD dans vos sources : ça envoie de la rosette, et vous pouvez vous la péter grave.</li>
<li>&#8230;</li>
</ul>
<p>Dans un usage Flex, l’objectif serait de pouvoir transformer nos objets AS en XML, et l’inverse, via les schémas de définitions. Ça tombe bien ! C’est ce qu’on va faire.</p>
<h2>Où tu te caches XSD ?!</h2>
<p>Dans la plupart des langages, nous avons la possibilité de discuter avec notre serveur en utilisant le protocole SOAP, basé sur XML. En utilisant ce protocole, nos objets sont “transformés” en XML, et transmis vers notre serveur. L’opération inverse existe lors de réception de données.<br />
Mais pourquoi je vous parle de ça? Tout simplement parce que tout langage faisant du SOAP (ou du web service), à besoin de valider et de convertir de manière automatique les objets. Et je vous le donne en mille, ce sont les définitions XSD qui entrent en jeux (souvent <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>La mécanique XSD est utilisée, en interne dans Flex, pour l’encodage et le décodage d’objet SOAP ou WSDL. Ces classes, exclues du framework (vous n’y avez pas accès directement avec l’autocomplétion), se trouvent dans le package mx.rpc.xml.*.<br />
<center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/rpcxml.png" alt="rpcxml" title="rpcxml" width="306" height="648" class="aligncenter size-full wp-image-1508" /></center><br />
Et c’est bien dommage que ces classes soit exclues !  Selon moi, elles seraient bien plus utiles ouvertes, documentées, et dans un package plus global comme flash.xml par exemple (flash.xsd ou flash.xml.xsd&#8230; ça pourrait être cool !). </p>
<p>Car vous allez le voir, il est relativement simple d’utiliser cette partie de Flex, pour un usage personnalisé du XML, en dehors du contexte RPC. </p>
<h2>Des groupes, des geeks, des bidules</h2>
<p>Donc c’est parti pour l’exemple. Je ne me casse pas la tête, et vous propose un biniou qui aura 3 éléments : des groupes, des gens (geek forcement), et des bidules&#8230; Je n’étais pas inspiré sur le 3ème éléments, mais il m’en fallait un&#8230;.</p>
<h3>XML et la définition XSD</h3>
<p>Nous avons une infinité d’écriture XML possible, comme celle-ci :</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;groups&gt;
    &lt;group&gt;
        &lt;groupName&gt;klingons&lt;/groupName&gt;
        &lt;geeks&gt;
            &lt;geek&gt;
                &lt;firstName&gt;francis&lt;/firstName&gt;
                &lt;stuffs&gt;
                    &lt;stuff&gt;
                        &lt;name&gt;mac&lt;/name&gt;
                  &lt;/stuff&gt;
                   &lt;stuff&gt;
                        &lt;name&gt;Flex&lt;/name&gt;
                    &lt;/stuff&gt;
                &lt;/stuffs&gt;
            &lt;/geek&gt;
        &lt;/geeks&gt;
    &lt;/group&gt;

    &lt;group&gt;
        ...
&lt;/groups&gt;
</pre>
<p>Ou celle là :</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;groups&gt;
    &lt;group groupName=&quot;klingons&quot;&gt;
        &lt;geeks&gt;
            &lt;geek firstName=&quot;francis&quot;&gt;
                &lt;stuffs&gt;
                    &lt;stuff name=&quot;mac&quot; /&gt;
                    &lt;stuff name=&quot;Flex&quot; /&gt;
                &lt;/stuffs&gt;
            &lt;/geek&gt;
            &lt;geek firstName=&quot;roger&quot;&gt;
                &lt;stuffs&gt;
                    &lt;stuff name=&quot;pc&quot; /&gt;
                    &lt;stuff name=&quot;photoshop&quot; /&gt;
                &lt;/stuffs&gt;
            &lt;/geek&gt;
        &lt;/geeks&gt;
    &lt;/group&gt;

    &lt;group&gt;
        ...
&lt;/groups&gt;
</pre>
<p>Ou un mélange à votre sauce, vous faites bien comme vous voulez !</p>
<p>Nous allons donc écrire notre XSD, qui va définir le XML définit ci-dessus, celui qui utilise pleins d’attributs. Je prend celui là parce que la sortie XML est moins longue&#8230;. et mon article gagnera quelques lignes&#8230;. En ce moment mes articles sont un peu trop pépère&#8230; Ca doit être l’approche des fêtes.</p>
<p>Bref !</p>
<p>Le but est de réaliser une XSD la plus complète possible, ou toutes les parties sont typées (SimpleType ou ComplexeType). C’est important pour la suite, car chaque type sera “mappé” avec la classe ActionScript qui lui correspond.</p>
<p>Dans notre exemple, nous avons 3 collections (groups geeks, stuffs) et 3 éléments (group, geek, stuff)&#8230; D’accord je ne me suis pas foulé les doigts sur ce coup là !</p>
<p>Le schéma XSD n’est finalement qu’un fichier XML standard : </p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xsd:schema
    xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
    targetNamespace=&quot;schemas/geeks&quot;
    xmlns=&quot;schemas/geeks&quot;&gt;

    &lt;xsd:element name=&quot;groups&quot; type=&quot;groupsCollectionType&quot; /&gt;

&lt;/xsd:schema&gt;
</pre>
<p>L’élément principale, le noeud “&lt;groups&gt;”, est la base de notre schéma. Le type correspondant va s’appeler <strong>groupsCollectionType</strong>.</p>
<p>La version actionScript de ce type <strong>groupsCollectionType</strong> serait un Array ou ArrayCollection (ou tout autre type de collection d’objet).<br />
<strong>groupsCollectionType</strong> est une séquence, un réceptacle de 0 à n éléments de type group (le nombre d’instances minimum et maximun est défini par <strong>minOccurs</strong> et  <strong>maxOccurs</strong>).</p>
<pre class="brush: xml">
&lt;xsd:complexType name=&quot;groupsCollectionType&quot; mixed=&quot;true&quot;&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name=&quot;group&quot; type=&quot;groupType&quot;
            maxOccurs=&quot;unbounded&quot; minOccurs=&quot;0&quot; /&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;
</pre>
<p>Le type group est composé comme suit :</p>
<pre class="brush: xml">
&lt;xsd:complexType name=&quot;groupType&quot; mixed=&quot;true&quot;&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name=&quot;geeks&quot; type=&quot;geeksCollectionType&quot;
            minOccurs=&quot;0&quot; maxOccurs=&quot;1&quot;  /&gt;
    &lt;/xsd:sequence&gt;

    &lt;xsd:attribute name=&quot;groupName&quot; use=&quot;required&quot; type=&quot;xsd:string&quot; /&gt;

&lt;/xsd:complexType&gt;
</pre>
<p>On retrouve le noeud <strong>geeks</strong>, unique, mais non obligatoire (minOccurs=&nbsp;&raquo;0&#8243; maxOccurs=&nbsp;&raquo;1&#8243;), qui sera défini dans un type <strong>geeksCollectionType</strong> de la même manière que <strong>groupsCollectionType</strong>.<br />
Les attributs du noeud sont placé à la suite de la séquence d’éléments. Ils peuvent être requis ou optionnel, définit par l’attribut use. On peut aussi le définir “prohibited” même si je ne vois pas vraiment l’intérêt&#8230;</p>
<p>Et on continue comme cela, en rentrant en profondeur dans nos différent objets. La syntaxe n’est pas compliquée, il suffit de se pencher un peu sur <a href="http://www.w3.org/XML/Schema#dev">les spécifications de la W3C</a>. </p>
<p><a href="http://www.lafabrick.com/labz/xsdconverter/srcview/source/geeks.xsd">Vous trouverez ici la XSD complète</a> de notre exemple.</p>
<h3>Côté ActionScript</h3>
<p>Nous avons besoin de 3 objets, qui correspondent aux 3 types d’éléments de notre XML : des groupes de Geek, des Geeks, des Stuffs.</p>
<p>Là, rien de plus basique.</p>
<ul>
<li>La classe <strong>GeekGroup </strong>: avec une propriété <strong>groupName</strong>, et une collection <strong>geeks </strong>(les geeks membres du groupe)</li>
<li>La classe <strong>Geek </strong>: avec une propriété <strong>firstName</strong>, et une collection <strong>stuffs</strong> (les bidules du geek)</li>
<li>La classe <strong>Stuff</strong> : avec une propriété <strong>name</strong>, le nom du bidule</li>
</ul>
<p>Vous vous rendez compte, tout d’un coup, que je ne vous ai absolument rien appris dans ce paragraphe. Passons à la suite.</p>
<h2>Les classes de gestion XSD</h2>
<p>Nous avons une XSD et des objets AS prêts à être convertis. Regardons de plus près les classes exclues dont nous avons besoin:</p>
<ul>
<li><strong>mx.rpc.xml.SchemaTypeRegistry</strong> : cette classe est une sorte de dictionnaire, ou l’on référence les différents types du schéma XSD, avec leurs classes actionScript associées.</li>
<li><strong>mx.rpc.xml.XMLDecoder</strong> : la classe qui permet de décoder une source XML, en suivant la XSD, vers un object typé actionScript.</li>
<li><strong>mx.rpc.xml.XMLEncoder</strong> : la classe qui permet d’encoder un objet AS en un fichier XML, en suivant la définition XSD.</li>
<li><strong>mx.rpc.xml.Schema</strong> : la classe contenant le schema XSD chargé.</li>
<li><strong>mx.rpc.xml.SchemaManage</strong>r : point central du système, cette classe est utilisée par l’encodeur et le décodeur. Elle possède une référence au schéma (elle peut d&#8217;ailleurs contenir plusieurs schéma XSD), et utilise les références de classes et de type XSD enregistrés dans mx.rpc.xml.SchemaTypeRegistry.</li>
</ul>
<h2>Votre object en XML, via XSD</h2>
<p>Dans un premier temps, il nous faut charger la définition XSD via un URLLoader : </p>
<pre class="brush: js">
var urlLoader : URLLoader = new URLLoader();
urlLoader.addEventListener( Event.COMPLETE, onLoadXsdComplete );
urlLoader.load( new URLRequest( &quot;geek.xsd&quot; ) );	
</pre>
<p>A la réception de la XSD, nous initialisons la classe Schema et le SchemaManager :</p>
<pre class="brush: js">
var _schema:Schema = new Schema();
var _schemaManager:SchemaManager = new SchemaManager();

_schema.xml = XML( urlLoader.data );
_schemaManager.addSchema( _schema );
</pre>
<p>Nous ajoutons la référence du manager de schéma dans nos objets d’encodage/décodage :</p>
<pre class="brush: js">
var _xmlDecoder:XMLDecoder = new XMLDecoder();
var _xmlEncoder:XMLEncoder = new XMLEncoder();

_xmlDecoder.schemaManager = _schemaManager;
_xmlEncoder.schemaManager = _schemaManager;
</pre>
<p>Ensuite, nous référençons les types contenus dans la XSD, avec les classes AS correspondantes : </p>
<pre class="brush: js">
var _schemaTypeRegistry : SchemaTypeRegistry;
_schemaTypeRegistry = SchemaTypeRegistry.getInstance();

_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;groupsCollectionType&quot;), ArrayCollection);
_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;groupType&quot;), GeekGroup);

_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;geeksCollectionType&quot;), ArrayCollection);
_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;geekType&quot;), Geek);

_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;stuffCollectionType&quot;), ArrayCollection);
_schemaTypeRegistry.registerClass(
    new QName(_schema.targetNamespace.uri, &quot;stuffType&quot;), Stuff);
</pre>
<p>Enfin, nous récupérons notre XML tout bien valide, image de l’objet targetObject, via l’encodeur XML (il faut préciser le nom du noeud “root” de la XSD) : </p>
<pre class="brush: js">
var xmlList : XMLList = _xmlEncoder.encode( targetObject,
    new QName( _schema.targetNamespace.uri, &quot;groups&quot;) );
</pre>
<p>Super simple.</p>
<h2>D&#8217;un XML vers un Object</h2>
<p>C’est magique, c’est tout pareil ! au lieu d’utiliser XMLEncoder, on utilise XMLDecoder, et on change la référence de l’objet par notre XML : </p>
<pre class="brush: js">
var obj : ArrayCollection = _xmlDecoder.decode( myXml,
    new QName( _schema.targetNamespace.uri, &quot;groups&quot;) ) as ArrayCollection;
</pre>
<h2>Automatisation</h2>
<p>Je vous propose un set de classes pour faire tout ça de manière automatique. </p>
<ul>
<li><a href="http://www.lafabrick.com/labz/xsdconverter/srcview/source/com/lafabrick/converter/XSDConverter.as.html">XSDConverter</a> : un convertisseur XML via XSD.<br />
2 méthodes : </p>
<ul>
<li>importFromXml( xml : *, xsdUrl : String, schemaTypes : Vector.<XSDType> = null ) : void</li>
<li>exportToXml( target : Object, xsdUrl : String, schemaTypes : Vector.<XSDType> = null ) : void</li>
</ul>
<p>En paramètre de ces méthodes : </p>
<ul>
<li><strong>la source</strong> : Object pour l’exportation, une String, un XML ou un XMLList pour l’importation;</li>
<li><strong>xsdUrl</strong> : l’url de la xsd a charger;</li>
<li><strong>schemaType</strong> : une collection (Vector) d’objet de type XSDType, définissant le mapping entre les types XSD, et les classes référentes AS.</li>
</ul>
</li>
<li><a href="http://www.lafabrick.com/labz/xsdconverter/srcview/source/com/lafabrick/converter/XSDEvent.as.html">XSDEvent</a> : l’évènement diffusé par XSDConverter (importSuccess, exportSuccess et conversionError (en cas de problème de conversion ou de chargement de la XSD ) ).</li>
<li><a href="http://www.lafabrick.com/labz/xsdconverter/srcview/source/com/lafabrick/converter/XSDType.as.html">XSDType</a> : définition d’un type XSD, avec la classe AS associée.</li>
</ul>
<p><a href="http://www.lafabrick.com/labz/xsdconverter/">Un petit exemple est disponible là</a>, avec <a href="http://www.lafabrick.com/labz/xsdconverter/srcview/index.html">les sources sous ce lien</a>.</p>
<h2>Et donc&#8230;.</h2>
<p>&#8230; vous pouvez vous dire que  “Ahh ! Maintenant que mes données sont automatiquement transformées en XML, je me sens mieux. Et comme j’ai gagné plein de temps, ba du coup je peux lire des articles fort intéressants comme ceux concernant <a href="http://www.lafabrick.com/blog/2009/11/27/1373-flex4-custom-component-skinnig/">le skinning</a> ou <a href="http://www.lafabrick.com/blog/2009/12/04/1453-flex4-skin-et-primitives/">les primitives dans Flex4</a>. De toutes façons y’a trop de monde à la Fnac pour finir mes cadeaux&#8230;.”</p>
<p>Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2008/02/06/301-tips-of-the-day-les-collectionevent/" rel="bookmark" title="6 février 2008">Pti truc du jour : Les CollectionEvent</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/01/10/288-cairngorm-pour-les-fainants-tour-d-horizons-des-code-generator/" rel="bookmark" title="10 janvier 2008">Cairngorm pour les fainéants&#8230; Tour d&#8217;horizons des code generator</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/" rel="bookmark" title="21 janvier 2009">Developing with AFCS a.k.a Cocomo &#8211; Introduction</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/15/819-reflex-2-vous-reprendez-bien-un-peu-de-ioc/" rel="bookmark" title="15 janvier 2009">Reflex #2 : vous reprendrez bien un peu de IOC ?</a></li>
</ul>
<p><!-- Similar Posts took 12.236 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/12/14/1492-object-to-xml-to-object-conversion-xsd/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Flex4 : skin et primitives</title>
		<link>http://www.lafabrick.com/blog/2009/12/04/1453-flex4-skin-et-primitives/</link>
		<comments>http://www.lafabrick.com/blog/2009/12/04/1453-flex4-skin-et-primitives/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 16:52:36 +0000</pubDate>
		<dc:creator>Fabien</dc:creator>
				<category><![CDATA[Nos projets]]></category>
		<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[FlashBuilder]]></category>
		<category><![CDATA[flex4]]></category>
		<category><![CDATA[skinning]]></category>
		<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[UI Design]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=1453</guid>
		<description><![CDATA[Dans le dernier article, nous avons fait un petit tour d’horizon du nouveau système de skin de Flex4. J’ai brièvement présenté EazeElement que j’utilise dans l’article. Nous allons maintenant rentrer un peu plus profondément dans les primitives, qui vous permettent de créer vos propres formes et autres éléments graphiques personnalisés. Retour sur les primitives Dans [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/bandeauskinprimitive.jpg" alt="bandeauskinprimitive" title="bandeauskinprimitive" width="520" height="132" class="aligncenter size-full wp-image-1480" /></center><br />
Dans le dernier article, nous avons fait un petit tour d’horizon du nouveau système de skin de Flex4. J’ai brièvement présenté EazeElement que j’utilise dans l’article. Nous allons maintenant rentrer un peu plus profondément dans les primitives, qui vous permettent de créer vos propres formes et autres éléments graphiques personnalisés.<br />
<span id="more-1453"></span></p>
<h2>Retour sur les primitives</h2>
<p>Dans Flex4, une Skin est une agglomération d’éléments graphiques, définis avec un type de ligne, de fond, et des filtres. L&#8217;objet graphique final est une superposition de rectangles, de lignes, d&#8217;ellipses, d’images, de formes complexes.</p>
<p>Intéressons nous à celles qui utilisent directement l’API de dessin : Rect, Ellipse, Line, Path</p>
<h3>Comment ça marche?</h3>
<p>L’architecture des primitives utilisant l’API de dessin est la suivante :<br />
<center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/organigrammeprimitives.png" alt="organigrammeprimitives" title="organigrammeprimitives" width="652" height="379" class="aligncenter size-full wp-image-1464" /></center></p>
<h4>Les classes de bases : </h4>
<ul>
<li><strong>GraphicElement</strong> : la base des primitives. Cette classe définit les tailles et positionnement de l’objet dans l’espace, avec ses contraintes de position. Les getters protégés drawX et drawY, utilisés par toutes les primitives, renvoient la position réelle en x et y de l’objet.</li>
<li><strong>StrokedElement</strong> : définit le Stroke (interface mx.graphics.IStroke), l’apparence de la ligne, de la primitive. La base des méthodes de dessin est présente : beginDraw, draw, endDraw. La méthode beginDraw applique le style du Stroke dans l’élément graphique Graphics de la primitive.</li>
<li><strong>FilledElement</strong> : définit le Fill (interface mx.graphics.IFill), l’apparence du fond, de la primitives. La méthode beginDraw prépare l’objet graphique en appliquant la ligne Stroke et le fond Fill. A ce niveau, la méthode draw n’effectue aucun tracé.</li>
</ul>
<p>Les primitives :</p>
<ul>
<li><strong>Line</strong> : (extension de StrokedElement) dessine une ligne, passant par 2 points (xFrom/yFrom et xTo/yTo). Si votre ligne est encadrée dans des contraintes top, bottom, left, right; la ligne dessinée sera une diagonale, respectant les contraintes top/left et bottom/right;</li>
<li><strong>Ellipse</strong> : (extension de FilledElement) dessine une ellipse définie par ses contraintes de positionnement;</li>
<li><strong>Rect</strong> : (extension de FilledElement) dessine un rectangle défini par ses contraintes de positionnement. Sa particularité est de pouvoir définir des rayons de courbure globaux (radiusX/radiusY), ou localisés aux angles du rectangle (topLeftRadiusX/topLeftRadiusY, bottomLeftRadiusX/bottomLeftRadiusY, &#8230;).</li>
<li><strong>Path</strong> : (extension de FilledElement) dessine une forme complexe, définie dans une propriété data. Cette source utilise la syntaxe SVG.</li>
</ul>
<h2>Digression : Définition et obtention d’un “data Path”</h2>
<p>Le “data source” d’une primitive Path est définit par un code, identique à celui utilisé dans le format vectoriel SVG. Ce code ressemble a celui-ci :<br />
 <strong>M 8 4 C 8 4 15 4 15 4 L 15 0 L 27 8 L 15 15 L 15 11 L 8 11 L 8 11 L 8 11 L 0 11 C 0 11 0 11 0 11 C 0 7 3 4 8 4 Z </strong></p>
<p>Il représente une flèche avec un bord arrondi, d’une largeur de 27 pixels, et une hauteur de 15 pixels. </p>
<h3>Fonctionnement du code</h3>
<p>c’est une succession de commandes (définies par des lettres), et de positions de points (les chiffres) en pixels utilisées par la commande.</p>
<p>Les différentes commandes sont :</p>
<ul>
<li><strong>M</strong> : <em>Move</em>, déplacement de la ligne vers le point définit par le couple de chiffres suivant. Exemple : “M 8 4” déplace le point courant de la ligne à la position x=8 et y=4. C’est toujours la première commande du code.</li>
<li><strong>L</strong> : <em>Line</em>, création d’une ligne, avec comme point de destination le couple de chiffres suivant. Exemple “ L 15 11” crée la ligne depuis le point précédent, vers le point x=15 et y 11.</li>
<li><strong>H</strong> : <em>Horizontal Line</em>, identique à la commande L, à la différence que seul le point de destination x est nécessaire. Exemple : “H 15” construit une ligne horizontale depuis le point précédent, vers le point x=15.</li>
<li><strong>V</strong> : <em>Vertical Line</em>, identique à la commande H, en vertical.</li>
<li><strong>Q</strong> : <em>Quadratic Bezier</em>, création d’une ligne courbe, a partir du précédent point, à destination du point définit par le dernier couple x/y, et passant par le point de contrôle définit par le premier couple x/y. exemple : “Q 15 11 20 22” la ligne est créée entre le point précédent et le point x=20, y=22, en passant par le point de contrôle x=15, y=11;</li>
<li><strong>C</strong> : <em>Cubic Bezier</em>, identique à la commande Q, à la différence que la ligne passe par un point de contrôle supplémentaire. Exemple : “ C 0 7 3 4 8 4” la ligne est créée entre le point précédent et le point x=8 / y=4, en passant par un premier point de contrôle x=0, y=7, et un second x=3, y=4;</li>
<li><strong>Z</strong> : <em>Close</em>, définit la fermeture de la forme. C’est aussi le dernier code du data.</li>
</ul>
<h3>Obtenir un code à partir d’une forme</h3>
<p>La meilleur méthode pour obtenir le code de votre forme vectorielle est de passer par Fireworks. Je vous recommande fortement d’utiliser ce logiciel pour vos créations d’interface, car très complet, performant, et beaucoup plus adapté à la création graphique web que Photoshop ou Illustrator. </p>
<p>Fireworks, depuis la CS4, dispose d’une commande d’exportation FXG. Vous pouvez la trouver sous “<strong>Commandes</strong>” > “<strong>Exporter au format FXG</strong>”.</p>
<p>Il vous suffit de sélectionner votre forme, (si rien n’est sélectionné, c’est la totalité du document, y compris les calques masqué, qui sera exporté), et de lancer la commande d’exportation.<br />
<center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/flechefireworks.png" alt="flechefireworks" title="flechefireworks" width="520" height="269" class="aligncenter size-full wp-image-1461" /></center><br />
Vous obtenez un document de ce type : </p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;Graphic version=&quot;1.0&quot;
    xmlns=&quot;http://ns.adobe.com/fxg/2008&quot;
    xmlns:d=&quot;http://ns.adobe.com/fxg/2008/dt&quot;
    xmlns:fc=&quot;http://ns.adobe.com/flashcatalyst/2009&quot;
    viewHeight= &quot;40&quot; viewWidth= &quot;150&quot;&gt;
    &lt;Library&gt;

        &lt;Definition name=&quot;Selection&quot;&gt;
            &lt;Group d:userLabel=&quot;Symbol&quot;&gt;
                &lt;Group d:userLabel=&quot;Group_0&quot;&gt;
                    &lt;Path winding=&quot;evenOdd&quot;
                    data=&quot;M 8 4 C 8 4 15 4 15 4 L 15 0 L 27 8 L 15 15 L 15 11 L 8 11 L 8 11 L 8 11 L 0 11 C 0 11 0 11 0 11 C 0 7 3 4 8 4 Z &quot;
                    blendMode=&quot;normal&quot; alpha=&quot;1&quot;&gt;
                        &lt;fill&gt;
                            &lt;SolidColor color=&quot;#b8b3af&quot;/&gt;
                        &lt;/fill&gt;
                    &lt;/Path&gt;
                &lt;/Group&gt;
            &lt;/Group&gt;
        &lt;/Definition&gt;
    &lt;/Library&gt;
    &lt;Selection x=&quot;0&quot; y=&quot;0&quot; /&gt;
&lt;/Graphic&gt;
</pre>
<p>Copiez le data du noeud &lt;Path /&gt;, et utilisez le dans votre skin comme dans cette exemple : </p>
<pre class="brush: xml">
&lt;s:Path
    top=&quot;0&quot; left=&quot;0&quot;
    data=&quot;M 8 4 C 8 4 15 4 15 4 L 15 0 L 27 8 L 15 15 L 15 11 L 8 11 L 8 11 L 8 11 L 0 11 C 0 11 0 11 0 11 C 0 7 3 4 8 4 Z &quot;&gt;

    &lt;s:fill&gt;
        &lt;s:LinearGradient rotation=&quot;90&quot;&gt;
            &lt;s:GradientEntry color.selected=&quot;#FCD301&quot; color=&quot;#F7F7F7&quot; ratio=&quot;0&quot; /&gt;
            &lt;s:GradientEntry color.selected=&quot;#F19000&quot; color=&quot;#C2C6C7&quot; ratio=&quot;1&quot; /&gt;
        &lt;/s:LinearGradient&gt;
    &lt;/s:fill&gt;
    &lt;s:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot;
            distance=&quot;1&quot;
            blurX=&quot;4&quot; blurY=&quot;4&quot; quality=&quot;3&quot;
            alpha=&quot;0.8&quot; /&gt;
    &lt;/s:filters&gt;

&lt;/s:Path&gt;
</pre>
<h3>Et maintenant?</h3>
<p>L’idée serait de pouvoir créer des primitives, spécialisées ou non, utilisables dans un contexte de composants très précis, comme la primitive EazeElement du dernier article; ou dans une perspective plus globale, type librairie&#8230; Allons-y <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Un trou dans mon Rectangle</h2>
<p>Il peut être intéressant dans certains cas d’avoir un “trou” dans un rectangle. Pour créer par exemple une bordure qui pourrait avoir un Stroke ET un Fill. C’est ce que j’ai fais ici.</p>
<p>Pour obtenir un rectangle “troué” avec l’api de dessin, c’est extrêmement simple : il suffit de dessiner 2 rectangles l’un dans l’autre, à la suite : les points de vecteurs faisant partie du même chemin, cela génère l’exclusion du rectangle 2 dans le rectangle 1.<br />
<center></p>
<table>
<tr>
<td><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/forme1-150x150.png" alt="forme1" title="forme1" width="150" height="150" class="aligncenter size-thumbnail wp-image-1462" /></td>
<td><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/forme2-150x150.png" alt="forme2" title="forme2" width="150" height="150" class="aligncenter size-thumbnail wp-image-1463" /></td>
</tr>
</table>
<p></center><br />
Bon c’est une méthode rapide, mais qui est suffisante pour nos besoin&#8230; Nous ne sommes pas en train de coder un outil de Pathfinding !</p>
<h3>Dessin de rectangle</h3>
<p>Au lieu d’utiliser les méthodes de dessin de rectangle fournies par Flex, j’utilise celle proposée par <a href="http://twitter.com/elsassph">Philippe Elsass</a>. Performante, elle m’évite de recourir au méthode de base, qui lance des contrôles de positions évitable.<br />
Pour plus d’information sur son fonctionnement, je vous invite à vous rendre <a href="http://philippe.elsass.me/2009/05/as3-rounding-corners/">sur cette explication</a>.</p>
<p>La méthode utlisée dans la librairie, que j&#8217;expose ci-après, <a href="http://www.lafabrick.com/projects/uigfx-lib/sample/srcview/source/uigfx/src/com/lafabrick/uigfx/utils/UigfxUtils.as.html">derrière ce lien</a>.</p>
<h3>La primitive ExclusionRect</h3>
<p>Donc nous avons besoin de 2 rectangles. Le premier est celui qui correspond aux contraintes de positionnement de base de la primitive. J’utilise une petite méthode getOutterVectorPoint qui me renvoie le vecteur définissant les points de ce rectangle. Le second rectangle, celui définissant la zone à exclure, à lui besoin de contraintes spécifiques, que j’ai ajouté dans la classe (innerTop, innerRight, innerLeft, innerBottom). la méthode getInnerVectorPoint remplit la même fonction que getOutterVectorPoint. Dans l’override de la méthode draw, celle qui “dessine”, les 2 rectangles sont créés l’un après l‘autre. Cela donne : </p>
<pre class="brush: js">
/**
 * Return the Vector of Point for the rectangle
 */
protected function getOutterVectorPoint() : Vector.&lt;Point&gt;
{
    var vector : Vector.&lt;Point&gt; = new Vector.&lt;Point&gt;();
    vector.push( new Point( drawX, drawY ) );
    vector.push( new Point( drawX+width, drawY ) );
    vector.push( new Point( drawX+width, drawY+height ) );
    vector.push( new Point( drawX, drawY+height ) );
    return vector;
}
/**
 * Return the Vector of Point for the inner rectangle
 */
protected function getInnerVectorPoint() : Vector.&lt;Point&gt;
{
    var vector : Vector.&lt;Point&gt; = new Vector.&lt;Point&gt;();
    vector.push( new Point( drawX+innerLeft, drawY+innerTop ) );
    vector.push( new Point( drawX+width-innerRight, drawY+innerTop ) );
    vector.push( new Point( drawX+width-innerRight, drawY+height-innerBottom) );
    vector.push( new Point( drawX+innerLeft, drawY+height-innerBottom ) );
    return vector;
}

/**
 * Draw the rectangle
 * @see com.lafabrick.uigfx.utils.UigfxUtils
 */
override protected function draw(g:Graphics) : void
{
    UigfxUtils.drawRoundPath( g, getOutterVectorPoint(), radius, true );

    if( enableExclusion ) {
        UigfxUtils.drawRoundPath( g, getInnerVectorPoint(), innerRadius, true );
    }
}
</pre>
<h3>Utilisation</h3>
<p>L’utilisation est très proche de celle de Rect, avec les contraintes et radius intérieur : </p>
<pre class="brush: xml">
&lt;primitives:ExclusionRect id=&quot;excl&quot;
    radius=&quot;10&quot;
    innerRadius=&quot;30&quot;
    top=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot; bottom=&quot;0&quot;
    innerTop=&quot;0&quot; innerBottom=&quot;20&quot; innerLeft=&quot;0&quot; innerRight=&quot;20&quot;&gt;

    &lt;primitives:fill&gt;
        &lt;s:SolidColor color=&quot;#353535&quot; /&gt;

    &lt;/primitives:fill&gt;
    &lt;primitives:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot; inner=&quot;false&quot; distance=&quot;1&quot;
            blurX=&quot;4&quot; blurY=&quot;4&quot;
            quality=&quot;3&quot; alpha=&quot;0.8&quot; /&gt;
    &lt;/primitives:filters&gt;

&lt;/primitives:ExclusionRect&gt;
</pre>
<p><a href="http://www.lafabrick.com/projects/uigfx-lib/sample/srcview/source/uigfx/src/com/lafabrick/uigfx/primitives/ExclusionRect.as.html">La classe complète de la primitive</a></p>
<p><center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/excludedrect.png" alt="excludedrect" title="excludedrect" width="239" height="238" class="aligncenter size-full wp-image-1458" /></center></p>
<h2>Dessine moi une forme !</h2>
<p>Une primitive qui me manque est celle permettant de dessiner une forme, à la manière de Path, mais en définissant un tableau de points. Quelque chose qui ressemble à ça : </p>
<pre class="brush: xml">
&lt;primitives:PointsPath
    radius=&quot;60&quot; width=&quot;100%&quot; height=&quot;100%&quot;
    horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot;&gt;

    &lt;primitives:points&gt;
        &lt;mx:Point x=&quot;100&quot; y=&quot;0&quot; /&gt;
        &lt;mx:Point x=&quot;125&quot; y=&quot;75&quot; /&gt;
        &lt;mx:Point x=&quot;200&quot; y=&quot;75&quot; /&gt;
        &lt;mx:Point x=&quot;140&quot; y=&quot;125&quot; /&gt;
        &lt;mx:Point x=&quot;160&quot; y=&quot;200&quot; /&gt;
        &lt;mx:Point x=&quot;100&quot; y=&quot;155&quot; /&gt;
        &lt;mx:Point x=&quot;40&quot; y=&quot;200&quot; /&gt;
        &lt;mx:Point x=&quot;60&quot; y=&quot;125&quot; /&gt;
        &lt;mx:Point x=&quot;0&quot; y=&quot;75&quot; /&gt;
        &lt;mx:Point x=&quot;75&quot; y=&quot;75&quot; /&gt;
    &lt;/primitives:points&gt;

    &lt;primitives:fill&gt;
        &lt;s:SolidColor color=&quot;#222222&quot; /&gt;
    &lt;/primitives:fill&gt;

    &lt;primitives:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot; inner=&quot;true&quot; distance=&quot;1&quot;
            blurX=&quot;4&quot; blurY=&quot;4&quot;
            quality=&quot;3&quot; alpha=&quot;0.8&quot; /&gt;
    &lt;/primitives:filters&gt;

&lt;/primitives:PointsPath&gt;
</pre>
<p>Bien, mais pas suffisant.<br />
Dans ce premier essai, les points sont définis “statiquement”. Une utilisation parfaite pour moi d’une telle primitive serait de pouvoir définir des contraintes de placement sur les points (top, verticalCenter, bottom et left, horizontalCenter, right), par rapport à la primitive.</p>
<p>J’ai donc fait une classe ConstraintPoint.</p>
<h3>ConstraintPoint : un point “contraint”</h3>
<p>Cette classe toute simple, extension de Point, dispose de propriétés de placement, en getter/setter : top, left, bottom, right, horizontalCenter, verticalCenter. Une méthode getConstraintPoint() renvoie un point x/y, calculer par rapport à une cible GraphicElement, en tenant compte des contraintes de placement. J’ai préféré avoir ce type de fonctionnement, plutôt que d’avoir le couple x/y directement modifié lors du set des différentes propriétés de contraintes. </p>
<p>Une primitive se dessine par rapport à son positionnement global. GraphicElement fournit les propriétés protégés drawX et drawY, qui donne les positions x/y de la primitive de manière global, par rapport à l’application. </p>
<p>La méthode getConstraintPoint() doit donc renvoyer le point par rapport à l’application. GraphicElement fournit tout la mécanique de calcul nécessaire, notamment l’objet postLayoutTransformOffsets, qui contient la position globale de la primitive.</p>
<p>La méthode en question :</p>
<pre class="brush: js">
public function getConstraintPoint( graphicElement : GraphicElement ) : Point
{
    var px : Number = 0;
    var py : Number = 0;

    var xOffset : Number;
    var yOffset : Number;

    if (graphicElement.displayObjectSharingMode ==
                        DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT) {
        xOffset = 0;
        yOffset = 0;
    }
    else {
        xOffset = graphicElement.postLayoutTransformOffsets ?
                        graphicElement.x + graphicElement.postLayoutTransformOffsets.x : graphicElement.x;
        yOffset = graphicElement.postLayoutTransformOffsets ?
                        graphicElement.y + graphicElement.postLayoutTransformOffsets.y : graphicElement.y;
    }

    // Calcutates y position
    if( !isNaN( top ) ) {
        py = yOffset + top;
    }
    else if( !isNaN( bottom ) ) {
        py = yOffset + graphicElement.height - bottom;
    }
    else if( !isNaN( verticalCenter ) ) {
        py = ( yOffset + graphicElement.height ) / 2 + verticalCenter;
    }
    else {
        py = yOffset + y;
    }

    // Calcutates x position
    if( !isNaN( left ) ) {
        px = xOffset + left;
    }
    else if( !isNaN( right ) ) {
        px = xOffset + graphicElement.width - right;
    }
    else if( !isNaN( horizontalCenter ) ) {
        px = ( xOffset + graphicElement.width ) / 2 + horizontalCenter;
    }
    else {
        px = xOffset + x;
    }

    return new Point( px, py );
}
</pre>
<p>La classe complète ce trouve <a href="http://www.lafabrick.com/projects/uigfx-lib/sample/srcview/source/uigfx/src/com/lafabrick/uigfx/geom/ConstraintPoint.as.html">derrière ce lien.</a></p>
<p>Intéressons nous maintenant à la primitive.</p>
<h3>Primitive PointsPath</h3>
<p>J’utilise toujours la méthode de dessin drawRoundPath, contenu dans ma classe static UigfxUtils.</p>
<p>Ici, la classe étend FilledElement. Une propriété points, définit les différents points de type ConstraintPoint de la primitive. J’utilise ici un vecteur comme conteneur des points : Vector.&lt;ConstraintPoint&gt;. Le “set” de cette propriété appelle invalidateDisplayList(), afin de lancer le processus de dessin de la forme.</p>
<p>La méthode draw parcour le vecteur de points ConstraintPoint, appelle pour chacun sa méthode getConstraintPoint, et pousse le point dans un vecteur. C’est ce vecteur qui est utilisé par drawRoundPath.</p>
<p>Le code de cette mécanique : </p>
<pre class="brush: js">
public function get points():Vector.&lt;ConstraintPoint&gt;
{
    return _points;
}

/**
 * @private
 */
public function set points(value:Vector.&lt;ConstraintPoint&gt;):void
{
    _points = value;
    invalidateDisplayList();
}

/**
 * Draw the path
 * &lt;p&gt;Drawing method is static, in UiGfxUtils&lt;/p&gt;
 * @see com.lafabrick.uigfx.utils.UiGfxUtils
 */
override protected function draw(g:Graphics) : void
{
    // replace points from local to global position
    var vectorPoint : Vector.&lt;Point&gt; = new Vector.&lt;Point&gt;();
    for each( var point : ConstraintPoint in points ) {
        vectorPoint.push( point.getConstraintPoint( this ) );
    }
    // launch drawing method
    UigfxUtils.drawRoundPath( g, vectorPoint, radius, true );
}
</pre>
<p><a href="http://www.lafabrick.com/projects/uigfx-lib/sample/srcview/source/uigfx/src/com/lafabrick/uigfx/primitives/PointsPath.as.html">La classe PointsPath en entier</a></p>
<h3>Utilisation</h3>
<p>Reprenons l’exemple, avec cette primitive et les contraintes de placement : </p>
<pre class="brush: xml">
&lt;primitives:PointsPath
    radius=&quot;60&quot; width=&quot;100%&quot; height=&quot;100%&quot;
    horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot;&gt;

    &lt;primitives:points&gt;
        &lt;geom:ConstraintPoint top=&quot;0&quot; horizontalCenter=&quot;0&quot; /&gt;
        &lt;geom:ConstraintPoint horizontalCenter=&quot;25&quot; verticalCenter=&quot;-25&quot;/&gt;
        &lt;geom:ConstraintPoint right=&quot;0&quot; verticalCenter=&quot;-25&quot; /&gt;
        &lt;geom:ConstraintPoint horizontalCenter=&quot;40&quot; verticalCenter=&quot;25&quot; /&gt;
        &lt;geom:ConstraintPoint right=&quot;40&quot; bottom=&quot;0&quot; /&gt;
        &lt;geom:ConstraintPoint horizontalCenter=&quot;0&quot; verticalCenter=&quot;40&quot; /&gt;
        &lt;geom:ConstraintPoint left=&quot;40&quot; bottom=&quot;0&quot; /&gt;
        &lt;geom:ConstraintPoint horizontalCenter=&quot;-40&quot; verticalCenter=&quot;25&quot; /&gt;
        &lt;geom:ConstraintPoint left=&quot;0&quot; verticalCenter=&quot;-25&quot; /&gt;
        &lt;geom:ConstraintPoint horizontalCenter=&quot;-25&quot; verticalCenter=&quot;-25&quot; /&gt;
    &lt;/primitives:points&gt;

    &lt;primitives:fill&gt;
        &lt;s:SolidColor color=&quot;#222222&quot; /&gt;
    &lt;/primitives:fill&gt;

    &lt;primitives:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot; inner=&quot;true&quot; distance=&quot;1&quot;
            blurX=&quot;4&quot; blurY=&quot;4&quot;
            quality=&quot;3&quot; alpha=&quot;0.8&quot; /&gt;
    &lt;/primitives:filters&gt;

&lt;/primitives:PointsPath&gt;
</pre>
<p><center> </p>
<table>
<tr>
<td><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/starstd-150x150.png" alt="starstd" title="starstd" width="150" height="150" class="aligncenter size-thumbnail wp-image-1459" /></td>
<td><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/12/startextended-150x150.png" alt="startextended" title="startextended" width="150" height="150" class="aligncenter size-thumbnail wp-image-1460" /></td>
</tr>
</table>
<p></center></p>
<p>La forme respecte les contraintes de placement, en fonction de l’évolution de la taille de la primitive. Amazing ! <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
L&#8217;exemple complet (les sources au clic droit), <a href="http://www.lafabrick.com/projects/uigfx-lib/sample/">ce cache sous ce lien</a>.</p>
<h2>Librairie Uigfx</h2>
<p>Tout ce que je viens d’exposer fait partie d’une librairie nommée par <a href="http://twitter.com/rick_lafabrick">Erick</a> &laquo;&nbsp;uigfx&nbsp;&raquo;.<br />
Cette petite librairie, sera bientôt disponible publiquement sur le svn lafabrick. Vous pouvez d’ores et déjà <a href="http://www.lafabrick.com/projects/uigfx-lib/project/uigfx.fxpl">télécharger le projet</a> (format .fxpl), dans la version proposée dans cette article. La documentation ( en anglais&#8230; pas parfait ! ) <a href="http://www.lafabrick.com/projects/uigfx-lib/apidoc/">est disponible là</a>.</p>
<p>[UPDATE]<br />
Le projet uigfx a maintenant sa page sur <a href="http://code.google.com/p/uigfx/">google code</a>. Pour plus d&#8217;information, <a href="http://www.lafabrick.com/blog/2010/02/09/1559-uigfx-project-flex4-primitives-fireworks-extension/">la présentation de ce projet</a>.<br />
[/UPDATE]</p>
<p>Je vous laisse la place sur le fil de commentaire !</p>
<p>Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2006/11/16/19-petit-cour-sur-lapi-de-dessin/" rel="bookmark" title="16 novembre 2006">Petit cours sur l’API de dessin</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/11/27/1373-flex4-custom-component-skinnig/" rel="bookmark" title="27 novembre 2009">Flex4 : composant personnalisé et skinning</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/02/09/1964-uigfx-project-flex4-primitives-library-fireworks-extension/" rel="bookmark" title="9 février 2010">uigfx project : Flex4 primitives library / Fireworks extension</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/07/14/1920-flex-4-layouts-viewstack-pure-spark/" rel="bookmark" title="14 juillet 2010">Flex 4 et les layouts &#8211; Faire une ViewStack &laquo;&nbsp;pure&nbsp;&raquo; Spark</a></li>
</ul>
<p><!-- Similar Posts took 12.923 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/12/04/1453-flex4-skin-et-primitives/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flex4 : composant personnalisé et skinning</title>
		<link>http://www.lafabrick.com/blog/2009/11/27/1373-flex4-custom-component-skinnig/</link>
		<comments>http://www.lafabrick.com/blog/2009/11/27/1373-flex4-custom-component-skinnig/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 16:49:45 +0000</pubDate>
		<dc:creator>Fabien</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[FlashBuilder]]></category>
		<category><![CDATA[flex4]]></category>
		<category><![CDATA[skinning]]></category>
		<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[UI Design]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=1373</guid>
		<description><![CDATA[Je vous propose un petit tour d’horizon de la création de compo personnalisés avec Flex4 et le skinning. Vous allez voir ! Comme moi, vous ne voudrez plus jamais faire de Flex3. Moi ça fait 5 mois&#8230; et j’en suis bien content ! Alors voila. Nous allons voir comment faire un composant personnalisé avec le [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/11/backcompo.jpg" alt="backcompo" title="backcompo" width="520" height="132" class="aligncenter size-full wp-image-1419" /></center><br />
Je vous propose un petit tour d’horizon de la création de compo personnalisés avec Flex4 et le skinning. Vous allez voir ! Comme moi, vous ne voudrez plus jamais faire de Flex3. Moi ça fait 5 mois&#8230; et j’en suis bien content !<br />
<span id="more-1373"></span><br />
Alors voila. Nous allons voir comment faire un composant personnalisé avec le SDK4, de la conception actionScript, au skinning.<br />
Il me fallait une idée de départ&#8230; Ceux qui me suivent sur <a href="http://twitter.com/fabienbizot">Twitter</a> aurons vu/lu qu’en ce moment je m’éclate avec <a href="http://philippe.elsass.me/2009/11/as3-eaze-tween-library-update/">Eaze</a>, la librairie d’animation de <a href="http://twitter.com/elsassph">Philippe Elsass</a>. Super légère, facile d’utilisation et performante (<a href="http://twitter.com/nicoptere">Nicoptère</a> a réalisé <a href="http://en.nicoptere.net/?p=632">quelques “petites” démos</a> sur le sujet). Je ne saurais que trop vous la conseiller.<br />
Et bien on va se faire un petit compo de visualisation de ces fonctions d’animations <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Première étapes : la primitive étendue</h2>
<p>Avant de partir sur le composant, nous allons d’abord faire une extension de <a href="http://help.adobe.com/en_US/Flex/4.0/langref/spark/primitives/supportClasses/StrokedElement.html">StrokedElement</a>, qui va se charger de dessiner les courbes d’animations.</p>
<p>La classe StrokedElement est, dans Flex4, la classe de base pour tous les éléments graphiques ayant à dessiner une ligne. FilledElement, extensions de StrokedElement, s’occupe du remplissage. Les classes Line, Rect, Ellipse, Path&#8230; sont elles mêmes des extensions de FilledElement.</p>
<p>Nous allons donc créer une classe EazeElement, qui étend StrokedElement.<br />
L’idée ici n’est pas d’afficher la “vraie” courbe d’accélération, mais plutôt d’avoir une “information visuelle” qui nous donne une idée sur l’évolution de l’animation, avec un point de départ et d’arrivé identique&#8230; Le voir en vrai c’est plus simple qu’à expliquer&#8230;</p>
<p>Nous allons associer à cette primitive 2 propriétés : <strong>eazeFunction</strong> : la fonction d’animation a tracer, et <strong>step</strong> la “précision” de la ligne.</p>
<p>Ensuite, il suffit d’overrider la méthode <strong>draw</strong>, et de faire ce que l’on veut dedans.<br />
En gros nous allons boucler sur la largeur de l’élément, en se décalant à chaque passe de la valeur step, et calculer la position x, y de notre ligne en fonction de eazeFunction&#8230;. <a href="http://www.lafabrick.com/labz/eazeViewer/srcview/source/com/lafabrick/primitives/EazeElement.as.html">Vous pouvez voir en vrai la classe sous ce lien</a>.</p>
<p>Aller hop on test tout ça ! Pour l’apparence, nous ajoutons à notre élément un “IStroke”. Cela peut être, &lt;s:SolidColorStroke /&gt;, &lt;s:LinearGradientStroke /&gt;, &#8230; Y’en à d’autres : à vous de tester !</p>
<pre class="brush: xml">
&lt;primitives:EazeElement
    eazeFunction=&quot;Elastic.easeInOut&quot; step=&quot;2&quot;
    horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot; width=&quot;400&quot; height=&quot;200&quot;&gt;

    &lt;primitives:stroke&gt;

        &lt;s:LinearGradientStroke rotation=&quot;90&quot;&gt;
            &lt;s:GradientEntry color=&quot;#F19000&quot; /&gt;
            &lt;s:GradientEntry color=&quot;#00FF00&quot; /&gt;
            &lt;s:GradientEntry color=&quot;#009EE0&quot; /&gt;
        &lt;/s:LinearGradientStroke&gt;

    &lt;/primitives:stroke&gt;

&lt;/primitives:EazeElement&gt;
</pre>
<p><center><img class="aligncenter size-full wp-image-1385" title="eaze element" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/11/imageeazeelt.jpg" alt="eaze element" width="400" height="132" /><br />
Rhooo ! C&#8217;est jouli !</center></p>
<h2>C’est parti pour le composant</h2>
<p>Notre composant va étendre SkinnableContainer, base pour la création de composant.</p>
<pre class="brush: js">
package com.lafabrick.components
{
    public class SimpleEazeViewer extends SkinnableContainer
    ...
</pre>
<p>Nous voulons utiliser notre primitive EazeElement dans ce compo. Il pourra aussi être redimensionnable, via une “ancre”. Nous devons donc définir ces différents objets de contrôles, dans la définition de notre composant. Nous utilisons ici les SkinPart.</p>
<h3>SkinPart</h3>
<p>Une skinPart définit un objet, visuel ou non, devant être présent (de manière obligatoire ou non) dans la skin. Ajoutons nos parties :</p>
<pre class="brush: js">
public class SimpleEazeViewer extends SkinnableContainer
{
    [SkinPart(required=&quot;false&quot;)]
    public var anchor : Group;

    [SkinPart(required=&quot;true&quot;)]
    public var eazeElement : EazeElement;
</pre>
<p>ici, eazeElement est requis et obligatoire. anchor, l’ancre pour redimensionner le composant, par contre est optionnel.</p>
<p>Nous verrons plus bas comment les utiliser dans le composant. Occupons nous des états de ce composant.</p>
<h3>SkinState</h3>
<p>SkinnableContainer définit 2 états de base : “normal” et “disabled”. Ces états devront être présents dans la skin. Nous allons ajouter un état “selected” : lorsque l’utilisateur déplacera l’ancre, le composant passera en état “selected”. Pour ajouter un état personnalisé, dans l’en-tête de classe, ajoutons le tag suivant :</p>
<pre class="brush: js">
[SkinState(name=&quot;selected&quot;)]
</pre>
<p>Nous allons également créer une propriété selected, qui définira si le composant est sélectionné&#8230;</p>
<p>dans le setter, nous allons appeler la fonction invalidateSkinState(), qui va déclencher le processus de changement d’état. Pour relier la propriété selected à l’état sélectionner, nous devons overrider la fonction protégée getCurrentSkinState().</p>
<pre class="brush: js">
private var _selected : Boolean = false;

public function get selected():Boolean
{
    return _selected;
}

public function set selected(value:Boolean):void
{
    _selected = value;
    invalidateSkinState();
}

override protected function getCurrentSkinState() : String
{
    return selected ? &quot;selected&quot; : &quot;normal&quot;;
}
</pre>
<p>Ajoutons enfin la dernière propriété eazeFonction : Function qui va nous permettre de définir la fonction à tracer par la primitive.</p>
<h3>Overridons un brin</h3>
<p>Il est temps de passer à la gestion de tout ça. Ce que l’on a besoin, c’est de savoir quand les différents éléments définit dans les SkinPart sont ajoutés, pour leur pousser les propriétés et autres écouteurs qui vont bien. Pour cela, nous devons overrider la méthode partAdded de la manière suivante.</p>
<pre class="brush: js">
override protected function partAdded(partName:String, instance:Object) : void
{
    super.partAdded( partName, instance );

    if( instance == eazeElement ) {
        eazeElement.eazeFunction = eazeFunction;
    }

    if( instance == anchor ) {
        anchor.addEventListener(MouseEvent.MOUSE_DOWN, onAnchorMouseDown );
        systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_UP, onMouseUp );
        systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove );
    }
}
</pre>
<p>Dans le sens inverse, il faut overrider partRemoved pour, entre autre chose, enlever les écouteurs sur les éléments.</p>
<pre class="brush: js">
override protected function partRemoved(partName:String, instance:Object) : void
{
    super.partRemoved( partName, instance );

    if( instance == anchor ) {
        anchor.removeEventListener(MouseEvent.MOUSE_DOWN, onAnchorMouseDown );
        systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, onMouseUp );
        systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove );
    }
}
</pre>
<p>Plus qu’à mettre la mécanique dans les fonctions qui vont bien.</p>
<p><a href="http://www.lafabrick.com/labz/eazeViewer/srcview/source/com/lafabrick/components/SimpleEazeViewer.as.html">La classe complète ici</a></p>
<p>plutôt super simple ce fonctionnement !</p>
<h2>Côté skin</h2>
<h3>Skin ou SparkSkin ?</h3>
<p>Vous avez 2 possibilités : partir de Skin ou SparkSkin, la dernière étant une extension de la première. La différence est que SparkSkin ajoute une mécanique spéciale pour exclure des éléments de la mécanique de skinning. Dans Flex4 vous pouvez injecter des couleurs de base à vos skin, avec la propriété baseColor. L’exclusion permet d’éviter de coloriser les éléments sélectionnés. Je vous invite a faire un saut dans les classes Skin des boutons (ex: spark.skins.spark.ToggleButtonSkin ) pour voir à quoi cela ressemble.</p>
<p>Nous allons choisir Skin.</p>
<h3>Pointer sur le composant cible</h3>
<p>En premier lieu, nous devons spécifier quel est le composant cible de cette skin. Cela se passe dans le tag metadata :</p>
<pre class="brush: xml">
&lt;fx:Metadata&gt;
    [HostComponent(&quot;com.lafabrick.components.SimpleEazeViewer&quot;)]
&lt;/fx:Metadata&gt;
</pre>
<h3>Les états</h3>
<p>Nous devons aussi retrouver les états définit dans le composants : normal, disabled et selected :</p>
<pre class="brush: xml">
&lt;s:states&gt;
    &lt;s:State name=&quot;normal&quot; /&gt;
    &lt;s:State name=&quot;selected&quot; /&gt;
    &lt;s:State name=&quot;disabled&quot; /&gt;
&lt;/s:states&gt;
</pre>
<p>Plus qu’a ajouter vos éléments définit dans les skinPart (un Group avec l’id “anchor” et un EazeElement avec l’id “eazeElement” ). Et puis vous amusez a faire de la déco à grand coup de Rect, Ellipse, Line, Path, &#8230;. La grande classe !<br />
Tout ces éléments se calibrent avec les contraintes top, left, bottom, right. Les possibilités sont infinies.</p>
<pre class="brush: xml">
&lt;s:Group id=&quot;anchor&quot; top=&quot;0&quot; bottom=&quot;0&quot; width=&quot;16&quot; right=&quot;0&quot;&gt;
    &lt;s:Rect
        topRightRadiusX=&quot;8&quot; topRightRadiusY=&quot;8&quot;
        bottomRightRadiusX=&quot;8&quot; bottomRightRadiusY=&quot;8&quot;
        top=&quot;0&quot; bottom=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot;&gt;
        &lt;s:fill&gt;
            &lt;s:SolidColor color=&quot;#212121&quot; alpha=&quot;0&quot; /&gt;
        &lt;/s:fill&gt;
    &lt;/s:Rect&gt;

    &lt;s:Group verticalCenter=&quot;0&quot; height=&quot;16&quot; horizontalCenter=&quot;0&quot;&gt;
        &lt;s:Line top=&quot;0&quot; bottom=&quot;0&quot; horizontalCenter=&quot;-2&quot;&gt;
            &lt;s:stroke&gt;
                &lt;s:SolidColorStroke color=&quot;#353535&quot; /&gt;
            &lt;/s:stroke&gt;
        &lt;/s:Line&gt;
        &lt;s:Line top=&quot;0&quot; bottom=&quot;0&quot; horizontalCenter=&quot;0&quot;&gt;
            &lt;s:stroke&gt;
                &lt;s:SolidColorStroke color=&quot;#353535&quot; /&gt;
            &lt;/s:stroke&gt;
        &lt;/s:Line&gt;
        &lt;s:Line top=&quot;0&quot; bottom=&quot;0&quot; horizontalCenter=&quot;2&quot;&gt;
            &lt;s:stroke&gt;
                &lt;s:SolidColorStroke color=&quot;#353535&quot; /&gt;
            &lt;/s:stroke&gt;
        &lt;/s:Line&gt;
    &lt;/s:Group&gt;	

&lt;/s:Group&gt;
</pre>
<h3>Pimp my State! inclusion, exclusion, groupage&#8230;.</h3>
<p>Voyons comment gérer notre skin en fonction de ses états.<br />
Le nouveau système de gestion d&#8217;états est bien loin de celui proposé dans Flex3. Plus simple et bien plus logique, il vous permet un contrôle total de votre skin.<br />
Admettons que vous ayez un composant avec les états suivants :</p>
<pre class="brush: xml">
&lt;s:states&gt;

    &lt;s:State name=&quot;up&quot; /&gt;
    &lt;s:State name=&quot;down&quot; /&gt;
    &lt;s:State name=&quot;over&quot; /&gt;
    &lt;s:State name=&quot;upAndSelected&quot; /&gt;
    &lt;s:State name=&quot;downAndSelected&quot; /&gt;
    &lt;s:State name=&quot;overAndSelected&quot; /&gt;
    &lt;s:State name=&quot;disabled&quot; /&gt;

&lt;/s:states&gt;
</pre>
<p>Un rectangle est définit dans la skin,  et doit être inclus dans les états &laquo;&nbsp;up&nbsp;&raquo;, &laquo;&nbsp;down&nbsp;&raquo;, &laquo;&nbsp;over&nbsp;&raquo;. La déclaration de l&#8217;inclusion, et des différentes couleurs en fonction des états devra se faire suivant cette exemple : </p>
<pre class="brush: xml">
&lt;s:Rect includeIn=&quot;over, down, up&quot; top=&quot;0&quot; bottom=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot;&gt;
    &lt;s:stroke&gt;
        &lt;s:SolidColorStroke color=&quot;#212121&quot; /&gt;
    &lt;/s:stroke&gt;

    &lt;s:fill&gt;
        &lt;s:LinearGradient rotation=&quot;90&quot;&gt;
            &lt;s:GradientEntry color.down=&quot;#FCD301&quot; color.over=&quot;#FCD301&quot; color=&quot;#F7F7F7&quot; ratio=&quot;0&quot; /&gt;
            &lt;s:GradientEntry color.down=&quot;#F19000&quot; color.over=&quot;#F19000&quot; color=&quot;#C2C6C7&quot; ratio=&quot;1&quot; /&gt;
        &lt;/s:LinearGradient&gt;
    &lt;/s:fill&gt;

    &lt;s:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot; distance=&quot;1&quot;
            blurX.over=&quot;10&quot; blurX.down=&quot;10&quot; blurX=&quot;4&quot;
            blurY.over=&quot;10&quot; blurY.down=&quot;10&quot; blurY=&quot;4&quot;
            quality=&quot;3&quot; alpha=&quot;0.8&quot; /&gt;
    &lt;/s:filters&gt;
&lt;/s:Rect&gt;
</pre>
<p>Vous pouvez voir ici que l&#8217;attribution de valeur en fonction des états fonctionne aussi bien sur des couleurs que sur n&#8217;importe quelle autre propriété, comme sur le filtre.</p>
<p>Les états proposent une mécanique de groupage par nom, qui vous permet de pousser encore plus loin la gestion de la skin. Un état peut faire partie de plusieurs groupes : </p>
<pre class="brush: xml">
&lt;s:states&gt;

    &lt;s:State name=&quot;up&quot; /&gt;
    &lt;s:State name=&quot;down&quot; stateGroups=&quot;mouseOn&quot; /&gt;
    &lt;s:State name=&quot;over&quot; stateGroups=&quot;mouseOn&quot; /&gt;
    &lt;s:State name=&quot;upAndSelected&quot;  stateGroups=&quot;selected, mouseOn&quot; /&gt;
    &lt;s:State name=&quot;downAndSelected&quot;  stateGroups=&quot;selected, mouseOn&quot; /&gt;
    &lt;s:State name=&quot;overAndSelected&quot; stateGroups=&quot;selected, mouseOn&quot; /&gt;
    &lt;s:State name=&quot;disabled&quot; /&gt;

&lt;/s:states&gt;
</pre>
<p>Les états down et over, en vue &laquo;&nbsp;normal&nbsp;&raquo; et &laquo;&nbsp;sélectionné&nbsp;&raquo; font partie d&#8217;un même groupe &laquo;&nbsp;mouseOn&nbsp;&raquo;. De même, les états sélectionnés sont regroupés dans un groupe &laquo;&nbsp;selected&nbsp;&raquo;.</p>
<p>Nous pouvons alors modifier la skin de notre rectangle. Au lieu de définir dans quel état le rectangle est présent, nous allons plutôt lui définir dans quels groupes d&#8217;états il est exclu : </p>
<pre class="brush: xml">
&lt;s:Rect excludeFrom=&quot;selected&quot; top=&quot;0&quot; bottom=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot;&gt;
</pre>
<p>De même, la définition des couleurs et des propriétés du filtre peut être affectée globalement en fonction du groupe d&#8217;état : </p>
<pre class="brush: xml">
&lt;s:Rect excludeFrom=&quot;selected&quot; top=&quot;0&quot; bottom=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot;&gt;
    &lt;s:stroke&gt;
        &lt;s:SolidColorStroke color=&quot;#212121&quot; color.mouseOn=&quot;#F7F7F7&quot; weight.mouseOn=&quot;2&quot; /&gt;
    &lt;/s:stroke&gt;

    &lt;s:fill&gt;
        &lt;s:LinearGradient rotation=&quot;90&quot;&gt;
            &lt;s:GradientEntry color.mouseOn=&quot;#FCD301&quot; color=&quot;#F7F7F7&quot; ratio=&quot;0&quot; /&gt;
            &lt;s:GradientEntry color.mouseOn=&quot;#F19000&quot; color=&quot;#C2C6C7&quot; ratio=&quot;1&quot; /&gt;
        &lt;/s:LinearGradient&gt;
    &lt;/s:fill&gt;

    &lt;s:filters&gt;
        &lt;s:DropShadowFilter color=&quot;#000000&quot; distance=&quot;1&quot;
            blurX.mouseOn=&quot;10&quot; blurX=&quot;4&quot;
            blurY.mouseOn=&quot;10&quot; blurY=&quot;4&quot;
            quality=&quot;3&quot; alpha=&quot;0.8&quot; /&gt;
    &lt;/s:filters&gt;
&lt;/s:Rect&gt;
</pre>
<p>Le rectangle est exclu des états sélectionnés, et les couleurs sont attribuées en fonction du groupe définissant une interaction de l&#8217;utilisateur &laquo;&nbsp;mouseOn&nbsp;&raquo;.</p>
<p>Sympa non?</p>
<h3>Je veux mon composant !</h3>
<p>Vous pouvez bien sur accéder a votre composant via hostComponent : si par exemple vous définissez un texte dans votre composant, vous avez possibilité de l’affecter directement dans votre skin comme ceci :</p>
<pre class="brush: xml">
&lt;s:Label id=&quot;labelDisplay&quot;

    text=&quot;{hostComponent.monTitre}&quot;

    textAlign=&quot;center&quot;
    verticalAlign=&quot;middle&quot;
    maxDisplayedLines=&quot;1&quot;
    horizontalCenter=&quot;0&quot; verticalCenter=&quot;1&quot;
    left=&quot;10&quot; right=&quot;10&quot; top=&quot;2&quot; bottom=&quot;2&quot; /&gt;
</pre>
<h3>Bon a savoir : le contentGroup</h3>
<p>SkinnableContainer définit un Group optionnel, contentGroup, qui, comme son nom l’indique est le groupe du contenu <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ce groupe est le réceptacle des différents éléments que vous pouvez ajouter a votre compo. Par exemple un Panel dispose de ce contentGroup. Sinon on met rien dedans et ce ne serait plus un Panel&#8230;. Bon nous n’en avons pas besoin ici, mais si jamais vous avez besoin d’un composant qui peut être aussi un réceptacle de composants, n’oublier pas le contentGroup !</p>
<h3>Retournons à notre compo&#8230;</h3>
<p>&#8230; et regardons<a href="http://www.lafabrick.com/labz/eazeViewer/srcview/source/com/lafabrick/skins/SimpleEazeViewerSkin.mxml.html"> la skin complète.</a></p>
<h2>Un peu plus loin&#8230;</h2>
<p>Imaginons maintenant que vous ne vouliez plus afficher une courbe mais plusieurs à la suite, définit dans un tableau. Vous n’aurez donc plus un eazeElement, mais un Group qui contiendra vos primitives.<br />
Le problème alors est de pouvoir skinner le trait de vos primitives. Vous devrez donc définir un IStroke. Ce qui est intéressant dans ce nouveau système de skin, c’est qu’il est aussi possible de définir ce Stroke, pourtant élément non visuel, dans une SkinPart.</p>
<pre class="brush: js">
[SkinPart(required=&quot;false&quot;)]
public var anchor : Group;

[SkinPart(required=&quot;true&quot;)]
public var eazeGroup : Group;

[SkinPart(required=&quot;true&quot;)]
public var eazeStroke : IStroke;
</pre>
<p>La déclaration côté Skin ce fera a l’intérieur des balises déclaration :</p>
<pre class="brush: xml">
&lt;fx:Metadata&gt;
    [HostComponent(&quot;com.lafabrick.components.MultipleEazeViewer&quot;)]
&lt;/fx:Metadata&gt;

&lt;fx:Declarations&gt;
    &lt;s:LinearGradientStroke id=&quot;eazeStroke&quot; rotation=&quot;90&quot;&gt;
        &lt;s:GradientEntry color=&quot;#F19000&quot; /&gt;
        &lt;s:GradientEntry color=&quot;#00FF00&quot; /&gt;
        &lt;s:GradientEntry color=&quot;#009EE0&quot; /&gt;
    &lt;/s:LinearGradientStroke&gt;
&lt;/fx:Declarations&gt;
</pre>
<p>La nouvelle classe, <a href="http://www.lafabrick.com/labz/eazeViewer/srcview/source/com/lafabrick/components/MultipleEazeViewer.as.html">se cache derrière ce lien</a>, et la skin associée <a href="http://www.lafabrick.com/labz/eazeViewer/srcview/source/com/lafabrick/skins/MultipleEazeViewerSkin.mxml.html">derrière celui-ci</a>.</p>
<p><center><a href="http://www.lafabrick.com/labz/eazeViewer/"><img class="aligncenter size-full wp-image-1384" title="compos final" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/11/composfinal-1.jpg" alt="compos final" width="513" height="551" /></a></center></p>
<p><center><a href="http://www.lafabrick.com/labz/eazeViewer/">La démo finale</a> (<a href="http://www.lafabrick.com/labz/eazeViewer/srcview/index.html"> les sources</a> )</center><br />
J’espère que comme moi vous tomberez sous le charme. C’est fou comme une évolution peut vous montrer à quel point c’était tout nul avant !Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2009/12/04/1453-flex4-skin-et-primitives/" rel="bookmark" title="4 décembre 2009">Flex4 : skin et primitives</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/07/14/1920-flex-4-layouts-viewstack-pure-spark/" rel="bookmark" title="14 juillet 2010">Flex 4 et les layouts &#8211; Faire une ViewStack &laquo;&nbsp;pure&nbsp;&raquo; Spark</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/05/04/1962-uigfx-practice-a-circularslider-component-2/" rel="bookmark" title="4 mai 2010">UIGFX practice : a CircularSlider component</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/03/05/1675-proches-de-lohio-les-etats-esthetes-de-flex4/" rel="bookmark" title="5 mars 2010">Proches de l&#8217;Ohio??? Les états esthètes de Flex4</a></li>
</ul>
<p><!-- Similar Posts took 12.608 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/11/27/1373-flex4-custom-component-skinnig/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Hello AFCS ( bye Cocomo ) : première application multi-utilisateurs</title>
		<link>http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/#comments</comments>
		<pubDate>Sat, 31 Jan 2009 21:48:24 +0000</pubDate>
		<dc:creator>Erick</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[cocomo]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[interactivité]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=1040</guid>
		<description><![CDATA[[ 5 mars 2009 : Mise à jour de l'article : Cocomo devient AFCS et passe en version 0.9.1, corrigeant quelques bugs ] Dans ce 1er exemple d’application Cocomo Adobe Flash Collaboration Services aka A.F.C.S, nous allons développer, à vrai dire «&#160;assembler&#160;», une application de visioconférence intégrant un tchat, des notes partagées et un gestionnaire [...]]]></description>
			<content:encoded><![CDATA[<p>[ 5 mars 2009 : Mise à jour de l'article : <del datetime="2009-03-05T19:23:22+00:00">Cocomo</del> devient AFCS et passe en version 0.9.1, corrigeant quelques bugs ]</p>
<p>Dans ce 1er exemple d’application <del datetime="2009-03-05T19:23:22+00:00">Cocomo</del> <strong>Adobe Flash Collaboration Services</strong> aka <strong>A.F.C.S</strong>, nous allons développer, à vrai dire «&nbsp;assembler&nbsp;», une application de <strong>visioconférence</strong> intégrant un <strong>tchat, </strong>des<strong> notes partagées </strong>et un gestionnaire de <strong>partage de fichiers</strong>. Pour cela nous allons utiliser des <strong>pods</strong>, les composants de plus haut-niveau fournis dans <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS .</p>
<p>L’un des principaux composants d’une application <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS  est le <strong>gestionnaire de session</strong>. C’est lui qui sera chargé de la communication avec les serveurs <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS , et donc de l’identification des utilisateurs, de la gestion de leur connexion, de la synchronisation des données… et plus encore…</p>
<p>Deux composants peuvent jouer ce rôle : <strong>ConnectSessionContainer</strong> et <strong>ConnectSession</strong> ( tous deux implémentent <em><strong>com.adobe.rtc.session.IConnectSession </strong></em>).</p>
<p><img src="http://lafabrick.free.fr/blogImg/Cocomo_prez1-20081218-051847.jpg" alt="Connexion Cocomo" /><br />
<span id="more-1040"></span></p>
<h3>Hello AFCS ( bye Cocomo )</h3>
<p>Pour commencer :</p>
<p>- créer un <strong>nouveau projet Flex</strong>,<br />
- <strong>copier le SWC <del datetime="2009-03-06T16:02:18+00:00">Cocomo</del> AFCS (depuis CocomoSDK_0.9/lib/player 9 ou 10/afcs.swc) et collez-le dans votre répertoire /libs/</strong></p>
<p>Il s’agit d’un composant basé sur la classe Canvas, et intégrant toute la «&nbsp;mécanique&nbsp;» nécessaire à la communication avec les serveurs <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS .</p>
<p>Il est à noter que le ConnectSessionContainer, et donc ses «&nbsp;composants-enfants&nbsp;», resteront invisibles tant que la communication avec salon ne sera pas établie. C’est pour cette raison que nous allons lui intégrer nos <strong><em>pods ( WebCamera, SimpleChat, Notes et FileShare ).</em></strong>Tant que la connexion ne sera pas établie, aucun des composants ne sera visible.</p>
<p>Pour débuter une session, nous devrons renseigner deux propriétés du <strong>container de session</strong> :</p>
<ul>
<li>l’adresse du salon: <strong>roomURL</strong> ( exemple : http://connectnow.acrobat.com/votreCompte/nomSalon )</li>
<li>les identifiants de connexion : <strong>authenticator</strong></li>
</ul>
<p>La transmission des identifiants se fait par l’intermédiaire de la classe <strong>AdobeHSAuthenticator</strong>.Elle a pour fonction d’encapsuler les informations relatives à l’identification( <strong>userName</strong>, <strong>password</strong> ). Plusieurs modes d’authentification sont possibles, nous nous y interresserons plus tard.</p>
<p>Dans un premier temps nous nous contenterons d’inscrire nos identifiants «&nbsp;en dur&nbsp;» dans notre application.</p>
<p>On peut noter que les composants liés à AFCS se référent au namespace ‘AfcsNameSpace’ ( anciennement ‘CocomoNameSpace’ dans version 0.9 )</p>
<pre class="brush: xml">

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;mx:Application layout=&quot;absolute&quot;
 xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
 xmlns:rtc=&quot;AfcsNameSpace&quot;
 &gt;
&lt;rtc:ConnectSessionContainer id=&quot;sessionManager&quot; width=&quot;500&quot; height=&quot;400&quot;
 roomURL=&quot;http://connectnow.acrobat.com/yourAccount/roomName&quot;
 authenticator=&quot;{identificator}&quot;
 backgroundColor=&quot;#FFFFFF&quot;
/&gt;
&lt;rtc:AdobeHSAuthenticator id=&quot;identificator&quot;
 userName=&quot;votreLogin&quot; password=&quot;VotreMotDePasse&quot;
/&gt;
&lt;/mx:Application&gt;
</pre>
<p>À ce stade, l’application peut déjà se connecter. Par défaut, dès que le connectSessionContainer est créé, il tente d’initier la communication avec les serveurs. Dans cet exemple, j’ai ajouté une couleur de fond pour le container, de manière à pouvoir observer lorsque la connexion au salon est réussie.</p>
<p>Si vous publiez le projet en mode debug vous verrez les logs relatifs aux communications client/serveur.</p>
<p><img src="http://lafabrick.free.fr/blogImg/Flex_Builder-20081218-065625.jpg" alt="Logs Connexion Serveurs Cocomo" /></p>
<p>Pour vérifier si l’authentification est correcte, nous pouvons déclarer des écouteurs d’événements <strong>AuthenticationEvent.AUTHENTICATION_FAILURE </strong>et <strong>AuthenticationEvent.AUTHENTICATION_SUCCESS </strong>sur <strong>AdobeHSAuthenticator</strong>.</p>
<p>Pour capter le moment où notre application est connectée et synchronisée, nous pouvons ajouter un écouteur d’événement <strong>SessionEvent.SYNCHRONIZATION_CHANGE</strong> sur le container, et surveiller sa propriété ‘<strong>isSynchronized</strong>‘. Nous reviendrons prochainement sur les différents aspects et acteurs en jeu lors de cette synchronisation.</p>
<pre class="brush: xml">

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;mx:Application layout=&quot;absolute&quot;
    xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
    xmlns:rtc=&quot;AfcsNameSpace&quot;
&gt;
     &lt;mx:Script&gt;
         &lt;![CDATA[
             import mx.controls.Alert;
             import com.adobe.rtc.events.SessionEvent;

             // session&#039;s state
             private var isConnected:Boolean = false;

			// when a &quot;server synchronization&quot; event is dispatched
             public function onSynchro( e:SessionEvent ):void
             {
                 if ( sessionManager.isSynchronized &amp;&amp;  ! isConnected )
                 {
                     Alert.show(&quot;Application connectée&quot;);
                     isConnected = true ;
                 }
             }
     ]]&gt;
 &lt;/mx:Script&gt;
&lt;rtc:ConnectSessionContainer id=&quot;sessionManager&quot;
    width=&quot;100%&quot; height=&quot;100%&quot; backgroundColor=&quot;#FFFFFF&quot;
    authenticator=&quot;{identificator}&quot;
    roomURL=&quot;http://connectnow.acrobat.com/regartdemo/meetingzone&quot;
    synchronizationChange=&quot;onSynchro( event )&quot;
/&gt;
&lt;!-- Authentication component --&gt;
 &lt;rtc:AdobeHSAuthenticator id=&quot;identificator&quot;
   userName=&quot;YourUserName&quot; password=&quot;YourPassword&quot;
   authenticationSuccess=&quot;Alert.show(&#039;authentication success&#039;)&quot;
   authenticationFailure=&quot;Alert.show(&#039;authentication failed&#039;)&quot;/&gt;
&lt;/mx:Application&gt;
</pre>
<p>Maintenant que notre connexion parvient à se connecter au salon, nous allons pouvoir intégrer les pods.</p>
<h3>Utilisation des pods</h3>
<p>Les pods sont des composants collaboratifs «&nbsp;<strong>prêt à l’emploi</strong>«&nbsp;. Lorsque vous utilisez un <strong>ConnectSessionContainer</strong>, il suffit d’insérer vos pods à l’intérieur pour qu’ils puissent repérer la connexion établie et l’utiliser.</p>
<p>À ce jour, les pods disponibles sont :</p>
<ul>
<li><strong>SimpleChat</strong> : composant de «&nbsp;clavardage&nbsp;» permettant l’envoi de messages publics et privés</li>
<li><strong>WebCamera</strong> : composant de visioconférences</li>
<li><strong>FileShare</strong> : composant de partage de fichier ( upload / download )</li>
<li><strong>Note</strong> : composant de partage de notes</li>
<li><strong>Roster</strong> et <strong>HorizontalRoster</strong> : composant de gestion d’utilisateurs</li>
<li><strong>SharedWhiteBoard</strong> : tableau blanc partagé</li>
</ul>
<p>Nous allons maintenant insérer les pods souhaités :</p>
<pre class="brush: xml">

&lt;rtc:ConnectSessionContainer id=&quot;sessionManager&quot; width=&quot;100%&quot; height=&quot;100%&quot; backgroundColor=&quot;#FFFFFF&quot;
   authenticator=&quot;{identificator}&quot;
   roomURL=&quot;http://connectnow.acrobat.com/votreCompte/nomSalon&quot;
   synchronizationChange=&quot;onSynchro( event )&quot;
   &gt;

   &lt;!-- PODS --&gt;
   &lt;mx:VBox width=&quot;50%&quot; height=&quot;100%&quot; horizontalAlign=&quot;center&quot;&gt;

      &lt;rtc:WebCamera id=&quot;webcam&quot; width=&quot;300&quot; /&gt;

      &lt;rtc:SimpleChat id=&quot;chat&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;

   &lt;/mx:VBox&gt;

   &lt;mx:VBox width=&quot;50%&quot; height=&quot;100%&quot;  right=&quot;0&quot;&gt;

     &lt;rtc:FileShare id=&quot;fileManager&quot; width=&quot;100%&quot; height=&quot;50%&quot; /&gt;

      &lt;rtc:Note id=&quot;notes&quot; width=&quot;100%&quot; height=&quot;50%&quot; /&gt;
   &lt;/mx:VBox&gt;
&lt;/rtc:ConnectSessionContainer&gt;
</pre>
<p><img src="http://lafabrick.free.fr/blogImg/hello_cocomo-20081218-081901.jpg" alt="Hello Cocomo" /></p>
<p>Les pods intégrent des mécanismes de gestion de droits. Nous y reviendrons …</p>
<p>Toujours est-il que voilà, vous avez créé votre première application <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS , ou devrais je dire votre première application de «&nbsp;communication en temps réelle&nbsp;». Mais comment faisait-on avant ???…</p>
<h3>Identification et gestion de la connexion aux serveurs</h3>
<p>Bon il manque encore quelque chose peut être… Pour un seul utilisateur çà irait presque… mais c’est pas le but :s…Comment fera-t-on si un jour on trouve des amis et qu’on veut collaborer avec eux ??? Tout le monde va se connecter avec le compte «&nbsp;d’admin&nbsp;» ??? Et n’importe quel décompileur AS3 va pouvoir récupérer les identifiants ? Pas très sécure… Heureusement <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS  nous permet de gérer facilement tous ces aspects.</p>
<p>Les serveurs <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS  permettent plusieurs types d’identification, notamment une connexion en tant que <strong>hôte</strong>, basée sur le compte <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS  Developper, et une connexion en tant <strong>qu’invité</strong>, ne nécessitant qu’un nom de participant.</p>
<p>Nous allons donc supprimer les attributs userName et password de l’AdobeHSAuthenticator, et ajouter un formulaire d’authentification à notre application. Ce formulaire permettra de choisir le type d’identification ( hôte ou invité ) :</p>
<pre class="brush: xml">

&lt;mx:Panel id=&quot;logPanel&quot; &gt;
   &lt;mx:Form&gt;

      &lt;mx:FormItem label=&quot;Login&quot;&gt;
         &lt;mx:TextInput id=&quot;chp_login&quot; /&gt;
      &lt;/mx:FormItem&gt;

      &lt;mx:FormItem label=&quot;your role :&quot; direction=&quot;horizontal&quot; &gt;

         &lt;mx:RadioButtonGroup id=&quot;userRole&quot; /&gt;

         &lt;mx:RadioButton id=&quot;isGuest&quot; groupName=&quot;userRole&quot;
            label=&quot;Guest&quot; value=&quot;{UserRoles.VIEWER}&quot;  selected=&quot;true&quot;
         /&gt;
         &lt;mx:RadioButton id=&quot;isOwner&quot; groupName=&quot;userRole&quot;
            label=&quot;Host&quot; value=&quot;{UserRoles.OWNER}&quot;
         /&gt;
      &lt;/mx:FormItem&gt;

      &lt;mx:FormItem label=&quot;Password&quot;  enabled=&quot;{ userRole.selectedValue == UserRoles.OWNER }&quot;&gt;
         &lt;mx:TextInput id=&quot;field_password&quot; displayAsPassword=&quot;true&quot;  /&gt;
      &lt;/mx:FormItem&gt;

      &lt;mx:FormItem &gt;
         &lt;mx:Button label=&quot;Enter&quot;
            click=&quot;login(chp_login.text , userRole.selectedValue == UserRoles.OWNER ? field_password.text : null  )&quot;
          /&gt;
      &lt;/mx:FormItem&gt;

   &lt;/mx:Form&gt;
&lt;/mx:Panel&gt;
</pre>
<p>La définition des <strong>rôles des utilisateurs</strong> est basée sur des valeurs numériques, définies dans des constantes de la classe <strong>UserRoles</strong>.</p>
<p>Les principaux rôles sont <strong>Owner</strong> ( hôte / propriétaire du salon ), <strong>Publisher</strong> ( participant autorisé à publier sur un ou plusieurs pods ) et <strong>Viewer</strong> ( invité seulement autorisé à utiliser le tchat ). Normallement, les invités ne peuvent utiliser un salon que si l’hôte est présent. Il est possible de modifier la configuration initiale des salons ( droit de publication automatique, persistence des données, entrée libre… ), ainsi que les rôles et les droits des utilisateurs connectés, pour cela nous pourrons utiliser l’application <del datetime="2009-03-05T19:23:22+00:00">CocomoDevConsole</del> AFCSDevConsole ou l’API directement. Mais c’est déjà une autre histoire…</p>
<p>Pour le moment, nous allons permettre à l’utilisateur de s’identifier à l’aide du formulaire. Pour cela nous devons <strong>désactiver la connexion automatique du gestionnaire de session</strong> en déclarant sa propriété <strong>autoLogin=&nbsp;»false&nbsp;»</strong>.</p>
<p>Pour finir, nous allons ajouter une méthode <strong><em>login()</em></strong> qui sera chargée de renseigner le <strong><em>AdobeHSAuthenticator</em></strong>, et de lancer la connexion du gestionnaire de session :</p>
<pre class="brush: js">

private function login ( login:String, password:String ):void
{
   identificator.userName = login;
	//if password is set : log as host
	//else log as guest
   identificator.password = password ;

	// run sessionManager connection
   sessionManager.login();
}
</pre>
<p>Nous allons ensuite rajouter un bouton et une fonction de déconnexion.</p>
<pre class="brush: js">

// disconnection
// in actual 0.9 beta, mostly pods, can&#039;t be re-connected after a disconnection

private function logout():void
{
    sessionManager.logout();

	// close() is supposed to disconnect et remove all childNodes, but seems not work yet
    //sessionManager.close();
}
</pre>
<pre class="brush: xml">

&lt;mx:VBox width=&quot;50%&quot; height=&quot;100%&quot; horizontalAlign=&quot;center&quot; right=&quot;0&quot;&gt;
    &lt;mx:Button label=&quot;Logout&quot; click=&quot;logout()&quot; /&gt;

    &lt;rtc:FileShare id=&quot;fileManager&quot; width=&quot;100%&quot; height=&quot;50%&quot; /&gt;

    &lt;rtc:Note id=&quot;notes&quot; width=&quot;100%&quot; height=&quot;50%&quot; /&gt;
&lt;/mx:VBox&gt;
</pre>
<p>Dès que l’application sera connectée, nous supprimerons le formulaire, et en cas de déconnexion le gestionnaire de session sera supprimé :</p>
<pre class="brush: js">

// for each synchronization event
// : connection, disconnection , state&#039;s change, ...
private function onSynchro( e:SessionEvent ):void
{

	// once application is successfully connected / synchronized
    if ( sessionManager.isSynchronized &amp;&amp; ! isConnected )
    {
        Alert.show(&quot;Application connectée&quot;);

        isConnected = true ;

        removeChild( logPanel );

    } else if ( ! sessionManager.isSynchronized &amp;&amp; isConnected ){
    // if disconnected
    isConnected = false ;

   /* remove the connectSessionContainer
   *  » in this version disconnected pods can&#039;t re-connect
   *
   *  » For re-connect, you can :
   *     - reload html page
   *     - dynamically re-create connectSession and pods
   */
   removeChild( sessionManager );

   // display logout message
   Alert.show( &#039;vous avez quitté la réunion, recharger la page pour entrer à nouveau&#039;);
   }
}
</pre>
<p><strong>La gestion des déconnexions / reconnexions semblent pour le moment un peu instables.</strong> Mais bon on est prévenu, c’est une béta. Après quelques tests, je crois que le meilleur moyen de revenir dans un salon après s’être déconnecté, est de recharger la page.</p>
<p>Accéder aux <a href="http://www.e-actif.com/lab/hello_cocomo">sources complétes</a></p>
<p>Voilà la fin de ce premier exemple d’utilisation de <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS , et il est bien entendu possible d’aller beaucoup plus loin. La prochaine fois nous nous intéresserons de plus près aux différents mécanismes articulés au sein de <del datetime="2009-03-05T19:23:22+00:00">cocomo</del> AFCS , et plus globalement à l’architecture du service. Nous utiliserons également la <del datetime="2009-03-05T19:23:22+00:00">CocomoDevConsole</del>AFCSDevConsole et le <strong>LocalConnectionServer</strong>, les deux outils AIR proposés dans le SDK.</p>
<p>D’ici là bonne collaboration !!! <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  </p>
<p>Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/12/07/274-cocomo-dbarque-et-personne-me-prvient/" rel="bookmark" title="7 décembre 2007">Cocomo est là et personne me prévient ??!!</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/12/22/568-cocomo-kezako/" rel="bookmark" title="22 décembre 2008">Cocomo ? Kezako ?</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/12/13/506-utiliser-le-dragmanager-de-flex-1ere-partie/" rel="bookmark" title="13 décembre 2008">Utiliser le DragManager de Flex ( 1ère partie )</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/" rel="bookmark" title="21 janvier 2009">Developing with AFCS a.k.a Cocomo &#8211; Introduction</a></li>
</ul>
<p><!-- Similar Posts took 12.356 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Developing with AFCS a.k.a Cocomo &#8211; Introduction</title>
		<link>http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 23:38:28 +0000</pubDate>
		<dc:creator>Hervé</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[cocomo]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[RIA]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=999</guid>
		<description><![CDATA[[ 05.03.2009 : Update : Cocomo is now called Adobe Flash Collaboration Services / AFCS and 0.9.1 was released with some bug fixes and a new namespace ] Hey there! Here is, as a first English article, an introduction to Adobe Cocomo AFCS. (Translated from French tutorial on FlashXPress ) Cocomo is an abbreviation of [...]]]></description>
			<content:encoded><![CDATA[<p>[ 05.03.2009 : Update : Cocomo is now called Adobe Flash Collaboration Services / AFCS and 0.9.1 was released with some bug fixes and a new namespace ]</p>
<p>Hey there!<br />
Here is, as a first English article, an introduction to <del datetime="2009-03-06T00:25:09+00:00">Adobe Cocomo</del> AFCS.<br />
(Translated from <a href="http://www.flashxpress.net/ressources-flex/developper-avec-cocomo-introduction/"> French tutorial on FlashXPress </a>)</p>
<p style="text-align: center;"><a href="https://cocomo.acrobat.com/"><img class="aligncenter" title="AFCS/Cocomo developer account" src="http://lafabrick.free.fr/blogImg/cocomo-20090121-005745.png" alt="" width="520" height="180" /></a></p>
<p><span id="more-999"></span></p>
<p><strong> Cocomo </strong> is an abbreviation of «<strong>COmmon COllaboration MOdel</strong>», which was the first name given by Adobe to its new online service dedicated to <strong>collaborative application development</strong>. The final commercial name is Adobe Flash Collaboration Services a.k.a AFCS </p>
<p>This name both references :</p>
<ul>
<li>a <strong>SDK</strong> that includes a Flex components library and tools dedicated to multi-users applications development. Just so you know, those components are used by Adobe for developing ConnectNow, a video conference application part of the <a href="http://www.acrobat.com/">Acrobat.com</a> platform.</li>
<li>a <strong>free online service</strong> (with some limitations), enabling creation and deployment of collaborative applications on <a href="http://www.adobe.com/fr/products/flashmediaserver/">FMS</a> servers hosted and maintained by Adobe.</li>
</ul>
<p>In short, <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS will allow us to develop applications that will use real-time communications capabilities of FMS servers, without taking care of those servers&#8230; cooool !!!</p>
<p>But what are the «<strong>real-time communications</strong> capabilities of those FMS servers» ???</p>
<p>In fact, the <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  servers will allow us to:</p>
<ul>
<li>exchange <strong>audio and video data flows</strong>, useful to create visioconference application for example,</li>
<li><strong>synchronize different types of data between multiple client applications</strong>. It allows you to add a chat to an existing application, to develop a co-navigation system, a document co-edition functionnality, some multi-users game&#8230;</li>
<li><strong>share files</strong></li>
<li><strong>manage user rights</strong> regarding their role</li>
</ul>
<p><img src="http://lafabrick.free.fr/blogImg/Cocomo_prez1-20090120-220414.png" alt="AFCS /  Cocomo  " /></p>
<p>This schema describes the interaction between a room, hosted on a developer account of a cocomo server, and some Flex clients : the host user (owner), an active guest (publisher), and a passive guest. The host send his webcam output, and both host and publisher can update notes on the server, these data are broadcasted to the other clients.</p>
<p>The library contains «high-level» graphical components, known as <strong>pods</strong>, but also some more «low-level» classes that a developer can use to create his own components (<strong>SharedModel</strong>, <strong>CollectionNode</strong>).</p>
<p><img src="http://lafabrick.free.fr/blogImg/Cocomo_Pods-2-3-20090121-003644.png" alt="AFCS / Cocomo built-in Pods" /></p>
<p>This schema shows an example of pods (Tchat, Notes, User management, Webcam and File sharing)</p>
<p>The pods are <strong>collaborative «plug’n’play» components</strong>, that we will use to create our first <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  applications without having to write a single line of code (Tchat, Webcam, Notes&#8230;). The lower level classes will help us to go deeper and create components that will fit more specific needs.</p>
<p>But, first things first : let’s create a «<del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  Developer» account&#8230;</p>
<h3><del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  Developer account creation</h3>
<p>To create an account :</p>
<ul>
<li>Go to the <a href="https://cocomo.acrobat.com/"><del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  portal (https://cocomo.acrobat.com)</a>,</li>
<li>Create a <strong>new account</strong> (you can also use your existing Adobe account)</li>
<li>Choose a <strong><del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  account identifier</strong> («account name», room access URLs will be based on that identifier)
<ol>
<li>The Account URL situation in the screen</li>
<li>The Room instances panel (click the &laquo;&nbsp;Add&nbsp;&raquo; button)</li>
<li>The &laquo;&nbsp;Download SDK&nbsp;&raquo; button</li>
</ol>
</li>
<p><img src="http://lafabrick.com/blog/images/erick//AFCS_Developer_Portal-20090305-213035.jpg" alt="Cocomo Developper Console" /><br />
This capture represents the <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  home page. It mainly illustrates the three steps to follow:</p>
<li>Once your account has been created, make sure to note your <strong>Account URL</strong></li>
<li>In the &laquo;&nbsp;<strong>Room instances</strong>&nbsp;&raquo; panel, create a new <strong>room. </strong>A room represents a &laquo;&nbsp;virtual meeting point&nbsp;&raquo; where several client application will be able to <strong>exchange audio / video flows, files or messages</strong>. Your account will allow you to create several rooms, with a single configuration for each room. A room is also identified by a URL that looks like <em>http://connectnow.acrobat.com/yourAccount/roomName</em>.</li>
<li>Once your room has been created, download the SDK.</li>
</ul>
<p>You&#8217;ll find within the downloaded ZIP:</p>
<ul>
<li><strong>documentation</strong></li>
<li><strong>application examples</strong></li>
<li>Air utilities: <strong><del datetime="2009-03-06T00:25:09+00:00">CocomoDevConsole</del> AFCSDevConsole</strong> for your accounts and rooms management, and <strong>LocalConnectionServer</strong>, a local <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  server emulation that will allow you to test some of your applications features without having to connect to a &laquo;&nbsp;real&nbsp;&raquo; <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  server (mainly messaging)</li>
<li>library <strong>sources</strong></li>
<li>library SWC for Flash Player 9 and Flash Player 10</li>
</ul>
<h3><del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  installation</h3>
<p>For this version (0.9), installation will reside in including <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  library documentation at Eclipse&#8217;s one. To do so:</p>
<ul>
<li>create a &#8216;<em>com.adobe.afcs</em>&#8216; folder in the &#8216;<em>plugins</em>&#8216; folder of your Flex Builder installation<br />
<strong>Windows</strong>: C:\Program Files\Adobe\Flex Builder 3\plugins\com.adobe.afcs<br />
<strong>Macintosh</strong>: /Applications/Adobe Flex Builder 3/plugins/com.adobe.afcs</li>
<li>Copy the content of the downloaded file into that folder</li>
<li>(Re)Launch Flex Builder and open the help contents (Help / Help Contents)</li>
</ul>
<p>You should now find the <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  API documentation</p>
<p><img src="http://lafabrick.free.fr/blogImg/cocomo_help-20081218-031802.jpg" alt="Cocomo Doc in Flex Builder / Eclipse" /><br />
This schema is a screen capture of the cocomo documentation opened within the Flex Builder environment.</p>
<p>And noooow&#8230; <a href="http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/">let&#8217;s collaborate</a> !!! <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
&gt;&gt; Next : <a href="http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/">My first <del datetime="2009-03-06T00:25:09+00:00">Cocomo</del> AFCS  Application</a>Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/12/07/274-cocomo-dbarque-et-personne-me-prvient/" rel="bookmark" title="7 décembre 2007">Cocomo est là et personne me prévient ??!!</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/12/22/568-cocomo-kezako/" rel="bookmark" title="22 décembre 2008">Cocomo ? Kezako ?</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/12/23/591-cocomo-wiibot/" rel="bookmark" title="23 décembre 2008">Introducing r.CØ &#8230; First &laquo;&nbsp;Cocomo ready&nbsp;&raquo; Air Wiibot&#8230;</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/" rel="bookmark" title="31 janvier 2009">Hello AFCS ( bye Cocomo ) : première application multi-utilisateurs</a></li>
</ul>
<p><!-- Similar Posts took 13.325 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Développer une application iPhone &#8211; XCode et Interface Builder passés au crible</title>
		<link>http://www.lafabrick.com/blog/2009/01/16/807-developper-une-application-iphone-xcode-et-interface-builder-passes-au-crible/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/16/807-developper-une-application-iphone-xcode-et-interface-builder-passes-au-crible/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 22:00:38 +0000</pubDate>
		<dc:creator>Hervé</dc:creator>
				<category><![CDATA[Logiciels / extensions / plugins...]]></category>
		<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[Conseils]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=807</guid>
		<description><![CDATA[Cet article suit la <a href="http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/">description des concepts de base permettant d'appréhender le développement d'une application pour iPhone</a>.
Il présente les outils de développement utilisés pour faire une application pour iPhone en analysant rapidement un projet de base proposé avec le SDK iPhone.
Il ne parle pas de la syntaxe de développement Objective-C.]]></description>
			<content:encoded><![CDATA[<p>Cet article suit la <a href="http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/">description des concepts de base permettant d&#8217;appréhender le développement d&#8217;une application pour iPhone</a>.<br />
Il présente les outils de développement utilisés pour faire une application pour iPhone en analysant rapidement un projet de base proposé avec le SDK iPhone.<br />
Il ne parle pas de la syntaxe de développement Objective-C.</p>
<p>Je vous suggère vivement si vous n&#8217;avez pas lu l&#8217;article ou si vous ne connaissez pas encore grand chose au développement sous iPhone de vous y intéresser pour mieux aborder cette suite&#8230;</p>
<p><img class="aligncenter" title="XCode and Interface Builder" src="http://lafabrick.free.fr/blogImg/xbuilderInterface-20090121-010351.png" alt="" width="520" height="224" /></p>
<p>Une dernière chose avant de démarrer : massez-vous les tempes, faites-vous un petit café&#8230;<br />
Prêt ?<br />
<span id="more-807"></span></p>
<h3>Installer le SDK iPhone</h3>
<p>A l&#8217;heure ou j&#8217;écris ces lignes, Apple en est à la <a href="http://developer.apple.com/iPhone/program/download.html">version 2.2 du SDK iPhone</a>.<br />
L&#8217;installation vous mettra à disposition tous les outils dont je vais parler ici.</p>
<h3>Ouvrir un projet d&#8217;exemple pour se familiariser avec la structure d&#8217;un projet iPhone</h3>
<p>Je considère à présent que vous avez déjà un Mac (bah oui&#8230;), et le SDK iPhone installé dessus.</p>
<ol>
<li>Ouvrez XCode.<br />
<img class="alignnone size-medium wp-image-785" title="Xcode" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/welcome-to-xcode-300x206.jpg" alt="Xcode" width="300" height="206" /></li>
<li>Faites Fichier &gt; Nouveau projet&#8230;<br />
<img class="alignnone size-full wp-image-787" title="New project" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/new-project.jpg" alt="New project" width="503" height="477" /></li>
<li>Choisissez &laquo;&nbsp;View-Based Application&nbsp;&raquo;</li>
<li>Entrez le nom de projet &laquo;&nbsp;LaFabrick&nbsp;&raquo; puis choisissez un emplacement, vous arrivez alors sur l&#8217;interface principale d&#8217;Xcode.</li>
</ol>
<p>Voyons maintenant les fichiers que nous avons :<br />
<img class="alignnone size-full wp-image-792" title="Accueil Xcode View-Based application" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/lafabrick.jpg" alt="Accueil Xcode View-Based application" width="676" height="479" /><br />
Nous sommes en Objective-C, donc pour chaque classe, vous trouverez un fichier .h définissant l&#8217;interface et un fichier .m contenant l&#8217;implémentation (amis du C bonjour !).<br />
Ouvrons &laquo;&nbsp;LaFabrickAppDelegate.h&nbsp;&raquo;<br />
<img class="alignnone size-full wp-image-799" title="LaFabrickAppDelegate.h" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/lafabrickappdelegateh.png" alt="LaFabrickAppDelegate.h" width="554" height="331" /><br />
On constate dans cette interface les déclarations d&#8217;un objet fenêtre (objet de base utilisé pour l&#8217;affichage) et le contrôleur <strong>LaFabrickViewController</strong> que nous étudierons rapidement après.<br />
L&#8217;implémentation est simple :<br />
<img class="alignnone size-full wp-image-801" title="LaFabrickAppDelegate.m" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/lafabrickappdelegatem.png" alt="LaFabrickAppDelegate.m" width="530" height="386" /><br />
Lorsque l&#8217;application vient d&#8217;être démarrée <code>applicationDidFinishLaunching</code>, on demande l&#8217;affichage de la vue contrôlée par notre LaFabrickViewController dans la fenêtre <code>[window addSubview:viewController.view];</code>.<br />
Notez enfin la notation à crochet pour appeler une méthode d&#8217;un objet : oui oui, c&#8217;est relou.</p>
<p>Jetons maintenant un oeil à LaFabrickViewController (.h et .m) : il est quasiment vide ! C&#8217;est effectivement là qu&#8217;on doit travailler un peu&#8230;<br />
Quelques questions se posent :</p>
<ul>
<li>Où est la vue ?</li>
<li>Comment est-elle associée au contrôleur ?</li>
</ul>
<p>Nous allons voir cela avec l&#8217;interface builder.</p>
<h3>Utilisation de l&#8217;Interface Builder pour gérer la vue</h3>
<p>Première réponse : notre vue est ici créée à partir d&#8217;un fichier de description d&#8217;interface géré par l&#8217;interface builder : <strong>LaFabrickViewController.xib</strong>. Double-cliquez dessus, l&#8217;interface suivante s&#8217;affiche alors :<br />
<img class="alignnone size-full wp-image-846" title="Interface Builder" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/interface-builder.png" alt="Interface Builder" width="727" height="481" /><br />
On constate notamment dans la fenêtre centrale, les éléments suivants :</p>
<ul>
<li>File&#8217;s owner : LaFabrickViewController</li>
<li>View : UIView</li>
</ul>
<p>OK, donc le .xib permet de dire que la vue est associée au contrôleur LaFabrickViewController, voilà la deuxième réponse !</p>
<p>Sélectionnez à présent la ligne <strong>View : UIView</strong> puis sélectionnez le second onglet dans la fenêtre de droite.<br />
<strong>Note :</strong> si cette fenêtre n&#8217;est pas visible, faites <em>Tools &gt; Identity Inspector</em></p>
<p>Vous pouvez visualiser l&#8217;association entre la vue <strong>View</strong> et la propriété <strong>view</strong> du contrôleur LaFabrickViewController.<br />
<img class="alignright size-full wp-image-847" title="View connections" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/view-connections.png" alt="View connections" width="290" height="104" /></p>
<p>Cette partie est primordiale pour que l&#8217;affichage de la vue soit effectif : souvenez-vous que dans LaFabrickAppDelegate, on charge la propriété &laquo;&nbsp;view&nbsp;&raquo; de LaFabrickViewController, aussi sans l&#8217;association effectuée dans l&#8217;Interface Builder, il serait impossible d&#8217;afficher quoi que ce soit !</p>
<p><strong>D&#8217;une manière générale, chaque élément ajouté depuis l&#8217;Interface Builder devra être lié à une propriété du contrôleur (ou d&#8217;un délégué) via l&#8217;Interface Builder afin que vous puissez interagir avec depuis le code.<br />
La propriété en question est alors nommée &laquo;&nbsp;Outlet&nbsp;&raquo; côté Interface Builder, soit &laquo;&nbsp;Sortie&nbsp;&raquo; si l&#8217;on traduit litéralement : c&#8217;est effectivement un paramètre de sortie de votre interface.</strong></p>
<h3>Personnaliser un peu l&#8217;interface</h3>
<p>Depuis l&#8217;Interface Builder, ajoutez deux champs texte, deux labels et un bouton histoire d&#8217;obtenir à peu près ça :<br />
<img class="alignnone size-full wp-image-899" title="iPhone - View" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/view.png" alt="iPhone - View" width="321" height="308" /></p>
<p>Si vous faites <em>Tools &gt; Reveal in Document Window&#8230;</em> vous verrez l&#8217;arborescence de contrôles de la vue mise à jour.<br />
<img class="alignnone size-full wp-image-901" title="iPhone - Arborescence de contrôles" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/lafabrickviewcontrollerxib.png" alt="iPhone - Arborescence de contrôles" width="435" height="232" /></p>
<p>Il est maintenant temps de contrôler ces éléments depuis notre LaFabrickViewController.<br />
Pour cela deux méthodes :</p>
<ol>
<li>Directement depuis Interface Builder (cf. <a href="#videodemo">vidéo de démonstration</a>)
<ul>
<li>Sélectionnez LaFabrickViewController depuis le Document Window</li>
<li>Dans &laquo;&nbsp;l&#8217;Inspector&nbsp;&raquo; (fenêtre de droite) choisissez le dernier onglet (i) puis ajoutez les propriétés via la section &laquo;&nbsp;Class Outlets&nbsp;&raquo;<br />
<img class="alignnone size-full wp-image-905" title="Interface Builder - Propriétés de classe" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/la-fabrick-view-controller-identity.png" alt="Interface Builder - Propriétés de classe" width="277" height="421" /></li>
<li>Ceci fait vous devez enregistrer les modifications dans le fichier LaFabrickViewController.m. Pour cela, vous devez utiliser la fonction <em>File &gt; Write class files&#8230;</em></li>
<li>Faites alors &laquo;&nbsp;Save&nbsp;&raquo;</li>
<li>L&#8217;outil vous demande si vous souhaitez fusionner ou écraser : choisissez Merge (fusionner)</li>
<li>Le fichier .m n&#8217;est pas modifié, vous pouvez le fermer, en revanche vous constaterez que le .h peut être modifié comme suit :<br />
<img class="alignnone size-full wp-image-908" title="Merging de fichier sous Interface Builder" src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/lafabrickviewcontrollerh.png" alt="Merging de fichier sous Interface Builder" width="785" height="101" /><br />
sous réserve que vous choisissiez l&#8217;action &laquo;&nbsp;Choose left&nbsp;&raquo; depuis le menu déroulant du bas</li>
<li>Sauvegardez (enfin) votre fichier fusionné</li>
</ul>
</li>
<li>Mix XCode et Interface Builder
<ul>
<li>Déclarez manuellement les propriétés correspondant aux contrôles que vous souhaitez manipuler dans l&#8217;interface (LaFabrickViewController.h) :<code><br />
IBOutlet UITextField *lastNameField;<br />
IBOutlet UITextField *nameField;<br />
IBOutlet UIButton *validateButton;<br />
</code></li>
<li>Compilez le projet</li>
<li>Rouvrez l&#8217;Interface Builder pour faire les liens</li>
</ul>
</li>
</ol>
<p><strong>Note :</strong> la première méthode a le mauvais goût d&#8217;ouvrir l&#8217;outil de fusion de fichiers pour que vous validiez que rien n&#8217;est écrasé ou ajouté sans votre accord.<br />
J&#8217;avoue que, malgré la nécessité de la fusion, je trouve ça très peu pratique voire franchement lourdingue, je m&#8217;attendais à mieux venant d&#8217;un monstre de l&#8217;ergonomie. Mais c&#8217;est le prix à payer pour avoir deux outils quasiment indépendants, et enfin, si vous connaissez une meilleure méthode, n&#8217;hésitez pas à poster !</p>
<p><em>&#8211; ca se voit tant que ça que je préfère la méthode à l&#8217;ancienne ? &#8211;</em></p>
<p>Ce n&#8217;est pas encore tout à fait terminé ! (si si je vous jure, c&#8217;est long)<br />
Il reste à faire les fameux liens entre les contrôles de la vue et les propriétés que nous avons créé dans LaFabrickViewController. Pour cela, rien ne vaut l&#8217;image (et en plein écran tant qu&#8217;à faire) :</p>
<div id="videodemo">
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="swfobj_0" width="800" height="600" align="center">
      <param name="movie" value="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/Tuto-iPhone.swf" />
      <param name="align" value="center" />
      <param name="allowfullscreen" value="true" />
      <!--[if !IE]>-->
      <object type="application/x-shockwave-flash" data="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/Tuto-iPhone.swf" width="800" height="600" align="center" allowfullscreen="true">
      <!--<![endif]-->
        
      <!--[if !IE]>-->
      </object>
      <!--<![endif]-->
    </object>
 </div>
<p>Voilà ! Vous avez lié les contrôles de votre vue à des propriétés de votre contrôleur.<br />
Nous utiliserons désormais la technique décrite ci-dessus pour gérer nos association vue-contrôleur.</p>
<p>Reprenons Interface Builder pour créer un handler gérant le clic sur le bouton. Pour cela :</p>
<ol>
<li>Sélectionnez <strong>LaFabrickViewController</strong> depuis la <em>Document Window</em></li>
<li>Dans le dernier onglet de <em>l&#8217;Inspector</em>, cliquez sur le bouton + de la section <em>Class Actions</em> en entrez <code>buttonClick:</code>. Laissez le <em>Type</em> sur <strong>id</strong></li>
<li>Sauvegardez, faites <em>Write class files&#8230;</em>, fusionnez les sources et enregistrez</li>
<li>Faites un lien entre l&#8217;événement <em>Touch up Inside</em> de votre bouton et <strong>LaFabrickViewController</strong>, l&#8217;éditeur vous propose alors votre fonction <code>buttonClick:</code></li>
</ol>
<p>Maintenant que votre événement est lié à votre contrôleur, ajoutons un bout de code bateau juste pour valider que l&#8217;ensemble fonctionne bien :</p>
<ol>
<li>Retournez sous XCode, et ouvrez LaFabrickViewController.m</li>
<li>Modifiez le code pour avoir la méthode <strong>buttonClick:</strong> sous la forme suivante :<br />
<code>- (IBAction)buttonClick:(id)sender {<br />
[firstNameField setText:[lastNameField text]];<br />
}</code> </p>
<p>Le principe étant simplement de modifier le texte du prénom avec le texte du nom (je vous avais prévenu, c&#8217;est un bout de code bateau)</li>
<li>Faites <strong>Build and Go</strong> et testez !</li>
</ol>
<p>Bien, il ne reste plus qu&#8217;à apprendre Objective-C. Pour cela, rien ne vaut quelques ressources dédiée au sujet :</p>
<ul>
<li><a href="http://pierre-chatelier.developpez.com/tutoriels/mac/objectivec/migration/">Passage de C++ à Objective-C</a></li>
<li><a href="http://sylvain-gamel.developpez.com/tutoriel/mac/cocoa/java/">Passage de Java à Objective-C</a></li>
</ul>
<p>Voilà, vous avez à présent les bases nécessaires pour démarrer le développement d&#8217;une application iPhone.<br />
A bientôt !Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/11/15/266-debuguer-un-projet-flex-distant-via-flex-builder/" rel="bookmark" title="15 novembre 2007">L&#8217;erreur est humaine&#8230; debuguer un projet Flex distant via Flex Builder</a></li>
<li><a href="http://www.lafabrick.com/blog/2007/09/04/206-flex-3-beta-rsolution-de-bug-comment-placer-fichier-d-application/" rel="bookmark" title="4 septembre 2007">[Flex 3 Beta] bug : Application File doesn&#8217;t exist</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/" rel="bookmark" title="12 janvier 2009">Développer une application iPhone &#8211; Introduction aux concepts de base</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/" rel="bookmark" title="13 janvier 2009">Reflex #1: une micro-architecture pour Flex&#8230; simple !</a></li>
</ul>
<p><!-- Similar Posts took 15.026 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/16/807-developper-une-application-iphone-xcode-et-interface-builder-passes-au-crible/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Reflex #2 : vous reprendrez bien un peu de IOC ?</title>
		<link>http://www.lafabrick.com/blog/2009/01/15/819-reflex-2-vous-reprendez-bien-un-peu-de-ioc/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/15/819-reflex-2-vous-reprendez-bien-un-peu-de-ioc/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 22:16:49 +0000</pubDate>
		<dc:creator>Fabien</dc:creator>
				<category><![CDATA[Bientôt chez vous]]></category>
		<category><![CDATA[La Fabrick]]></category>
		<category><![CDATA[Nos projets]]></category>
		<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[IOC]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=819</guid>
		<description><![CDATA[Reflex intègre un système d’Injection de contenu, qui est l’une des représentations de l’IOC. Nous allons voir ici à quoi cela sert, et comment le mettre en œuvre dans Reflex. Si ce n’est déjà fait, je vous laisse jeter un œil sur la première partie de cette architecture, et de récupérer le swc avant de [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter" title="reflex image tuto 2" src="http://www.lafabrick.com/labz/reflex/images/reflexImgTuto2.jpg" alt="" width="520" height="230" /><br />
Reflex intègre un système d’Injection de contenu, qui est l’une des représentations de l’IOC.<br />
Nous allons voir ici à quoi cela sert, et comment le mettre en œuvre dans Reflex.</p>
<p>Si ce n’est déjà fait, je vous laisse jeter un œil sur <a href="http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/">la première partie de cette architecture</a>, et de <a href="http://www.lafabrick.com/blog/reflex/">récupérer le swc</a> avant de lire la suite.<br />
<span id="more-819"></span></p>
<h3><strong>A quoi ça sert l’IOC ?</strong></h3>
<p>L’IOC ( Inversion Of Control ) est un patron d’architecture, possédant plusieurs représentations ( inversion de contrôle, injection de dépendance, &#8230;).  Je ne vais pas faire un cours sur l’Injection de contenu : je vous laisse <a href="http://fr.wikipedia.org/wiki/Inversion_de_contr%C3%B4le">voir ici </a>pour plus d’informations.</p>
<p>Dans Reflex, le but du package IOC est de décentraliser les objets de configurations de l’application. En gros, mettre les services d’accès aux données dans un fichier de configuration XML au lieu de les coder en dur dans l&#8217;application Flex.</p>
<p>Certains spécialistes me diront certainement que l’Injection de contenu n’est pas forcement une représentation de l’IOC, et donc un abus de langage pour Reflex : je répondrais par “traduisez ici IOC par Injection Of Content, et laissons tomber les patrons d’architecture !”.</p>
<h3><strong>Au commencement, le ServicesLocator</strong></h3>
<p>Nous avons vu dans la première partie comment réaliser simplement un appel à une méthode distante. Avoir un point d’accès global aux différents services est pratique lorsque l’on commence à avoir plusieurs services, ou si des vues différentes utilisent un service identique. Voyons comment procéder avec le premier exemple.</p>
<p>Reprenons l’exemple du <a href="http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/">tuto #1</a> :  il faut charger <strong>les services</strong> dans le <strong>ServicesLocator</strong>. Nous allons donc modifier notre vue :</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	layout=&quot;absolute&quot;

	creationComplete=&quot;init()&quot;

	xmlns:controller=&quot;controller.*&quot;
	xmlns:model=&quot;model.*&quot;&gt;

	&lt;mx:Script&gt;
		&lt;![CDATA[
			import com.lafabrick.reflex.service.ServicesLocator;

			public static const SERVICE_USER:String = &quot;userService&quot;;
			public static const SERVICE_OTHER:String = &quot;otherService&quot;;

			private function init() : void
			{
				ServicesLocator.addService( SERVICE_USER, remoteUser );
				ServicesLocator.addService( SERVICE_OTHER, remoteOther );

				userControl.service = ServicesLocator.getService( SERVICE_USER );
			}

		]]&gt;
	&lt;/mx:Script&gt;

	&lt;mx:RemoteObject id=&quot;remoteUser&quot;
		destination=&quot;javaFacadeUser&quot; showBusyCursor=&quot;true&quot; /&gt;

	&lt;mx:RemoteObject id=&quot;remoteOther&quot;
		destination=&quot;javaFacadeOther&quot; showBusyCursor=&quot;true&quot; /&gt;

	&lt;controller:UserController id=&quot;userControl&quot; /&gt;

	&lt;model:UserModel id=&quot;userModel&quot; /&gt;

	&lt;mx:VBox&gt;
		&lt;mx:TextInput id=&quot;login&quot; /&gt;
		&lt;mx:TextInput id=&quot;password&quot; displayAsPassword=&quot;true&quot; /&gt;

		&lt;mx:Button label=&quot;connect&quot;
			click=&quot;{userControl.login(login.text, password.text)}&quot; /&gt;

		&lt;mx:Label x=&quot;208&quot; y=&quot;44&quot;
			text=&quot;User Name : {userModel.userLogged.name}&quot;/&gt;
	&lt;/mx:VBox&gt;

&lt;/mx:Application&gt;
</pre>
<ul>
<li>À la création de l’application ( <em>creationComplete</em> ), nous déclenchons la fonction<strong> init();</strong>.</li>
<li>Nous ajoutons les services <strong>RemoteObject</strong> dans le <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/service/ServicesLocator.html">ServicesLocator</a>. La signature de cette méthode est la suivante :
<pre class="brush: js">
ServicesLocator.addService( serviceName:String, serviceObject:AbstractService )
</pre>
<p> </p>
<ul>
<li>  <strong><em>  serviceName:String</em></strong> est le nom de référence utilisé pour indexer, et plus tard retrouver le bon service.</li>
<li><strong><em>serviceObject:AbstractService</em></strong> est l’identifiant (id) de l’object service (le RemoteObject). </li>
</ul>
</li>
<li>Nous supprimons la propriété <strong><em>service</em></strong> dans la déclaration mxml de <strong>UserController</strong>, pour la déclarer en ActionScript dans la fonction<strong> init()</strong>.   ServicesLocator.getService( serviceName:String ) renvoie l’instance du service défini par serviceName, référencée dans le locator.</li>
</ul>
<p><strong>Note</strong> : Au niveau de l’appel du service, nous pourrions appeler la méthode <strong>getController</strong> de <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/controller/ControllerLocator.html">ControllerLocator</a>.</p>
<pre class="brush: js">
userControl.login(login.text, password.text); 
</pre>
<p>devient :</p>
<pre class="brush: js">
( ControllerLocator.getController( MonApplication.SERVICE_USER )
	as UserController ).login(login.text, password.text);
</pre>
<p>Dans ce cas, nous devons &laquo;&nbsp;caster&nbsp;&raquo; le retour de <strong>getController(&#8230;)</strong> en <strong>UserController</strong> ( sinon erreur ! Flex ne connaîtrait pas la méthode login )</p>
<h3><strong>Un composant pour la vue</strong></h3>
<p>Histoire de mettre en pratique un peu plus l’utilisation des “locators” de Reflex, nous allons créer un composant MXML étendant <strong>Canvas</strong>, qui va contenir la représentation visuelle de notre application. Nous allons utiliser <strong>ControllerLocator</strong> dans ce fichier pour récupérer le <strong>UserController</strong>.</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Canvas
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	width=&quot;100%&quot;
	height=&quot;100%&quot;&gt;

	&lt;mx:Script&gt;
		&lt;![CDATA[
			import model.UserModel;
			import controller.UserController;
			import com.lafabrick.reflex.controller.ControllerLocator;
			import com.lafabrick.reflex.model.ModelLocator;

			[Bindable]
			private var userDataModel:UserModel =
				( ModelLocator.getModel( UserModel ) as UserModel);

		]]&gt;
	&lt;/mx:Script&gt;

	&lt;mx:VBox horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot;&gt;
		&lt;mx:TextInput id=&quot;login&quot; /&gt;
		&lt;mx:TextInput id=&quot;password&quot; displayAsPassword=&quot;true&quot; /&gt;

		&lt;mx:Button
			label=&quot;connect&quot;
			click=&quot;{ ( ControllerLocator.getController( UserController )
				as UserController ).login( login.text, password.text )}&quot; /&gt;

		&lt;mx:Label x=&quot;208&quot; y=&quot;44&quot;
			text=&quot;User Name : {userDataModel.userLogged.name}&quot;/&gt;
	&lt;/mx:VBox&gt;

&lt;/mx:Canvas&gt;
</pre>
<p>Pour que le “<strong>Binding</strong>” fonctionne correctement entre la vue et le modèle, nous devons utiliser des pointeurs vers les modèles à utiliser.</p>
<h3><strong>Le fichier de configuration XML (IOC)</strong></h3>
<p>Nous venons de voir comment utiliser le <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/service/ServicesLocator.html">ServiceLocator</a>. Intégrons maintenant le système <strong>IOC</strong> pour ne plus avoir à le gérer  !</p>
<p>Ce fichier vous permet de décrire des objets, pour ensuite les récupérer et les instancier dans votre application ( via <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/ioc/ApplicationContext.html">ApplicationContext</a> ). Ce fichier s’inspire fortement des fichiers de configuration de Spring, un framework puissant pour Java.</p>
<p>Ci-dessous le fichier représentant 2 services <strong>RemoteObject</strong> :</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;objects&gt;

	&lt;object id=&quot;remotingUser&quot; className=&quot;mx.rpc.remoting.mxml.RemoteObject&quot;&gt;
		&lt;property name=&quot;destination&quot; className=&quot;String&quot;&gt;javaFacadeUser&lt;/property&gt;
		&lt;property name=&quot;showBusyCursor&quot; className=&quot;Boolean&quot;&gt;true&lt;/property&gt;
	&lt;/object&gt;

	&lt;object id=&quot;remotingOther&quot; className=&quot;mx.rpc.remoting.mxml.RemoteObject&quot;&gt;
		&lt;property name=&quot;destination&quot; className=&quot;String&quot;&gt;javaFacadeOther&lt;/property&gt;
		&lt;property name=&quot;showBusyCursor&quot; className=&quot;Boolean&quot;&gt;true&lt;/property&gt;
	&lt;/object&gt;

&lt;/objects&gt;
</pre>
<ul>
<li>Le tag <strong>&lt;objects&gt;</strong> englobe les différents objets définis dans le fichier. Il est défini par :</li>
<li>Un objet <strong>&lt;object&gt;</strong> est défini par :
<ul>
<li>un identifiant <strong><em>id</em></strong>. Cet id est celui que nous utiliserons plus tard dans l’application Flex pour retrouver et instancier l’objet.</li>
<li> un nom de classe <strong><em>className</em></strong> : la classe de référence.</li>
</ul>
</li>
<li>Les propriétés des objets sont définies par :
<ul>
<li>leur nom <strong><em>name</em></strong></li>
<li>leur classe <strong><em>className</em></strong> de référence.</li>
</ul>
</li>
</ul>
<p>Ici, un <a href="http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/mxml/RemoteObject.html">RemoteObject</a> a besoin de 2 propriétés : la <em>destination</em> du type String, et éventuellement <em>showBusyCursor</em> du type Boolean.</p>
<h3><strong>Régler le problème d’inclusion de classe</strong></h3>
<p>Le “petit” problème de ce système est que la déclaration externe des objets fait que les classes ne sont pas intégrées dans le projet Flex. Le compilateur Flex ne trouve pas de référence aux classes, et ne les intègre donc pas dans la compilation. Un façon très simple de régler ce problème est de créer un petit fichier actionScript, et d’ajouter des objets bidons du même type que ceux définis dans votre fichier de config.</p>
<p>Exemple avec les services : (fichier includeService.as)</p>
<pre class="brush: js">
import mx.rpc.http.mxml.HTTPService;
import mx.rpc.remoting.mxml.RemoteObject;
import mx.rpc.soap.mxml.WebService;

private var ser1:RemoteObject;
private var ser2:HTTPService;
private var ser3:WebService;
</pre>
<p>Ce fichier sera intégré dans votre application.</p>
<h3><strong>Chargement et gestion du contexte XML</strong></h3>
<p>Vous allez voir : simple comme bonjour !<br />
Nous allons ajouter le chargement du fichier via <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/ioc/ApplicationContext.html">ApplicationContext</a>. <strong>ApplicationContext</strong> permet de charger automatiquement le contexte cible, et de retrouver, instancier, et<strong> enregistrer automatiquement tous les service</strong>s qui se trouvent dans votre fichier de configuration XML dans le <strong>ServicesLocator</strong>.</p>
<p>Votre application finale :</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	layout=&quot;absolute&quot;

	creationComplete=&quot;init()&quot;

	xmlns:model=&quot;model.*&quot;
	xmlns:view=&quot;view.*&quot;
	xmlns:controller=&quot;controller.*&quot;
	xmlns:service=&quot;service.*&quot;&gt;

	&lt;mx:Script&gt;
		&lt;![CDATA[
			import com.lafabrick.reflex.ioc.event.ContextEvent;
			import com.lafabrick.reflex.ioc.ApplicationContext;
			import com.lafabrick.reflex.controller.ControllerLocator;
			import com.lafabrick.reflex.service.ServicesLocator;

			include &quot;includeService.as&quot;

			private function init() : void
			{
				ApplicationContext.addEventListener(
					ContextEvent.CONTEXT_LOADED, onLoaded );

				ApplicationContext.load( &quot;ioc/application-config.xml&quot; );
			}

			private function onLoaded( event:ContextEvent ) :void
			{
				// Contexte chargé
				// ...
			}

		]]&gt;
	&lt;/mx:Script&gt;

	&lt;controller:UserController id=&quot;userControl&quot; /&gt;

	&lt;model:UserModel id=&quot;userModel&quot; /&gt;

	&lt;view:LoginView id=&quot;view&quot; /&gt;

&lt;/mx:Application&gt;
</pre>
<ul>
<li>Nous continuons à utiliser le “<strong>creationComplete</strong>” pour déclencher la fonction<strong> init()</strong> qui chargera le fichier de configuration.</li>
<li>Il ne faut pas oublier d’inclure au besoin les classes contenues dans notre fichier de config !
<pre class="brush: js">
include &quot;includeService.as&quot;
</pre>
</li>
<li>Dans la fonction<strong> init()</strong>, nous ajoutons un écouteur sur <strong>ApplicationContext</strong> (<a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/ioc/event/ContextEvent.html#CONTEXT_LOADED">ContextEvent.CONTEXT_LOADED</a>), qui déclenchera la fonction <strong>onLoaded</strong> quand le fichier de configuration sera chargé. Puis nous lançons le chargement du fichier de config (<strong> ioc/application-config.xml</strong> ).</li>
<li>&#8230; Et nous incluons la vue LoginView.</li>
</ul>
<h3><strong>Modification de notre UserController</strong></h3>
<p>Dans un soucis de clarté, nous allons créer 2 classes contenants les constantes référençants les noms des services (contenus dans le fichier de configuration), et les noms des méthodes de ces services.</p>
<p>MethodConstant (dans notre exemple uniquement la méthode login)</p>
<pre class="brush: js">
package service
{
	public class MethodConstant
	{
		public static const LOGIN:String = &quot;login&quot;;
	}
}
</pre>
<p>ServiceConstant (les identifiants des objets contenus dans le fichier de configuration)</p>
<pre class="brush: js">
package service
{
	public class ServiceConstant
	{
		public static const SERVICE_USER:String = &quot;remotingUser&quot;;
		public static const SERVICE_OTHER:String = &quot;remotingOther&quot;;
	}
}
</pre>
<p>Nous venons de charger notre fichier de configuration au niveau de notre Application. Nous devons maintenant modifier notre contrôleur pour qu&#8217;il <strong>écoute le chargement du fichier</strong> (événement ContextEvent.CONTEXT_LOADED), et <strong>mette à jour sa propriété service</strong>.</p>
<pre class="brush: js">
package controller
{
	import com.lafabrick.reflex.controller.BaseController;
	import com.lafabrick.reflex.ioc.ApplicationContext;
	import com.lafabrick.reflex.ioc.event.ContextEvent;
	import com.lafabrick.reflex.model.ModelLocator;
	import com.lafabrick.reflex.service.ServicesLocator;

	import dataObject.UserDo;

	import model.UserModel;

	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;

	import service.MethodConstant;
	import service.ServiceConstant;

	public class UserController extends BaseController
	{

		public function UserController() : void
		{
			ApplicationContext.addEventListener(ContextEvent.CONTEXT_LOADED, onLoaded);
		}

		private function onLoaded( event:ContextEvent ) :void
		{
			// Contexte chargé
			this.service = ServicesLocator.getService( ServiceConstant.SERVICE_USER );
		}

		public function login( log:String, pass:String ) : void
		{
			executeMethod(MethodConstant.LOGIN, onLoginResult, onLoginFault, log, pass);
		}

		public function onLoginResult( event:ResultEvent ) : void
		{
			(ModelLocator.getModel( UserModel ) as UserModel).userLogged =
				event.result as UserDo;

			trace((ModelLocator.getModel( UserModel ) as UserModel).userLogged.name);
		}
		public function onLoginFault( event:FaultEvent ) : void
		{
			trace(&quot;resultat pourri ...&quot;+event.fault);
		}

	}
}
</pre>
<p><strong><a href="http://www.lafabrick.com/labz/reflex/tuto/reflexTuto2.zip">Les sources de cette exemple</a></strong></p>
<p>Et voilà ! Je vais préparer d&#8217;autres articles, notemment l&#8217;intégration de Reflex dans un projet Gumbo/Flex4. N&#8217;hésitez pas à poster vos retours, c&#8217;est en flexant qu&#8217;on devient flexeron.Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/10/03/256-titre/" rel="bookmark" title="3 octobre 2007">Utiliser Cairngorm dans un projet Flex / AMFPHP</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/06/06/327-google-language-api-flex/" rel="bookmark" title="6 juin 2008">Google AJAX Language API&#8230; et ton Flex devient polyglotte !</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/" rel="bookmark" title="13 janvier 2009">Reflex #1: une micro-architecture pour Flex&#8230; simple !</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/07/14/1920-flex-4-layouts-viewstack-pure-spark/" rel="bookmark" title="14 juillet 2010">Flex 4 et les layouts &#8211; Faire une ViewStack &laquo;&nbsp;pure&nbsp;&raquo; Spark</a></li>
</ul>
<p><!-- Similar Posts took 17.205 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/15/819-reflex-2-vous-reprendez-bien-un-peu-de-ioc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Reflex #1: une micro-architecture pour Flex&#8230; simple !</title>
		<link>http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 23:05:01 +0000</pubDate>
		<dc:creator>Fabien</dc:creator>
				<category><![CDATA[La Fabrick]]></category>
		<category><![CDATA[Nos projets]]></category>
		<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=786</guid>
		<description><![CDATA[Après un temps de test, de mise en place et re-factorisation en tout genre, j’ai décidé de partager la petite micro-architecture que j’ai mis en place à l’université, et que j’utilise dans mes projets. Let&#8217;s gamble ! Encore un MVC ? Oui. Plus sérieusement, l’écriture de cette micro-architecture est partie d’un besoin de simplicité et [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.lafabrick.com/labz/reflex/images/reflexImgTuto1.jpg" alt="reflex image tut 1" title="reflex image tut 1" width="520" height="220" class="aligncenter size-full wp-image-915" /><br />
Après un temps de test, de mise en place et re-factorisation en tout genre, j’ai décidé de partager la petite micro-architecture que j’ai mis en place à l’université, et que j’utilise dans mes projets.</p>
<p><strong>Let&#8217;s gamble !</strong><br />
<span id="more-786"></span></p>
<h3><strong>Encore un MVC ?</strong></h3>
<p>Oui.<br />
Plus sérieusement, l’écriture de cette micro-architecture est partie d’un besoin de simplicité et de robustesse.</p>
<p>Souvent dans le monde de Flex, les équipes ne sont pas forcement homogènes. Certains sont habitués à la rigueur de Java, d’autres sont plus “devsigners freestyle” venant du monde Flash. Les premiers aiment les grosses mécaniques comme <a href="http://puremvc.org/">PureMVC</a>, ou <a href="http://www.pranaframework.org/">Prana Framework</a> “Spring like”. Les seconds connaissent au mieux <a href="http://opensource.adobe.com/wiki/display/cairngorm/Cairngorm">Cairngorm</a>, au pire confondent <a href="http://en.wikipedia.org/wiki/Model-view-controller">MVC</a> et <a href="http://fr.wikipedia.org/wiki/Ventilation_m%C3%A9canique_contr%C3%B4l%C3%A9e">VMC</a> &#8211; ce qui n’a rien a voir, sauf si vous faites une application riche sur le thème de la ventilation.<br />
Il fallait donc trouver la solution la plus efficace pour avoir un flux de production  le plus optimal.</p>
<p>Bon vous me direz “ba Cairngorm c’est pas mal” ! Oui mais voilà. Cairngorm est plus une ligne de conduite qu’une micro-architecture. Il suffit en gros de suivre les interfaces et d’écrire son MVC. C’est simple, mais pourquoi diable utiliser ces #?~! d’événements synchrones pour déclencher des commandes ! Et il devient assez pénible de dupliquer le travail déjà fait côté serveur&#8230; sans compter le temps de compilation à rallonge. C’est rigolo pour se faire les dents, mais au bout d’un moment faut être sérieux.</p>
<p>Donc Reflex.</p>
<h3><strong>Le MVC en 2 mots</strong></h3>
<p>MVC, pour Model View Controller, est le design pattern le plus connu. Le but de ce pattern est de décomposer la représentation graphique (la vue), la couche métier et le modèle de données.</p>
<p>Le modèle MVC de Reflex peut se visualiser comme suit :</p>
<p><img src="http://www.lafabrick.com/labz/reflex/images/MVCReflex.png" alt="MVC architecture" /></p>
<ul>
<li>La vue demande au contrôleur la récupération de données.</li>
<li>Le contrôleur lance la méthode avec les arguments associés, et capte les retours du serveur.</li>
<li>À la réception des données, le contrôleur met à jour le modèle de données.</li>
<li>Le modèle notifie à la vue son changement et la met à jour.</li>
</ul>
<h3><strong>Préparation de votre projet d’exemple</strong></h3>
<p><b><a href="http://www.lafabrick.com/blog/reflex/">Une page de ressources pour Reflex</a> est disponible sur le Blog.</b></p>
<p>Commencez par récupérer <a href=" http://www.lafabrick.com/labz/reflex/bin/reflex.swc">le swc reflex</a>.<br />
<a href="http://www.lafabrick.com/labz/reflex/source/reflex-src.zip">Les sources</a>, et <a href="http://www.lafabrick.com/labz/reflex/apidoc/">la documentation</a> sont aussi disponibles en lignes. </p>
<p>Pour cette exemple, nous allons utiliser un petit service Java. Je vous laisse <a href="http://www.lafabrick.com/labz/reflex/tuto/reflexTuto1.zip">télécharger le projet d’exemple “reflexTuto1”</a>, et regarder :</p>
<ul>
<li>le répertoire “java” : les sources Java ( UserDo : l’object de donnée, UserDs : la couche métier ).</li>
<li>Les fichiers de configuration dans le répertoire <strong>WebContent/WEB-INF/flex/remoting-config.xml</strong> : la configuration des services distants.</li>
</ul>
<p>Pour cette exemple vous aurez besoin d&#8217;un environnement Flex avec les WTP installés ainsi qu&#8217;un serveur Tomcat (pour lancer les exemples).</p>
<p>Petit rappel : </p>
<ul>
<li>
<strong>Pour installer les WPT</strong> ( qui vous donne accès à la perspective J2EE et à la vue server) :</p>
<ul>
<li>Ouvrez le menu <strong>Help > Software updates > Find and install…</strong></li>
<li>Faites “<strong>Search new features to install</strong>”</li>
<li>Dans la fenêtre qui apparaît, cochez “<strong>Europa Discovery Site</strong>”</li>
<li>Cliquez sur “<strong>Finish</strong>”</li>
<li>La recherche de plugins commence. Vous devrez choisir votre miroir. La fenêtre de résultats s’affiche. Déployez “<strong>Europa Update Site</strong>” et cochez “<strong>Web and J2EE Development</strong>”</li>
<li>Cliquez sur le bouton “<strong>Select Required</strong>”</li>
<li>Faites “<strong>Next</strong>”</li>
<li>Cochez <strong>“I accept…</strong>”</li>
<li>Faites “<strong>Next</strong>” de nouveau</li>
<li>Faites “<strong>Finish</strong>”</li>
</ul>
</li>
<li>
<strong>Pour installer un serveur TOMCAT</strong></p>
<ul>
<li>Téléchargez un <a href="http://apache.cict.fr/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip">Tomcat 6</a></li>
<li>Décompressez l&#8217;archive dans le répertoire de votre choix</li>
<li>Vous devez configurer votre serveur dans Flex à partir de la vue Server : &laquo;&nbsp;<strong>Windows > Other View&#8230;</strong>&nbsp;&raquo; puis &laquo;&nbsp;<strong>Servers</strong>&laquo;&nbsp;</li>
<li>Un fois configuré (clic droit dans la vue servers et &laquo;&nbsp;<strong>New&#8230;</strong>&laquo;&nbsp;), n&#8217;oubliez pas d&#8217;ajouter votre projet sur votre serveur ! (clic droit dans la vue servers et &laquo;&nbsp;<strong>Add and remove projects&#8230;</strong>&laquo;&nbsp;)</li>
</ul>
</li>
</ul>
<h3><strong>Au départ : un service et un objet de données</strong></h3>
<p>Tout d’abord nous devons représenter l’objet de données du serveur dans votre projet.</p>
<p>L’objectif est d’avoir une image identique des données côté serveur et côté Flex, afin que les 2 parties “parlent la même langue” : cette classe contient une référence vers son “image” côté serveur.</p>
<pre class="brush: js">
package dataObject
{

	[Bindable]
	[RemoteClass(alias=&quot;User.UserDo&quot;)]
	public class UserDo
	{
		public function UserDo()
		{
		}

		public var login:String;
		public var name:String;

	}
}
</pre>
<p>Nous voulons discuter avec la couche server : nous allons donc utiliser un service de type <strong><a href="http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/mxml/RemoteObject.html">RemoteObject</a></strong>, faisant référence à notre couche serveur, défini dans le fichier <strong>remoting-config.xml</strong>.</p>
<pre class="brush: xml">
&lt;mx:RemoteObject
	id=&quot;remoteUser&quot;
	destination=&quot;javaFacadeUser&quot;
	showBusyCursor=&quot;true&quot; /&gt;;
</pre>
<h3><strong>Le Modèle</strong></h3>
<p>Le modèle est notre réceptacle de données.<br />
Cette classe étend <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/model/BaseModel.html">BaseModel</a>, qui permet l’enregistrement automatique du modèle dans le <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/model/ModelLocator.html">ModelLocator</a>.<br />
C’est lui qui sera mis à jour par le <strong>contrôleur</strong>, et qui, via le tag <strong>[Bindable]</strong>, mettra a jour là vue. Dans notre exemple nous allons stocker le UserDo, résultant de la requête serveur login().</p>
<pre class="brush: js">
package model
{
	import com.lafabrick.reflex.model.BaseModel;

	import dataObject.UserDo;

	public class UserModel extends BaseModel
	{
		[Bindable]
		public var userLogged:UserDo;

	}
}
</pre>
<h3><strong>Le Contrôleur</strong></h3>
<p>C’est l’intelligence du système. C’est lui qui invoque le service, récupère et met à jour les données.</p>
<pre class="brush: js">
package controller
{
	import com.lafabrick.reflex.controller.BaseController;
	import com.lafabrick.reflex.model.ModelLocator;

	import dataObject.UserDo;

	import model.UserModel;

	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;

	public class UserController extends BaseController
	{

		public function login( log:String, pass:String ) : void
		{
			executeMethod( &quot;login&quot;, onLoginResult, onLoginFault, log, pass);
		}

		public function onLoginResult( event:ResultEvent ) : void
		{
			(ModelLocator.getModel( UserModel ) as UserModel).userLogged =
				event.result as UserDo;
		}

		public function onLoginFault( event:FaultEvent ) : void
		{
			trace(&quot;Bad result ...&quot;+event.fault);
		}
	}
}
</pre>
<ul>
<li>Cette classe étend <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/controller/BaseController.html">BaseController</a>, qui permet l’enregistrement automatique du contrôleur dans le <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/controller/ControllerLocator.html">ControllerLocator</a>.</li>
<li> La méthode <strong>login()</strong> contient la mécanique de déclenchement du <strong>service</strong> (méthode de BaseController). La méthode <strong>executeMethod</strong> est définie par les propriétés suivantes :
<ul>
<li><strong><em>method:String</em></strong> : le nom de la méthode ( “login” ),</li>
<li><strong><em>resultFunction:Function</em></strong> : la fonction déclenchée lorsque le serveur renvoie un résultat (onLoginResult)</li>
<li><strong><em>faultFunction:Function = null</em></strong> : la fonction déclenchée lorsque le serveur renvoie une faute (onLoginFault)</li>
<li><strong><em>&#8230; args</em></strong> : tous les arguments à passer à la méthode distante&#8230;</li>
</ul>
</li>
<li>Le modèle est mis à jour dans le fonction de résultat. Pour récupérer l’instance du modèle, il suffit d’utiliser le <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/model/ModelLocator.html">ModelLocator</a> :
<pre class="brush: xml">
// Renvoie l&#039;instance UserModel enregistré dans ModelLocator
trace( ( ModelLocator.getModel( UserModel ) as UserModel ) );
</pre>
</li>
</ul>
<p><span style="color: #800000;"><br />
<b>NOTE</b> : les “locator” <b>ModelLocator</b> et <b>ControllerLocator</b> n’enregistrent qu’une et une seul instance d’un même modèle / contrôleur. Si deux instances d’un même modèle / contrôleur sont déclarées, une erreur <a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/ReflexError.html">ReflexError</a> est levée. Les classes étendant <b>BaseController</b> et <b>BaseModel</b> sont automatiquement référencées dans <b>ModelLocator</b> et <b>ControllerLocator</b>.<br />
</span></p>
<h3><strong>La Vue</strong></h3>
<p>Construisons maintenant notre vue.</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	layout=&quot;absolute&quot;
	xmlns:controller=&quot;controller.*&quot;
	xmlns:model=&quot;model.*&quot;&gt;

&lt;mx:RemoteObject
	id=&quot;remoteUser&quot;;
	destination=&quot;javaFacadeUser&quot;;
	showBusyCursor=&quot;true&quot; /&gt;

	&lt;controller:UserController id=&quot;userControl&quot; service=&quot;{remoteUser}&quot; /&gt;

	&lt;model:UserModel id=&quot;userModel&quot; /&gt;

	&lt;mx:VBox&gt;
		&lt;mx:TextInput id=&quot;login&quot; /&gt;
		&lt;mx:TextInput id=&quot;password&quot; displayAsPassword=&quot;true&quot; /&gt;

		&lt;mx:Button label=&quot;connect&quot;
			click=&quot;{userControl.login( login.text, password.text )}&quot; /&gt;

		&lt;mx:Label x=&quot;208&quot; y=&quot;44&quot;
			text=&quot;User Name : {userModel.userLogged.name}&quot;/&gt;;
	&lt;/mx:VBox&gt;

&lt;/mx:Application&gt;
</pre>
<ul>
<li>Nous créons une instance RemoteObject permettant de pointer sur le service côté serveur. La propriété <em>destination</em> est l’identifiant du service dans le fichier <strong>remoting-config.xml</strong>.</li>
<li>Nous créons une instance de <b>UserController</b>, avec comme propriété <em>service</em> l’identifiant du RemoteObject “<strong>remoteUser</strong>”.</li>
<li>De la même manière, nous créons l’instance du modèle UserModel.</li>
<li>Au final, la vue appel la méthode <strong>login()</strong> du contrôleur, qui se charge d’envoyer et de réceptionner les données au serveur. Au retour, le contrôleur met à jour le modèle, en “poussant” le UserDo provenant du serveur. La vue est automatiquement mise à jour via le principe de Binding des données.</li>
</ul>
<p><b><a href="http://www.lafabrick.com/labz/reflex/tuto/reflexTuto1.zip">Les sources de cette exemple</a></b></p>
<h3><strong>Conclusion</strong></h3>
<p>Reflex n’a pas la prétention de concurrencer des architectures reconnues comme <a href="http://puremvc.org/">PureMVC</a> ou <a href="http://mate.asfusion.com/">MATE</a>. L’objectif, vous l’aurez compris, est d’aller à l’essentiel, sans se perdre dans la forêt des Design Pattern,  pour une productivité la plus efficace possible. A vous d’implémenter cette architecture selon vos besoins.</p>
<p>Le prochain tutoriel ira un peu plus loin dans cette micro-architecture : comment mieux découper son projet, et comment associer un fichier de configuration XML externe (<a href="http://www.lafabrick.com/labz/reflex/apidoc/com/lafabrick/reflex/ioc/package-detail.html">package IOC</a>).</p>
<p>J’attends vos retours !Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/10/03/256-titre/" rel="bookmark" title="3 octobre 2007">Utiliser Cairngorm dans un projet Flex / AMFPHP</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/06/06/327-google-language-api-flex/" rel="bookmark" title="6 juin 2008">Google AJAX Language API&#8230; et ton Flex devient polyglotte !</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/15/819-reflex-2-vous-reprendez-bien-un-peu-de-ioc/" rel="bookmark" title="15 janvier 2009">Reflex #2 : vous reprendrez bien un peu de IOC ?</a></li>
<li><a href="http://www.lafabrick.com/blog/2010/07/14/1920-flex-4-layouts-viewstack-pure-spark/" rel="bookmark" title="14 juillet 2010">Flex 4 et les layouts &#8211; Faire une ViewStack &laquo;&nbsp;pure&nbsp;&raquo; Spark</a></li>
</ul>
<p><!-- Similar Posts took 21.407 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/13/786-reflex-1-une-micro-architecture-pour-flex-simple/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Développer une application iPhone &#8211; Introduction aux concepts de base</title>
		<link>http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/</link>
		<comments>http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 23:33:28 +0000</pubDate>
		<dc:creator>Hervé</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[Conseils]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=753</guid>
		<description><![CDATA[<p>Il est des petits appareils qui font envie de nos jours : l'iPhone fait certainement partie des premiers de cette liste.</p>
<p>Voilà donc un tutoriel d'approche d'une technologie nouvelle pour des personnes n'ayant aucune notion de développement dans ce domaine.</p>]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Il est des petits appareils qui font envie de nos jours : l&#8217;iPhone fait certainement partie des premiers de cette liste.</p>
<p>Voilà donc un tutoriel d&#8217;approche d&#8217;une technologie nouvelle pour des personnes n&#8217;ayant aucune notion de développement dans ce domaine.</p>
<p>Je parlerai donc ici :</p>
<ul>
<li>Des principaux concepts à maîtriser <strong>absolument</strong> pour bien démarrer un développement pour iPhone</li>
<li>De quelques exemples permettant d&#8217;illustrer les concepts</li>
</ul>
<p>Je ne parlerai pas :</p>
<ul>
<li>Des différences entre un développement pour Mac par rapport à un développement pour iPhone</li>
<li>De quelconques &laquo;&nbsp;best practices&nbsp;&raquo; de développement</li>
</ul>
<p>Il s&#8217;agit plutôt d&#8217;un retour d&#8217;expérience qui permettra peut-être à d&#8217;autres personnes d&#8217;appréhender un développement pour iPhone sans trop se casser les dents.</p>
<p>Pour la suite, la documentation fournie par Apple est très complète et peut vous donner de quoi satisfaire vos nuits blanches pour un bon moment !</p>
<p><span id="more-753"></span></p>
<h4>Pour bien démarrer</h4>
<ol>
<li>Comprendre l&#8217;environnement nécessaire au développement d&#8217;une application iPhone
<ol>
<li>Les principaux concepts</li>
<li>Les outils</li>
</ol>
</li>
<li>Ouvrir quelques projets d&#8217;exemple pour se familiariser avec la syntaxe Objective-C</li>
<li>Créer son premier projet</li>
</ol>
<p>Ce premier article présente les concepts et introduit la liste des outils nécessaires au développement.</p>
<h4>Note aux pressés (j&#8217;en fais généralement partie)</h4>
<p>Si vous grillez les deux premières étapes, vous risquez rapidement de vous rendre compte qu&#8217;elles vous manquent et perdrez certainement beaucoup plus de temps que si vous y consacrez une petite journée.</p>
<h3>Comprendre l&#8217;environnement nécessaire au développement d&#8217;une application iPhone</h3>
<h4>Les principaux concepts</h4>
<p>Pour commencer, il est indispensable de maîtriser quelques bases de fonctionnement d&#8217;un programme iPhone.</p>
<p><strong>Une application iPhone est une application MVC</strong> dans sa plus pure forme. Vous concevez des <strong>vues</strong>, manipulées par des <strong>contrôleurs</strong> en faisant transiter des données d&#8217;un <strong>modèle</strong>.</p>
<h5>Application delegate</h5>
<p>Il s&#8217;agit de la classe en charge du lancement de l&#8217;application et de l&#8217;affichage de la fenêtre principale.<br />
Vous pouvez vous en servir pour initialiser des éléments particuliers communs à l&#8217;ensemble des éléments de votre application :</p>
<ul>
<li>connexion à une base de données,</li>
<li>configuration générale,</li>
<li>&#8230;</li>
</ul>
<h5>View controller</h5>
<p>Classe gérant la vue et pouvant recevoir les événements propres aux composants de la vue gérée.</p>
<h5>View</h5>
<p>Une vue, chargée d&#8217;afficher des contrôles. </p>
<p>Il faut savoir qu&#8217;une vue peut être créée par programme ou en utilisant des fichiers de ressources définis à l&#8217;aide de l&#8217;interface builder.</p>
<p>Ce sont deux moyens différents qui présentent leurs avantages et inconvénients&#8230; A vous de voir lequel convient le mieux à telle ou telle situation.</p>
<h5>Delegate</h5>
<p>C&#8217;est un terme souvent employé dans un programme.</p>
<p>Un délégué est un objet prenant en charge un certain nombre de méthodes remplissant des fonctions propres à un émetteur.</p>
<p>En pratique, un view controller est, dans la plupart des cas, désigné comme délégué des composants de la vue et va implémenter les méthodes répondant aux événements que chacun d&#8217;entre eux déclenche.</p>
<p>Par exemple, un composant table view (tableau) va appeler différentes méthodes de son délégué pour pouvoir s&#8217;afficher convenablement :</p>
<p><code>- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView</code><br/>Doit renvoyer le nombre de sections dans le tableau</p>
<p><code>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section</code><br/>Doit renvoyer le nombre de lignes du tableau à afficher pour la section dont le numéro est passé en paramètre</p>
<p><code>- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath</code><br/>Doit initialiser une cellule du tableau pour le numéro de section et de ligne passé en paramètre</p>
<p>Ce mode de fonctionnement permet notamment que n&#8217;importe que objet soit désigné comme délégué. On peut donc très bien imaginer avoir les deux possibilités suivantes :</p>
<p><img src="http://www.lafabrick.com/blog/wp-content/uploads/2009/01/iphone-delegates.png" alt="iPhone - Concept de delegate" title="iPhone - Concept de delegate" width="500" height="444" class="alignnone size-full wp-image-779" /></p>
<ul>
<li><strong>Le schéma A</strong> montre l&#8217;exemple le plus courant : une seule classe faisant office de ViewController et de Delegate pour l&#8217;ensemble des contrôles de la vue.</li>
<li><strong>Le schéma B</strong> montre une alternative intéressante lors de gestion de vues complexes : une classe Delegate par contrôle et un ViewController standard.</li>
</ul>
<p>La différence entre ces deux solutions, c&#8217;est que le premier ViewController contiendra l&#8217;ensemble du code de BoutonDelegate, Tableau1Delegate et Tableau2Delegate, le rendant peut-être plus complexe à lire et à comprendre.</p>
<p>Ceci étant dit passons aux outils.</p>
<h3>Les outils</h3>
<p>Vous avez trois outils à votre disposition :</p>
<ol>
<li><strong>XCode</strong> : l&#8217;environnement de développement en charge de coder, compiler et lancer la deuxième application</li>
<li><strong>Le simulateur iPhone</strong> : une application simulant à quelques restrictions près un iPhone et vous permettant de tester unitairement vos fonctionnalités</li>
<li><strong>Interface Builder</strong> : l&#8217;outil de création d&#8217;interfaces (écrans, vues&#8230;)</li>
</ol>
<p>XCode est un peu l&#8217;application maître et lance ses 2 gentils larbins pour faciliter le développement.</p>
<p>Dans le prochain article, passage aux choses sérieuses : nous ouvrirons XCode pour voir comment cette théorie se traduit en pratique, histoire d&#8217;illustrer un peu ces jolis concepts.</p>
<p>A la prochaine !<br />
Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2006/11/16/19-petit-cour-sur-lapi-de-dessin/" rel="bookmark" title="16 novembre 2006">Petit cours sur l’API de dessin</a></li>
<li><a href="http://www.lafabrick.com/blog/2008/01/10/288-cairngorm-pour-les-fainants-tour-d-horizons-des-code-generator/" rel="bookmark" title="10 janvier 2008">Cairngorm pour les fainéants&#8230; Tour d&#8217;horizons des code generator</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/16/807-developper-une-application-iphone-xcode-et-interface-builder-passes-au-crible/" rel="bookmark" title="16 janvier 2009">Développer une application iPhone &#8211; XCode et Interface Builder passés au crible</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/" rel="bookmark" title="31 janvier 2009">Hello AFCS ( bye Cocomo ) : première application multi-utilisateurs</a></li>
</ul>
<p><!-- Similar Posts took 13.282 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2009/01/12/753-developper-une-application-iphone-introduction-aux-concepts-de-base/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Cocomo ? Kezako ?</title>
		<link>http://www.lafabrick.com/blog/2008/12/22/568-cocomo-kezako/</link>
		<comments>http://www.lafabrick.com/blog/2008/12/22/568-cocomo-kezako/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 15:58:49 +0000</pubDate>
		<dc:creator>Erick</dc:creator>
				<category><![CDATA[[Dev] Flash / Flex / AIR...]]></category>
		<category><![CDATA[cocomo]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[RIA]]></category>
		<category><![CDATA[Tutoriels]]></category>

		<guid isPermaLink="false">http://www.lafabrick.com/blog/?p=568</guid>
		<description><![CDATA[LaFabrick invitée sur FlashXpress » votre première application collaborative en 15mn ! Mais pourquoi diable se priver !!??? Autres articles sur le même sujet Cocomo est là et personne me prévient ??!! L&#8217;erreur est humaine&#8230; debuguer un projet Flex distant via Flex Builder Developing with AFCS a.k.a Cocomo &#8211; Introduction Hello AFCS ( bye Cocomo [...]]]></description>
			<content:encoded><![CDATA[<p>LaFabrick invitée sur FlashXpress » <a title="FlashXpress : introduction à Cocomo ... by LaFabrick" href="http://www.flashxpress.net/category/ressources-flex/" target="_blank">votre première application collaborative</a> en 15mn ! Mais pourquoi diable se priver !!??? <img src='http://www.lafabrick.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p style="text-align: center;"><a href="http://www.flashxpress.net/category/ressources-flex/" target="_blank"><img class="aligncenter" title="FlashXPress : introduction à Cocomo... by laFabrick" src="http://lafabrick.free.fr/blogImg/lien_tuto_cocomo-20081222-070459.jpg" alt="" width="520" height="168" /></a></p>
<p>Autres articles sur le même sujet
<ul>
<li><a href="http://www.lafabrick.com/blog/2007/12/07/274-cocomo-dbarque-et-personne-me-prvient/" rel="bookmark" title="7 décembre 2007">Cocomo est là et personne me prévient ??!!</a></li>
<li><a href="http://www.lafabrick.com/blog/2007/11/15/266-debuguer-un-projet-flex-distant-via-flex-builder/" rel="bookmark" title="15 novembre 2007">L&#8217;erreur est humaine&#8230; debuguer un projet Flex distant via Flex Builder</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/21/999-what-is-adobe-cocomo/" rel="bookmark" title="21 janvier 2009">Developing with AFCS a.k.a Cocomo &#8211; Introduction</a></li>
<li><a href="http://www.lafabrick.com/blog/2009/01/31/1040-hello-cocomo-first-app/" rel="bookmark" title="31 janvier 2009">Hello AFCS ( bye Cocomo ) : première application multi-utilisateurs</a></li>
</ul>
<p><!-- Similar Posts took 12.556 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lafabrick.com/blog/2008/12/22/568-cocomo-kezako/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

