Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Eclipse : composants de additionnels avec JFace

Eclipse : composants de additionnels avec JFace

Ce support de cours s'intéresse à présenter les composants additionnels JFace suivants : les boîtes de dialogue, les Wizards, les Preferences et la gestion des ressources.

Mickael BARON

January 26, 2013
Tweet

More Decks by Mickael BARON

Other Decks in Programming

Transcript

  1. Développement de clients riches : Plateforme Eclipse Mickaël BARON -

    2008 (Rév. Janvier 2009) mailto:[email protected] ou mailto:[email protected] mickael-baron.fr mickaelbaron Composants additionnels avec JFace Chapitre 2 : Boîtes à outils
  2. 2 JFace II - 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. 3 JFace II - 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. 4 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    Organisation du cours sur JFace : composants additionnels † Dialog : gérer les messages utilisateur † Wizard : création d’assistants † Preference : création de pages de préférences † Resource : gestion des ressources † Nous décrirons lors de la partie « plugin » qu’un Wizard ou une boîte de préférence peut être conçu par extension Tous les exemples du cours sont disponibles directement à l’adresse mickael-baron.fr/eclipse/intro-jface2
  5. 5 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue † Dans le cours SWT, nous avons présenté les boîtes de dialo- gue qui couvrent la majorité des besoins des IHM † Toutefois, JFace fournit une abstraction permettant † Afficher des messages de validation † Valider des entrées † Faciliter la spécialisation selon les besoins de la plateforme † Dans cette partie nous étudions les points suivants † Présentation des principales boîtes de dialogue et différences avec celles de SWT † Personnalisation de boîtes de dialogue † Nous verrons dans les prochaines parties du cours que l’API boîtes de dialogue de JFace est chapeau aux Wizards et aux boîtes de préférences
  6. 6 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue † Les API de boîtes de dialogue sont fournies dans le package org.eclipse.jface.dialogs † Toutes les boîtes de dialogue dérivent directement ou indirectement de la classe Dialog † Nous présentons principalement trois types de dialogue † IconAndMessageDialog : boîtes de dialogues qui affichent une icône et un texte comme principaux composants accompagnés de boutons de contrôle † InputDialog : boîtes de dialogues pour la saisie d’une chaîne de caractères accompagnées de boutons de contrôle † TitleAreaDialog : boîtes de dialogues décomposées en zones. Une zone de contenus (un titre), une zone de dialogue, une zone de progression et une zone de contrôle
  7. 7 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue † Hiérarchie des principales classes de dialogue Dialog InputDialog IconAndMessageDialog TrayDialog PreferenceDialog TitleAreaDialog WizardDialog ErrorDialog MessageDialog ProgressMonitorDialog Classes étudiées Classes génériques Etudiées dans les parties Preference et Wizard
  8. 8 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue † Boîtes de dialogue de type IconAndMessageDialog † ErrorDialog † MessageDialog † ProgressMonitorDialog Une IconAndMessageDialog se caractérise par un message d’information … et une icône
  9. 9 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : MessageDialog † Les boîtes de dialogue de type MessageDialog sont utilisées pour afficher un message suivant une sévérité donnée † MessageDialog hérite de IconAndMessageDialog † L’icône affiché est fonction de la sévérité (MessageDialog) † ERROR † INFORMATION † NONE † QUESTION † WARNING † La classe MessageDialog fournit une méthode statique pour chaque sévérité (factory de MessageDialog) † boolean openConfirm(Shell parent, String title, String message) : ouvre une boîte de confirmation (OK/Cancel) † autant qu’il y a de sévérité (sauf NONE)
  10. 10 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : MessageDialog † Exemple : afficher différents types de MessageDialog public class MessageDialogExample { public static void confirmDialog(Shell pShell) { boolean confirmationStatus = MessageDialog.openConfirm(pShell, "JFace Message Dialog : Confirmation", "[Placer ici votre message] ..."); System.out.println("Valeur retournée : " + confirmationStatus); } public static void errorDialog(Shell pShell) { MessageDialog.openError(pShell, "JFace Message Dialog : Error", "[Placer ici votre message] Attention une erreur est survenue."); } public static void informationDialog(Shell pShell) { MessageDialog.openInformation(pShell, "JFace Message Dialog : Information", "[Placer ici votre message] Message à caractère informatif."); } public static void questionDialog(Shell pShell) { boolean questionStatus = MessageDialog.openQuestion(pShell, "JFace Message Dialog : Question", "[Placer ici votre message] Etes-vous sur de vouloir faire cela."); System.out.println("Valeur retournée : " + questionStatus); } public static void warningDialog(Shell pShell) { MessageDialog.openWarning(pShell, "JFace Message Dialog : Warning", "[Placer ici votre message] Attention, il s'est passé quelque chose d’étrange ..."); } } MessageDialogExample.java du projet DialogExamples
  11. 11 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : MessageDialog † Exemple (suite) : afficher différents types de MessageDialog Confirmation Error Information Question Warning
  12. 12 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ErrorDialog † Les boîtes de dialogue de type ErrorDialog sont utilisées pour gérer une ou plusieurs erreur(s) † ErrorDialog hérite de IconAndMessageDialog † A la différence de la boîte MessageDialog (sévérité ERROR), une ErrorDialog contient un objet IStatus qui décrit le status des erreurs † La classe ErrorDialog fournit une méthode statique pour construire une boîte de dialogue erreur † static int openError(Shell parent, String dialogTitle, String message, IStatus status)
  13. 13 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ErrorDialog † Un objet IStatus est défini par les attributs suivants † id du plugin : id du plugin associé au status (voir chapitre suivant) † une sévérité (CANCEL, ERROR, INFO, OK, MESSAGE) † code : code donné par le plugin † un message : un message qui accompagne le status † une exception : une exception liée au problème (peut être null) † La classe Status est une implémentation par défaut † Status(int severity, String pluginId, int code, String message, Throwable exception) † La classe MultiStatus est une sous classe de Status permet- tant de gérer plusieurs status † MultiStatus(String plugId, int code, IStatus[] status, String message, Throwable exception)
  14. 14 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ErrorDialog † Exemple : afficher des boîtes ErrorDialog public class ErrorDialogExample { public static void errorDialog(Shell pShell, int severity) { String statusMessage = "[Placer ici le status de l'erreur]\n\n"; switch (severity) { case IStatus.ERROR: statusMessage += "Status Error Message"; break; case IStatus.INFO: statusMessage += "Status Info Message"; break; case IStatus.WARNING: statusMessage += "Status Warning Message"; break; default: statusMessage += "Status Error Message"; break; } IStatus errorStatus = new Status(severity, "My Plug-In ID", 0, statusMessage, null); ErrorDialog.openError(pShell, "JFace Error Dialog", "[Placer ici le message d'erreur] \n\n Un problème est survenu au niveau ...", errorStatus); } } ErrorDialogExample.java du projet DialogExamples
  15. 15 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ErrorDialog † Exemple : afficher des boîtes ErrorDialog Status : Info Status : Warning Status : Error
  16. 16 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ProgressMonitorDialog † Les boîtes de dialogue de type ProgressMonitorDialog permettent d’afficher l’état progressif d’une opération de longue durée † ProgressMonitorDialog(Shell parent) : construction d’une dialogue † ProgressMonitorDialog hérite de IconAndMessageDialog † L’usage typique est de passer par la méthode run † run(boolean fork, boolean canceable, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException † boolean fork : l’opération dans un thread séparé ou pas † boolean canceable : pour activer l’annulation † IRunnableWithProgress runnable : l’opération à démarrer † InvocationTargetException : si problème lors de l’opération † InterruptedException : si action annulation
  17. 17 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ProgressMonitorDialog † Un objet de type IRunnableWithProgress permet de décrire une opération de longue durée † Une classe de type IRunnableWithProgress doit implémenter † run(IProgressMonitor monitor) : traitement de l’opération dont le rapport en cours de traitement est envoyé à monitor † Un IProgressMonitor renseigne l’état d’avancement d’une opération (concepts de tâches et sous-tâches) † beginTask(String name, int tw) : notifie que l’opération a débuté name message à afficher, tw nombre d’unités à réaliser (UNKNOWN si pas déterminable) † worked(int work) : nombre d’unités déjà réalisée † subTask(String name) : notifie qu’une sous tâche a débuté † done() : notifie que l’opération est terminée (tâche complétée ou l’utilisateur a affectué une annulation) † boolean isCanceled() : savoir si l’utilisateur a annulé l’opération
  18. 18 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ProgressMonitorDialog † Exemple : afficher des boîtes ProgressMonitorDialog public class ProgressMonitorDialogExample { public static void progressMonitorDialog(Shell pShell, boolean indeterminate) { try { new ProgressMonitorDialog(pShell).run(true, true, new WorkLessOperation(indeterminate)); } catch (InvocationTargetException e) { MessageDialog.openError(pShell, "Erreur", e.getMessage()); } catch (InterruptedException e) { MessageDialog.openInformation(pShell, "Annulée", e.getMessage()); } } } ProgressMonitorDialogExample.java du projet DialogExamples
  19. 19 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : ProgressMonitorDialog † Exemple (suite) : afficher des boîtes ProgressMonitorDialog public class WorkLessOperation implements IRunnableWithProgress { private static final int TOTAL_TIME = 10000; private static final int INCREMENT = 500; private boolean indeterminate; public WorkLessOperation(boolean indeterminate) { this.indeterminate = indeterminate; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Operation \"WorkLess\" en cours", indeterminate ? IProgressMonitor.UNKNOWN : TOTAL_TIME); for (int total = 0; total < TOTAL_TIME && !monitor.isCanceled(); total += INCREMENT){ Thread.sleep(INCREMENT); monitor.worked(INCREMENT); if (total == TOTAL_TIME / 2) monitor.subTask("La moitiée de l'opération \"WorkLess\" est réelisée"); } monitor.done(); if (monitor.isCanceled()) throw new InterruptedException("Opération \"WorkLess\" annulée"); } } WorkLessOperation.java du projet DialogExamples Démarrage de l’opération Evolution de l’opération Opération terminée
  20. 20 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue † Boîtes de dialogue de type InputDialog Une InputDialog se caractérise par un message d’information … une zone de saisie de texte Et une zone de messages pour la validation des données Une zone de boutons de contrôle généralement cancel et ok pour valider ou pas la saisie
  21. 21 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : InputDialog † Les boîtes InputDialog permettent la saisie d’un texte † InputDialog hérite directement de la classe Dialog † Possibilité d’effectuer une validation sur la saisie effectuée au travers d’un objet IInputValidator † InputDialog(Shell pshell, String dialogTitle, String dialogMessage, String initialValue, IInputValidator validator) : constructeur † String getValue() : accesseur sur la valeur saisie dans le dialogue † L’interface IInputValidator fournit une méthode de validation † String isValid(String newText) : doit retourner un message d’erreur si la validation échoue, sinon retourne null
  22. 22 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : InputDialog † Exemple : afficher des boîtes InputDialog public class InputDialogExample { public static void validationIntegerInputDialog(Shell pShell) { InputDialog myInputDialog = new InputDialog(pShell, "JFace Input Dialog", "[Placer Message pour la saisie] Saisir votre texte", "Ma Valeur", new IntegerInputValidator()); if (myInputDialog.open() == Window.OK) { System.out.println("Vous avez sélectionné la validation en saisissant : " + myInputDialog.getValue()); } else { System.out.println("Vous avez sélectionné l'annulation."); } } ... } InputDialogExample.java du projet DialogExamples
  23. 23 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : InputDialog † Exemple (suite) : afficher des boîtes InputDialog public class IntegerInputValidator implements IInputValidator { public String isValid(String newText) { try { int value = new Integer(newText).intValue(); if (value < 0) return "Doit être positif"; if (value > 1000) return "Ne doit pas être supérieur à 1000"; } catch (NumberFormatException e) { return "Ne correspond pas à un entier"; } return null; } } public class StringInputValidator implements IInputValidator { public String isValid(String newText) { int length = newText.length(); if (length < 4) return "Chaîne trop courte (doit être supérieure à 4)"; if (length > 10) return "Chaîne trop longue (doit être inférieure à 10)"; return null; } } StringInputValidator.java du projet DialogExamples IntegerInputValidator.java du projet DialogExamples
  24. 24 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue Zone de contenu Zone de dialogue Zone de progression (optionnelle) Zone de contrôle † Boîtes de dialogue de type TitleAreaDialog † SaveAsDialog † WizarDialog † …
  25. 25 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : custom TitleAreaDialog † Nous avons étudié pour l’instant les dialogues prédéfinis par la bibliothèque JFace † Intéressons-nous à montrer comment fournir une boîte de dialogue personnalisée basée sur une TitleAreaDialog † Quelques méthodes à redéfinir … † Control createContents(Composite parent) : construit la partie contenu (partie haute) † Control createDialogArea(Composite parent) : construit la partie dialogue (partie médiane) † void createButtonsForButtonBar(Composite parent) : ajoute des boutons à la zone de boutons (partie basse) Nous reviendrons sur les aspects liés à TitleAreaDialog au moment des Wizards
  26. 26 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : custom TitleAreaDialog † Exemple : afficher une TitleAreaDialog personnalisée public class CustomTitleAreaDialog extends TitleAreaDialog { private String title; private String message; private String dialogMessage; public CustomTitleAreaDialog(Shell parentShell, String pTitle, String pMessage, String pDialogMessage) { super(parentShell); this.title = pTitle; this.message = pMessage; this.dialogMessage = pDialogMessage; this.setShellStyle(this.getShellStyle() | SWT.RESIZE); } protected void createButtonsForButtonBar(Composite parent) { this.createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); } ... } CustomTitleAreaDialog.java du projet DialogExamples
  27. 27 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace / Boîtes de dialogue : custom TitleAreaDialog † Exemple (suite) : afficher une TitleAreaDialog personnalisée public class CustomTitleAreaDialog extends TitleAreaDialog { ... // Suite protected Control createContents(Composite parent) { Control contents = super.createContents(parent); this.setTitle(title); this.setMessage(message); this.getShell().setText(title); return contents; } protected Control createDialogArea(Composite parent) { Composite composite = (Composite)super.createDialogArea(parent); Composite inComposite = new Composite(composite, SWT.NONE); inComposite.setLayout(new GridLayout(1, false)); GridData gd = new GridData(); gd.horizontalIndent = 5; gd.verticalIndent = 5; inComposite.setLayoutData(gd); Label label = new Label(inComposite, SWT.NONE); label.setText(dialogMessage); Button button = new Button(inComposite, SWT.FLAT); button.setText("Ceci est un Bouton"); return composite; } } CustomTitleAreaDialog.java du projet DialogExamples Création de la partie dialogue
  28. 28 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard † Un Wizard est un assistant qui permet de guider l’utilisateur à réaliser une tâche structurée † Un Wizard se présente sous la forme d’une IHM avec plusieurs traces opérationnelles possibles † En sortie de l’assistant un post-traitement est réalisé † Génération de code à partir d’un squelette prédéfini † Configuration d’une installation † Cette partie est guidée par un exemple file rouge « Assistant de réservation d’un transport pour les vacances » † L’exemple est inspiré de celui proposé par l’article suivant † Tutorial Wizard : www.eclipse.org/articles/Article-JFace Wizards/wizardArticle.html Le projet Akrogen permet de décrire les Wizards en XML/XUL et génère automatiquement le Wizard Eclipse akrogen.sourceforge.net
  29. 29 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : exemple « fil rouge » Le bouton « Next » est disponible à la condition que certaines informations soient saisies et valides Le bouton « Cancel » permet de sortir à tout moment de l’assistant Le bouton « Finish » permet de réaliser le post traitement selon les informations saisies Contrainte 1 : la date de départ doit être inférieure à la date de retour Contrainte 2 : le lieu de départ doit être différent du lieu d’arrivée Une page définie un squelette d’IHM (une zone de contenu, une zone de dialogue et des boutons de contrôle Selon le choix du transport la page suivante est différente
  30. 30 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : exemple « fil rouge » Une page qui gère un transport par voiture Une page qui gère un transport par avion Le bouton « Finish » est maintenant disponible. Le traitement relatif à la page sera alors réalisé
  31. 31 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : caractéristiques † Page † Squelette d’IHM : boutons prédéfinis, conteneur disponible pour personnaliser l’interface et champs paramétrables (description et titre) † Contraintes de validation : indiquent si certains boutons de contrôles doivent être activés ou pas (finish, next, …) † Règles de navigation : condition qui permet de savoir quelle page sera affichée lors de l’action « next » ou « back » † Wizard † Conteneur des pages : toutes les pages sont stockées dans le Wizard † Gestion du modèle : création de l’instance du modèle † Traitement terminal : retourne l’état du bouton « finish » (selon l’état du modèle) et effectue le traitement associé
  32. 32 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : schéma de fonctionnement Wizard IWizard Page 1 IWizardPage Page 2 IWizardPage Page n IWizardPage WizardModel - propriété 1 - propriété 2 - … + getPropriété1() + setPropriété1() + getPropriété2() + setPropriété2() + ... WizardMain WizardDialog 1..n 1 1 2 4 1 1 1 3 2 3 4 1 2 3 4 Cancel Next Previous Finish Le modèle du Wizard, instancié par Wizard Le Wizard qui gère les pages et les traitements terminaux Les pages qui gèrent les différentes IHMs du Wizard Les différents états de l’automate Une classe conteneur qui permet de manipuler un Wizard dans une boite de dialogue
  33. 33 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : IWizard/Wizard † L’interface IWizard définit le contrôleur de l’assistant en gérant les différentes pages † Affiche en premier plan, selon le contexte, la page via l’utilisation d’un CardLayout † Décide quand l’assistant peut être terminé et comment il doit le faire † La classe Wizard fournit une implémentation par défaut en ajoutant des méthodes spécifiques † De nombreuses méthodes … † void addPage(IWizardPage) : ajoute une page à l’assistant † void addPages() : endroit où sont ajoutées toutes les pages † boolean canFinish() : utilisée pour indiquer l’état du bouton « finish » † abstract boolean performFinish() : implémentation du traitement final † Et pleins d’autres méthodes … Utilisez de préférence la classe Wizard
  34. 34 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : IWizard/Wizard † Exemple : contrôleur du Wizard public class HolidayWizard extends Wizard { ... public void addPages() { holidayPage = new HolidayMainPage(); addPage(holidayPage); planePage = new PlanePage(""); addPage(planePage); carPage = new CarPage(""); addPage(carPage); } public boolean canFinish() { if (this.getContainer().getCurrentPage() == holidayPage) return false; if (model.usePlane) return planeCompleted; return carCompleted; } public boolean performFinish() { String summary = model.toString(); System.out.println(summary); return true; } ... } Ne peut terminer l’assistant sur la première page Selon le type de transport, retourne l’état de terminaison Le traitement terminal est simpliste, il consiste à afficher un résumé des données du modèle sur la console HolidayWizard.java du projet WizardExamples
  35. 35 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : modèle du Wizard † L’objectif du modèle est de persister les différentes données saisies dans les pages de l’assistant † Il n’existe pas d’API pour le modèle puisque les données de l’assistant sont fonctionnelles † Les données sont utilisées lors du traitement final et doivent donc être accessibles † Plusieurs approches sont à envisager pour la mise en place d’un modèle dans un Wizard † Chaque page abrite les données qui lui sont propres † Un modèle transverse contenant les données utiles pour le traitement
  36. 36 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : modèle du Wizard † Exemple : modèle du Wizard public class HolidayModel { protected String departureDate; protected String returnDate; protected String destination; protected String departure; protected boolean usePlane; protected boolean resetFlights; protected String selectedFlights; float price; protected String seatChoice; protected String rentalCompany; protected String carPrice; protected boolean buyInsurance; boolean discounted = false; public String toString() { // Construction de la chaîne suivant les données saisies ... } } public class HolidayWizard extends Wizard { ... HolidayModel model; public HolidayWizard() { model = new HolidayModel(); } public boolean performFinish() { String summary = model.toString(); System.out.println(summary); return true; } ... } HolidayModel.java du projet WizardExamples HolidayWizard.java du projet WizardExamples Liste des attributs utilisés par l’assistant
  37. 37 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : IWizardPage † Un objet IWizardPage fournit une description concernant une page d’un assistant † La classe WizardPage fournit une implémentation par défaut et des méthodes spécifiques † De nombreuses méthodes … † boolean canFlipToNextPage() : page suivante est-elle affichable ? † IWizardPage getNextPage() : référence sur la page suivante † IWizardPage getPreviousPage() : référence sur la page précédente † boolean isPageComplete() : page finalisée ou pas ? † void setPageComplete(boolean v) : modifie l’état de finalisation † IWizard getWizard() : référence de l’assistant (important pour accéder à la référence du modèle)
  38. 38 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : IWizardPage † Exemple : interface utilisateur d’une page public class CarPage extends WizardPage implements Listener { ... public CarPage(String pTitle) { super(pTitle); setTitle("Travel by car"); setDescription("Specify car choices"); ... } public void createControl(Composite parent) { // Construction de l’IHM } public void handleEvent(Event e) { if (e.widget == companyCombo) { // Traitement relatif à la sélection sur le Combo } setPageComplete(isPageComplete()); getWizard().getContainer().updateButtons(); } public boolean canFlipToNextPage() { return false; } ... // Suite dans le prochain transparent } CarPage.java du projet WizardExamples Lors d’une modification sur l’IHM, une demande de validation est réalisée Construction classique d’une IHM via SWT/JFace
  39. 39 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard : IWizardPage † Exemple (suite) : valider les données d’une page public class CarPage extends WizardPage implements Listener { ... public boolean isPageComplete() { HolidayWizard wizard = (HolidayWizard)getWizard(); if (companyCombo.getText().length() == 0) { wizard.carCompleted = false; return false; } saveDataToModel(); return true; } private void saveDataToModel() { HolidayWizard wizard = (HolidayWizard) getWizard(); wizard.model.rentalCompany = companyCombo.getText(); wizard.model.carPrice = priceText.getText(); wizard.model.buyInsurance = insuranceButton.getSelection(); wizard.carCompleted = true; } } CarPage.java du projet WizardExamples Extraction de la référence du Wizard Sauvegarde des données dans le modèle quand la page peut être complétée
  40. 40 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard † Pour afficher le Wizard deux solutions sont disponibles † Utiliser un WizardDialog qui fournit directement une boîte de dialogue † Utiliser la plateforme UI d’Eclipse (voir chapitre plugin) en se connectant au point d’extension fourni par org.eclipse.ui.newWizards † La classe WizardDialog fournit une encapsulation d’une boîte de dialogue (TitleAreaDialog de JFace) † WizardDialog permet de modifier et d’accéder à certaines propriétés graphiques de l’assistant (taille d’une page, page en cours, …) † De nombreuses méthodes … † WizardDialog(Shell parentShell, IWizard newWizard) : constructeur † open() : ouverture de la boîte de dialogue TitleAreaDialog : voir partie précédente
  41. 41 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Wizard † Exemple : afficher l’assistant public class HolidayWizard extends Wizard { ... public static void main(String[] args) { Display display = new Display(); final Shell shell = new Shell(display); shell.setText("Wizard Example"); shell.setLayout(new FillLayout()); Button myButton = new Button(shell, SWT.FLAT); myButton.setText("Ouvrir Holiday Wizard"); myButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { HolidayWizard wizard = new HolidayWizard(); wizard.setWindowTitle("Holiday Wizard"); WizardDialog refWizardDialog = new WizardDialog(shell, wizard); refWizardDialog.open(); } }); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } } HolidayWizard.java du projet WizardExamples Ouverture de l’assistant encapsulé dans une boîte de dialogue
  42. 42 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference † Les préférences permettent de gérer le paramétrage d’une application † La plateforme Eclipse fournit une gestion homogène et extensible des préférences † Caractéristiques principales de l’API Preference fournies par la plateforme Eclipse † Gestion du chargement et de la sauvegarde des paramètres † Squelette d’IHM : boutons prédéfinis (apply, default, cancel et ok) conteneur disponible pour personnaliser l’interface et champs paramétrables (description et titre) † Conteneur de pages de préférences
  43. 43 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : caractéristiques Pour un nœud est associée, une page de préférence Des boutons actions pour la boîte de dialogue de préférences Des boutons actions pour la page de préférences Des interfaces personnalisées par page Pour un autre nœud est associée une autre page de préférences
  44. 44 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : schéma de fonctionnement PreferenceMain PreferenceDialog PreferenceStore IPreferenceStore PreferenceManager PreferenceManager PreferenceNode IPreferenceNode PreferencePage IPreferencePage FieldEditorPreferencePage FieldEditorPreferencePage FieldEditor FieldEditor Relation hiérarchique entre les nœuds et les pages 1 Définition d’une page (associée à un nœud) Gestion implicite du chargement/sauvegarde des préférences Fichier de properties 1..n 1 1 Contient un ensemble de Composite pour l’IHM 1 1..n Le gestionnaire de persistance des préférences Boîte de dialogue des préférences Définition d’un nœud Définition d’une page de préférences qui gère exclusivement les FieldEditors Composants prédéfinis qui gère implicitement la persistance
  45. 45 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : IPreferencePage/PreferencePage † Une page fournit un regroupement de composants et de boutons de contrôle (defaults, apply, cancel et ok) † Une page est définie par l’interface IPreferencePage et son implémentation par défaut PreferencePage † La classe PreferencePage demande l’implémentation de † Control createContents(Composite parent) : retourne le contrôle en charge de définir l’IHM † Différentes méthodes sont également utilisables † performApply(), performOk, … : réalise le traitement associé à l’action sur un bouton de contrôle † setValid(boolean v) : si false, les boutons ok et valid sont désactivés † setMessage(String message, int newType) : affiche un message de sévérité donné par newType (ERROR, INFORMATION, NONE, WARNING)
  46. 46 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : IPreferencePage/PreferencePage † Exemple : page de préférences public class PreferencePageOne extends PreferencePage { private Text textFieldOne; private Text textFieldTwo; public PreferencePageOne() { super("Page Une"); setDescription("Préféence des options 'Page Une'"); } protected Control createContents(Composite comp) { Composite myComposite = new Composite(comp, SWT.NONE); myComposite.setLayout(new GridLayout(2, false)); Label label = new Label(myComposite,SWT.LEFT); label.setText("Champs 1:"); textFieldOne = new Text(myComposite, SWT.BORDER); textFieldOne.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); label = new Label(myComposite,SWT.LEFT); label.setText("Champs 2:"); textFieldTwo = new Text(myComposite, SWT.BORDER); textFieldTwo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return myComposite; } } Construction de l’IHM de cette page Définition du titre et de la description qui seront affichés en position haute de la page PreferencePageOne.java du projet PreferenceExamples
  47. 47 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : IPreferencePage/PreferencePage † Exemple (suite) : page de préférences public class PreferencePageOne extends PreferencePage { ... protected Control createContents(Composite comp) { ... textFieldOne = new Text(myComposite, SWT.BORDER); textFieldOne.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { validFieldOneValue(); } } return myComposite; } private void validFieldOneValue() { String value = textFieldOne.getText(); if (value == null || value.equals("")) { PreferencePageOne.this.setValid(false); } if (this.isValid()) { this.setMessage(null); } else { this.setMessage("Champs 1 : ne peut être vide", ERROR); } } } Vérifie à chaque saisie que le champ n’est pas vide PreferencePageOne.java du projet PreferenceExamples
  48. 48 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : IPreferenceNode/PreferenceNode † Le gestionnaire de préférences s’occupe de gérer les pages par l’intermédiaire de nœuds † Un nœud est associé à une seule page (IPreferencePage) † Un nœud est décrit par l’interface IPreferenceNode et son implémentation par défaut PreferenceNode † Plusieurs constructeurs définis † PreferenceNode(String id, IPreferencePage page) : construit un nœud id associé un objet PreferencePage page † PreferenceNode(String id, String label, ImageDescriptor image, String className) : un nœud id avec un nom, une icône et la page † Le nom et l’image donnent une représentation au nœud † Plusieurs méthodes de gestion de nœuds † add(IPreferenceNode node) : ajouter un sous nœud † IPreferenceNode[] getSubNodes() : retourne les sous noeuds
  49. 49 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : IPreferenceNode/PreferenceNode † Exemple : associer un nœud avec une page public class PreferenceExample { public PreferenceExample() { Display myDisplay = new Display(); ... PreferenceNode one = new PreferenceNode("one", new PreferencePageOne()); PreferenceNode two = new PreferenceNode("two", new PreferencePageTwo()); PreferenceNode three = new PreferenceNode("three", "three", null, PreferencePageTwo.class.getName()); one.add(two); one.add(three); System.out.println(one.getSubNodes().length); // Doit retourner 2 ... ... } public static void main(String[] args) { new PreferenceExample(); } } PreferenceExample.java du projet PreferenceExamples Construit un nœud trois en se basant sur la définition du nœud 2 Ajout du nœud two et three à la racine de one
  50. 50 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : PreferenceDialog † La gestion de la hiérarchie entre les nœuds et les pages est obtenue par un objet de type PreferenceManager † Différentes méthodes à utiliser † boolean addTo(String path, IPreferenceNode node) : ajoute un sous nœud au nœud identifié par path † void addToRoot(IPreferenceNode node) : ajoute le nœud node à la racine du gestionnaire de préférences † L’objet PreferenceManager est utilisé comme point de départ à l’affichage de la boîte de préférences via PreferenceDialog † PreferenceDialog(Shell parent, PreferenceManager pm) : construit une boîte de préférence sous le contrôle d’un PreferenceManager
  51. 51 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : PreferenceDialog † Exemple : afficher une boîte de dialogue de préférences public class PreferenceExample { public PreferenceExample() { ... PreferenceNode one = new PreferenceNode("one", new PreferencePageOne()); PreferenceNode two = new PreferenceNode("two", new PreferencePageTwo()); PreferenceNode three = new PreferenceNode("three", "Page Three", null, PreferencePageTwo.class.getName()); one.add(two); one.add(three); PreferenceManager mgr = new PreferenceManager(); mgr.addToRoot(one); // Autre écriture pour ajouter two et three à one // mgr.addTo("one", two); // mgr.addTo("one", three); PreferenceDialog myPreferenceDialog = new PreferenceDialog(null, mgr); myPreferenceDialog.open(); myDisplay.dispose(); } public static void main(String[] args) { new PreferenceExample(); } } PreferenceExample.java du projet PreferenceExamples Construction d’un gestionnaire de préférences Ajout du nœud one à la racine Construction d’une boîte de dialogue de préférences
  52. 52 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : PreferenceStore † L’API JFace fournit un mécanisme qui permet de persister les informations de préférences † L’API de persistance s’appuie sur la classe PreferenceStore qui permet la sauvegarde et le chargement à partir d’un flux † Principales méthodes … † boolean getBoolean(String name) … : des accesseurs sur des valeurs de préférence par l’intermédiaire d’un nom † boolean getDefaultBoolean(String name) … : des accesseurs sur les valeurs par défaut au travers d’un nom † void setValue(String name, boolean value) : des modifieurs sur les valeurs au travers d’un nom et d’une valeur † void setDefaultValue(String name, boolean value) : des modifieurs sur les valeurs par défaut par l’intermédiaire d’un nom et d’une valeur † save() et save(OutputStream, String header) : sauvegarde † load() et load(InputStream) : chargement
  53. 53 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : PreferenceStore † Exemple : chargement et sauvegarde de préférences public class PreferenceStoreExample { public PreferenceStoreExample() { ... PreferenceNode one = new PreferenceNode("one", new PreferenceStorePageOne()); PreferenceNode two = new PreferenceNode("two", new PreferenceStorePageTwo()); PreferenceManager mgr = new PreferenceManager(); mgr.addToRoot(one); mgr.addTo("one", two); PreferenceDialog myPreferenceDialog = new PreferenceDialog(null, mgr); PreferenceStore ps = new PreferenceStore("prefs.properties"); try { ps.load(); } catch (IOException e) { e.printStackTrace(); } myPreferenceDialog.setPreferenceStore(ps); myPreferenceDialog.open(); try { ps.save(); } catch (IOException e) { e.printStackTrace(); } ... } } PreferenceStoreExample.java du projet PreferenceExamples Création d’un PreferenceStore à partir d’un fichier « plat » prefs.properties Chargement des préférences Associe l’objet PreferenceStore à l’objet PreferenceDialog qui le dispatchera à toutes les pages
  54. 54 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : PreferenceStore † Exemple (suite) : chargement et sauvegarde de préférences public class PreferenceStorePageOne extends PreferencePage { private static final String FIELD1_PROPERTIES = "pageOne.field1"; private static final String FIELD2_PROPERTIES = "pageOne.field2"; protected Control createContents(Composite comp) { ... textFieldOne.setText(currentPreferenceStore.getString(FIELD1_PROPERTIES)); textFieldTwo.setText(currentPreferenceStore.getString(FIELD2_PROPERTIES)); ... } public boolean performApply() { this.performOk(); } public boolean performOk() { IPreferenceStore currentPreferenceStore = getPreferenceStore(); // Modification du contenu de la sauvegarde à partir des champs de texte if (this.textFieldOne != null) currentPreferenceStore.setValue(FIELD1_PROPERTIES, textFieldOne.getText()); if (this.textFieldTwo != null) currentPreferenceStore.setValue(FIELD2_PROPERTIES, textFieldTwo.getText()); return t rue; } } PreferenceStorePageOne.java du projet PreferenceExamples A la construction besoin d’initialiser le contenu des composants Appeler lors de l’action Apply Récupération de gestionnaire de persistance Sauvegarde des préférences Appeler lors de l’action Ok
  55. 55 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor † La construction d’une page de préférences impose de devoir gérer explicitement la persistance des valeurs † Les composants FieldEditor fournissent une encapsulation de la gestion de la persistance de manière à masquer cette étape répétitive † Un composant FieldEditor encapsule également un composant graphique † Selon le composant utilisé, des contrôles de cohérence implicites peuvent être réalisés (Integer correctement formé) † JFace fournit une bibliothèque prédéfinie de composants graphiques † Construction commune d’un composant FieldEditor † FieldEditor(String name, String label, Composite parent) : FieldEditor identifié par name, une valeur pour un label et le composant parent
  56. 56 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor PreferenceFieldEditorPageOne.java du projet PreferenceExamples BooleanFieldEditor StringFieldEditor IntegerFieldEditor ColorFieldEditor DirectoryFieldEditor FileFieldEditor
  57. 57 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor PreferenceFieldEditorPageTwo.java du projet PreferenceExamples FontFieldEditor RadioGroupFieldEditor PathEditor ScaleFieldEditor
  58. 58 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditorPreferencePage † Pour intégrer des objets FieldEditors dans une page de préférences, la page doit étendre FieldEditorPreferencePage † Une page FieldEditorPreferencePage positionne verticalement les objects FieldEditors † Styles des FieldEditors lors de la construction d’une page † GRID : l’espace entre le label et le composant est uniforme † FLAT : l’espace entre le champ de texte et le composant varie † FieldEditorPreferencePage nécessite l’implémentation de † Control createContents(Composite parent) : retourne le contrôle en charge de définir l’IHM † Différentes méthodes sont également utilisables † addField(FieldEditor fe) : ajoute l’objet FieldEditor à la page † getFieldEditorParent() : permet de retourne le parent de la page (à utiliser lors de la construction des composants FieldEditors)
  59. 59 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditorPreferencePage † Exemple : page de préférences pour FieldEditors public class PreferenceFieldEditorPageOne extends FieldEditorPreferencePage { private static final String FILE_PROPERTIES = "pageOne.file"; ... public PreferenceFieldEditorPageOne() { super("Page Une", GRID); } protected void createFieldEditors() { BooleanFieldEditor bfe = new BooleanFieldEditor(CHECK_PROPERTIES, "Booléen", getFieldEditorParent()); addField(bfe); StringFieldEditor sfe = new StringFieldEditor(STRING_PROPERTIES, "Chaîne de caractères", getFieldEditorParent()); addField(sfe); IntegerFieldEditor ife = new IntegerFieldEditor(INTEGER_PROPERTIES,"Entier", getFieldEditorParent()); addField(ife); ColorFieldEditor cfe = new ColorFieldEditor(COLOR_PROPERTIES,"Couleur", getFieldEditorParent()); addField(cfe); DirectoryFieldEditor dfe = new DirectoryFieldEditor(DIRECTORY_PROPERTIES, "Répertoire", getFieldEditorParent()); addField(dfe); FileFieldEditor ffe = new FileFieldEditor(FILE_PROPERTIES, "Fichier", getFieldEditorParent()); addField(ffe); } } PreferenceFieldEditorPageOne.java du projet PreferenceExamples Style GRID définit comment sont affichés les FieldEditors L’identifiant du FieldEditor est utilisé pour persister la préférence
  60. 60 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditorPreferencePage † Exemple (suite) : page de préférences pour FieldEditors public class PreferenceFieldEditorExample { public PreferenceFieldEditorExample() { ... PreferenceNode one = new PreferenceNode("one", new PreferenceFieldEditorPageOne()); PreferenceNode two = new PreferenceNode("two", new PreferenceFieldEditorPageTwo()); PreferenceNode three = new PreferenceNode("three", new PreferenceFieldEditorPageThree()); PreferenceManager mgr = new PreferenceManager(); mgr.addToRoot(one); mgr.addToRoot(two); mgr.addToRoot(three); PreferenceDialog myPreferenceDialog = new PreferenceDialog(null, mgr); PreferenceStore ps = new PreferenceStore("fieldprefs.properties"); try { ps.load(); } catch (IOException e) { e.printStackTrace(); } myPreferenceDialog.setPreferenceStore(ps); myPreferenceDialog.open(); try { ps.save(); } catch (IOException e) { e.printStackTrace(); } ... } } PreferenceFieldEditorExample.java du projet PreferenceExamples Construction identique aux objets de type PreferencePage Fichier contenant les valeurs des préférences
  61. 61 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditorPreferencePage † Exemple (suite) : page de préférences pour FieldEditors PreferenceFieldEditorPageOne.java du projet PreferenceExamples fieldprefs.properties du projet PreferenceExamples pageOne.string
  62. 62 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Il se peut que les composants FieldEditor ne correspondent pas directement aux besoins † Possibilité de créer facilement de nouveaux FieldEditor † Principales méthodes † int getNumberOfControls() : retourne le nombre de composants contenu dans le FieldEditor † adjustForNumColumns(int nC) : ajuste la valeur « horizontal span » par le nombre de colonne nC † doFillIntoGrid(Composite p, int nC) : construction des composants via le parent p et le nombre de colonne nC † doLoad() : chargement des préférences † doLoadDefault() : chargement par défaut † doStore() : sauvegarde des préférences
  63. 63 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple : composant FieldEditor min/max PreferenceFieldEditorPageFour.java du projet PreferenceExamples La valeur min est supérieure à la valeur max => génération erreur La valeur min ou la valeur max contient une valeur non cohérente => génération erreur Le but de ce FieldEditor est de fournir deux zones de saisies d’entier dont la valeur min est strictement inférieure à la valeur max Un composite contient un label et un champ de texte
  64. 64 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple (suite) : composant FieldEditor min/max public class MinMaxFieldEditor { ... protected void doFillIntoGrid(Composite parent, int numColumns) { top = parent; ... Label label = this.getLabelControl(parent); GridData labelData = new GridData(); labelData.horizontalSpan = numColumns; label.setLayoutData(labelData); ... minField = new Text(minComposite, SWT.BORDER); minField.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { clearErrorMessage(); } }); minField.addFocusListener(new FocusAdapter()) { public void focusGained(FocusEvent e) { refreshValidateState(); } public void focusLost(FocusEvent e) { valueChanged(); clearErrorMessage(); } } } } La validation est réalisée lors de la perte du focus MinMaxFieldEditor.java du projet PreferenceExamples Le label est positionné sur la partie haute
  65. 65 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple (suite) : composant FieldEditor min/max public class MinMaxFieldEditor { ... protected void adjustForNumColumns(int numColumns) { GridData layoutData = (GridData)top.getLayoutData(); layoutData.horizontalSpan = numColumns; } public int getNumberOfControls() { return 2; } protected void doLoadDefault() { if (minField != null && maxField !=null) { int minValue = getPreferenceStore().getDefaultInt(getPreferenceName() + MIN_NAME); int maxValue = getPreferenceStore().getDefaultInt(getPreferenceName() + MAX_NAME); minField.setText("" + minValue); maxField.setText("" + maxValue); } valueChanged(); } protected void doLoad() { ... } protected void doStore() { if (minField != null && maxField !=null) { Integer i = new Integer(minField.getText()); Integer j = new Integer(maxField.getText()); getPreferenceStore().setValue(getPreferenceName() + MIN_NAME, i.intValue()); getPreferenceStore().setValue(getPreferenceName() + MAX_NAME, j.intValue()); } } MinMaxFieldEditor.java du projet PreferenceExamples Modification des paramètres de l’agent de placement du parent Deux composites • minComposite • maxComposite Même principe que doLoadDefault()
  66. 66 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    public class PreferencePersoFieldEditorExample { public PreferencePersoFieldEditorExample() { PreferenceManager mgr = new PreferenceManager(); PreferenceNode three = new PreferenceNode("three", new PreferenceFieldEditorPageThree()); PreferenceNode four = new PreferenceNode("four", new PreferenceFieldEditorPageFour()); mgr.addToRoot(three); mgr.addToRoot(four); PreferenceDialog myPreferenceDialog = new PreferenceDialog(null, mgr); PreferenceStore ps = new PreferenceStore("persofieldprefs.properties"); ... } } JFace/Preference : FieldEditor personnalisé † Exemple (suite) : composant FieldEditor min/max public class PreferenceFieldEditorPageFour extends FieldEditorPreferencePage { public PreferenceFieldEditorPageFour() { super("Page Quatre", GRID); } protected void createFieldEditors() { MinMaxFieldEditor bfe = new MinMaxFieldEditor("tolerance", "Tolérence", 3, getFieldEditorParent()); addField(bfe); } } PreferencePersoFieldEditorExample.java du projet PreferenceExamples PreferencePersoFieldEditorPageFour.java du projet PreferenceExamples
  67. 67 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple : espaces entre FieldEditors PreferencePersoFieldEditorPageTwo.java du projet PreferenceExamples PreferencePersoFieldEditorPageFour.java du projet PreferenceExamples Construction d’objets SpacerFieldEditor pour définir explicitement des espaces entre les FieldEditors Exemple basé sur celui-ci … www.eclipse.org/articles/Article-Field-Editors/field_editors.html
  68. 68 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple (suite) : espaces entre FieldEditors public class LabelFieldEditor extends FieldEditor { private Label label; private int vGap; public LabelFieldEditor(String value, Composite parent, int pVGap) { init("label", value); this.vGap = pVGap; if (vGap < 0) { this.vGap = 0; } createControl(parent); } protected void adjustForNumColumns(int numColumns) { ((GridData) label.getLayoutData()).horizontalSpan = numColumns; } protected void doFillIntoGrid(Composite parent, int numColumns) { label = getLabelControl(parent); GridData gridData = new GridData(); ... gridData.heightHint = vGap; label.setLayoutData(gridData); } public int getNumberOfControls() { return 1; } protected void doLoad() {} protected void doLoadDefault() {} protected void doStore() {} } LabelFieldEditor.java du projet PreferenceExamples Spécifier la hauteur du composant label Ne sauvegarde pas les préférences FieldEditor spécifique permettant d’afficher un label et de spécifier une hauteur
  69. 69 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Preference : FieldEditor personnalisé † Exemple (suite) : espaces entre FieldEditors public class SpacerFieldEditor extends LabelFieldEditor { public SpacerFieldEditor(Composite parent, int pVGap) { super("", parent, pVGap); } } public class PreferenceFieldEditorPageThree extends FieldEditorPreferencePage { protected void createFieldEditors() { FontFieldEditor ffe = new FontFieldEditor(FONT_PROPERTIES, "Police", getFieldEditorParent()); addField(ffe); SpacerFieldEditor spacer = new SpacerFieldEditor(getFieldEditorParent(), V_GAP); addField(spacer); RadioGroupFieldEditor rfe = new RadioGroupFieldEditor(RADIO_PROPERTIES, "Radio Group", 2, strings, getFieldEditorParent(), true); addField(rfe); spacer = new SpacerFieldEditor(getFieldEditorParent(), V_GAP); addField(spacer); ... } } SpacerFieldEditor.java du projet PreferenceExamples PreferenceFieldEditorPageThree.java du projet PreferenceExamples Entre chaque FieldEditor un SpacerFieldEditor pour ajouter un espace horizontal Un SpacerFieldEditor est un LabelFieldEditor sans valeur de texte
  70. 70 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Resource : ImageDescriptor † Nous avons vu dans la partie SWT que la création d’objets Image nécessitait l’utilisation d’un Display † Un descripteur d’image définit par ImageDescriptor est une sorte de factory d’images sans utilisation explicite d’un Display † A partir d’un ImageDescriptor, il est possible de † Image createImage() : créer un objet Image † ImageData getImageData() : créer un objet ImageData † Création à partir d’un fichier † static ImageDescriptor createFromFile(Class location, String filename) † location chemin de la classe qui définit le répertoire de la ressource † filename nom du fichier † Création à partir d’une URL † static ImageDescriptor createFromURL(URL url)
  71. 71 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Resource : ImageDescriptor † Exemple : afficher une image via un ImageDescriptor package eclipse.jface.resourceexamples; public class ImageDescriptorExample { public ImageDescriptorExample() { Display display = new Display(); final Shell shell = new Shell(display); shell.setText("ImageDescriptor : File and URL"); shell.setLayout(new GridLayout(1, false)); ImageDescriptor imageDescr = ImageDescriptor.createFromFile( eclipse.jface.resourceexamples.ImageDescriptorExample.class, "image/superstar.jpg"); Label myLabelImage = new Label(shell, SWT.NONE); myLabelImage.setImage(imageDescr.createImage()); shell.pack(); shell.open(); ... } public static void main(String[] args) { new ImageDescriptorExample(); } } ImageDescriptorExample.java du projet ResourceExamples L’image est localisée dans un sous répertoire image qui est à la racine du sous package resourceexamples Création d’un Image à partir d’un ImageDescriptor
  72. 72 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Resource : Resource † Lors de la conception d’interfaces utilisateurs, il est souvent nécessaire de réutiliser des mêmes ressources : couleurs, fontes, images, ressources bundles † JFaceResources fournit un mécanisme pour la déclaration de ressources dans des registres et de les appeler par un nom † Chaque type de ressource est défini dans un registre dont les accès sont définis dans JFaceResources † ColorRegistry pour les couleurs via getColorRegistry() † FontRegistry pour les fontes via getFontRegistry() † ImageRegistry pour les images via getImageRegistry() † Les registres fonctionnent sur un principe commun : cas du registre ColorRegistry † put(String id, RGB colorData) : ajouter une couleur au registre † Color get(String id) : accesseur sur la couleur identifiée par id
  73. 73 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Resource : Resource † Exemple : gestion des ressources via les registres public class ResourcesExample { public static final String SUPERSTAR_KEULKEUL_IMAGE = "superstar"; public static final String ARIAL_KEULKEUL_FONT = "Arial"; public static final String RED_KEULKEUL_COLOR = "red"; public static final String BLACK_KEULKEUL_COLOR = "black"; public void ResourcesExample() { // Color resources definition ColorRegistry colorRegistry = JFaceResources.getColorRegistry(); colorRegistry.put(BLACK_KEULKEUL_COLOR, new RGB(0,0,0)); colorRegistry.put(RED_KEULKEUL_COLOR, new RGB(255, 0, 0)); // Font resources definition FontRegistry fontRegistry = JFaceResources.getFontRegistry(); FontData fontData = new FontData(ARIAL_KEULKEUL_FONT, 40, SWT.BOLD); fontRegistry.put(ARIAL_KEULKEUL_FONT, new FontData[]{fontData}); // Image resources definition ImageRegistry imageRegistry = JFaceResources.getImageRegistry(); ImageDescriptor myImageDescriptor = ImageDescriptor.createFromFile(eclipse.jface.resourceexamples.ResourcesExample. class, "image/superstar.jpg"); imageRegistry.put(SUPERSTAR_KEULKEUL_IMAGE, myImageDescriptor); } ... } ResourcesExample.java du projet ResourceExamples
  74. 74 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    JFace/Resource : Resource † Exemple (suite) : gestion des ressources via les registres public class ResourcesExample { public ResourcesExample() { Display display = new Display(); initResources(); final Shell shell = new Shell(display); shell.setText("JFaceResources : Registry"); shell.setLayout(new GridLayout()); // The first parameter gives the peer to localize the image file. Label myLabelImage = new Label(shell, SWT.NONE); myLabelImage.setImage(JFaceResources.getImageRegistry() .get(SUPERSTAR_KEULKEUL_IMAGE)); Label myLabelColor = new Label(shell, SWT.NONE); myLabelColor.setBackground(JFaceResources.getColorRegistry() .get(BLACK_KEULKEUL_COLOR)); myLabelColor.setForeground(JFaceResources.getColorRegistry() .get(RED_KEULKEUL_COLOR)); myLabelColor.setFont(JFaceResources.getFontRegistry() .get(ARIAL_KEULKEUL_FONT)); myLabelColor.setText("He is a super star baby"); ... } } ResourcesExample.java du projet ResourceExamples Récupération des ressources via les registres associés
  75. 75 JFace II - M. Baron - Page mickael-baron.fr mickaelbaron

    Bilan … † Premières impressions … † De nombreuses APIs pour gérer des fonctionnalités indispensables à des applications classiques † Des composants homogènes via l’héritage de la classe Dialog † Les choses non étudiées, prochainement † Gestion de texte via le composant TextViewer † Intégration des Wizards et des Preferences dans la plateforme Eclipse via la notion d’extension (voir chapitre Conception de plug-ins) † Prochaine étape : Conception de plug-ins † Pour l’instant nous avons étudié les APIs qui se limitent à la couche graphique † Le prochain chapitre s’intéressera à la conception de plug-ins