dimanche, décembre 23, 2007

Communication bidirectionnelle entre application Eclipse RCP et page HTML

Depuis peu je m'intéresse à la bibliothèque DWR qui permet de cacher les niveaux XMLHttpRequest et d'appeler, du côté JavaScript, des méthodes Java très facilement comme si elles étaient présentes dans le navigateur (voir précédent billet). Avec DWR, il est donc possible de communiquer du client vers le serveur (pull client) mais également du côté serveur vers le client (push server).

L'objectif de ce billet est de vous présenter un premier prototype qui utilise les deux types de communication de manière à réaliser une communication bidirectionnelle entre une page html et une application RCP.

De manière synthétique voici le fonctionnement général de ce prototype.

Côté client léger
Une page HTML classique est utilisée contenant un champ de texte et un bouton. Lors de la saisie puis de la validation sur le bouton, le contenu via DWR est envoyé du côté serveur.

Client lourd
Une application RCP propose une vue contenant un composant Browser (pour diffuser l'application web précédente), un champ de texte et un bouton de validation. Lors de la validation la donnée du champ de texte est envoyée vers la page HTML et affichée dans le champ de texte de cette page. L'application Eclipse RCP embarque un serveur d'application Jetty de façon à déployer l'application web contenant la page HTML et la librairie DWR.


Ce prototype met en avant plusieurs points techniques que nous détaillons dans la suite de ce billet.

Code de l'application RCP
L'idée est de pouvoir démarrer un serveur d'application au travers d'une application Eclipse RCP, voir code ci-dessous.
class ServerThread extends Observable implements Observer, Runnable {
private String value;

public ServerThread() {
new Thread(this).start();
}

public void run() {
Server server = new Server();
Connector connector = new SelectChannelConnector();
connector.setPort(Integer.getInteger("jetty.port", 8080).intValue());
server.setConnectors(new Connector[] { connector });
webapp = new WebAppContext();
webapp.setAttribute("desktopandweb", this);
webapp.setContextPath("/");
webapp.setWar("c:\\javaee.dwr.clientside");
server.setHandler(webapp);
try {
server.start();
server.join();
} catch (Exception exception) {
exception.printStackTrace();
}
}

public void setValue(String value) {
this.setChanged();
this.notifyObservers(value);
}

public void update(Observable observable, Object param) {
value = param.toString();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
View.this.myText.setText(value.toString());
}
});
}

Pour simplifier, j'ai placé arbitrairement l'application web à déployer à la racine du lecteur C. Par ailleurs, le serveur est démarré dans un processus différent de celui du thread principal de l'application RCP. A ce stade pour accéder à l'application Web lors de l'exécution de l'application RCP, il suffit de modifier l'URL du composant Browser à la valeur http://localhost:8080

