Le contexte:
Le projet a pour but d'améliorer l'ergonomie et l'usabilité du back office d’un produit en cours de développement réalisé en collaboration avec SFEIR
Dans le cadre de ce projet, la version de GWT utilisée passe de la 1.7.1 à la 2.0.3 afin de bénéficier des nouvelles fonctionnalités offertes par cette version. De nouveaux pattern de développement ont également été mis en place au cours de ce projet.
Voici une série d'article sur les nouveautés de GWT 2, les choix d'architectures, et bibliothèques utilisés qui font part de notre retour d'expérience sur le sujet. Ces articles ont été écris par David Aboulkheir, Patrice de Saint Steban et Cyril Lakech
- Nouveautés de GWT 2.0
- UiBinder, enfin une forte collaboration entre le designer et le développeur
- Intégration facile de maquette Html en GWT 2
- Architecture Modèle-Vue-Presenteur
- Implémentation Modèle-Vue-Présenteur
- Ecrire des tests unitaires avec Mockito
- Mise en place de Gin sur le projet
- Internationalisation
Exemple d'intégration d'un composant d'une page Web dans un projet GWT 2:
Nous devons intégrer un nouveau composant qui nous est livré sous la forme de maquette HTML qui se compose de fichiers HTML, d'image et éventuellement de fichier CSS.
Voici le fichier HTML fourni, il contient le code HTML et le style CSS utilisé:
<style>
<!--
* {
font-family:calibri;
font-size:12px;
}
.menu {
padding: 0px;
background: url('bgmenu.gif') repeat-y right top white;
display:block;
color:#1783c4;
width:250px;
height:100%;
}
.menu h2{
font-family:calibri;
font-size:18px;
background: url('menutop.gif') no-repeat bottom left;
width:250px;
padding-bottom:10px;
margin:0px;
}
.menu .close{
float:right;
margin:4px;
margin-right:7px;
}
.menu textarea {
width:240px;
min-height:300px;
border:1px solid #dddddd;
background: #f6f6f6;
margin-top:20px;
margin-bottom:5px;
}
.pages{
padding:3px 7px 7px 7px;
}
.pages.selected{
background: url('menubottom.gif') no-repeat bottom left #f5f5f5;
}
.pages .close{
float:right;
}
.pages a.element{
color:black;
font-size:13px;
font-weight:bold;
margin-bottom:3px;
text-decoration:none;
display:block;
}
.pages a.element:hover{
text-decoration:underline;
background:url('croixnoire.gif') 223px 3px no-repeat;
}
.pages .close{
float:right;
width:13px;
height:11px;
}
.right {float:right;}
a.bouton {
color:white;
font-size:12px;
font-weight:bold;
text-transform:uppercase;
margin-right:10px;
padding:2px 5px;
text-decoration:none;
font-family:calibri;
border:1px solid #909090;
text-align:center;
}
a.bouton.bleu {
background:#0099cb;
}
a.bouton.bleu:hover {
background:#0fb3e9;
}
a.bouton.vert {
background:#4ba600;
}
a.bouton.vert:hover {
background:#5cc803;
}
-->
</style>
<div class="menu">
<div class="close"><a href="#"><img src="croix.gif" border="0"></a></div>
<h2>Jean-Pierre Dupont</h2>
<div class="pages selected">
<a href="#" class="element"><img src="1ptrans.gif" border="0" class="close">Ma page personnel (0)</a>
</div>
<div class="pages">
<a href="#" class="element"><img src="1ptrans.gif" border="0" class="close">Autre page (0)</a>
</div>
<br/>
<a href="#" class="bouton bleu">Créer une nouvelle page</a>
<textarea>
Ici je peux mettre des notes
</textarea>
<a href="#" class="bouton vert right">Enregistrement</a>
</div>
Nous créons un nouvel élément UiBinder que nous appelons HomePageMenu :

