Author: kmorin Date: 2009-08-27 15:43:32 +0200 (Thu, 27 Aug 2009) New Revision: 1614 Added: trunk/src/site/resources/deployDiag.png trunk/src/site/rst/codeGeneration.rst trunk/src/site/rst/model.rst Removed: trunk/src/site/rst/fonctionnement.rst Modified: trunk/src/site/rst/architecture.rst trunk/src/site/rst/index.rst trunk/src/site/site.xml Log: update doc Added: trunk/src/site/resources/deployDiag.png =================================================================== (Binary files differ) Property changes on: trunk/src/site/resources/deployDiag.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/src/site/rst/architecture.rst =================================================================== --- trunk/src/site/rst/architecture.rst 2009-08-27 13:42:46 UTC (rev 1613) +++ trunk/src/site/rst/architecture.rst 2009-08-27 13:43:32 UTC (rev 1614) @@ -1,6 +1,17 @@ Architecture ------------ -Le projet comporte plusieurs sous-modules : - * 2 modules génériques qui seront lancés quelque soit le langage généré : guix-compiler et guix-runtime. - * 2 modules par langage générés : e.g. guix-swing-compiler et guix-swing-runtime seront appelés si le langage que l'on veut générer est du Swing. +Le projet Guix est décomposé en 3 grandes parties comme le montre le diagramme ci-dessous : + +guix-compiler : + ce module est le même quelle que soit la librairie graphique utilisée pour la génération. Il comprend le parsing des fichiers Guix et la génération du modèle. Il contient également les classes permettant de représenter un fichier java. +guix-generator : + ce module est différent selon la librairie graphique demandée par l'utilisateur. Il existe pour l'instant guix-generator-swing et guix-generator-gwt. Ces modules contiennent les gestionnaires des différentes balises communes, ainsi que les générateurs de code. +guix-maven-plugin : + ce module est celui qui permet de lancer le programme en interprétant les paramètres du fichier POM. + + +.. image:: deployDiag.png + :align: center + +Chaque application qui aura besoin de générer du code n'aura qu'à ajouter le module guix-maven-plugin aux dépendences du POM et y configurer le plugin. Added: trunk/src/site/rst/codeGeneration.rst =================================================================== --- trunk/src/site/rst/codeGeneration.rst (rev 0) +++ trunk/src/site/rst/codeGeneration.rst 2009-08-27 13:43:32 UTC (rev 1614) @@ -0,0 +1,107 @@ +Génération du code +================== + +La génération du code est globlement la même pour toutes les librairies graphiques demandées, mais certains points diffèrent. + +Fichiers générés +---------------- +Pour toutes les librairies graphiques, chaque fichier XML en entrée est généré sous trois formes : + +interface : + elle contient les méthodes que l'utilisateur peut surcharger, ainsi que les accesseurs et modifieurs +classe abstraite : + elle hérite de la superclasse du GuixModelObject racine, implémente l'interface générée et contient le code généré +classe implémentée : + c'est une sous-classe de la classe abstraite qui ne contient rien de plus, mais qui permet d'instancier la classe abstraite + +L'intérêt de cette classe d'implémentation séparée est que l'utilisateur peut créer ses propres classes d'implémentation sans riquer que son code ne soit effacé par une nouvelle génération. + +Les méthodes générées +--------------------- +Les classes générées possèdent plusieurs types de méthodes : + +Accesseurs et Modifieurs +~~~~~~~~~~~~~~~~~~~~~~~~ +Pour chaque GuixModelObject, Guix génère automatiquement un attribut privé et un accesseur publique. Si l'utilisateur n'a pas mis l'attribut *javaBean* à faux, un modifieur publique est également généré. + +Si un attribut de même identifiant existe déjà dans la superclasse et qu'il est du même type, alors ni l'attribut ni les modifieurs et accesseurs ne sont générés. En revanche, s'il est de type différent que sa classe est une superclasse de l'attribut à générer, alors on surcharge l'attribut de la superclasse. + +Constructeur +~~~~~~~~~~~~ +Le constructeur ne prend aucun paramètre. Si la classe à générer hérite d'une autre classe à générer, alors on appelle le constructeur de la superclasse. Dans tous les cas, on appelle la méthode *initialize()*. +Cette méthode appelle les quatre méthodes générées automatiquement : + +componentsCreation : + c'est la méthode qui instancie les composants +componentsSettings : + c'est la méthode qui paramétrise les attributs des composants +componentsTree : + c'est la méthode qui lie les composants les uns aux autres +initDataBinding : + c'est la méthode qui initialise le data binding (ajoute les écouteurs sur les objets) + +Méthodes surchargeables +~~~~~~~~~~~~~~~~~~~~~~~ +Il existe 5 méthodes vides par défaut, que l'utilisateur peut surcharger et qui s'effectueront chacune à un moment précis, dans cet ordre : +beforeCreation : + s'exécute avant la création des composants +beforeSettings : + s'exécute avant l'affectation des attributs des composants +beforeTree : + s'exécute avant la mise en page des composants +beforeBinding : + s'exécute avant l'application du data binding +inTheEnd : + s'exécute à la fin, quand l'application est prête + +Pour les surcharger, il suffit qu'il les redéfinisse dans un script. + + +Représentation des fichiers à générer +------------------------------------- +La génération de code ne se fait en écrivant directement dans un fichier, mais en utilisant des classes qui représentent les fichiers, comme le montre le diagramme ci-dessous : + +.. image:: file.png + :align: center + +La classe *JavaFile* représente un fichier Java (classe ou interface), *JavaField* un attribut d'une classe, *JavaMethod* une méthode d'une classe et *JavaArgument* ses arguments. + +Cette représentation permet de vérifier l'existence d'attributs dans des fichiers en train d'être générés. + +Gestion des évènements +---------------------- +L'utilisateur peut définir les actions déclenchées par les évènements, directement dans les balises en spécifiant les valeurs des attributs dont le nom est le même que celui de l'évènement déclenché, précédé de "on" (si le nom de l'attribut ne commence pas déjà par "on"). Guix se charge tout seul au moment de la génération de chercher le listener à ajouter à l'objet grâce aux *EventSetDescriptor* contenus dans le *BeanInfo* de la classe de l'objet. + +Data Binding +------------ +Derrière ce terme se cache un mécanisme très utile, celui de lier la valeur d'un attribut d'un objet, à la valeur d'un (ou plusieurs) attribut d'un (ou plusieurs) objet. + +L'utilisateur définit la valeur à laquelle lier un attribut en la mettant entre accolades. Le code entre accolades est analysé et les différents objets ou méthodes sont séparés. + +Guix cherche alors la classe et le *TagHandler* associé pour chaque élément du binding, afin de lui ajouter le bon écouteur. Cet écouteur, lorqu'un évènement est déclenché, appelle une méthode générée qui remet à jour la valeur liée. + +Tag Handlers +------------ +Les tag handlers sont les classes qui permettent d'avoir les balises universelles. Ils sont différents pour chaque module de génération (i.e. pour chaque librairie graphique). + +Chaque module possède une classe d'initialisation qui permet d'associer un tag handler à chaque balise universelle. Ces tag handlers possèdent la classe à générer pour ces balises, ainsi que les vrais noms des attributs universels. + +Ils possèdent également des ProxyEventInfo : il s'agit d'une classe interne qui permet de définir des listeners particuliers pour certains attributs, mais aussi l'attribut sur lequel est appliqué ce listener. Les ProxyEventInfo sont très utiles pour le data binding. Par exemple, en Swing, si on veut lier le texte d'un JLabel au texte d'un JTextField, on n'applique pas le listener sur la méthode *getText()* mais sur la méthode *getDocument()* du JTextField. De même, ce listener ne sera pas un PropertyChangeListener, mais un DocumentListener. + +Héritage +-------- +Si un composant du fichier guix a le même identifiant qu'un composant (ou attribut) de sa superclasse, alors il surcharge ce dernier. + +Si leur classe est la même, alors l'attribut n'est pas généré dans le fichier. En revanche, si la classe du composant du fichier guix est une sous-classe de la classe du composant de la superclasse, alors il est généré. Si ce n'est pas une sous-classe, alors une erreur est déclenchée. + +Différences +----------- +GWT +*** +Pour GWT, Guix génère automatiquement un fichier .*gwt*.*xml*, le fichier *web*.*xml* et un *index*.*html*. Ces fichiers peuvent être redéfini par l'utilisateur s'il les place dans le bon dossier source. Ces fichiers sont principalement des fichiers de configuration. + +De plus, le code CSS présent dans les fichiers guix n'est pas appliqué aux objets, il faut l'écrire dans des fichiers CSS. + +Swing +***** +Pour Swing, guix génère une classe dont le nom est défini par la propriété *launcherName* du POM. Cette classe possède un méthode *main* qui lance le programme généré. Deleted: trunk/src/site/rst/fonctionnement.rst =================================================================== --- trunk/src/site/rst/fonctionnement.rst 2009-08-27 13:42:46 UTC (rev 1613) +++ trunk/src/site/rst/fonctionnement.rst 2009-08-27 13:43:32 UTC (rev 1614) @@ -1,19 +0,0 @@ -Fonctionnement du programme ---------------------------- - -Déroulement de la phase de compilation (génération de l'arbre du modèle) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. image:: guixcompilationactivity.png - :align: center - -Au lancement de la compilation, le programme charge les fichiers *.script* et *.css* du même nom que le fichier à compiler. S'ils existent, il enregistre leur contenu respectivement dans le conteneur des scripts et dans un nouveau *StyleSheet* associé au *GuixModelObject* racine. - -Tout au long du parcours du fichier Guix, on enregistre le contenu des balises *<script>*. À la fin du parcours, on enregistre ce contenu dans le *ClassDescriptor* du *GuixModelObject* racine. - -Dès que le parser rencontre une balise *<style>*, il ajoute une nouvelle instance de *StyleSheet* au *GuixModelObject* racine, contenant soit le fichier spécifié par l'attribut *source* (s'il est renseigné) ou les données entre les balises. - -Représentation de l'arbre du modèle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. image:: guixmodeltree.png Modified: trunk/src/site/rst/index.rst =================================================================== --- trunk/src/site/rst/index.rst 2009-08-27 13:42:46 UTC (rev 1613) +++ trunk/src/site/rst/index.rst 2009-08-27 13:43:32 UTC (rev 1614) @@ -4,11 +4,9 @@ Présentation ------------ -Guix est un projet de générateur d'IHM à partir de fichiers XML et CSS. +Guix est un projet de générateur d'IHM à partir de fichiers XML et CSS. Il permet, à partir de fichiers XML, de générer la même interface graphique sous plusieurs librairies différentes. Pour l'instant, les librairies graphiques disponibles sont Swing et Google Web Toolkit. -Il fait partie du projet Buix consultable sur le labs de Libre Entreprise : `https://labs.libre-entreprise.org/projects/buix/`_ +Il fait partie du projet Buix consultable sur le site Nuiton : http://www.nuiton.org/projects/show/buix Il est basé sur le projet JAXX dont la documentation est présente sur la page suivante : http://buix.labs.libre-entreprise.org/original-jaxx/www.jaxxframework.org/wi... - -.. _https://labs.libre-entreprise.org/projects/buix/: https://labs.libre-entreprise.org/projects/buix/ Added: trunk/src/site/rst/model.rst =================================================================== --- trunk/src/site/rst/model.rst (rev 0) +++ trunk/src/site/rst/model.rst 2009-08-27 13:43:32 UTC (rev 1614) @@ -0,0 +1,78 @@ +Génération de l'arbre du modèle +=============================== + +La première étape du processus de génération est la génération du modèle des données contenues dans les fichiers XML. Guix utilise le parseur XML Pull Parser 3 (XPP3) pour parcourir ces fichiers. Il s'agit d'un parseur qui permet seulement de parcourir un fichier XML de bout en bout (ce qui nous suffit largement dans Guix) mais qui est beaucoup plus léger que SAX par exemple. + +Pour représenter ce modèle, Guix utilise 6 classes comme le montre le diagramme ci-dessous : + +.. image:: guixmodeltree.png + +GuixModelObject +--------------- +La classe GuixModelObject est la classe centrale de la représentation des données : c'est elle qui représente les composants. + +Lorsque le parseur XML rencontre une balise ouvrante, il crée une nouvelle instance de GuixModelObject avec pour attributs *id*, *constructor, *javaBean* et *styleClass, les valeurs das attributs de même nom de la balise. Le nom de la balise correspond à la future classe de ce composant. + +L'attribut *id* correspond au nom du composant dans le fichier. Sa valeur par défaut est "_" suivi du nom de la balise et d'un nombre incrémenté à chaque balise n'ayant pas d'attribut *id*. + +L'attribut *constructor* correspond aux paramètres du constructeur du composant. Sa valeur par défaut est nulle. + +L'attribut *javaBean* indique si le composant doit posséder un modifieur dans le fichier généré. Sa valeur par défaut est *true*. + +L'attribut *styleClass* correspond à la classe de style du composant. Elle est utile quand on définit le style dans le CSS. Sa valeur par défaut est nulle. + +L'attribut *parent* est le GuixModelObject représentant la balise mère et l'attribut *children* est la liste des GuixModelObject représentant les balises filles. + +Le contenu des commentaires situés juste au dessus de la balise est ajouté à l'attribut *javadoc* du GuixModelObject. + +Au GuixModelObject représentant la balise racine, on ajoute tous les fichiers CSS rencontrés dans les balises *style* du fichier XML. Ainsi, lors de la génération, on pourra si besoin est, les copier dans le dossier adéquat (dans le cas de GWT par exemple). + +ClassDescriptor +--------------- +La classe ClassDescriptor est comme son nom l'indique une classe servant à décrire les classes des GuixModelObject. Ces dernières sont définies par le nom de la balise représentant le composant. Ce nom est décomposé en nom de package et nom de classe. + +La génération du modèle doit être complètement indépendante de la librairie graphique de l'IHM à générer. C'est pourquoi on utilise un ClassDescriptor et pas directement la classe Class de java. Pour utiliser la classe Class, il faudrait faire de l'introspection en utilisant par exemple la méthode *Class*.*forName(String className)*, mais ça ne fonctionne pas en GWT sans spécifier le ClassLoader de GWT. L'introspection est donc repoussée à la phase de génération. + +On utilise quand même la méthode *Classe.*forName(String className)* lors de cette phase, afin de vérifier s'il s'agit d'une classe existante : si on ne trouve pas la classe, on cherche le fichier .*guix* ou .*jaxx* correspondant. S'il existe, on ajoute ce fichier aux dépendances du fichier que l'on est en train de compiler, et s'il n'a pas été déjà compilé, on le compile. + +Balise racine +~~~~~~~~~~~~~ +La balise racine est différente des autres car le descripteur de classe du GuixModelObject qui la représente n'est pas défini par le nom de cette balise, mais par le nom du fichier à générer et son chemin. En revanche, le nom de la balise correspond à la superclasse du fichier à générer. Les ClassDescriptor décrivant les fichiers à générer sont les seuls à posséder des superclasses. + +Le contenu de toutes les balises *script* d'un fichier est rattaché au ClassDescriptor du GuixModelObject racine, après avoir été parsé par *javacc* pour vérifier que le code du script est correct. + +Balises filles +~~~~~~~~~~~~~~ +Pour les autres balises, on crée juste une nouvelle instance de ClassDescriptor avec le nom de la balise. Ces instances n'ont ni superclasse ni script. + +Enregistrement des ClassDescriptor +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Quand le ClassDescriptor a été complètement créé, on l'enregistre en vérifiant qu'un ClassDescriptor de même package et même nom n'aie pas une superclasse différente ou un script différent (si ces derniers ne sont pas nuls). + +Si le ClassDescriptor a déjà été enregistré, on lie le GuixModelObject au ClassDescriptor déjà enregistré, afin que tous les composants d'une même classe soient représentés par des GuixModelObject de même ClassDescriptor. + +AttributeDescriptor +------------------- +La classe AttributeDescriptor représente les attributs des balises. Pour chaque attribut d'un balise, on crée une instance d'AttributeDescriptor avec son nom et sa valeur, et on l'ajoute à la liste d'AttributeDescriptor du GuixModelObject représentant la balise. + +CSS +--- +L'intégration du CSS dans le modèle n'est pas nécessaire pour toutes les librairies graphiques, mais comme la génération du modèle est commune, elle est effectuée quand même (ceci pourrait être paramétré dans le POM à l'avenir). + +Le code CSS présent entre les balises *style*, ou le contenu des fichiers CSS définis par l'attribut *source* de ces balises, est analysé par le parser CSS de *javacc*. + +Il est alors décomposé en différentes classes : + +StyleSheet : + cette classe représente un fichier CSS et possède la liste des Selector et des Rule +Selector : + cette classe représente le sélecteur qui permet de déterminer à quels objets s'applique la liste des Rule qu'il contient +Rule : + cette classe représente les valeurs à attribuer aux attributs d'un composant + +Déroulement de la compilation +----------------------------- +Le déroulement de la compilation est représenté sur le diagramme ci-dessous : + +.. image:: guixcompilationactivity.png + :align: center Modified: trunk/src/site/site.xml =================================================================== --- trunk/src/site/site.xml 2009-08-27 13:42:46 UTC (rev 1613) +++ trunk/src/site/site.xml 2009-08-27 13:43:32 UTC (rev 1614) @@ -27,6 +27,7 @@ <menu ref="parent"/> <menu name="Utilisateur"> + <item name="Accueil" href="index.html" /> <item name="Fichiers Guix" href="guixFiles.html" /> <item name="Balises universelles" href="commonTags.html" /> <item name="Installation" href="installation.html"/> @@ -36,9 +37,8 @@ <menu name="Développeur"> <item name="Architecture" href="architecture.html" /> - <item name="Fonctionnement du programme" href="fonctionnement.html" /> - <!--item name="Avancement" href="Avancement.html"/--> - <item name="A faire" href="todo.html"/> + <item name="Génération du modèle" href="model.html" /> + <item name="Génération du code" href="codeGeneration.html" /> </menu> <menu ref="reports"/>