La communication entre l'application RCP et l'application Web est obtenue au travers du contexte de l'application Web. En fait, l'instance courante de ServerThread est placée comme attribut du contexte (nom de l'attribut : desktopandweb). De cette manière du côté de l'application Web, il suffira de récupérer l'instance de la classe ServerThread pour réaliser un pont de communication entre les deux applications. Par ailleurs comme l'application Web ne peut connaître la classe ServerThread, puisqu'elle est localisée dans l'application RCP, nous utilisons l'API Observer/Observable comme service de communication.

Ainsi, l'application RCP est à la fois Observable et Observer. Elle est Observable puisqu'elle peut notifier ses Observers (en l'occurence l'application Web) que des modifications ont été réalisées de son côté. Elle est Observer puisqu'elle est notifiée de changements via un Observable (en l'occurence l'application web). Comme vous vous en doutez, l'application Web est également Observer et Observable. Lorsque l'application RCP est notifiée de changement, la méthode update est déclenchée. La nouvelle valeur à afficher dans le champ de texte de l'application RCP est passée en paramètre.

Code de l'application Web
Du côté de l'application Web à déployer une classe Java (ClientSide) sert de relais entre la page HTML et l'application RCP. La communication entre cette classe Java et la page HTML est obtenue via DWR (pull client et push server). Le code ci-dessous présente la classe ClientSide.

public class ClientSide extends Observable implements Observer {
private WebContext wctx = null;
private static final Log log = LogFactory.getLog(ClientSide.class);

public ClientSide() {
wctx = WebContextFactory.get();
Object tt = wctx.getServletContext().getAttribute("desktopandweb");
if (tt instanceof Observable) {
log.info("Observable trouvé");
Observable tto = (Observable) tt;
tto.addObserver(this);
}

if (tt instanceof Observer) {
log.info("Observer trouvé");
Observer te = (Observer) tt;
this.addObserver(te);
}
}

public void setValue(String value) {
this.setChanged();
this.notifyObservers(value);
}

public void update(Observable observable, Object param) {
try {
String currentPage = wctx.getCurrentPage();
Util pages = new Util(wctx.getScriptSessionsByPage(currentPage));
pages.setValue("text", param.toString());
log.info("Valeur envoyée aux clients");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Lors de l'instanciation de cette classe par DWR, la valeur de l'attribut desktopandweb est récupérée du contexte. Cette valeur correspond à l'instance de l'objet précédemment défini. L'abonnement entre Observable et Observer est réalisé. Nous venons de finaliser le lien bidirectionnelle entre l'application RCP et l'application Web.

Quand une valeur de la page HTML est envoyée à l'objet ClientSide (par le biais de DWR), la méthode setValue est appelée. Son objectif est de notifier tous les Observers d'un changement en passant en paramètre cette valeur. L'Observer dans ce cas correspond à l'application RCP qui va modifier le contenu de son champ de texte.

Inversement, si une valeur est modifiée du côté application RCP l'objet ClientSide est notifié et la méthode update est appelée. Dans ce cas, le champ identifé par l'id text est modifié par l'intermédiaire de la solution ReverseAjax fournie par DWR.

Code source du prototype
Le code source complet de l'application est fournie ici.

Vous devez par ailleurs installer XULRunner puisque le navigateur
utilisé sous l'application RCP est celui de Mozilla.

Perspectives ...
Ceci est un premier prototype mais l'idée générale est posée :
  1. embarquer un serveur d'application du côté client lourd
  2. utiliser DWR pour la communication entre les pages web et l'application web
  3. appliquer le Design Pattern Observer/Observable pour la communication bidirectionnelle entre application RCP et application web
Dans la prochaine itération nous tenterons d'effectuer une communication sur une page qui n'est pas localisée dans l'application Web. Nous prendrons arbitrairement une page sur Internet. L'idée est d'instrumentaliser cette page en ajoutant un écouteur sur chaque champ de texte. L'écouteur transmettra à notre application la valeur du champ lors d'une modification via DWR. L'instrumentalisation se fera en injectant du javascript via la méthode execute du composant Browser de SWT.

Si vous êtes intéressés par les aspects communication entre Desktop et Web, rendez-vous ici, plusieurs solutions sont présentées.

mardi, décembre 18, 2007

Liens pratiques de la semaine

Vous trouverez sur ce billet une sélection de liens pratiques autour des technologies Java qui m'ont particulièrement intéressées cette semaine.

Eclipse

vendredi, décembre 14, 2007

Liens pratiques de la semaine

Vous trouverez sur ce billet une sélection de liens pratiques autour des technologies Java qui m'ont particulièrement intéressées cette semaine.

Java
  • Java SE 6 Update N Build 08 (connu également sous le nom de "Consumer JRE") permet entre autre de démarrer plus rapidement les applications Java. Adieu, l'attente pour charger les Applets et les applications Java Web Start.
Eclipse

mercredi, décembre 12, 2007

Push Server via Multipart et DWR

Vous trouverez sur le blog technique de SERLI un article qui présente deux solutions pour faire du push serveur. La première n'utilise pas de librairies mais s'appuie sur le protocole HTTP via le ContentType multipart/mixed. La seconde utilise la librairie DWR (Direct Web Remoting). Pour chacune des solutions le code source est présenté.

Vous trouverez ci-contre les codes sources des exemples : multipart.zip et dwrclock.zip


mardi, décembre 11, 2007

Clients riches : les technologies du marché

Vous trouverez dans ce billet un support de cours qui présente les différentes technologies du marché concernant les clients riches. Le plan proposé est le suivant :
  • Définition et clarification du terme "client riche" (client lourd riche et client léger riche)
  • XUL
  • Ajax ("à la mano" et via GWT)
  • FLASH (Flex, AIR, Lazlo)
  • Eclipse RCP, Eclipse RAP
  • .NET Framework (ClockOne.Net, WPF, XAML, Silverlight)
  • Java (Applet, Java Web Start)
Voici l'adresse du support de cours : http://mbaron.developpez.com/divers/richclients/

Par ailleurs, vous trouverez ci-dessous la liste des liens des démonstrations utilisées tout au long du support de cours :
Ce support de cours a été dispensé aujourd'hui mardi 11 décembre aux étudiants du Master 2 STIC et Master 2 GPHY de l'Université de Poitiers.

vendredi, décembre 07, 2007

Cours sur les Servlets : mise à jour

Une mise à jour du support de cours sur les Servlets vient d'être réalisé. J'ai procédé à un petit nettoyage et tous les exemples sont maintenant nommés et disponibles dans une archive.

Le lien du cours : servlet.pdf
Le lien sur les exemples : servlet_examples.zip

Bonne lecture

Liens pratiques de la semaine

Vous trouverez sur ce billet une sélection de liens pratiques autour des technologies Java qui m'ont particulièrement intéressées cette semaine.

Plateforme Eclipse
Plateforme Java
  • un excellent site avec des tonnes de ressources concernant les technologies Java (www.javapassion.com)

mardi, novembre 27, 2007

Résultat du sondage

Le sondage concernant "les cours que vous souhaiteriez voir prochainement" est maintenant terminé. Arrive en tête le cours sur JFace. A l'heure actuelle seule la partie sur le composant viewer est terminée (voir le précédent billet). J'ai débuté la partie JFace sur les concepts suivant Wizard, Resource, Dialog et Text. Pour quand ? trop tôt pour l'annoncer ...

Concernant le deuxième cours plébiscité et que je vais mener en parallèle c'est Spring. Toutefois, je vais m'intéresser uniquement à l'injection de dépendances et à la programmation orientée aspect (AOP). De cette manière je pourrai facilement mettre en parallèle Spring et Guice de Google.

A bientôt pour de nouveaux cours

vendredi, novembre 16, 2007

Composants de Visualisation (Viewer) avec JFace

Le cours sur JFace est enfin disponible. Il traite uniquement des aspects liés aux Viewers pour la version Eclipse 3.3. Les autres concepts (Wizard, Ressource, ...) seront présentés dans un prochain cours.

Au menu de ce support de cours :
  • la partie modèle d'un Viewer via ContentProvider
  • le modèle graphique avec LabelProvider
  • gestion des colonnes via ViewerColumn
  • scope de tous les composants Viewers (TableViewer, TreeViewer, TableTreeViewer, ListViewer, ComboViewer)
  • le modèle de sélection via ISelection
  • les composants d'édition
  • la mise en place d'un CellEditor personnalisé
  • techniques de tri et de filtre.
Voilà le lien du cours (jface1.pdf)

Autre nouvelle, tous les exemples utilisés pour le cours sont également disponibles. Vous les trouverez ici (jface1_examples.zip)

Je retourne à la rédaction de la suite de ce cours ...

jeudi, novembre 15, 2007

Nouvelle version du support de cours Java

Je viens de mettre à jour le support de cours sur la programmation orientée objet appliquée à Java.

Au programme des nouveautés :
  • Ajout des varargs
  • Ajout d'un bilan à la fin du cours
  • Modification du style des transparents
Vous trouverez le cours ici


samedi, novembre 10, 2007

CellEditor personnalisé

Tous les composants de type ColumnViewer (TableViewer et TreeViewer) peuvent éditer des éléments. Une édition se caractérise par :
  • un modèle qui détermine si l'édition est autorisée, la valeur à afficher lors de l'édition et la nouvelle valeur saisie
  • un composant appelé Editor permettant de modifier la valeur d'un élément. Un Editor doit satisfaire la classe CellEditor
C'est ce dernier point qui nous intéresse. L'API Eclipse fournit un ensemble de CellEditor prédéfini :
  • TextCellEditor pour l'édition d'un simple texte
  • ColorCellEditor pour le choix d'une couleur
  • ComboboxCellEditor pour le choix d'une boite à sélection multiple
  • CheckboxCellEditor pour le choix dans une boite à cocher
  • DialogCellEditor pour la saisie d'une valeur dans une boite de dialogue
Si par contre vous devez fournir votre propre Editor, lisez la suite ...

La capture d'écran (une table avec trois colonnes dont la 1ère fournit un éditeur personnalisé composé d'un Label avec la valeur "Saisir :" et d'un Text pour l'édition)

Chaque colonne a un ViewerColumn pour définir le LabelProvider et EditingSupport. C'est ce dernier qui est employé pour préciser si l'édition est autorisé ou pas, la valeur à afficher lors de l'édition et retourner la valeur au modèle.

Le code
class MyEditingSupport extends EditingSupport {
private MyCustomCellEditor editor;
private Viewer myViewer;

public MyEditingSupport(ColumnViewer viewer) {
super(viewer);
myViewer = viewer;
editor = new MyCustomCellEditor((Composite)viewer.getControl(), SWT.NONE);
}

protected boolean canEdit(Object element) {
return true;
}

protected CellEditor getCellEditor(Object element) {
return editor;
}

protected Object getValue(Object element) {
Person current = (Person)element;
return current.getName();
}

protected void setValue(Object element, Object value) {
Person current = (Person)element;
current.setName((String)value);
myViewer.refresh();
}
}
La méthode getCellEditor permet de préciser l'éditeur à afficher au moment de l'édition. Cette méthode doit retourner un objet de type CellEditor.
class MyCustomCellEditor extends CellEditor {
private Text myText;
private Composite myComposite;

public MyCustomCellEditor(Composite parent, int style) {
super(parent, style);
}

protected Control createControl(Composite parent) {
myComposite = new Composite(parent, SWT.NONE);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
gridLayout.marginTop = -5;
gridLayout.marginBottom = -5;
gridLayout.verticalSpacing = 0;
gridLayout.marginWidth = 0;
myComposite.setLayout(gridLayout);
Label myLabel = new Label(myComposite, SWT.NONE);
myLabel.setText("Saisir : ");
myText = new Text(myComposite, SWT.NONE);
myText.setLayoutData(new GridData(GridData.FILL_BOTH));
myText.addSelectionListener(new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
MyCustomCellEditor.this.fireApplyEditorValue();
}
});
return myComposite;
}

protected Object doGetValue() {
return myText.getText();
}

protected void doSetFocus() {
myText.setFocus();
myText.selectAll();
}

protected void doSetValue(Object element) {
if (element instanceof String) {
myText.setText((String)element);
}
}
}
Ci-dessus un CellEditor personnalisé : les méthodes createControl, doGetValue, doSetFocus et doSetValue doivent être implémentées car elles sont abstraites.

La construction du composant d'édition est réalisée par la méthode createControl. Comme vous pouvez le constater cette méthode doit retourner un objet de type Control. Par conséquent toutes les folies sont possibles. Nous pourrions imaginer lors de l'édition d'une cellule, d'afficher une autre Table.

L'exemple complet peut être trouvé ici.

mercredi, octobre 24, 2007

Eclipse RAP (suite)

Eclipse RAP en version 1.0 est sorti depuis le 16 octobre 2007. J'avais déjà listé dans un précédent billet les ressources sur ce projet très prometteur.

Une introduction est proposée sur le site d'IBM. Il s'agit de la partie 1, il faut donc s'attendre à de nouvelles ressources.

Voici le lien

jeudi, octobre 18, 2007

TableTreeViewer deprecated, TreeViewer à la rescousse ...

Depuis la nouvelle version d'Eclipse 3.3, il est déconseillé d'utiliser directement le composant TableTreeViewer pour mixer un arbre avec une table. La raison est simple. Eclipse 3.3 intègre une gestion des colonnes via la classe ViewerColumn (sous types TableViewerColumn et TreeViewerColumn).

Par conséquent, pour éviter d'utiliser le composant TableTreeViewer, il faut utiliser un TreeViewer avec des colonnes de type TreeViewerColumn.

La capture d'écran (un arbre pour la première colonne et une table pour les autres colonnes)

Le code
final TreeViewer viewer = new TreeViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());

TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.CENTER);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
if (element instanceof Person) {
Person current = (Person)element;
return current.getName();
} else {
return element.toString();
}
}
});
column.getColumn().setText("Métier / Nom");

column = new TreeViewerColumn(viewer, SWT.CENTER);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
if (element instanceof Person) {
Person current = (Person)element;
return current.getAdress();
} else {
return null;
}
}
});
column.getColumn().setText("Adresse");

...
La première colonne appelée Métier / Nom contient l'arbre tandis que les autres décrivent les colonnes de la table.

L'exemple complet peut être trouvé ici.

samedi, octobre 06, 2007

Glasspane en SWT ...

S'il y a bien une chose assez pénible dans la toolkit SWT quand on vient du monde Swing, c'est l'absence de glasspane au niveau des fenêtres. Pour rappel le glasspane est une couche (layout) au niveau d'une fenêtre permettant de fournir une zone translucide. L'intérêt est de pouvoir dessiner ce que l'on souhaite et de combiner la partie translucide avec le contenu de la fenêtre de l'application. Concrètement, le glasspane permet d'ajouter des effets assez intéressants (voir démos de Romain Guy).

L'exemple proposé dans ce billet n'a pas la prétention d'émuler à l'identique le glasspane de Swing. Il s'agit d'une première ébauche ...

