|
 |
:: Présentation de SWT/JFace :: Principes de fonctionnement
::
SWT (Standard Widget Toolkit) est une bibliothèque graphique
Java développée par IBM pour eclipse. Celle-ci
est distribuée librement en open source par IBM et peut
donc être utilisée par les développeurs
pour créer des plugins pour eclipse ou des applications
en standalone.
Au-delà de considérations commerciales, on peut
se demander pourquoi IBM a développé cette bibliothèque
et n'a pas utilisé le célèbre AWT/Swing
de Sun. L'article " SWT:
The Standard Widget Toolkit - PART 1: Implementation Strategy
for Java Natives " donne une argumentation technique
à ce choix.
Les bibliothèques graphiques multi-plateformes comme
Swing sont difficiles à écrire et à maintenir.
Les grandes différences entre plateformes rendent leurs
composants graphiques complexes. SWT résout ce problème
en utilisant des techniques d'implémentation de bas niveau.
En effet, la stratégie de SWT est totalement différente.
SWT à la particularité de procurer des composants
graphiques natifs d'une manière indépendante de
l'OS.
:: Stratégie de SWT ::
L'API SWT est implémentée sur différentes
plateformes en utilisant une combinaison de Java et de JNI spécifique
à chaque plateforme. Il ne faut pas s'y tromper, SWT
est développé en totalité en Java : le
JNI est uniquement utilisé pour invoquer le système
d'exploitation. Il y a un mapping " one to one " entre
les méthodes natives Java et les appels à l'OS.
Pour comprendre cette stratégie, l'article précédemment
cité explique par un exemple comment est développée
en SWT la sélection sur une zone de texte.
Le composant graphique concerné (zone de texte) est un
objet Java de type Text.
Voici le code utilisé par une application pour initialiser
le texte affiché et pour fixer la selection :
/* Select positions 2 to 5 */
text.setText ("0123456780");
text.setSelection (2, 5);
L'implémentation de la méthode setSelection est
différente sur chaque plateforme.
Windows
|
Motif
|
public void setSelection (int start, int end)
{
OS.SendMessage (handle, OS.EM_SETSEL, start, end);
} |
public void setSelection (int start, int end)
{
int xDisplay = OS.XtDisplay (handle);
if (xDisplay == 0) return;
OS.XmTextSetSelection (handle, start, end, OS.XtLastTimestampProcessed
(xDisplay));
OS.XmTextSetInsertionPosition (handle, end);
} |
class OS {
public static final int EM_SETSEL = 0xB1;
public static final native int SendMessage (int hWnd, int
Msg, int wParam, int lParam);
...
}
|
class OS {
public static final native void XmTextSetSelection (int widget,
int first, int last, int time);
public static final native int XtLastTimestampProcessed (int
display);
public static final native void XmTextSetInsertionPosition
(int widget, int position);
public static final native int XtDisplay (int widget);
...
} |
JNIEXPORT jint JNICALL Java_org_eclipse_swt_internal_win32_OS_SendMessage__IIII
(JNIEnv *env, jclass that, jint hWnd, jint Msg, jint wParam,
jint lParam)
{
return (jint) SendMessage((HWND)hWnd, Msg, wParam, lParam);
}
|
JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_motif_OS_XmTextSetSelection
(JNIEnv *env, jclass that, jint widget, jint first, jint last,
jint time)
{
XmTextSetSelection((Widget)widget, first, last, time);
}
|
On constate bien que les implémentations spécifiques
à chaque plateforme sont faites uniquement en Java dans
la méthode setText. Le code natif, mis à disposition
dans la classe OS, ne fait qu'appeler les fonctions natives
de l'OS.
Il y a donc une implémentation des composants SWT pour
chaque plateforme mais la signature des méthodes publiques
reste la même. L'application qui utilise les composant
SWT est donc bien multiplateforme.
La stratégie " one to one " est appliquée
strictement pour diverses raisons. Les principales sont :
- la séparation des responsabilités : les développeurs
Windows développent les implémentations de composants
sous Windows et les développeurs Motif développent
les implémentations en Motif ; sans se soucier l'un de
l'autre.
- le langage Java est un langage de haut niveau. Il présente
en tant que tel un grand nombre d'avantages connus par rapport
à d'autres langages comme le C : gestion de la mémoire,
classes réutilisables,
- le code source se situe à un seul endroit. Ainsi la
maintenance est plus simple. Il est également plus simple
de faire du " performance tuning " sachant qu'une
fois que le code natif est appelé, les performances dépendent
uniquement du système d'exploitation.
:: Gestion des ressources en SWT ::
Nous l'avons vu précédemment, SWT utilise des
ressources du système d'exploitation.
Comme dans toute application, les ressources allouées
se doivent d'être libérées, faute de quoi,
on risque de faire planter son application ou les autres applications
tournant sur le système par manque de ressource.
L'article " SWT:
The Standard Widget Toolkit - PART 2: Managing Operating System
Resources " explique très clairement comment
gérer les ressources allouées par SWT à
l'aide de 2 règles à retenir :
- Si on le créé, on le
libère
Les ressources sont allouées automatiquement dans les
constructeurs des composants SWT. Ainsi, chaque fois que l'on
créé une instance d'un composant SWT, il est
nécessaire après son utilisation de libérer
les ressources allouées en appelant la méthode
dispose() dessus. Attention, il
faut uniquement libérer les ressources de ce que l'on
a créé explicitement. En effet, la création
d'un composant SWT peut engendrer l'allocation d'autres ressources
telles que des polices ou des couleurs. Ce n'est pas au développeur
de les libérer, elles seront libérées
automatiquement par la classe qui les a créé.
Ainsi, la présente règle doit également
être comprise dans le sens : " on ne libère
que ce qu'on a créé ".
Prenons un exemple : si on alloue explicitement une police
" Font font = new Font(device, fontData);
", il est nécessaire de la libérer ultérieurement
avec " font.dispose(); ". Par contre, si on récupère
une police d'un composant " Font font=
control.getFont(); ", il ne faut pas la libérer.
- La libération d'un parent
libère les enfants
Un composant graphique ne peut pas exister dans le système
d'exploitation sans composant parent. Ainsi, si le composant
parent est libéré, les composants enfants seront
automatiquement libérés. Cette règle
simplifie grandement la gestion des ressources.
Ceci dit, certains composants dits " non graphiques "
comme Font ou Color ne sont pas des enfants. Il faudra systématiquement
les libérer " manuellement " lorsqu'ils auront
été alloués explicitement par le développeur.
En effet, un composant SWT ne libèrera jamais une ressource
qui a été allouée par un développeur.
Ceci enfreindrait la première règle.
On peut se demander pourquoi la libération des composants
SWT n'est pas prise en charge par le garbage collector Java.
L'article explique que ceci est principalement dû au fait
qu'il est impossible de connaître l'ordre de libération
des objets par le garbage collector. De ce fait, la libération
aléatoire de certains composants avant d'autres risquerait
de provoquer des bugs graphiques, voire des plantages.
|
|
|