mardi 2 août 2011

Le 'Code Behind' en Flex

Comme on sait tous, développer en Flex voudrait dire manipuler deux langages : MXML et ActionScript. Le plus gros avantage de la présence des deux langages est de distinguer les parties 'Vue' des parties 'Traitement' (même si on pourrait tout faire avec un seul des deux). Cependant dès qu'on commence à avoir des composants MXML volumineux qui contiennent un bloc 'Script' (ou plusieurs!!) qui inclut du code ActionScript ou fait appel à un fichier script externe (ou les deux!!), ça devient difficile de se repérer dans le code. Sans oublier que des fois l'assistance au développement de FB3/4 (linkage Ctrl+click par exemple) ne marche plus.

Une manière d'éviter tous ces problème en mettant un peu d'ordre dans son code, sans pour autant se contraindre à suivre un patron de conception (pattern) sophistiqué est d'utiliser la méthode code behind (le code à coté en français) en l'adaptant au flex. Cela consiste à ce que chaque composant mxml hérite d'une classe ActionScript. Du coup chaque appel de méthode ou de gestionnaire d’évènement est faite d'une manière transparante depuis le composant mxml et implémenté du coté classe ActionScipt.

Exemple :

Composant mxml : HelloWorldComposant
<?xml version="1.0" encoding="utf-8"?>
<HelloWorldBase xmlns:mx="http://www.adobe.com/2006/mxml">
       <mx:Label id="monBouton"
                 text="Dire bonjour!"
                 click="onButtonClick(event)"/>
</HelloWorldBase>



Classe ActionScript : HelloWorldBase
package com.test
{
 import mx.controls.Button;
        import flash.events.Event;

 public class HelloWorldBase extends VBox
 {
         // déclaration du bouton dans la classe mère
         var monBouton:Button;
                 
         public function HelloWorldBase ()
         {
            super();
         }
 
         protected function onButtonClick(event:Event):void {
            Alert.show("Hello World!");
            monBouton.text = "bravo!";
         }
 }
}




Comme dans l'exemple, pour utiliser un composant mxml internes dans une méthode actionscript , il suffit de le déclarer comme attribut de la classe mère, avec comme nom l'id du composant ('monBouton' dans l'exemple).


Voilà, bon courage!

vendredi 29 juillet 2011

La guerre des scrollbars

Je vous fait part d'un bug sur flex 3 que j'ai rencontré (et que j'ai contourné bien sûre  :D) qui concerne les barres de défilement.

Prenons un exemple : un Canvas qui a un width à 100%  par rapport à son conteneur, c'est à dire que sa largeur est égal à celle de son conteneur (à quelques pixels près en fonction des bordures). Lorsque la barre de défilement vertical est affichée (pour une raison ou pour une autre : manque de hateur dans le contenur, verticalScrollPolicy à ON ... ), la barre de défilement horizental est affiché automatiquement, à tort!

La raison est que la largeur du Canvas ne se met pas à jour automatiquement pour prendre en compte la barre de défilement vertical qui est apparu. Ce qui fait que le conteneur du Canvas n'a pas assez de place pour visualiser entièrement un composant (le Canvas) qui a 100% de largeur et une barre qui à 20 pixel de largeur ça fait un truc genre 100%+20pixel qui est supérieur à 100% qui est la largeur du conteneur :D ...


Bref la barre de défilement horizontal est affichée du coup, et c'est un bug flex 3. CQFD.


Et c'est la même chose si on jout avec la largeur du Canvas ...

Pour contourner le problème j'ai surchargé la méthode validateSize() de mon Canvas pour décider du fait d'afficher ou pas les barres : 
override public function validateSize(recursive:Boolean = false):void {
       super.validateSize(recursive);
       if (!initialized) return;
              validateHorizontalScrollPolicy();
              validateVerticalScrollPolicy();
       }
      
private function validateHorizontalScrollPolicy():void{
       if (width < measuredWidth){ // measuredWidth : largeur visualisée ?!
             horizontalScrollPolicy = ScrollPolicy.AUTO;
       }else{
              horizontalScrollPolicy = ScrollPolicy.OFF;
       }
}
private function validateVerticalScrollPolicy():void{
       if (height < measuredHeight){ // measuredHeight : hauteur visualisée ?!
             verticalScrollPolicy = ScrollPolicy.AUTO;
       }else{
             verticalScrollPolicy = ScrollPolicy.OFF;
       }
}



Le seul problème qui reste est que la méthode validateSize n'est pas appelé à chaque changement de taille du Canvas (c'est un mystère je sais :D). C'est pour ça que dans mon composant je fait l'appel à la méthode  validateSize au déclenchement de l’évènement resize.


Bon voilà le composant : VBoxScrollBugFixed

Sur flex 4 je ne sais pas si le même bug existe, mais je sais que le mécanisme d'ajout/affichage des scrollbar différe de celui de flex 3.

Bon courage, à ciao bonsoir!