Le principe utilisé consiste à ajouter à la fenêtre principale de l'application deux sous fenêtres. Celles-ci utilisent la transparence via une fonction native de l'OS pour aboutir à un effet glasspane (Pour Win32 il s'agit de la fonction SetLayeredWindowAttributes). La première sous fenêtre appelée transparencyShell à un niveau de transparence complet. L'alpha est placé au minimum à 1, pas à 0, sinon la Shell serait invisible et donc il n'y aurait plus de réaction aux événements utilisateur mais assez pour ne plus la voir. La seconde fenêtre appelée glassPaneShell est aussi transparente mais uniquement pour une couleur donnée (couleur à choisir).

Plusieurs scénarios pour comprendre le fonctionnement
  • quand le glasspane est activé (les deux sous Shell sont visibles et la transparence est activée) et si l'interaction est effectuée sur une zone balayée par le couleur transparente, transparencyShell récupère alors l'événement et le route à glassPaneShell.
  • quand le glasspane est activé et si l'interaction est effectuée sur une zone non balayée par la couleur transparente, glassPaneShell récupère l'événement.
Par conséquent, transparencyShell n'est utile que pour bloquer les événements à la fenêtre principale et à les transférer à glassPaneShell.

La mécanique du glasspane en SWT est déléguée à la classe SWTGlassPane (création des sous Shell's, activation de la transparence, routage des événements, etc.).

Pour tester le tout, je me suis inspiré de l'exemple fourni par le tutorial de Swing au sujet du Glasspane.

Sans Glasspane
Avec Glasspane

L'aspect intéressant montré dans cet exemple est la possibilité de communiquer avec le contenu de la Shell principale. Si le Glasspane est activé, il n'est pas possible d'interagir directement avec l'IHM de la Shell principale. En effet, tous les événements sont routés à glassPaneShell. Par conséquent, du côté client il faut préciser les retours possibles sur l'IHM de la fenêtre principale.

Les problèmes à résoudre prochainement :
  • quand le Glasspane est activé et qu'une interaction via la sours se produit, le focus sur la fenêtre principale est perdu. Normal le focus passe sur une sous Shell.
  • le niveau d'opacité sur la Shell de glassPaneShell.
  • les deux sous fenêtres (transparencyShell et glasspaneShell) sont liées à la fenêtre applicative. Ainsi tout déplacement/redimensionnement de cette dernière implique le déplacement et le redimensionnement des deux autres. Pour l'instant, un problème de refresh subsiste.
  • ...
Voici le code source : ici

Si vous avez des commentaires ou des propositions d'amélioration, n'hésitez pas.

La démonstration Java Web Start de SWTTipOfTheDay

Keulkeul

Shell transparente via JNA

Dans un précédent billet, j'avais présenté JNA. Je vous propose ici un petit exemple permettant de rendre transparent une Shell SWT tout en utilisant JNA.

Capture d'écran : sans transparence

Capture d'écran : avec transparence


Il faut cependant passer par un appel natif. Pour simplifier les choses je me limiterai à la plateforme Windows. Sous WIN32, un appel aux fonctions suivantes est nécessaire :
  • int getWindowLong(int hWnd, int nIndex)
  • int setWindowLong(int hWnd, int nIndex, int dwNewLong)
  • boolean setLayeredWindowAttributes(int hWnd, int crKey, byte bAlpha, int dwFlags)
Par l'intermédiaire de JNA, l'appel aux fonctions natives se fait très facilement, adieu code C ... Ci-dessous vous trouverez l'interface qui contiendra les définitions des fonctions natives.
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
int GWL_EXSTYLE = -20;
int WS_EX_LAYERED = 0x80000;

int LWA_COLORKEY = 1;
int LWA_ALPHA = 2;

int GetWindowLong(int hWnd, int nIndex);
int SetWindowLong(int hWnd, int nIndex, int dwNewLong);

boolean SetLayeredWindowAttributes(int hwnd, int crKey, byte bAlpha, int dwFlags);
}
La transparence est gérée par setLayeredWindowAttributes. hWnd correspond au handle window de la Shell, nIndex désigne la couleur transparente, bAlpha précise le niveau de transparence et enfin dwFlags permet d'indiquer le type de transparence : soit par une couleur, soit au niveau globale, soit un mixte des deux (utilisation d'un pipe).
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
User32 lib = User32.INSTANCE;
int flags = lib.GetWindowLong(myShell.handle, User32.GWL_EXSTYLE);
flags |= User32.WS_EX_LAYERED;
lib.SetWindowLong(myShell.handle, User32.GWL_EXSTYLE, flags);
Color myColor = Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE);
lib.SetLayeredWindowAttributes(myShell.handle, myColor.handle, (byte)200, User32.LWA_COLORKEY | User32.LWA_ALPHA);
}
});
Dans cet exemple, je réalise à la fois une transparence de la fenêtre globale et une transparence de la couleur (DARK_BLUE).

