Ce support de cours s'intéresse à présenter les composants de visualisation (Viewer) de la bibliothèque JFace pour Eclipse : la partie modèle d'un Viewer via ContentProvider, le modèle graphique avec LabelProvider, gestion des colonnes via ViewerColumn, 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.
Développement de clients
riches : Plateforme Eclipse
Mickaël BARON - 2007 (Rév. Janvier 2009)
mailto:[email protected] ou mailto:[email protected]
mickael-baron.fr
mickaelbaron
Composants de Visualisation (Viewer) avec JFace
Chapitre 2 : Boîtes à outils
2
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Creative Commons
Contrat Paternité
Partage des Conditions Initiales à l'Identique
2.0 France
http://creativecommons.org/licenses/by-sa/2.0/fr
Licence
3
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
3
À propos de l’auteur …
Mickaël BARON
Ingénieur de Recherche au LIAS
https://www.lias-lab.fr
Equipe : Ingénierie des Données et des Modèles
Responsable des plateformes logicielles, « coach » technique
Ancien responsable Java de Developpez.com (2011-2021)
Communauté Francophone dédiée au développement informatique
https://java.developpez.com
4 millions de visiteurs uniques et 12 millions de pages vues par mois
750 00 membres, 2000 forums et jusqu'à 5000 messages par jour
mickael-baron.fr
mickaelbaron
4
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Organisation du cours sur JFace : partie Viewers
Composants de visualisation avec SWT
Manipulation du modèle par le ContentProvider
Manipulation du rendu par le LabelProvider
Tour complet de tous les viewers
Sélection
Edition
Techniques de Tri et de Filtre
Tous les exemples du cours
sont disponibles directement à l’adresse
mickael-baron.fr/eclipse/intro-jface1
Des informations complémentaires
peuvent être trouvées sur mon blog
mickael-baron.fr
5
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : généralités
Nous avons vu que la boîte à outils SWT fournissait un
ensemble de composants graphiques de base
JFace s’appuie sur la bibliothèque SWT pour fournir une API
de développement plus évoluée et plus structurée
Les principaux concepts proposés par JFace
une abstraction des composants natifs SWT
une séparation de la partie modèle et de la vue (modèle MVC)
des composants graphiques additionnels (Dialog, Preferences, …)
une utilisation plus fine des ressources (Action, ImageDescriptor, …)
6
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : généralités
JFace a pour fonction de simplifier les développements en
SWT, sans pour autant masquer totalement SWT
Nous verrons dans la suite que JFace ne cache pas
complètement SWT dans les sens où il est possible d’accéder
directement aux composants SWT
Combinée à SWT, JFace est utilisée pour le développement
d’applications pour la plateforme Eclipse
La boîte à outils connectée
aux composants natifs
L’extension et
l’encapsulation de SWT
La plateforme Eclipse
s’appuie sur JFace et SWT
7
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : généralités
Pré-requis : connaître Java et les principes de SWT
Plan du cours JFace
Les composants de visualisation (TableViewer, …) (Partie 1)
Les boîtes de dialogue évoluées (Partie 2)
Les préférences utilisateur (Partie 2)
La gestion de ressources (ImageDescriptor, Action, …) (Partie 2)
La création d’assistants (Wizards) (Partie 2)
Utilisation tant que possible des nouveautés proposées par
l’API Eclipse 3.3
Différents articles et exemples
www.eclipse.org/articles/Article-TreeViewer/TreeViewerArticle.htm
wiki.eclipse.org/index.php/JFaceSnippets
keulkeul.blogspot.com (mon blog perso)
8
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : installation
La librairie JFace fait partie intégrante du projet Eclipse, et
les binaires sont disponibles dans la distribution Eclipse
Les packages JFace sont préfixés par org.eclipse.jface
Les viewers : org.eclipse.jface.viewers
Les boîtes de dialogues : org.eclipse.jface.dialogs
Les préférences : org.eclipse.jface.preference
Les ressources : org.eclipse.jface.resource
Les assistants : org.eclipse.jface.wizard
Les sources sont également fournies avec la distribution
Eclipse
Tout comme pour la boîte à outils SWT, il est possible de
créer une application Java reposant sur JFace (hors
application Eclipse RCP ou plugin)
Pour SWT, il faut
télécharger l’archive
sur le site d’Eclipse
9
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : configuration …
La configuration présentée ci-dessous décrit l’utilisation du
package viewers pour un simple projet Java
Etape 1 : création d’un projet Java
Une autre configuration basée sur
l’utilisation de développement de
plug-in (via le PDE) sera décrite
dans la partie plug-in Eclipse
10
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace : configuration … (suite)
Etape 2 : ajout des dépendances aux librairies JFace
Les librairies ajoutées dans le chemin de
construction ne sont pas exhaustives. Il s’agit
d’un minimum pour utiliser une TableViewer
org.eclipse.core.commands
org.eclipse.equinox.app
org.eclipse.jface
org.eclipse.swt
11
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
Typiquement en SWT, vous créez le composant, ajoutez des
données et appelez des méthodes
De ce fait il devient difficile de mettre à jour proprement les
données des composants
Une approche MVC (Model, View, Control) est fournie par la
surcouche JFace
Elle permet la séparation « stricte » entre le modèle de
données et le modèle graphique
Ajouter plus facilement des écouteurs (listeners) sur le modèle de
données pour notifier de ces changements
Brancher plusieurs vues pour un même modèle
Accéder aux autres modèles (sélection, édition, …)
« Customiser » le rendu des données
12
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
M
L’implémentation proposée par JFace de MVC se rapproche
plus du Document/Vue ou Model/View (le contrôleur étant
associé à la vue)
Principe de l’architecture
Le modèle est l’élément principale du composant
La ou les vue(s) du composant sont abonnées au modèle
La modèle notifie ses vues suite à des modifications
La partie Document
(En Java le vue et le
contrôleur ne sont pas
dissociés)
La partie Modèle
(Notification des vues
après modification)
V
C
13
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
La boîte à outils SWT fournit des composants de
visualisation qui s’appuient sur des composants du système
Ces composants n’ont pas été étudiés dans le cours SWT
puisqu’il semble plus important de les présenter avec leur
« habillage MVC »
Liste des composants de visualisation :
Table : organisation des données dans un tableau
Tree : organisation des données sous forme d’arbre
List : organisation des données sous forme de liste
A noter que le composant TableTree n’est pas un composant
natif comme peut l’être Table ou Tree
Le composant TableTree est un composant de type custom
obtenu par composition d’un Tree et d’une Table
14
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
Le package org.eclipse.jfaces.viewers fournit un ensemble
de classes pour l’encapsulation des composants SWT
Les composants de visualisation sont appelés des Viewers
Le nom des classes est composé du nom de l’encapsulation
SWT suivi de « Viewer »
Dans la suite de ce cours, nous étudierons les composants :
TreeViewer : un arbre
TableViewer : un tableau
ListViewer : une liste
TableTreeViewer : un tableau avec un arbre sur la première colonne
CheckboxTableViewer : un tableau avec des éléments à cocher
CheckboxTreeViewer : un arbre avec des éléments à cocher
ComboViewer : une boite à valeurs
15
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
TableViewer
TreeViewer
TableTreeViewer
(TreeViewer avec
colonnes)
16
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : introduction
ListViewer
ComboViewer
CheckboxTreeViewer
CheckboxTableViewer
17
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : composants natifs
Nous allons nous intéresser à présenter, avant la description
des viewers, les composants natifs de visualisation
Composants présentés : Table, Tree, ComboBox
Nous ferons uniquement une présentation des concepts
nécessaires pour la suite (plus de détail voir API SWT)
L’intérêt ? Même si les viewers fournissent une abstraction
des composants natifs, il est souvent utile d’accéder aux
composants natifs pour :
Modifier le nom d’une colonne (TableColumn)
Modifier l’agencement d’un viewer (setLayoutData(…))
Pourquoi pas au niveau du cours SWT ? Redondant
avec cette partie car au final il est plus flexible d’utiliser les
composants de visualisation par l’API JFace
18
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
Un composant Table est construit suivant le principe des
composants SWT
Table(Composite p, int style) : construction à partir d’un parent et
d’un style
Différents styles disponibles
SINGLE, MULTI, FULL_SELECTION, HIDE_SELECTION : concerne le
type de sélection autorisée (FULL_SELECTION = ligne complète)
CHECK : la première colonne contient une boîte à cocher
VIRTUAL : pour afficher de nombreuses lignes (à voir plus tard)
Un composant Table est composé
de colonnes décrites par la classe TableColumn
de lignes décrites par la classe TableItem
TableColumn et TableItem hérite de la classe Item qui
rappelons-le (voir cours SWT) s’occupe de gérer une image
et un texte
19
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
La classe TableColumn décrit une colonne
TableColumn(Table parent, int style) : préciser l’objet parent Table et
un style
Le style donne la position du contenu : LEFT, RIGHT et CENTER
Un objet TableColumn peut être vu comme un composant
label dans le sens où il peut afficher du texte et une image
Les valeurs à afficher sont transmises par l’intermédiaire des
modifieurs setText(String p) et setImage(Image i)
De nombreuses autres informations peuvent être renseignées
setMoveable/Resizable(boolean p) : colonne déplaçable
setResizable(boolean p) : colonne redimensionnable
setToolTipText(String p) : modifier valeur de la bulle d’aide
setWidth(int width) : modifier largeur de la colonne
addSelectionListener(SelectionListener sl) : ajouter un écouteur sur la
sélection
20
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
Exemple : une table et ses colonnes
public class TableColumnExample {
public TableColumnExample() {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Exemple de la Table SWT");
shell.setLayout(new FillLayout());
Table table = new Table(shell, SWT.NONE);
table.setHeaderVisible(true);
for (int i = 0; i < 3; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setWidth(100);
column.setText("Colonnne " + i);
column.setMoveable(true);
column.setResizable(true);
}
...
}
...
}
Construction de trois
colonnes
TableColumnExample.java du
projet TableExamples
Fixe la largeur
Les colonnes sont
déplaçables et
redimensionnables
Il manque les
cellules !!
21
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
La classe TableItem représente une ligne d’un tableau et peut
être vu comme un ensemble de labels (cellule = Label)
TableItem(Table parent, int style) : préciser le parent Table et un style
Pas de style particulier, mais tout autre style qui s’applique à un Label
Possibilité de modifier pour chaque cellule du TableItem le
texte et l’image
setImage(int i, Image im) ou setImage(Image[] im)
setText(int i, String s) ou setText(String[] es)
Contrairement à TableColumn, TableItem fournit des
méthodes pour modifier l’apparence d’une cellule
setForeground(int i, Color c) et setBackground(int i, Color c) : modifi-
cation de la couleur de fond et du dessus
setFont(int i, Font f) : modification de la fonte pour une cellule donnée
setChecked(boolean b) : état de la boite à cocher uniquement pour la
première colonne
22
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
Exemple : une table, ses colonnes et ses lignes
public class TableRowColumnExample {
public TableRowColumnExample() {
...
for (int i = 0; i < 50; i++) {
new TableItem(table, SWT.NONE);
}
TableItem[] items = table.getItems();
for (int i = 0; i < items.length; i++) {
int backgroundColor = (i % 2 == 0 ? SWT.COLOR_CYAN : SWT.COLOR_RED);
items[i].setBackground(Display.getDefault().getSystemColor(backgroundColor));
for (int j = 0 ; j < 3 ; j++) {
items[i].setText(j, "cellule " + j
+ ":" + i);
}
}
...
}
...
}
Construction de 50
lignes
Couleur de fond des cellules
différente selon la « parité »
Modification du contenu de la
cellule de la ligne i de la colonne j
TableRowColumnExample.java
du projet TableExamples
23
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
Le composant Table fournit un ensemble de méthodes pour
Modifier la sélection
setSelection(int index) : sélectionne un seul élément
setSelection(int[] indices) : sélectionne un ensemble d’élément
Accéder aux TableColumn et TableItem
TableColumn getColumn(int i) : accesseur sur un TableColumn
TableItem getItem(int i) : accesseur sur un TableItem
TableItem getItem(Point p) : accesseur sur un TableItem à un
emplacement donné (x et y relatif au composant Table)
Customiser l’apparence graphique
setHeaderVisible(boolean s) : affiche ou pas les en-têtes des colonnes
setLinesVisible(boolean s) : affiche ou pas les lignes de la table
Effectuer des traitements sur le contenu
setTopIndex(int i) : positionne l’élément i en tête de la table
clear(int i) : efface le contenu d’une ligne
24
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Table
Exemple (suite) : une table, ses colonnes et ses lignes
public class AdvancedTableRowColumnExample {
public AdvancedTableRowColumnExample() {
...
Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
...
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.setTopIndex(20);
int[] selectedIndex = {22, 25};
table.setSelection(selectedIndex);
table.clear(23);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
...
}
AdvancedTableRowColumnExample
du projet TableExamples
Positionner la ligne 20
en haut de la table
Active la sélection multiple
et la sélection de la ligne
complète
Sélectionne les lignes
22 et 25
Efface le contenu de la
ligne 23 (suppression
du texte)
25
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
Un composant Tree est construit suivant le principe des
composants SWT
Tree(Composite p, int style) : construction à partir d’un parent et
d’un style
Les différents styles disponibles sont les mêmes que ceux
utilisés pour le composant Table
Un composant Tree est composé
de colonnes décrites par la classe TreeColumn
de lignes décrites par la classe TreeItem
TreeColumn et TreeItem hérite de la classe Item qui (voir
cours SWT) s’occupe de gérer une image et un texte
26
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
La classe TreeColumn décrit une colonne et possède les
mêmes fonctionnalités que la classe TableColumn
Depuis la version 3.1, possibilité d’avoir plusieurs colonnes
pour un composant Tree, ceci permet de remplacer le compo-
sant TableTree devenu « déprécié »
Plusieurs colonnes
Un arbre contenant
des noeuds sur la
colonne 1
Chaque item désigne
une ligne (1 nœud +
plusieurs cellules)
27
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
La classe TreeItem désigne une ligne contenant des cellules
Chaque cellule peut être vue comme un ensemble de labels
Une cellule du TreeItem contient un nœud de l’arbre les
autres sont considérées comme des cellules d’une table
A la différence des TableItem, les TreeItem peuvent contenir
d’autres TreeItem (un nœud peut contenir des sous nœuds)
TreeItem(Tree parent, int style) : préciser le parent Tree et un style
TreeItem(TreeItem parentItem, int style) : précise le nœud parent
Possibilité de modifier pour chaque cellule du TreeItem le
texte et l’image
Possibilité de déplier le contenu d’un nœud
setExpanded(boolean expanded) : si expanded est vrai, le nœud est
déplié
28
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
Exemple : un arbre et ses noeuds
public class TreeExample {
public TreeExample() {
...
Tree myTree = new Tree(shell, SWT.FULL_SELECTION);
final int ROW = 4;
for (int i = 0; i < ROW; i++) {
TreeItem current = new TreeItem(myTree, SWT.NONE);
current.setText("Noeud " + i);
final int SUB_ROW = 3;
for (int j = 0; j < SUB_ROW; j++) {
TreeItem subCurrent = new TreeItem(current, SWT.NONE);
subCurrent.setText("Sous Noeud " + j);
}
}
shell.open();
...
}
...
}
Les nœuds
parents x4
Les sous nœuds
parents x3
TreeExample du projet
TreeExamples
29
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
Exemple (suite) : un arbre, ses colonnes et ses noeuds
public class TreeColumnExample {
public TreeColumnExample() {
...
Tree myTree = new Tree(shell, SWT.FULL_SELECTION);
TreeColumn column = new TreeColumn(myTree, SWT.NONE);
column.setText("Colonne 1");
column.setResizable(true);
column.setMoveable(true);
column.setWidth(100);
...
final int ROW = 4;
for (int i = 0; i < ROW; i++) {
TreeItem current = new TreeItem(myTree, SWT.NONE);
current.setText("Noeud " + i);
final int SUB_ROW = 3;
for (int j = 0; j < SUB_ROW; j++) {
TreeItem subCurrent = new TreeItem(current, SWT.NONE);
subCurrent.setText("Sous Noeud " + j);
subCurrent.setText(1, "valeur 1 " + j);
subCurrent.setText(2, "valeur 2 " + j);
}
}
shell.open();
...
}
...
}
TreeColonneExample du projet
TreeExamples
Création des colonnes
30
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
Le composant Tree fournit un ensemble de méthodes pour
Modifier la sélection
setSelection(TreeItem index) : sélectionne un seul élément
setSelection(TreeItem[] indices) : sélectionne un ensemble d’élément
Accéder aux TableColumn et TableItem
TreeColumn getColumn(int i) : accesseur sur un TreeColumn
TreeItem getItem(int i) : accesseur sur un TreeItem
Customiser l’apparence graphique
setHeaderVisible(boolean s) : affiche ou pas les en-têtes des colonnes
setLinesVisible(boolean s) : affiche ou pas les lignes de la table
Effectuer des traitements sur le contenu
setTopItem(TreeItem i) : positionne l’élément i en tête de la table
clear(int i, boolean a) : efface le contenu d’une ligne, si a est vraie les
sous nœuds sont supprimés
31
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tree
Exemple (suite) : un arbre, ses colonnes et ses noeuds
public class TreeColumnSelectionExample {
public TreeColumnSelectionExample() {
...
Tree myTree = new Tree(shell, SWT.FULL_SELECTION);
...
final int ROW = 4;
for (int i = 0; i < ROW; i++) {
TreeItem current = new TreeItem(myTree, SWT.NONE);
for (int j = 0; j < SUB_ROW; j++) {
...
}
}
myTree.setTopItem(myTree.getItem(5));
myTree.setSelection(myTree.getItem(5));
myTree.getItem(5).setExpanded(true);
shell.open();
...
}
...
}
TreeColonneSelectionExample du
projet TreeExamples
Déplier le nœud 5
Afficher le nœud 5 en
haut du Tree
Modifier la sélection
sur le nœud 5
32
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Viewer
Un composant Viewer est organisé autour de trois concepts
Input
Objet métier qui sera affiché par le Viewer
Il peut s’agir d’un simple objet (une liste de String par exemple) ou
d’un objet « structurée »
ContentProvider
Adaptation des données de l’Input pour le type du Viewer
Remarque : notifié si l’input est modifié
LabelProvider
S’intéresse au rendu de chaque élément transmis par ContentProvider
Peut fournir du texte ou des images
Ces concepts seront étudiées très succinctement puis
détaillés pour chaque composant Viewer
33
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Viewer
Input
Person
- name : String
- firstName : String
- …
+ getName() : String
+ getFirstName() : String
+ …
List
myList
ContentProvider
LabelProvider
Table
TableViewer
Concept stockant les
données à afficher
Les données à afficher
par la table
List
myList
Transmission
des données à
l’Input
(Initialisation)
1 2
Les données sont transmises pour
structuration
getElements(myList)
3
Les données sont
structurées : Person[]
4
Pour chaque ligne et chaque colonne
transmission d’un objet Person et de
l’indice de colonne concerné
getColumnText(Person, i)
5
Retour pour appel à
getColumnText(…) d’une chaîne à
afficher dans la cellule : String
Transmission pour
chaque TableItem de
la table d’une chaîne
de caractères
6
IStructuredContentProvider
ITableLabelProvider
Le viewer centralise les
appels aux différents
concepts
Person, 0
"Dupont"
"Dupont"
List
Person[]
34
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Viewer
Viewer
TextViewer
ContentViewer
En charge de gérer le
LabelProvider, le
ContentProvider et
l’Input
…
StructuredViewer
En charge de
gérer le tri et le
filtre
AbstractListViewer
ComboViewer
ListViewer
Classe qui décrit le
comportement de
viewers de type Liste
ColumnViewer
AbstractTableViewer AbstractTreeViewer
En charge des Viewers
contenant des
colonnes (new 3.3)
En charge des
viewers de type
Arbre (new 3.3)
En charge des viewers
de type Table (new 3.3)
Hiérarchie des principaux Viewers
TableViewer
TreeViewer
Gestion des composants de
texte. Non étudiés dans ce
cours
35
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : un exemple pour débuter
Exemple : TableViewer et ses trois concepts
Cinq colonnes
Un objet Person
contenant un nom,
un prénom, un
sport, un age et une
habitude alimentaire
TableViewerExample.java du projet
TableViewerExamples
36
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : un exemple pour débuter
Exemple (suite) : TableViewer et ses trois concepts
public class Person {
private String name;
private String firstName;
private String sportName;
private int old;
private boolean vegetarian;
public Person(String name, String firstName, String sportName, int years,
boolean vegetarian) {
this.name = name;
this.firstName = firstName;
this.sportName = sportName;
this.old = years;
this.vegetarian = vegetarian;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
...
}
Cinq propriétés
Cinq modifieurs et
accesseurs
Person.java du projet
TableViewerExamples
37
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : un exemple pour débuter
Exemple (suite) : TableViewer et ses trois concepts
public class TableViewerExample {
public TableViewerExample() {
Display display = new Display();
Shell shell = new Shell(display);
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
...
viewer.setContentProvider(new MyStructuredContentProvider());
viewer.setLabelProvider(new MyTableLabelProvider());
List myPersonList = new ArrayList();
myPersonList...
viewer.setInput(myPersonList);
Table table = viewer.getTable();
new TableColumn(table, SWT.CENTER).setText("Nom");
new TableColumn(table, SWT.CENTER).setText("Prénom");
new TableColumn(table, SWT.CENTER).setText("Sport");
...
for (int i = 0; i < n; i++) {
table.getColumn(i).setWidth(100);
}
shell.open();
...
}...
Concept : Input
La description détaillée de
TableViewer sera réalisée
dans la suite du cours
TableViewerExample.java du projet
TableViewerExamples
38
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : un exemple pour débuter
Exemple (suite) : TableViewer et ses trois concepts
static class MyStructuredContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
ArrayList localInputElement = (ArrayList)inputElement;
return localInputElement.toArray();
}
}
static class MyTableLP extends BaseLabelProvider implements ITableLabelProvider {
public String getColumnText(Object element, int columnIndex) {
Person currentPerson = (Person)element;
switch(columnIndex) {
case 0 : return currentPerson.getName();
case 1 : return currentPerson.getFirstName();
case 2 : return currentPerson.getSportName();
case 3 : return Integer.toString(currentPerson.getOld());
case 4 : return Boolean.toString(currentPerson.isVegetarian());
default : return "";
}
}
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
}
Concept : LabelProvider
Concept : ContentProvider
TableViewerExample.java du projet
TableViewerExamples
39
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ContentProvider
Le rôle du ContentProvider est de fournir une adaptation
des données du modèle (fournies par Input) pour un type de
Viewer (TableViewer, TreeViewer, …)
Un ContentProvider générique est décrit par l’interface
IContentProvider
L’interface IContentProvider fournit une seule méthode
void inputChanged(Viewer, Object oldInput, Object newInput) : en
charge de notifier le ContentProvider si les données du modèle (Input)
ont changé
La méthode setContentProvider(IContentProvider) permet
d’associer un ContentProvider avec un Viewer
De façon générale vous n’aurez pas à implémenter directe-
ment l’interface IContentProvider
40
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Selon le Viewer utilisé, l’API fournit des ContentProvider
défini par des interfaces assurant les fonctionnalités des
viewers concernés
La méthode assertContentProvider(IContentProvider) s’assure
que le IContentProvider fourni à la vue est du bon type
La méthode assert est protected et ne peut être accessible
directement
Dans le cas où vous implémentez une mauvaise interface, le
viewer n’affiche aucune information
A noter que l’API fournit des implémentations « toutes
prêtes » offrant des fonctionnalités directement utilisables
Dans la suite, nous nous occuperons de nos propres
implémentations de IContentProvider
JFace / Viewers : ContentProvider
41
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ContentProvider
Nous fournissons ci-dessous un récapitulatif facilitant le choix
de l’interface à implémenter pour les viewers étudiés
IStructuredContentProvider : TableViewer, CheckboxTableViewer,
ListViewer
ILazyContentProvider : TableViewer, CheckboxTableViewer
ITreeContentProvider : TreeViewer, CheckboxTreeViewer
ILazyTreeContentProvider : TreeViewer, CheckboxTreeViewer
ITreePathContentProvider : TreeViewer, CheckboxTreeViewer
…
Seront étudiées en priorité les interfaces ITreeContentProvider
et IStructuredContentProvider
Il existe d’autres interfaces de type ContentProvider qui ne
seront pas étudiées dans ce cours
42
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ContentProvider
Hiérarchie des principales interfaces ContentProvider
IContentProvider
ILazyTreeContentProvider
ILazyContentProvider
IStructuredContentProvider
ITreeContentProvider
ITreePathContentProvider
…
Et pleins d’autres
encore …
Permet de connaître le
nombre d’éléments
(lignes, racines, …)
Quand le nombre
d’éléments est inconnu
Quand le nombre
d’éléments d’un arbre
est inconnu
Lazy pour Lazy Loading signifie que
l’élément considéré n’est chargé qu’au
moment où il est effectivement utilisé
Permet de connaître la relation entre
élément et son père et vice-et-versa
43
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ContentProvider
L’interface IStructuredContentProvider peut être considérée
comme le point de départ de l’utilisation des Viewers
IStructuredContentProvider fournit une API pour connaître le
nombre d’éléments d’un viewer
Nombre de lignes d’un tableau (TableViewer)
Nombre d’éléments d’une liste (ListViewer)
Nombre d’éléments racine d’un arbre (élément ne possédant pas de
père) (TreeViewer)
Cette interface propose une seule méthode
Object[] getElements(Object inputElement) : retourne toutes les
lignes à afficher
Le paramètre inputElement est donné par l’objet input du
composant viewer
44
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ContentProvider
Exemple : TableViewer et IStructuredContentProvider
public class TableViewerExample {
public TableViewerExample() {
Display display = new Display();
Shell shell = new Shell(display);
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
...
viewer.setContentProvider(new MyStructuredContentProvider());
List myPersonList = new ArrayList();
myPersonList...
viewer.setInput(myPersonList);
...
}
static class MyStructuredContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
ArrayList localInputElement = (ArrayList)inputElement;
return localInputElement.toArray();
}
}
...
}
L’input est de type
List
L’input est transmis en
paramètre de getElements(…)
En retour de cette méthode, il faut transmettre
les lignes du tableau qui seront affichées
TableViewerExample.java
du projet
TableViewerExamples
45
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Nous avons vu que le rôle du ContentProvider était de
fournir les objets du modèle (Input) au Viewer
Le rôle du LabelProvider est d’effectuer un rendu de
chaque élément transmis par le ContentProvider
Ce rendu s’effectue via un composant de type label qui
permet d’afficher une image et un texte
L’API proposée par JFace n’est pas aussi souple que celle de
Swing pour la gestion du rendu des éléments d’un viewer
Nous verrons dans les exemples proposés que des solutions
« bricolages » existent
Colonne d’un
TableViewer
Rendu de la cellule
obtenu par un label
(Image + Texte)
Ici un label sans
l’affichage de
l’image
46
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Un LabelProvider générique est défini par l’interface
IBaseLabelProvider qui ne propose rien d’exceptionnelle
Une implémentation par défaut de IBaseLabelProvider est
fournie par la classe BaseLabelProvider
Hiérarchie des principales interfaces LabelProvider
IBaseLabelProvider
ILabelProvider ITableLabelProvider
ITreePathLabelProvider
IViewerLabelProvider
Utilisée pour les viewers de type
StructuredViewer comme
TreeViewer sauf TableViewer
LabelProvider adapté
pour les composants de
type TableViewer
Ajoute une méthode updateLabel
spécialiser dans la mise à jour
d’élément (à voir plus tard)
Ajoute une méthode updateLabel
spécialiser dans la mise à jour de chemin
pour un TreeViewer (à voir plus tard)
47
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
L’interface ILabelProvider permet d’afficher une image et un
texte pour un élément d’un Viewer (excepté le TableViewer)
Rappelons qu’un élément peut correspondre à une ligne
d’une liste, à un nœud d’un arbre, …
L’interface possède deux méthodes :
Image getImage(Object element) : affichage d’un objet Image
String getText(Object element) : affichage d’un texte
Le paramètre element correspond à un élément transmis par
le ContentProvider (exemple : un objet de type Person)
A noter que pour supprimer l’affichage du texte ou d’une
image, il faut retourner null
48
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
L’interface ITableLabelProvider fournit du texte/image pour
chaque colonne d’un élément donné pour un TableViewer
L’interface possède deux méthodes :
Image getColumnImage(Object element, int columnIndex) : retourne
une image pour une colonne et un élément donnés
String getColumnText(Object element, int columnIndex) : retourne un
texte pour une colonne et un élément donnés
Concernant l’exemple, element est de type Person. Il faudra
donc en fonction de la valeur de columnIndex retourner de
l’attribut adéquate de l’objet Person
La méthode getColumnImage(…) sera appelée autant de fois
qu’il y a de lignes
49
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Depuis l’API Eclipse 3.3, il est possible d’associer à un viewer
un LabelProvider unique pour toutes les colonnes (avant 3.3)
un LabelProvider différent pour chaque colonne (depuis 3.3)
Cette nouvelle API permet donc de paramétrer plus finement
le rendu des différents éléments
Ceci a été rendu possible par l’ajout de ColumnViewer
Concernant la modification du LabelProvider unique pour
toutes les colonnes, ColumnViewer fournit une méthode
setLabelProvider(IBaseLabelProvider p) : associer un LabelProvider à
toutes les colonnes
50
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple : un LabelProvider pour toutes les colonnes
public class TableViewerExample {
public TableViewerExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setLabelProvider(new MyTableLabelProvider());
...
}
...
class MyTableLP extends BaseLabelProvider implements ITableLabelProvider {
public String getColumnText(Object element, int columnIndex) {
Person currentPerson = (Person)element;
switch(columnIndex) {
case 0 : return currentPerson.getName();
case 1 : return currentPerson.getFirstName();
case 2 : return currentPerson.getSportName();
case 3 : return Integer.toString(currentPerson.getOld());
case 4 : return Boolean.toString(currentPerson.isVegetarian());
default : return "";
}
}
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
}}
Implémentation par défaut de
IBaseLabelProvider
N’affiche pas d’image
Selon la valeur de
columnIndex on
sélectionne l’attribut à
afficher
TableViewerExample.java du projet
TableViewerExamples
51
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Pour la gestion de l’affichage de l’en-tête de la table il faut
passer par les objets natifs TableColumn
Exemple : un LabelProvider pour toutes les colonnes
public class TableViewerExample {
public TableViewerExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setLabelProvider(new MyTableLabelProvider());
Table table = viewer.getTable();
new TableColumn(table, SWT.CENTER).setText("Nom");
new TableColumn(table, SWT.CENTER).setText("Prénom");
new TableColumn(table, SWT.CENTER).setText("Sport");
new TableColumn(table, SWT.CENTER).setText("Age");
new TableColumn(table, SWT.CENTER).setText("Végétarien");
for (int i = 0; i < n; i++) {
table.getColumn(i).setWidth(100);
}
...
}
...
}
TableViewerExample.java du projet
TableViewerExamples
Nécessite de construire des
TableColumn pour
paramétrer chaque en-tête
de colonne
52
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Les LabelProviders peuvent être différents pour chaque
colonne (nouveauté Eclipse 3.3)
Ne concerne que les composants de type ColumnViewer,
c’est-à-dire les composants TableViewer et TreeViewer
La classe abstraite ViewerColumn s’occupe de représenter
une colonne d’un composant ColumnViewer
setLabelProvider(CellLabelProvider clp) : modifie le LabelProvider
pour une colonne
setEditingSupport(EditingSupport es) : modification de l’éditeur (à voir
plus tard)
CellLabelProvider, qui hérite de BaseLabelProvider, est une
nouveauté 3.3
53
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Selon le composant ColumnViewer utilisé (TableViewer ou
TreeViewer) l’API fournit respectivement deux sous classes à
ViewerColumn
TableViewerColumn pour associer un LabelProvider à une colonne
d’un TableViewer
TreeViewerColumn pour associer un LabelProvider à une colonne
d’un TreeViewer
Le principe d’utilisation entre ces deux classes reste le même
Nous détaillerons donc TableViewerColumn puis pour
TreeViewerColumn nous donnerons simplement des exemples
54
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Un TableViewerColumn fournit une seule méthode permet-
tant d’accéder au composant natif décrivant une colonne
TableColumn getColumn() : accesseur sur une colonne d’une Table
Rappelons qu’un TableColumn décrit « nativement » une
colonne d’un objet Table (Table contient n TableColumn)
L’accès à TableColumn va permettre de paramétrer le
contenu de la colonne (un nom, une image, une dimension)
La construction d’un TableViewerColumn précisera qu’une
nouvelle colonne doit être associer à un TableViewer
Nativement, cela revient à associer un TableColumn avec un
objet Table
Par conséquent, il n’est pas possible de supprimer des colon-
nes sans reconstruire l’objet TableViewer
55
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Différents constructeurs pour la classe TableViewerColumn
TableViewerColumn(TableViewer tv, int style) : construit une colonne
avec un style (associer un nouveau TableColumn avec une Table)
TableViewerColumn(TableViewer tv, int style, int index) : même chose
avec la possibilité de choisir l’index de la nouvelle colonne dans la table
Le style de la colonne précise l’emplacement du texte dans la
colonne (LEFT, RIGHT et CENTER)
Démarche pour utiliser un LabelProvider différent pour
chaque colonne
Construire le TableViewer
Construire et paramétrer (nom et taille par exemple) toutes les colon-
nes via un TableViewerColumn
A partir de chaque référence des TableViewerColumn, associer un
LabelProvider unique
56
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple : un LabelProvider pour chaque colonne
public class TableViewerColumnExample {
public TableViewerColumnExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyStructuredContentProvider());
TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
column.setLabelProvider(new ColumnLabelProvider() {
...
}
column.getColumn().setText("Nom");
column = new TableViewerColumn(viewer, SWT.NONE);
column.setLabelProvider(new ColumnLabelProvider() {
...
}
column.getColumn().setText("Sport");
...
viewer.setInput(myPersonList);
Table table = viewer.getTable();
table.setLayoutData(new GridData(GridData.FILL_BOTH));
...
}
}
TableViewerColumnExample.java
du projet TableViewerExamples
Nécessite toujours de
manipuler le composant
natif Table
Modification de l’en-
tête de la colonne
Un LabelProvider par
colonne (à voir après)
57
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Un objet ViewerColumn manipule un LabelProvider de type
CellLabelProvider (qui hérite de BaseLabelProvider)
Le rôle de CellLabelProvider est de fournir des méthodes pour
la manipulation des bulles d’aides de type
Color getToolTipBackgroundColor(Object objet) : retourne la couleur
du fond de la bulle d’aide
String getToolTipText(Object element) : retourne le texte contenu
dans la bulle d’aide
int getTooltipDisplayDelayTime(Object element) : durée qu’il faut pour
afficher la bulle d’aide
boolean useNativeToolTip(Object object) : indique si les bulles d’aides
natives doivent être utilisées
Pour utiliser les bulles d’aides il faut les activer …
JFace / Viewers : LabelProvider
ColumnViewerToolTipSupport.enableFor(myViewer, ToolTip.NO_RECREATE)
Activation des bulles d’aides
pour un viewer donné
58
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
CellLabelProvider est abstraite, deux classes concrètes sont
fournies par l’API
ColumnLabelProvider : LabelProvider spécifique à une colonne
OwnerDrawLabelProvider : LabelProvider pour dessiner le contenu
ColumnLabelProvider fournit des méthodes pour modifier
Color getBackground(Object element) : la couleur de fond
Color getForeground(Object element) : la couleur de l’avant
Font getFont(Object element) : la fonte
Image getImage(Object element) : l’image (si null = d’image)
String getText(Object element) : le texte
59
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple (suite) : LabelProvider pour chaque colonne
Cinq colonnes qui
ont chacune un
LabelProvider
La couleur de
fond de cette
colonne est
différente des
autres
TableViewerColumnExample.java du
projet TableViewerExamples
60
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple (suite) : LabelProvider pour chaque colonne
public class TableViewerColumnExample {
public TableViewerColumnExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyStructuredContentProvider());
TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
column.setLabelProvider(new ColumnLabelProvider() {
public Color getBackground(Object element) {
return Display.getDefault().getSystemColor(SWT.COLOR_GREEN);
}
public String getText(Object element) {
Person currentPerson = (Person)element;
return currentPerson.getName();
}
}
column.getColumn().setText("Nom");
column = new TableViewerColumn(viewer, SWT.NONE);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
Person currentPerson = (Person)element;
return currentPerson.getFirstName();
}
}
column.getColumn().setText("Sport");
...
}
}
Retourne le texte à
afficher dans la
cellule
Modifie la couleur de
fond de la première
colonne
TableViewerColumnExample.java du
projet TableViewerExamples
61
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple (suite) : LabelProvider pour chaque colonne
public class TableViewerColumnExample {
public TableViewerColumnExample() {
...
column.setLabelProvider(new ColumnLabelProvider() {
public int getToolTipDisplayDelayTime(Object object) {
return 500;
}
public int getToolTipTimeDisplayed(Object object) {
return 5000;
}
public Color getToolTipBackgroundColor(Object object) {
return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
}
public String getToolTipText(Object element) {
return "Ceci est un exemple de bulle d’aide";
}
public boolean useNativeToolTip(Object object) {
return false;
}
});
column.getColumn().setText("Végétarien");
ColumnViewerToolTipSupport.enableFor(viewer, ToolTip.NO_RECREATE);
}
}
Gestion des
bulles d’aides
par colonne
TableViewerColumnExample.java du
projet TableViewerExamples
N’oubliez pas d’activer les bulles d’aides
via ColumnViewerToolTipSupport
62
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Les LabelProvider proposés actuellement ne permettent
que d’afficher du texte et/ou une image
Pour dessiner dans le label (possibilité également de passer
par une image), l’API 3.3 fournit OwnerDrawLabelProvider
La classe abstraite OwnerDrawLabelProvider permet de
« dessiner » dans le label (ex : une cellule pour une table)
abstract void measure(Event event, Object e) : dimensionner le label
abstract void paint(Event event, Object e) : dessiner le contenu
abstract void erase(Event event, Object e) : dessiner la sélection
static void setUpOwnerDraw(ColumnViewer viewer) : rediriger les
événements du Viewer dans le LabelProvider
Pour qu’un ColumnViewer prenne en compte un
LabelProvider de type OwnerDrawLabelProvider,
employez obligatoirement setUpOwnerDraw
63
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple : dessiner le contenu des cellules
public class OwnerDrawLabelExample {
public OwnerDrawLabelExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
column.setLabelProvider(new OwnerDrawLabelProvider() {
protected void measure(Event event, Object element) {
Person currentPerson = (Person)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) {
// La suite dans le slide suivant ...
}
}
column.getColumn().setText("Nom");
... // Traitement des autres colonnes
OwnerDrawLabelProvider.setUpOwnerDraw(viewer);
}
}
OwnerDrawLabelExample.java du
projet TableViewerExamples
Style, couleur et fonte
différents dans un même label
Précise la
dimension du
label
64
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : LabelProvider
Exemple (suite) : dessiner le contenu des cellules
protected void paint(Event event, Object element) {
Person currentPerson = (Person)element;
Display display = viewer.getControl().getDisplay();
TextLayout layout = new TextLayout(display);
layout.setText(currentPerson.getName());
TextStyle plain = new TextStyle(JFaceResources
.getFont(JFaceResources.DEFAULT_FONT), display
.getSystemColor(SWT.COLOR_LIST_FOREGROUND), null);
TextStyle italic = new TextStyle(JFaceResources.getFontRegistry()
.getItalic(JFaceResources.DEFAULT_FONT), display
.getSystemColor(SWT.COLOR_BLUE), null);
Font newFont = new Font(display, "Arial", 9, SWT.BOLD);
TextStyle font = new TextStyle(newFont, display
.getSystemColor(SWT.COLOR_WHITE), display
.getSystemColor(SWT.COLOR_BLACK));
layout.setStyle(plain, 0, 2);
layout.setStyle(italic, 3, 5);
layout.setStyle(font, 6, currentPerson.getName().length() - 1);
layout.draw(event.gc, event.x, event.y);
}
La cellule la plus grande
fixe la taille de toutes
les autres dimensions
d’une même colonne
OwnerDrawLabelExample.java du
projet TableViewerExamples
Précise les
différents
styles
Utilisation d’un
TextLayout pour
faciliter l’agencement
du texte dans la cellule
65
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Nous avons vu que le composant TableViewer permettait
d’encapsuler le composant Table de l’API SWT
ContentProvider autorisés
IStructuredContentProvider et ILazyContentProvider
LabelProvider autorisés
ILabelProvider et ITableLabelProvider pour toutes les colonnes
ColumnLabelProvider et OwnerDrawLabelProvider pour chaque colon-
ne via le composant TableViewerColumn
Différents styles sont utilisables (voir partie Table pour con-
naître sont qui sont exploitables)
Particulièrement le style SWT.VIRTUAL permet d’utiliser le
ContentProvider ILazyContentProvider
JFace / Viewers : TableViewer
Si le style est SWT.VIRTUAL utilisez
obligatoirement ILazyContentProvider au
risque de lever une exception
66
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableViewer
Le principe du « Lazy Loading » est de ne charger en mé-
moire que les objets effectivement utilisés
Selon les besoins, de nouveaux objets sont alors ajoutés en
mémoire
Dans le cas de l’interface ILazyContentProvider seuls les
objets visibles, représentés par les lignes affichées, sont
pris en compte par le TableViewer
Si il y a affichage de nouvelles lignes, les objets associés
sont ajoutés dans le TableViewer
L’interface ILazyContentProvider contient une méthode
updateElement(int index) : appelée quand une nouvelle ligne
(index) est visible
67
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableViewer
Pour utiliser ILazyContentProvider, il faut connaître la taille
des éléments à afficher
AbstractTableViewer#setItemCount(int count) : précise le nombre
d’élément count géré par la table
A chaque nouvel objet dans la TableViewer (appelle de la
méthode updateElement), prise en compte de l’objet dans la
table par :
AbstractTableViewer#replace(Object el, int index) : objet el à ajouter
à la position index
12 objets ont été chargés
dans la TableViewer
68
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableViewer
Exemple : TableViewer et ILazyContentProvider
public class LazyContentProviderExample {
public LazyContentProviderExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.VIRTUAL | SWT.FULL_SELECTION);
viewer.setLabelProvider(new MyTableLabelProvider());
viewer.setContentProvider(new MyLazyContentProvider(viewer));
...
viewer.setInput(myPersonList);
viewer.setItemCount(myPersonList.size());
...
}
static class MyLazyContentProvider implements ILazyContentProvider {
private AbstractTableViewer ref;
private ArrayList myPersonList;
private MyLazyContentProvider(AbstractTableViewer pRef) {
this.ref = pRef;
}
public void updateElement(int index) {
ref.replace(myPersonList.get(index), index);
}
public void inputChanged(Viewer view, Object oldInput, Object newInput) {
this.myPersonList = (ArrayList)newInput;
}
public void dispose() {}
}
}
Précise le nombre de ligne
dans la table
Ajoute un objet à la
position index
LazyContentProviderExample.java
du projet TableViewerExamples
69
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Le composant TreeViewer permet d’encapsuler le composant
Tree de l’API SWT
ContentProvider autorisés
ITreeContentProvider, ILazyTreeContentProvider,
ITreePathContentProvider et ILazyTreePathContentProvider
LabelProvider autorisés
ILabelProvider pour toutes les colonnes
ColumnLabelProvider et OwnerDrawLabelProvider pour chaque colon-
ne via le composant TreeViewerColumn
Différents styles sont utilisables (voir partie Table pour con-
naître ceux qui sont exploitables)
Notons que le fait d’utiliser plusieurs TreeViewerColumn
permet de construire un TableTreeViewer
70
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
L’interface ITreeContentProvider est utilisée par un viewer de
type arbre (Tree)
Elle hérite de l’interface IStructuredContentProvider qui
fournit une méthode pour déterminer le nombre d’éléments
(dans ce cas, le nombre d’éléments racines)
ITreeContentProvider fournit trois méthodes
Object[] getChildren(Object paramElement) : retourne les enfants d’un
élément donné
Object getParent(Object element) : retourne l’élément père d’un
élément
boolean hasChildren(Object element) : précise si l’élément est racine
ou pas
71
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple : TreeViewer et ITreeContentProvider
public class Job {
private List myPerson;
private String job;
public void addPerson(Person pPerson) {
myPerson.add(pPerson);
pPerson.setParent(this);
}
public List getPersons() {
return myPerson;
}
public String getJob() {
return job;
}}
public class Person {
private String name;
...
private Job parent;
public Person(String pName, ...) {
name = pNamae; ...
}
public String getName() {
return name;
}
public void setParent(Job pJob) {
this.parent = pJob;
}
...
}
Person.java du projet
TreeViewerExamples
Job.java du projet
TreeViewerExamples
72
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple (suite) : TreeViewer et ITreeContentProvider
public class TreeViewerExample {
private List myPersonWork;
public TreeViewerExample() {
...
TreeViewer viewer = new TreeViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());
myPersonWork = new ArrayList();
Job currentWork = new Job("Informaticien");
currentWork.addPerson(new Person("Robert Glan", "Nancy", "25", "Voiture", "1600"));
currentWork.addPerson(new Person(...));
viewer.setInput(myPersonWork);
...
}
static class MyTreeContentProvider implements ITreeContentProvider {
public Object[] getElements(Object element) {
final Object[] currentPersonWorks = ((List) element).toArray();
return currentPersonWorks;
}
public void dispose() { }
public void inputChanged(Viewer v, Object belement, Object aelement) { }
...
}
}
Construction d’un
ContentProvider
Transformation des
données de l’Input
TreeViewerExample.java du projet
TreeViewerExamples
73
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple (suite) : TreeViewer et ITreeContentProvider
static class MyTreeContentProvider implements ITreeContentProvider {
...
public Object[] getChildren(Object element) {
final Job currentPersonWork = (Job) element;
return currentPersonWork.getPersons().toArray();
}
public Object getParent(Object element) {
if (element instanceof Person) {
return ((Person)element).getParent();
} else {
return null;
}
}
public boolean hasChildren(Object element) {
if (element instanceof Job) {
Job current = (Job) element;
return !current.isPersonEmpty();
} else return false;
}
}
}
TreeViewerExample.java du projet
TreeViewerExamples
Le nœud courant
comporte-il des sous
noeuds
Retourne le parent
du nœud element
Retourne les
nœuds enfants
74
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Certains ContentProvider comme ITreePathContentProvider
et ILazyTreePathContentProvider manipulent des éléments
via des chemins TreePath
Un TreePath est un chemin qui débute de la racine de l’arbre
et qui termine par l’élément considéré
Exemple de TreePath : « c:\, windows, system, user.dll »
Chaque élément du TreePath est appelé un segment
Principales méthodes de la classe TreePath
Object getFirstSegment() : récupère le premier élément du chemin
Object getLastSegment() : récupère le dernier élément du chemin
Object getSegment(int index) : récupère un élément à un index donné
int getSegmentCount() : retourne le nombre d’élément d’un chemin
75
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
L’interface ITreePathContentProvider permet de gérer le
ContentProvider via la notion de chemin
Elle hérite de l’interface IStructuredContentProvider qui
fournit une méthode pour déterminer le nombre d’éléments
ITreePathContentProvider fournit trois méthodes
Object[] getChildren(TreePath paramPath) : retourne les enfants du
dernier élément du chemin
TreePath[] getParents(Object element) : retourne les chemins parents
possibles d’un élément donné
boolean hasChildren(TreePath element) : précise si le dernier élément
du chemin a des enfants ou pas
76
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple : TreeViewer et ITreePathContentProvider
static class MyTreePathContentProvider implements ITreePathContentProvider {
...
public Object[] getChildren(TreePath parentPath) {
Object lastSegment = parentPath.getLastSegment();
final Job currentPersonWork = (Job) lastSegment;
return currentPersonWork.getPersons().toArray();
}
public TreePath[] getParents(Object element) {
TreePath[] refParents = new TreePath[1];
Person currentJob = (Person)element;
Object[] segmentTab = {currentJob.getParent()};
refParents[0] = new TreePath(segmentTab);
return refParents;
}
public boolean hasChildren(TreePath path) {
Object lastSegment = path.getLastSegment();
if (lastSegment instanceof Job) {
Job current = (Job)lastSegment;
return !current.isPersonEmpty();
} else {
return false;
}
}
}
}
Le nœud courant
comporte-il des sous
noeuds
Retourne les parents
du nœud element
Retourne les
nœuds enfants
TreeViewerWithPathExample.java
du projet TreeViewerExamples
77
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple : TreeViewer et LabelProvider
public class TreeViewerExample {
private List myPersonWork;
public TreeViewerExample() {
...
TreeViewer viewer = new TreeViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());
viewer.setLabelProvider(new MyTreeLabelProvider());
}
static class MyTreeLabelProvider extends BaseLabelProvider implements ILabelProvider {
public Image getImage(Object element) {
return null;
}
public String getText(Object element) {
if (element instanceof Person) {
Person current = (Person)element;
return current.getName();
} else {
return element.toString();
}
}
}
...
}
TreeViewerExample.java du projet
TreeViewerExamples
78
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple : Ouverture progressive d’un nœud
IDeferredWorkbenchAdapter pour la création différée du nœud (à
placer au niveau de l’objet qui modélise un nœud)
DeferredTreeContentManager pour la gestion des nœuds différés (à
placer dans le ContentProvider)
Basé sur www.ji.com.za/unplugged/index.php?paged=4
Chargement
progressif de
10 noeuds
79
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple (suite) : Ouverture progressive d’un nœud
public class DeferredTreeContentManagerView extends ViewPart {
private TreeParent invisibleRoot;
public TreeViewerExample() {
...
TreeViewer viewer = new TreeViewer(shell, SWT.VIRTUAL | SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());
viewer.setLabelProvider(new MyTreeLabelProvider());
TreeParent root = new TreeParent("Root");
invisibleRoot = new TreeParent("");
invisibleRoot.addChild(root);
viewer.setInput(invisibleRoot);
}
private static class TreeObject {
private String name;
private TreeObject parent;
public TreeObject(String pName) {
this.name = pName;
}
public void setParent(TreeObject pParent) {
this.parent = parent;
}
}
...
}
DeferredTreeContentManagerView.java
du projet TreeViewerExamples
Nœud acceptant un
nœud parent
C’est du LazyLoading
80
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple (suite) : Ouverture progressive d’un nœud
public class DeferredTreeContentManagerView extends ViewPart {
...
private static class TreeParent extends TreeObject implements IDeferredWorkbenchAdapter
{
private static final int leafLength = 10;
private ArrayList children;
public TreeParent(String name) {
super(name);
children = new ArrayList();
}
public boolean isContainer() { return (this instanceof TreeParent); }
public void fetchDeferredChildren(Object object, IElementCollector collector,
IProgressMonitor monitor) {
collector.add(new TreeParent("Parent"), monitor);
for (int i = 0; i < leafLength; i++) {
collector.add(new TreeObject("Leaf " + i), monitor);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean hasChildren() { return children.size() > 0; }
}
}
DeferredTreeContentManagerView.java
du projet TreeViewerExamples
Partie progressive …
Indique si cet objet
peut avoir des
enfants
81
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TreeViewer
Exemple (suite) : Ouverture progressive d’un nœud
public class DeferredTreeContentManagerView extends ViewPart {
...
static class MyTreeContentProvider implements ITreeContentProvider {
private DeferredTreeContentManager manager;
public Object[] getElements(Object element) {
TreeParent myParent = (TreeParent) element;
return myParent.getChildren(element);
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (viewer instanceof AbstractTreeViewer) {
manager = new DeferredTreeContentManager(this,(AbstractTreeViewer) viewer);
}
}
public Object[] getChildren(Object parentElement) {
return manager.getChildren(parentElement);
}
public Object getParent(Object element) {
if (element instanceof TreeObject) {
return ((TreeObject) element).getParent();
}
return null;
}
public boolean hasChildren(Object element) {
return manager.mayHaveChildren(element);
}
}
} DeferredTreeContentManagerView.java
du projet TreeViewerExamples
Si parentElement est un
« deferred element », il y a
création d’un thread
Y a t il potentiellement des
nœuds enfants ? C’est du
LazyLoading
82
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableTreeViewer
Le composant TableTreeViewer permet de mixer un arbre
avec une table
Tout comme TableViewer et TreeViewer, le composant
TableTreeViewer possède son équivalent en natif
Toutefois depuis la nouvelle API Eclipse 3.3, l’utilisation
directe du composant TableTreeViewer est « Deprecated »
En utilisant des TreeViewerColumn associés à un TreeViewer,
il est possible d’obtenir directement un TableTreeViewer
Le mécanisme de création d’un TreeViewerColumn (la
colonne) est similaire à un TableViewerColumn
TableColumn est remplacé par TreeColumn
Possibilité d’associer un CellLabelProvider par colonne
83
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableTreeViewer
Exemple : TableTreeViewer = TreeViewer + ViewerColumn
public class Person {
private String name;
private String address;
...
public Person(String pName, String pAddress, String pOld, String pVehicule,
String pSalary) {
name = pNamae;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
...
}
Person.java du projet
TreeViewerExamples
84
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : TableTreeViewer
Exemple (suite) : TableTreeViewer
public class TreeViewerColumnExample {
private List myPersonWork;
public TreeViewerExample() {
...
TreeViewer viewer = new TreeViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());
...
TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.CENTER);
column.setLabelProvider(new ColumnLabelProvider() {
public void getText(Object element) {
if (element instanceof Person) {
Person current = (Person)element;
return current.getName();
} else {
return element.toString(); // Redéfinie pour retourner le métier
}
}
}
column.getColumn().setText("Métier / Nom");
... // Address, Old, vehicule et salaire même principe
}
}
TreeViewerColumnExample.java du
projet TreeViewerExamples
85
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ListViewer
Le composant ListViewer permet d’encapsuler le composant
List de l’API SWT
ContentProvider autorisé
IStructuredContentProvider
LabelProvider autorisé
ILabelProvider pour toutes les colonnes
Le label permet d’afficher uniquement le contenu du texte.
Les images ne sont pas gérées
Si vous souhaitez gérer les images au niveau du label, préfé-
rez l’utilisation du composant TableViewer avec une colonne
86
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ListViewer
Exemple : ListViewer en action …
public class ListViewerExample {
private java.util.List myPerson = new ArrayList();
public ListViewerExample() {
...
ListViewer myListViewer = new ListViewer(shell, SWT.NONE);
myListViewer.setContentProvider(new MyStructuredContentProvider());
myListViewer.setLabelProvider(new MyLabelProvider());
myListViewer.setInput(myPerson);
List myList = myListViewer.getList();
GridData gridData = new GridData(GridData.FILL_BOTH);
myList.setLayoutData(gridData);
...
}
static class MyLabelProvider extends LabelProvider {
public String getText(Object element) {
if (element instanceof Person) {
return ((Person)element).getName();
} else {
return "";
}
}
}
...
}
ListViewerExample.java du projet
OtherViewersExamples
Affichage du texte
87
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ListViewer
Exemple (suite) : une liste avec un TableViewer
public class ListViewerWithTableViewerExample {
public ListViewerWithTableViewerExample() {
...
TableViewer myViewer = new TableViewer(shell, SWT.FULL_SELECTION);
myListViewer.setContentProvider(new MyStructuredContentProvider());
TableViewerColumn column = new TableViewerColumn(viewer,SWT.NONE);
column.setLabelProvider(new ColumnLabelProvider() {
public Image getImage(Object element) {
return null;
}
public String getText(Object element) {
Person currentPerson = (Person)element;
return currentPerson.getName();
}
public int getToolTipDisplayDelayTime(Object object) { return 500; }
public int getToolTipTimeDisplayed(Object object) { return 5000; }
public String getToolTipText(Object element) {
return "Ceci est un exemple de bulle d'aide";
}
public boolean useNativeToolTip(Object object) { return false; }
});
ColumnViewerToolTipSupport.enableFor(viewer,ToolTip.NO_RECREATE);
...
}
}
ListViewerWithTableViewerExample.java
du projet OtherViewersExamples
Possibilité d’ajouter
des images
Possibilité d’affiner
le paramétrage des
bulles d’aides
88
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : ComboViewer
Exemple : ComboViewer en action …
public class ComboViewerExample {
public ComboViewerExample() {
...
ComboViewer viewer = new ComboViewer(shell, SWT.NONE);
viewer.setContentProvider(new MyStructuredContentProvider());
viewer.setLabelProvider(new MyLabelProvider());
...
viewer.setInput(root);
Combo myCombo = viewer.getCombo();
GridData gridData = new GridData(GridData.FILL_BOTH);
myCombo.setLayoutData(gridData);
...
}
...
}
ComboViewerExample.java
du projet
OtherViewersExamples
89
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Checkbox…Viewer
Les composants CheckboxTableViewer, CheckboxTreeViewer
permettent de gérer une table et un arbre avec un compo-
sant CheckBox dans la première colonne
Ces composants fonctionnent sur le même principe que les
viewers étudiés précédemment
Une écouteur sur l’état des CheckBox permet de notifier tout
changement
addCheckStateListener(ICheckStateListener listener) : ajoute un
écouteur
ICheckStateListener#checkStateChanged(CheckStateChangedEvent) :
notifie un changement d’état
90
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : CheckboxTreeViewer
Exemple : CheckboxTreeViewer en action …
public class CheckBoxTreeViewerExample {
public CheckBoxTreeViewerExample () {
...
CheckboxTreeViewer viewer = new CheckboxTreeViewer(shell, SWT.FULL_SELECTION);
viewer.setContentProvider(new MyTreeContentProvider());
viewer.setLabelProvider(new MyTreeLabelProvider());
...
viewer.setInput(root);
viewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
if (event.getElement() instanceof TreeParent) {
viewer.setSubtreeChecked(event.getElement(),
viewer.getChecked(event.getElement()));
}
}
});
Tree myTree = viewer.getTree();
GridData gridData = new GridData(GridData.FILL_BOTH);
myTree.setLayoutData(gridData);
...
}
...
}
CheckBoxTreeViewerExample.java du
projet OtherViewersExamples
Si sélection du nœud
parent sélection de tous
les sous noeuds
91
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : CheckboxTableViewer
Exemple : CheckboxTableViewer en action …
public class CheckBoxTableViewerExample {
public CheckBoxTableViewerExample () {
...
CheckboxTableViewer viewer = CheckboxTableViewer.newCheckList(shell,
SWT.FULL_SELECTION);
myListViewer.setContentProvider(new MyStructuredContentProvider());
myListViewer.setLabelProvider(new MyTableLabelProvider());
myListViewer.setInput(root);
viewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
PersonData myPersonData = (PersonData)event.getElement();
System.out.println(myPersonData.getName());
}
});
Table table = viewer.getTable();
...
}
...
}
CheckBoxTableViewerExample.java
du projet
OtherViewersExamples
92
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection
Pour la gestion de la sélection, possibilité de passer par :
les composants natifs de la boîte à outils SWT
le viewer via un objet (ISelection)
Quels sont les besoins autour d’une sélection d’un viewer ?
Modifier programmatiquement la sélection
Récupérer la sélection courante
Notifier quand une sélection se produit
Il est préférable d’utiliser la solution par viewer puisqu’elle
est introduite avec l’API JFace et elle manipule des concepts
propre à l’Input
Nous étudions dans la suite tous les besoins en insistant sur
la sélection par le viewer
93
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection via composant natif
Les composants natifs SWT (Table et Tree) disposent de
méthodes pour les trois besoins de sélection du composant
Table (rappel)
Modifier la sélection
setSelection(int), setSelection(int[]), setSelection(int start, int end)
setSelection(TableItem it), setSelection(TableItem[])
Récupérer la sélection
TableItem[] getSelection()
int getSelectionCount(), int[] getSelectionIndices(), …
Notifier si changement de la sélection
Pas d’écouteur défini pour avertir d’un changement de sélection
L’écouteur SelectionListener notifie uniquement quand une action
utilisateur se produit sur la table
addSelectionListener(SelectionListener listener)
94
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection via composant natif
Exemple : sélection par composant natif
Si action sur la table affichage
de la sélection courante
Action = clique souris ou
déplacement via les flèche du
clavier
Modification de la sélection de
manière programmatique
NativeTableViewerSelectionExample.java
du projet SelectionExamples
95
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection via composant natif
Exemple (suite): sélection par composant natif
public class NativeTableViewerSelectionExample {
public NativeTableViewerSelectionExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setLabelProvider(new MyTableLabelProvider());
Button myButton = new Button(shell, SWT.FLAT);
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetDisposed(SelectionEvent e) {
int selectionIndex = viewer.getTable().getSelectionIndex();
System.out.println("Ancienne Valeur : " + selectionIndex);
int intemCount = viewer.getTable().getItemCount();
selectionIndex = (selectionIndex + 1) % itemCount;
viewer.getTable().setSelection(selectionIndex);
System.out.println("Nouvelle Valeur : " + selectionIndex);
}
});
viewer.getTable().addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
System.out.println(viewer.getTable().getSelectionIndex());
}
}
...
}
}
Récupération de la
sélection courante
NativeTableViewerSelectionExample.java
du projet SelectionExamples
96
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection
Remarquons que la gestion de la sélection via le composant
natif implique une utilisation de concepts différents que ceux
manipulés par l’Input
Par exemple, avec le composant natif Table, le programmeur
manipule des int et des TableItem
Il serait plus pratique de pouvoir maîtriser directement les
objets gérés par l’Input (exemple un objet Person)
Modifier une sélection : donner en paramètre un objet Person pour
sélectionner la ligne associée
Récupérer une sélection : un objet de type Person
Par ailleurs l’absence d’un modèle de sélection n’autorise
pas la notification du changement de la sélection
Utiliser si possible une gestion de la
sélection directement par le Viewer
97
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection
La gestion de la sélection au niveau d’un viewer est obtenue
est utilisant un objet de type ISelection
Un viewer fournit des méthodes pour récupérer et modifier
la sélection
ISelection getSelection() : accesseur sur la sélection courante
setSelection(ISelection, boolean visible) : modifie la sélection, si
visible est vraie la sélection est montrée
En passant par le viewer, il est possible d’être notifié quand
une sélection a changé
addSelectionChangedListener(ISelectionChangeListener) : abonne-
ment sur un écouteur de changement de sélection
98
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection
Le type de sélection est fonction du type de viewer utilisé
Différentes implémentations de ISelection sont alors fournies
StructuredSelection : pour les TableViewer
TreeSelection : pour les TreeViewer
TextSelection : pour la sélection de zones de texte
Un objet ISelection retourne toutes les informations concer-
nant une sélection
Pour modifier une sélection, il faut passer un objet ISelection
construit en fonction du type de viewer
S’il s’agit d’une TableViewer il faudra construire un objet de
type StructuredSelection
99
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (StructuredSelection)
Différents constructeurs pour StructuredSelection
StructuredSelection() : créé une sélection vide
StructuredSelection(List element) : créé une sélection multiple
StructuredSelection(Object element) : créé une sélection avec un seul
élément
Les éléments transmis aux constructeurs StructuredSelection
sont les éléments stockés dans l’Input (exemple : un objet
de type Person)
Pour chaque modification de la sélection, il faut construire
un nouvel objet StructuredSelection
Les classes TreeSelection
et TextSelection seront
utilisées ultérieurement
100
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (StructuredSelection)
Exemple : TableViewer et modification de la sélection
public class TableViewerSelectionExample {
public TableViewerSelectionExample() {
...
TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setLabelProvider(new MyTableLabelProvider());
...
Button myButton = new Button(shell, SWT.FLAT);
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetDisposed(SelectionEvent e) {
ISelection mySelection = viewer.getSelection();
if (mySelection instanceof IStructuredSelection) {
IStructuredSelection current = (IStructuredSelection)mySelection;
int index = myPersonList.indexOf(current.getFirstElement());
index = (index + 1) % myPersonList.size();
viewer.setSelection(new StructuredSelection(myPersonList.get(index)),
true);
}
}
});
...
}
}
TableViewerSelectionExample.java du
projet SelectionExamples
Identifier le type de
ISelection
101
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (StructuredSelection)
Exemple : notification du changement de sélection
La sélection de la second
table est « reliée » à la
première table
BothTableViewerSelectionExample.java
du projet SelectionExamples
102
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (StructuredSelection)
Exemple (suite) : notification du changement de sélection
public class BothTableViewerSelectionExample {
public BothTableViewerSelectionExample() {
...
final TableViewer viewer1 = new TableViewer(shell, SWT.FULL_SELECTION);
viewer1.setLabelProvider(new MyTableLabelProvider());
final TableViewer viewer2 = new TableViewer(shell, SWT.FULL_SELECTION);
viewer2.setLabelProvider(new MyTableLabelProvider());
...
viewer1.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection currentSelection = (IStructuredSelection)selection;
viewer2.setSelection(currentSelection);
}
}
});
}
}
BothTableViewerSelectionExample.java
du projet SelectionExamples
103
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (TreeSelection)
La sélection pour un TreeViewer passe par l’utilisation d’un
TreeSelection
Le concept manipulé par le TreeSelection est le TreePath
A chaque modification de la sélection il faut construire un
nouvel objet TreeSelection
TreeSelection(TreePath treePath) : sélection à partir d’un chemin
TreeSelection(TreePath[] treePaths) : plusieurs sélections
Accesseurs sur les sélections courantes
TreePath[] getPaths() : retourne les chemins de la sélection
TreePath[] getPathsFor(Object element) : retourne les chemins dont
le dernier segment est équivalent à element
104
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (TreeSelection)
Exemple : manipulation de TreeSelection
TreeViewerSelectionExample.java
du projet SelectionExamples
Affichage de la sélection
Modification de la
sélection
105
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : sélection (TreeSelection)
Exemple (suite) : manipulation de TreeSelection
public class TreeViewerSelectionExample {
public TreeViewerSelectionExample() {
...
TreeViewer viewer = new TreeViewer(shell, SWT.FULL_SELECTION);
Button myButton = new Button(shell, SWT.FLAT);
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
TreeSelection currentSelection = (TreeSelection)viewer.getSelection();
TreePath[] paths = currentSelection.getPaths();
for (TreePath treePath : paths) {
Object lastSegment = treePath.getLastSegment();
System.out.println(lastSegment.toString());
}
}
});
myButton = new Button(shell, SWT.FLAT);
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent arg0) {
Job firstJob = myPersonWork.get(0);
Object[] tabObject = {firstJob, firstJob.getPersons().get(0)};
TreePath path = new TreePath(tabObject);
viewer.setSelection(new TreeSelection(path));
}
});
}
...
}
TreeViewerSelectionExample.java du
projet SelectionExamples
106
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
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 à saisir
un composant appelé Editor permettant de modifier la valeur d’un
élément
Depuis la version 3.3 d’Eclipse, il est possible d’appliquer une
édition par élément pour chaque colonne via les
ViewerColumn
Nous étudierons l’édition pour le viewer dans sa globalité puis
de façon locale à chaque colonne
107
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Le modèle d’édition est défini par l’interface ICellModifier
boolean canModify(Object element, String property) : indique si la
propriété (property) de l’élément donné peut être modifié
Object getValue(Object element, String property) : retourne l’objet à
afficher lors de l’édition (appelée avec l’édition)
void modify(Object element, String property, Object value) : modifie la
valeur de la propriété de l’élément donné
Pour identifier la propriété (property) de l’élément considéré
(en générale il s’agit de la colonne), une identification par
label (une sorte d’étiquette) est réalisée
108
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Une fois le modèle d’édition implémentée, l’éditeur doit être
fourni pour éditer la nouvelle donnée
Un éditeur « Editor » est défini par la classe CellEditor
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
Un CellEditor repose sur un objet Composite pour l’édition
Nous verrons dans la suite qu’il est possible de fournir son
propre composant d’édition
109
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Comme il n’y a pas de notion de colonne dans cette approche
globale d’édition, il y autant d’éditeur qu’il y a de champs
(property) défini
Le composant ColumnViewer fournit des « setters » pour
préciser le modèle d’édition et les éditeurs
void setCellModifier(ICellModifier modifier) : définit le modèle d’édition
void setColumnProperties(String[] columnProperties) : défini le tableau
de label pour l’idenfication des colonnes
void setCellEditors(CellEditor[] editors) : défini le tableau d’éditeurs
Pour chaque propriété
un éditeur est défini
110
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple : édition de cellules d’un TableViewer
public class TableViewerEditorExample {
public TableViewerEditorExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
viewer.setUseHashlookup(true);
viewer.setContentProvider(new MyStructuredContentProvider());
viewer.setLabelProvider(new MyTableLabelProvider());
viewer.setColumnProperties(new String[] {"NOM", "AGE", "VEGETARIEN"});
viewer.setCellEditors(new CellEditor[] { new TextCellEditor(table),
new TextCellEditor(table), new TextCellEditor(table)});
new TableColumn(table, SWT.CENTER).setText("Nom");
new TableColumn(table, SWT.CENTER).setText("Age");
new TableColumn(table, SWT.CENTER).setText("Végétarien");
// Suite dans le prochain transparent
...
}
}
TableViewerEditorExample.java
du projet EditorExamples
111
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple (suite) : édition de cellules d’un TableViewer
public class TableViewerEditorExample {
public TableViewerEditorExample() {
... // Suite du précédent transparent
viewer.setCellModifier(new ICellModifier() {
public boolean canModify(Object element, String property) { return true; }
public Object getValue(Object element, String property) {
Person currentPerson = (Person)element;
if (property.equals("NOM")) { return (currentPerson).getName(); }
else if (property.equals("AGE")) {
return Integer.toString(currentPerson.getOld());
} else {
return Boolean.toString(currentPerson.isVegetarian());
}
}
public void modify(Object element, String property, Object value) {
TableItem currentItem = (TableItem)element;
Person currentPerson = (Person)currentItem.getData();
if (property.equals("NOM")) { currentPerson.setName((String)value); }
else ... // Modifier le reste des attributs.
viewer.refresh(currentPerson);
}
}
}
}
TableViewerEditorExample.java du
projet EditorExamples
Nécessaire pour mettre à
jour la vue
112
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Avec la gestion explicite des colonnes depuis la version 3.3,
il est possible de définir un éditeur particulier par colonne
Ainsi un ViewerColumn (la colonne) propose un modificateur
pour définir un éditeur
void setEditingSupport(EditingSupport es) : modifie l’éditeur de la
colonne considérée
Un éditeur d’une colonne est défini par EditingSupport
protected abstract boolean canEdit(Object element) : indique si la
valeur de la colonne peut être éditée d’une ligne donnée (element)
protected abstract CellEditor getCellEditor(Object element) : retourne
le composant de l’édition
protected abstract Object getValue(Object element) : retourne la
valeur à afficher dans l’éditeur
protected abstract void setValue(Object element, Object value) :
appelée après l’édition pour modifier les données de l’Input
113
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple : édition de cellules d’un TableViewerColumn
public class TableViewerColumnEditorExample {
public TableViewerColumnEditorExample() {
...
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 String getText(Object element) {
Person currentPerson = (Person)element;
return currentPerson.getName();
}
});
column.getColumn().setText("Nom");
column.setEditingSupport(new MyEditingSupport(viewer));
viewer.setInput(myPersonList);
...
}
}
Création d’un éditeur pour
la colonne « Nom »
TableViewerColumnEditorExample.java
du projet EditorExamples
114
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple (suite) : édition de cellules d’un TableViewerColumn
public class TableViewerColumnEditorExample {
...
static class MyEditingSupport extends EditingSupport {
private CellEditor editor;
private Viewer myViewer;
public MyEditingSupport(ColumnViewer viewer) {
super(viewer);
myViewer = viewer;
editor = new TextCellEditor((Composite)viewer.getControl());
}
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();
}
}
}
TableViewerColumnEditorExample.java
du projet EditorExamples
Utilisation d’un composant
prédéfini par l’API pour
l’édition de texte
115
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Nous avons vu que l’objet CellEditor permettait l’édition des
données (classes prédéfinies)
CellEditor fournit un nombre important de méthodes, dont
voici les plus importantes à implémenter
protected abstract Control createControl(Composite parent) : création
du Composite d’édition
protected abstract Object doGetValue() : retourne le contenu d’édition
protected abstract void doSetFocus() : donne le focus à l’éditeur
protected abstract void doSetValue(Object element) : modifie la valeur
de l’éditeur avant édition
Par ailleurs, il existe des méthodes pour notifier le viewer de
l’état de l’éditeur
protected void fireApplyEditorValue() : valider le résultat de l’éditeur
protected void fireCancelEditor() : annuler le résultat de l’éditeur
116
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple : un CellEditor personnalisé
public class TableViewerColumnCustomEditorExample {
...
static class MyEditingSupport extends EditingSupport {
private CellEditor editor;
private Viewer myViewer;
public MyEditingSupport(ColumnViewer viewer) {
super(viewer);
myViewer = viewer;
editor = new MyCustomCellEditor((Composite)viewer.getControl());
}
...
}
}
TableViewerColumnCustomEditorExample.java
du projet EditorExamples
Création d’un
composant d’édition
personnalisé
117
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
Exemple (suite) : un CellEditor personnalisé
public 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();
...
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;
}
... // La suite dans le prochain transparent
}
MyCustomCellEditor.java du projet
EditorExamples
Création d’un
Composite avec un
Label et un Text
118
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Edition
public class MyCustomCellEditor extends CellEditor {
... // Suite dans le précédent transparent
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);
}
}
}
Exemple (suite) : un CellEditor personnalisé
MyCustomCellEditor.java du projet
EditorExamples
Pour retourner le contenu
après la fin de l’édition
Avant l’édition, le focus est placé
sur le champ de texte et le texte
présent est sélectionné
Modification du champ de
texte avant l’édition
119
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Filtre
Un filtre permet d’afficher ou pas des éléments d’une liste
selon une condition donnée
Tout composant de type StructuredViewer (Tree, List et
Table) peuvent utiliser des filtres
Un filtre est défini par la classe ViewerFilter
abstract boolean select(Viewer c, Object parentElement, Object
element) :
element : précise si l’élément donné (element) doit être affiché
parentElement : objet transmis à l’Input
Possibilité de transmettre plusieurs filtres à un composant
StructuredViewer
void setFilters(ViewerFilter[] p) : applique les filtres
120
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Filtre
Exemple : filtrer le contenu d’un TableViewer
Filtre non appliqué
Filtre appliqué sur les
personnes végétaiens
121
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Filtre
Exemple : filtrer le contenu d’un TableViewer
public class TableViewerFilterExample {
private boolean isFiltred;
public TableViewerFilterExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
Button myButton = new Button(shell, SWT.CHECK);
myButton.setText("Filtrer les végétariens");
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
isFiltred = !isFiltred;
viewer.refresh();
}
});
viewer.setInput(myPersonList);
ViewerFilter current = new ViewerFilter() {
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (isFiltred) {
return ((Person)element).isVegetarian();
} else { return true; }
}
};
ViewerFilter[] viewerFilterTab = new ViewerFilter[1];
viewerFilterTab[0] = current;
viewer.setFilters(viewerFilterTab);
}
}
TableViewerFilterExample.java
du projet FilterExamples
Nécessaire pour re-déclencher le filtre
122
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Un tri permet d’organiser des éléments d’une liste selon une
comparaison de ces éléments
Tout Viewer de type StructuredViewer (Tree, List et Table)
peuvent utiliser de tris
La classe StructuredViewer fournit un modificateur pour
la gestion du tri
void setComparator(ViewerComparator comparator) : comparator
gère le tri
Comparator getComparator() : accesseur sur le tri en cours
L’activation du tri est obtenu par un ViewerComparator non
null
Pour désactiver le tri, le ViewerComparator doit être null
123
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
La classe ViewerComparator contient les méthodes suivantes
int compare(Viewer viewer, Object e1, Object e2) : retourne un entier
correspondant à la différence de e1 par rapport à e2
void sort(Viewer viewer, Object[] elements) : tri les éléments contenus
dans le viewer (Input) et retourne le résultat dans elements
La méthode int compare(…) retourne un entier signé dont le
signe va renseigner sur la position de e1 par rapport à e2
si zéro : e1 et e2 sont égaux
si négatif : e1 est inférieur à e2
si positif : e1 est supérieur à e2
Les méthodes de comparaison des types existant (ex : String)
retournent un entier correspondant à la différence
"Dupont".compareToIgnoreCase("Motte") retourne -9
"Dupont" est inférieur à "Motte" de 9 éléments (D à M)
124
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple : tri croissant sur une colonne
TableViewerGlobalSorterExample.java
du projet SortExamples
Désactivation du tri
Activation du tri
125
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple (suite) : tri croissant sur une colonne
public class TableViewerGlobalSorterExample {
private boolean isSorted = false;
public TableViewerGlobalSorterExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
Button myButton = new Button(shell, SWT.CHECK);
myButton.setText("Trier les noms");
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
isSorted = !isSorted;
If (isSorted) {
viewer.setComparator(new MyViewerComparer());
} else {
viewer.setComparator(null);
}
viewer.refresh();
}
});
}
private static class MyViewerComparer extends ViewerComparator {
public int compare(Viewer viewer, Object e1, Object e2) {
Person p1 = (Person) e1;
Person p2 = (Person) e2;
return p1.getName().compareToIgnoreCase(p2.getName());
}
}
...
}
TableViewerGlobalSorterExample.java
du projet SortExamples
Activation du tri
Désactivation du tri
126
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Un tri peut être croissant ou décroissant
Il peut être intéressant d’afficher le sens de tri sur la colonne
à trier
Cet affichage doit être précisé directement sur le composant
natif Table
La classe Table fournit deux méthodes
void setSortColumn(TableColumn tc) : précise la colonne à trier
void setSortDirection(int direction) : précise le sens du tri (SWT.UP,
SWT.DOWN et SWT.NONE)
Pour désactiver l’affichage du tri, mettre à null la colonne à
trier et mettre à NONE la direction du tri
127
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple : tri avec indicateur sur une colonne
public class TableViewerOneColumnSorterExample {
private boolean isSorted = false;
public TableViewerOneColumnSorterExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
Button myButton = new Button(shell, SWT.CHECK);
myButton.setText("Trier les noms");
myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
isSorted = !isSorted;
If (isSorted) {
viewer.setComparator(new MyViewerComparer());
myTable.setSortColumn(myTable.getColumn(0));
myTable.setSortDirection(SWT.UP);
} else {
viewer.setComparator(null);
myTable.setSortColumn(null);
myTable.setSortDirection(SWT.NONE);
}
viewer.refresh();
}
});
}
...
}
Affichage d’une flèche
vers le haut si trier
TableViewerOneColumnSorterExample.java
du projet SortExamples
128
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple : tri avec indicateurs sur une colonne cliquable
public class TableViewerOneBisColumnSorterExample {
...
private int direction = NONE;
public TableViewerOneBisColumnSorterExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
...
table.getColumn(0).addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Table myTable = viewer.getTable();
if (direction == NONE) {
viewer.setComparator(new MyViewerComparer());
myTable.setSortColumn(myTable.getColumn(0));
myTable.setSortDirection(SWT.UP);
direction = ASC;
} else if (direction == ASC) {
...
} else {
viewer.setComparator(null);
myTable.setSortColumn(null);
myTable.setSortDirection(SWT.NONE);
direction = NONE;
}
viewer.refresh();
}
});
...
}
}
TableViewerOneBisColumnSorterExample.java
du projet SortExamples
Cliquer directement
sur l’en-tête de la
colonne
129
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple : tri avec indicateurs sur colonnes cliquables
TableViewerSeveralColumnSorterExample.java
du projet SortExamples
Tri sur la première
colonne
Tri sur la deuxième
colonne
Tri sur la troisième
colonne
130
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple (suite) : tri avec indicateurs sur colonnes cliquables
public class TableViewerSeveralColumnSorterExample {
...
private int direction = NONE;
public TableViewerSeveralColumnSorterExample() {
...
final TableViewer viewer = new TableViewer(shell, SWT.FULL_SELECTION);
...
TableViewerColumn refNameColumn = new TableViewerColumn(viewer, SWT.NONE);
refNameColumn.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
Person currentPerson = (Person)element;
return currentPerson.getName();
}
});
refNameColumn.getColumn().setText("Nom");
ColumnSorter refCS = new ColumnSorter(viewer, refNameColumn) {
public int columnCompare(Viewer viewer, Object e1, Object e2) {
Person p1 = (Person) e1;
Person p2 = (Person) e2;
return p1.getName().compareToIgnoreCase(p2.getName());
}
};
...
}
}
TableViewerSeveralColumnSorterExample.java
du projet SortExamples
Autant de
TableViewerColumn
qu’il y a de colonnes
131
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple (suite) : tri avec indicateurs sur colonnes cliquables
public class ColumnSorter extends ViewerComparator {
private ColumnViewer refViewer;
private TableViewerColumn column;
public static final int ASC = 1;
...
private int direction = 0;
public ColumnSorter(ColumnViewer pViewer, TableViewerColumn pColumn) {
this.refViewer = pViewer;
this.column = pColumn;
this.column.getColumn().addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (ColumnSorter.this.refViewer.getComparator() != null) {
if (ColumnSorter.this.refViewer.getComparator() == ColumnSorter.this) {
int tdirection = ColumnSorter.this.direction;
if (tdirection == ASC) {
setSorter(ColumnSorter.this, DESC);
} else if (tdirection == DESC) {
setSorter(ColumnSorter.this, NONE);
}
} else {
setSorter(ColumnSorter.this, ASC);
}
} else {
setSorter(ColumnSorter.this, ASC);
}
}
});
}
Placer un écouteur sur
la sélection de la
colonne
ColumnSorter.java du projet
SortExamples
132
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
JFace / Viewers : Tri
Exemple (suite) : tri avec indicateurs sur colonnes cliquables
public class ColumnSorter extends ViewerComparator {
...
public void setSorter(ColumnSorter sorter, int direction) {
if (direction == NONE) {
column.getColumn().getParent().setSortColumn(null);
column.getColumn().getParent().setSortDirection(SWT.NONE);
refViewer.setComparator(null);
} else {
column.getColumn().getParent().setSortColumn(column.getColumn());
sorter.direction = direction;
if (direction == ASC) {
column.getColumn().getParent().setSortDirection(SWT.DOWN);
} else {
column.getColumn().getParent().setSortDirection(SWT.UP);
}
if (refViewer.getComparator() == sorter) {
refViewer.refresh();
} else {
refViewer.setComparator(sorter);
}
}
}
public int compare(Viewer viewer, Object e1, Object e2) {
return direction * columnCompare(viewer, e1, e2);
}
public abstract int columnCompare(Viewer viewer, Object e1, Object e2);
}
ColumnSorter.java du projet
SortExamples
133
JFace I - M. Baron - Page
mickael-baron.fr mickaelbaron
Bilan …
Premières impressions …
La version Eclipse 3.3 apporte la gestion des colonnes
Approche par modèles très souple
Dommage de devoir utiliser directement les objets natifs pour effec-
tuer certains traitements
Le nom des colonnes (TableColumn)
Le tri, …
Le rendu des éléments et le rendu des éditeurs ne sont pas aussi
souples qu’avec la boite à outils Swing
Les choses non étudiées, prochainement …
Approfondir par de nombreux exemples
Synchronisation de valeurs entre objets avec JFace Data Binding