On modifie le fichier HomePageMenu.gwt.xml comme suit:
- On ajoute les entêtes nécessaires pour UiBinder
- On modifie la balise <style /> en <ui:style />
- On remplace la div principale par une balise <g:HTMLPanel />
- Les libellés que l’on souhaite rendre dynamiques sont remplacés par des balises <g:InlineLabel />, les liens <a /> par des <g:Anchor /> et les <textarea /> par des <g:TextArea />
- Les nom des styles utilisés sont modifiés, en lieu et place de “monStyle” on utilise "{style.monStyle}"
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
* {
font-family: calibri;
font-size: 12px;
}
.menu {
padding: 0px;
display: block;
color: #1783c4;
width: 250px;
height: 100%;
}
.menu h2 {
font-family: calibri;
font-size: 18px;
background: url('module/images/homepage/menutop.gif')
no-repeat bottom left;
width: 250px;
padding-bottom: 10px;
margin: 0px;
}
.menu .close {
float: right;
margin: 4px;
margin-right: 7px;
}
.menu textarea {
width: 240px;
min-height: 300px;
border: 1px solid #dddddd;
background: #f6f6f6;
margin-top: 20px;
margin-bottom: 5px;
}
.pages {
padding: 3px 7px 7px 7px;
}
.pages.selected {
background: url('module/images/homepage/menubottom.gif')
no-repeat bottom left #f5f5f5;
}
.pages .close {
float: right;
}
.pages a.element {
color: black;
font-size: 13px;
font-weight: bold;
margin-bottom: 3px;
text-decoration: none;
display: block;
}
.pages a.element:hover {
text-decoration: underline;
background: url('module/images/homepage/croixnoire.gif') 223px
3px no-repeat;
}
.pages .close {
float: right;
width: 13px;
height: 11px;
}
.right {
float: right;
}
a.bouton {
color: white;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
margin-right: 10px;
padding: 2px 5px;
text-decoration: none;
font-family: calibri;
border: 1px solid #909090;
text-align: center;
}
a.bouton.bleu {
background: #0099cb;
}
a.bouton.bleu:hover {
background: #0fb3e9;
}
a.bouton.vert {
background: #4ba600;
}
a.bouton.vert:hover {
background: #5cc803;
}
</ui:style>
<g:HTMLPanel styleName="{style.menu}">
<div class="{style.close}">
<a href="#">
<img src="module/images/homepage/croix.gif" border="0" />
</a>
</div>
<h2><g:InlineLabel ui:field="userLabel">Jean-Pierre Dupont</g:InlineLabel></h2>
<div class="{style.pages} {style.selected}">
<a href="#" class="{style.element}">
<img src="module/images/homepage/1ptrans.gif" border="0"
class="{style.close}" />
Ma page personnel(0)
</a>
</div>
<div class="{style.pages}">
<a href="#" class="{style.element}">
<img src="module/images/homepage/1ptrans.gif" border="0"
class="{style.close}" />
Autre page (0)
</a>
</div>
<br />
<g:Anchor ui:field="newButton" href="#" styleName="{style.bouton} {style.bleu}">
Créer une nouvelle page
</g:Anchor>
<g:TextArea ui:field="noteTextArea">
Ici je peux mettre des notes
</g:TextArea>
<g:Anchor ui:field="saveNoteButton" href="#" styleName="{style.bouton} {style.vert} {style.right}">
Enregistrer
</g:Anchor>
</g:HTMLPanel>
</ui:UiBinder>
Puis on modifie la classe associée de la manière suivante:
/**
*
*/
package module.client.homepage.menu;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
/**
*
*
*/
public class HomePageMenu extends Composite {
private static HomePageMenuUiBinder uiBinder = GWT
.create(HomePageMenuUiBinder.class);
interface HomePageMenuUiBinder extends UiBinder<Widget, HomePageMenu> {
}
//Composant GWT que l'on veux utiliser lié avec l'attribut ui:field=""
@UiField InlineLabel userLabel;
@UiField Anchor newButton;
@UiField TextArea noteTextArea;
@UiField Anchor saveNoteButton;
public HomePageMenu() {
initWidget(uiBinder.createAndBindUi(this));
}
@UiHandler("newButton")
public void onNewClick(ClickEvent event){
//Création d'une nouvelle page
}
@UiHandler("saveNoteButton")
public void onNewClick(ClickEvent event){
saveNote(noteTextArea.getText());
}
public void setUserName(String userName){
userLabel.setText(userName);
}
}
Comme on a pu le voir, il est très simple d’intégrer des maquettes HTML/CSS en GWT abec UiBinder, ce qui n’était pas le cas avant la version 2 de GWT. Cela permet d’améliorer la collaboration entre le Web Designer et le développeur puisqu’ils utilisent un langage commun le XML/HTML pour réaliser les écrans. Cela permet également au Web Designer, après une rapide prise en main des outils type SVN/Eclipse, de pouvoir intervenir sur le design de l’application directement sans aucune aide du développeur.
Dans notre cas, on a eu l’agréable surprise de voir notre Web Designer créer des écrans GWT lui même, les modifier et même coder en java pour interagir avec l’IHM; modifier un style programmatiquement ou déclencher une action simple.


Il y a un peu plus d'une semaine, Google
annonçait la sortie de Google Chrome Frame.