Je ne vais pas m'attarder à expliquer le code, vous trouverez l'exemple ici.

A noter que je me suis basé sur le code fournit par le projet JNA.

Je profite de la discussion autour de JNA pour vous donner un lien sur un billet très intéressant à ce sujet (présentation JNI puis JNA) : blog Developpez.com

vendredi, octobre 05, 2007

Supports de cours, debriefing ...

Ce billet a pour objectif de vous présenter l'avancement des supports de cours.

Le cours JFace est bien partie pour être terminé dans un mois. La partie Viewers est pratiquement terminée. Il me reste à traiter les editors, les filtres et les tris. Pour l'instant, le cours atteint une centaine de transparents. J'essaye de traiter au maximum les nouveautés de la version 3.3 d'Eclipse. Concernant les autres parties du cours JFace, il me reste à traiter :
  • Les boites de dialogue évoluées
  • Les préférences utilisateur
  • La gestion de ressources
  • La création d'assistants
En parallèle, j'essaye de mettre à jour tous les autres cours de manière à fournir tous les codes sources complets. L'idée est d'identifier pour chaque exemple d'un cours le nom de la classe concernée et de pouvoir la localiser dans l'archive des exemples de cours qui sera fournie.

Par ailleurs, le cours de Java est en train de subir un gros lifting. Des nouveautés vont être ajoutées comme les varargs ou des mini-qcm à la fin de chaque partie.

Mise à jour du cours sur SWT

Une mise à jour du cours concernant la boîte à outils SWT vient d'être effectuée. Pour chaque exemple du cours, j'ai indiqué quelle était le nom de la classe concernée. Dans ce sens vous trouverez tous les codes sources utilisés pour le cours. A noter que seul l'exemple concernant la partie Win32 n'a pas été inclus. J'attends la partie Eclipse RCP pour l'ajouter.

Le lien pour le cours SWT : swt.pdf

Le lien pour télécharger les sources des exemples : swt_examples.zip

samedi, septembre 29, 2007

Effets sur les images, des ressources !!!!

Je viens de trouver un article qui traite de la manipulation des images et des effets qui peuvent y être appliqués (Ultimate Java Image Manipulation). Toutefois, cet article cible l'API Java2D et par conséquent la boîte à outils AWT/Swing.

J'en profite donc pour faire un état des articles/ressources concernant la manipulation d'image pour SWT.

Tout d'abord un article d'IBM (Java2D imaging for the SWT) permettant de passer une image AWT/Swing (BufferedImage) en une image SWT (ImageData). Au niveau performance, j'avoue ce n'est pas le top mais la solution de conversion existe.

Concernant les articles "purs" SWT traitant du sujet de la manipulation des images
Par ailleurs, si vous souhaitez des explications concernant la manière de réaliser des effets sur des images, je vous conseille cet excelent site JH Labs. Les démonstrations sont en Swing ...

vendredi, septembre 28, 2007

Prettify

Prettify est un module JavaScript et CSS permettant de formater un code. Je l'utilise depuis peu dans ce blog et le résultat est assez sympathique (mise en couleur des mots clés, zone délimitée pour le code, etc.).

Voilà un exemple
public class Voiture {
public Voiture() {
}

public int getPuissance() {
return 5;
}
}
Le site du projet : Prettify

A noter qu'au niveau de mon blog, j'ai remarqué un petit bug. Si on défile les billets contenant du code d'une autre page, les couleurs sur les mots clés ne sont pas prises en compte.

vendredi, septembre 21, 2007

Eclipse RAP

Le projet Eclipse RAP (Rich Ajax Platform) permet le développement d'applications serveur comme si vous développiez une application Eclipse RCP (composition de plugins). La bibliothèqe SWT a son équivalent pour cette plateforme, elle s'appelle RWT (RAP Widget Toolkit). L'API est très très proche de SWT et par conséquent la conversion d'une application Eclipse RCP en RAP demande très peu d'investissement (enfin ça c'est dans la pratique).


Par conséquent, le développeur n'a donc pas besoin de connaître l'HTML ou le JavaScript pour développer. Un concurrent de plus pour GoogleWebToolkit. Sans entrer dans les détails, la majeur partie des traitements sont effectués par le serveur. Un événement sur l'IHM est transmis au serveur qui retourne le feedback associé, un peu à la sauce du cycle de vie de JSF. Ces nombreux aller/retour entre le client et le serveur amèneront logiquement à se poser des questions de performance. Je suis curieux de savoir comment employer TPTP pour tester les IHM d'une application Eclipse RAP ?

A noter que le version 1.0 devrait sortir aux alentours de l'Eclipse Summit Europe où une session "Eclipse RAP" doit se dérouler.

Voilà quelques liens
Il se pourrait que dans un prochain cours je m'intéresse à ce projet ...

(Modification apportée le 16 octobre 2007) : la version 1.0 d'Eclipse RAP vient de sortir

TableViewer et TableViewerColumn

Dans un précédent billet (ici) je vous avais montré comment utiliser OwnerDrawLabelProvider pour dessiner le contenu des cellules d'une table. Dans ce billet je vais préciser la notion de LabelProvider unique par colonne. L'intérêt : des comportements spécifiques à chaque colonne pour les bulles d'aides et tout ce qui touche aux couleurs.

