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