Chaque Viewer de la famille des ColumnViewer (TableViewer et TreeViewer), c'est-à-dire des composants affichant plusieurs colonnes, peuvent manipuler pour chaque colonne un LabelProvider spécifique. Pour ce faire un ColumnViewer doit être associé à un ViewerColumn (la colonne en fait) pour être relié à un LabelProvider donné.

La capture d'écran (la bulle d'aide est customisable : déclenchement, temps d'affichage, couleurs)


Le code
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyStructuredContentProvider());

TableViewerColumn column = new TableViewerColumn(viewer,SWT.NONE);
column.setLabelProvider(new MyColumnLabelProvider() {
public Color getBackground(Object element) {
return Display.getDefault().getSystemColor(SWT.COLOR_GREEN);
}

public String getText(Object element) {
PersonData currentPerson = (PersonData)element;
return currentPerson.getName();
}

public Color getToolTipBackgroundColor(Object object) {
return Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA);
}

public String getToolTipText(Object element) {
PersonData myReference = (PersonData)element;
return "Le nom de cette personne est : " + myReference.getName();
}
});
column.getColumn().setText("Nom");

ColumnViewerToolTipSupport.enableFor(viewer,ToolTip.NO_RECREATE);


La colonne est créée par l'intermédiaire d'un objet TableViewerColumn (l'équivalent pour un TreeViewer est un TreeViewerColumn). Notez que ce composant est associé au Viewer concerné lors de la construction. Le LabelProvider est ensuite spécifié. Je factorise les comportements via la classe statique MyColumnLabelProvider (voir ci-dessous). Cette classe hérite de ColumnLabelProvider qui donne tous les services pour modifier la forme et le fond d'une cellule mais aussi pour customiser les bulles d'aides. Une spécialisation de MyColumnLabelProvider est obtenue au travers d'une classe anonyme où je précise la couleur de fond de la bulle d'aide et le contenu de la bulle d'aide. Bien entendu, c'est également dans ce LabelProvider que j'affiche le contenu de la cellule. La même démarche est appliquée à la seconde colonne. La dernière instruction du code ci-dessus est importante ColumnViewerToolTipSupport.enable(viewer,ToolTip.NO_RECREATE), elle permet d'activer la customisation des bulles d'aides.

static class MyColumnLabelProvider extends ColumnLabelProvider {
public int getToolTipDisplayDelayTime(Object object) {
return 500;
}

public int getToolTipTimeDisplayed(Object object) {
return 2000;
}

public Point getToolTipShift(Object object) {
return new Point(5, 5);
}

public boolean useNativeToolTip(Object object) {
return false;
}
}

Vous trouverez le code source de cet exemple ici.

mardi, septembre 18, 2007

EclEmma un assistant pour JUnit

EclEmma est un plugin pour Eclipse qui combiné à JUnit s'avère très utile. Une fois lancée les tests unitaires, l'outil va espionner le code appelé et va effectuer un marquage du code selon un code couleur. Par exemple, la couleur rouge est utilisée pour afficher le code que les tests unitaires ne couvrent pas. Il est donc possible de vérifier d'un coup d'œil les bouts de code qui sont pris en charge ou pas.

Le site du projet EclEmma

dimanche, septembre 16, 2007

De jolies demos en Swing ...

La première démo est une application qui simule l'ouverture de pages d'un magazine. Le composant JBookPanel a été défini. Ce genre d'application est généralement codé en flash et on peut les trouver dans les sites web.

La démo via JWS et les sources sont disponibles : jbookpanel_and_the_page_turn

La deuxième démonstration contient un ensemble des petites démonstrations assez sympathiques (un carrousel, un Dock à la MAC OS X, une version modifiée du JBookPanel et une animation de simulation de pluie).

Comme pour JBookPanel vous trouverez une démo via JWS et les sources : demonstrations

Les liens présentés ci-dessus ne sont pas nouveaux, ils avaient été listés sur le site de Java Desktop.

samedi, septembre 15, 2007

SWT Ribbon : sources disponibles en version ALPHA

Le composant SWT Ribbon essaye de s'inspirer de la barre d'outils d'Office 2007 comme montré sur l'image ci-dessous.

Tout ça pour dire qu'une première version ALPHA est disponible au téléchargement.
J'en profite pour faire un appel à témoin. Si vous connaissez des projets concernant des composants SWT faites moi un signe ...

Un mini cours sur l'API i18n

Un mini cours sur l'API i18n vient d'être publié sur le site de Developpez.com

Au menu vous trouverez des informations concernant les classes
  • Locale
  • ResourceBundle
  • MessageFormat
  • ChoiceFormat
Voilà le lien du cours : http://mbaron.developpez.com/javase/i18n/

Choses sérieuses, je retourne à la rédaction du cours sur JFace ...



jeudi, août 30, 2007

TableViewer et OwnerDrawLabelProvider

La classe OwnerDrawLabelProvider du package JFace apparue avec la nouvelle API d'Eclipse 3.3 permet de dessiner le contenu d'une cellule d'un TableViewer. Dans les précédentes API, pour dessiner quelque chose, il fallait ruser et générer une image affichée par la cellule (une cellule contient en fait un simple label = texte + image).

La capture écran (remarquez que le texte contient une police, un style et une couleur différents)

Le code
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyStructuredContentProvider());
TableViewerColumn column = new TableViewerColumn(viewer,SWT.NONE);

column.setLabelProvider(new OwnerDrawLabelProvider() {
protected void measure(Event event, Object element) {
PersonData currentPerson = (PersonData)element;
int height = event.gc.textExtent(currentPerson.getName()).y + 5;
int width = event.gc.textExtent(currentPerson.getName()).x;
event.setBounds(new Rectangle(0,0, width, height));
}

protected void paint(Event event, Object element) {
PersonData currentPerson = (PersonData)element;
Display display = viewer.getControl().getDisplay();
TextLayout layout = new TextLayout(display);
layout.setText(currentPerson.getName());

Font firstFont = JFaceResources.getFont(JFaceResources.DEFAULT_FONT);
Color firstColor = display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
TextStyle plain = new TextStyle(firstFont, firstColor, null);

Font secondFont = JFaceResources.getFontRegistry().getItalic(JFaceResources.DEFAULT_FONT);
Color secondColor = display.getSystemColor(SWT.COLOR_BLUE);
TextStyle italic = new TextStyle(secondFont, secondColor, null);

Font newFont = new Font(display, "Arial", 9, SWT.BOLD);
TextStyle font = new TextStyle(newFont, display.getSystemColor(SWT.COLOR_GREEN), null);

layout.setStyle(plain, 0, 2);
layout.setStyle(italic, 3, 5);
layout.setStyle(font, 6, currentPerson.getName().length() - 1);
layout.setOrientation(SWT.RIGHT_TO_LEFT);
layout.draw(event.gc, event.x, event.y);
}
});

column.getColumn().setText("Nom");
La table contient deux colonnes définie chacune par un TableViewerColumn (dans le code présenté seule la première colonne est décrite). Pour faire simple, un TableViewerColumn, également fournie dans l'API 3.3 d'Eclipse, permet d'associer à chaque colonne un LabelProvider et le support à l'édition. Par conséquent, j'y ai placé un LabelProvider de type OwnerDrawLabelProvider.

La classe OwnerDrawLabelProvider fournit trois méthodes :
  • measure(Event event, Object element) : pour le redimensionnement de la cellule;
  • paint(Event event, Object element) : pour le dessin dans la cellule;
  • erase(Event event, Object element) : pour dessiner la sélection.
Dans le code ci-dessus, je me sers d'un TextLayout pour placer mon texte dans la cellule. Trois styles différents sont appliqués au texte ce qui me permet d'obtenir une chaîne de caractères ayant des styles différents.

Je ne vais pas entrer dans les détails, je vous laisse le plaisir d'y regarder dans l'archive fournie ici.

Sachez également que je me suis basée sur le code présenté ici et que cet exemple fait partie du cours JFace que je suis en train de finaliser.

lundi, août 06, 2007

Cours en construction ...

Juste un message pour préciser sur quoi je travaille actuellement pour les supports de cours
  • GWT (Google Web Toolkit)
  • JFace pour la plateforme Eclipse
Pour ce dernier ça avance et pour GWT j'en suis à faire un état de l'art de ce qui existe sur le net.

Introduction sur JSF disponible

Les billets se font rares en ce moment, le temps manque et la fatigue se fait sentir ...

Bref tout ça pour dire que le support de cours sur JSF est disponible sur le site de Developpez.com.

Au menu
  • Configuration des bibliothèques
  • Beans managés
  • Cycle de vie
  • Navigation
  • Composants CORE et HTML
  • FacesContext
  • Backing Bean
  • Gestion des messages
  • Conversion et validation via les Converters et les Validators*
  • Gestion des événements
  • Composants supplémentaires Tomahawk
  • Création personnalisée de composants JSF*
Les parties suffixés par * ne sont complètement terminées. C'est déjà un gros bébé qui pèse 175 transparents.

Je suis en train de "proprifier" le code des exemples qui seront mis à disposition sur ce blog très prochainement.

Voici le lien du cours : http://mbaron.developpez.com/javaee/jsf/


vendredi, juin 29, 2007

Blogs concernant la plateforme Eclipse RCP

Un billet dont l'objectif est de lister l'ensemble des Blogs en relation avec le développement de clients riches via Eclipse RCP

Voilà une liste
Si vous avez des adresses, n'hésitez pas

Exemples JFace

Un site qui regroupe un ensemble d'exemples concernant JFace. Les exemples sont décomposés en quatre catégories :
  • Dialogs
  • Layout
  • Viewers
  • Window
L'aspect intéressant pour les exemples des Viewers est de présenter des fonctionnalités de Eclipse 3.3

Voici le lien JFaceSnippets

jeudi, juin 14, 2007

Un mini cours sur Java Web Start

Je viens de mettre à disposition un cours sur le déploiement d'applications Java via la technologie Java Web Start.

Au menu de mini cours :
  • Archive JAR
  • Signer un JAR
  • Format JNLP
Voilà le lien du cours : http://mbaron.developpez.com/javase/jws

Bonne lecture ...


Cours Eclipse : petite modification ...

La série de cours consacrée à la plateforme Eclipse a quelque peu changée. Vous trouverez maintenant un PDF pour découvrir l'univers de la plateforme Eclipse via une petite introduction (Java IDE, Frameworks [IDE, Outils et applications] et la communauté Eclipse) et également un PDF pour découvrir la boîte à outils SWT.

D'autres PDF arriveront prochainement ...

Les liens pour les supports de cours : introduction, SWT.

mercredi, juin 06, 2007

Java Native Access (JNA)

Il y a des projets qui font plaisirs quand on les découvre et JNA en fait partie. Ce projet actuellement dans l'incubateur des prochaines JDK offre la possibilité d'appeler des fonctions natives sans avoir besoin de passer explicitement par du JNI. Fini le temps où pour exploiter une fonction Win32 existante il fallait sortir l'arme lourde. J'entends par là qu'il fallait se munir d'un compilateur C, générer un .h et développer du C. Par contre si vous avez besoin de passer par du code natif vous avez simplement besoin de construire une DLL. La partie avec Javah n'est plus nécessaire.

Ce projet s'occupe donc de masquer le développement de la couche JNI pour appeler du code natif.

Bref voici un exemple tiré du site du projet. L'objectif étant de faire appel à la fonction GetSystemTime qui se trouve dans la DLL kernel32.lib.

On commence par définir une interface dont le but et la définition des fonctions et structure à exploiter. Noter l'héritage de StdCallLibrary qui précise l'ordre des paramètres. Enfin, on récupère une référence sur l'ouverture de la librairie concernée.
public interface Kernel32 extends StdCallLibrary {
Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);

public static class SYSTEMTIME extends Structure {
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}

void GetSystemTime(SYSTEMTIME result);
}
Au niveau utilisation de l'interface précédente voilà un petit exemple :
public class Kernel32Impl {
public static void main(String[] argv) {
Kernel32 lib = Kernel32.INSTANCE;
Kernel32.SYSTEMTIME time = new Kernel32.SYSTEMTIME();
lib.GetSystemTime(time);
System.out.println("Today's integer value is " + time.wDay);
}
}
Le projet JNA se trouve ici : JNA
Les sources du projet JNA sont disponibles. Vous trouverez par ailleurs un ensemble d'exemples.
Il y a également sur le blog de Romain Guy un post qui en parle.

Dans le même style que JNA, on peut trouver
A noter que JNA est dans l'incubateur de la JDK donc potentiellement disponible dans les prochaines versions de Java.

mercredi, mai 30, 2007

Cours de Java traduit en espagnol

En novembre dernier j'avais déposé sur le site de Developpez.com un cours sur Java. Ce cours a été traduit entièrement en espagnol par un membre de Developpez.com : Jérémie Habasque (Membre Developpez)

Cette version traduite a été dispensée pour le compte de l'IRD (Institut de recherche pour le devéloppement) à l'Institut de la Mer du Pérou par Jérémie.

Voilà, je voulais signaler le travail accompli. Un grand merci donc à Jérémie.

Le cours est disponible sur la page de mon cours Java en français (java).

Le lien du cours en espagnol : (javasp.pdf)

Miguel ...

samedi, mai 26, 2007

Mise à jour des supports de cours ...

J'ai procédé à une mise à jour de certains supports de cours :
  • Java : prise en compte de la version Java 6, correction de nombreuses fautes d'orthographe (merci Laurent pour la relecture), ajout d'un schéma pour expliquer le principe de fonctionnement d'une application Java;
  • SWT : ajout d'un transparent concernant les exceptions, correction de quelques fautes d'orthographe.
Juste un mot pour vous avertir que le cours sur JSF devrait arriver (1 à 2 semaines ~180 transparents). Par ailleurs, je fournirai surement les codes sources.

lundi, février 26, 2007

Drag and Drop : transfert de données

J'ai mis à disposition sur ma page de Developpez.com un cours sur le Drag and Drop en Swing en insistant, non pas sur l'aspect graphique de la technique d'interaction, mais plutôt sur l'aspect modèle.

Vous trouverez tout ce qu'il faut savoir sur :
  • Transferhandler
  • DataFlavor
  • Transferable
Voilà le lien du cours : http://mbaron.developpez.com/javase/dnddt/

Bonne lecture


samedi, février 17, 2007

Plugin Eclipse : Metrics

J'inaugure le premier post en relation avec les plugins Eclipse qui me facilitent la vie. En quelques sortes ce type de post me servira de memo pour lister tous les plugins que j'utilise et qui ne sont pas forcément facile à trouver (je ferai de même pour FireFox).

Le plugin Metrics offre la possibilité de donner comme son nom l'indique des métriques sur du code. Vous pouvez ainsi connaître : le nombre de classes, nombre de lignes, méthodes, ...

Vous avez même la possibilité d'afficher un graphe qui vous présente les relations entre les packages et classes.

Voilà le lien : Metrics
L'URL pour mettre à jour depuis Eclipse : http://metrics.sourceforge.net/update

lundi, février 05, 2007

Plateforme Eclipse : Partie SWT

Un message pour vous annoncer que mon premier cours concernant la plateforme Eclipse est disponible sur le site de Developpez.com

Au menu de ce cours :
  • Introduction sur la plateforme Eclipse
  • Evolution des boîtes à outils pour Java
  • Conteneurs
  • Composants de type Control
  • Agents de placement
  • Gestion des événements
  • Graphical Context
  • Co-habitation entre SWT et Swing
  • Traitement synchrone et asynchrone (threadui)
  • Boîtes de dialogue
Voilà le lien du cours : http://mbaron.developpez.com/eclipse/swt/

Bonne lecture ...


mercredi, janvier 31, 2007

Nouveau site perso ...

Je viens de changer de fournisseur d'accès. Je passe de Neuf à Free. Par conséquent la page sur baron.mickael.neuf.fr devrait bientôt disparaître (pour l'instant j'ai placé un re-direction) au profit de celle-ci baron.mick.free.fr

En fait, sur cette page seront stockés mes articles de recherches passés et en cours.

Cours Java EE

Depuis mi-décembre, on va dire que sur le blog c'est calme plat ...

Je profite du premier billet de l'année, pour annoncer que j'ai dispensé un cours de Java EE au M2 STIC de Poitiers.

C'était du technique et j'ai commencé par une introduction de manière à cibler mon discours et j'ai enchainé sur les Servlets, Tomcat et les JSP, le tout animé de petites démonstrations. 1 an sans développement avec Java EE, c'est dur!! C'est un peu pour ça que j'ai décidé de terminer prochainement mon cours sur JSF.