207
Développement de clients riches : Plateforme Eclipse Mickaël BARON - 2010 mailto:[email protected] ou mailto:[email protected] Chapitre 3 : Conception de plug Chapitre 3 : Conception de plug - - ins ins Workbench : Editors

Construction d'éditeurs avec la plateforme Eclipse

Embed Size (px)

DESCRIPTION

Ce support de cours s'intéresse à détailler la construction d'éditeurs avec la plateforme Eclipse. Il fait partie de la série des supports de cours liée au Workbench. Les aspects suivants sont étudiés : construction déclarative, registre des éditeurs, cycle de vie, MultiPageEditorPart, écouteurs, éditeur et les commandes, Workspace et les ressources, éditeur et le texte via TextEditor (coloration syntaxique, assistant de contenu, template, outline, spelling checking, ...).

Citation preview

Page 1: Construction d'éditeurs avec la plateforme Eclipse

Développement de clients riches : Plateforme Eclipse

Mickaël BARON - 2010 mailto:[email protected] ou mailto:[email protected]

Chapitre 3 : Conception de plugChapitre 3 : Conception de plug--insins

Workbench : Editors

Page 2: Construction d'éditeurs avec la plateforme Eclipse

2Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Creative Commons

Contrat Paternité

Partage des Conditions Initiales à l'Identique

2.0 France

http://creativecommons.org/licenses/by-sa/2.0/fr

Licence

Page 3: Construction d'éditeurs avec la plateforme Eclipse

3Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

� Construction déclarative

� IEditorPart, IEditorSite, IEditorInput

� Registre des éditeurs

� Cycle de vie

� MultiPageEditorPart

� Ecouteurs

� Editeur et les commandes

� Workspace et les ressources

� Editeur et le texte via TextEditor

Organisation du cours sur le Workbench : Editors

Page 4: Construction d'éditeurs avec la plateforme Eclipse

4Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkbench Editors : déroulement du cours

Ceci est une alerte

Ceci est une astuce

� Pédagogie du cours

� Illustration avec de nombreux exemples qui sont disponibles à

l’adresse mbaron.developpez.com/eclipse/editors

� Des bulles d’aide tout au long du cours

� Logiciels utilisés

� Eclipse 3.5.2 Galileo

� Pré-requis

� Connaître la structure d’un plug-ins et savoir créer une extension

� Structure du Workbench

Page 5: Construction d'éditeurs avec la plateforme Eclipse

5Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workbench Editors : ressources …

� Des liens sur les éditeurs de manière générale� www.vogella.de/articles/RichClientPlatform/article.html#editor

� wiki.eclipse.org/FAQ_What_is_the_difference_between_a_view_and_an_editor%3F

� wiki.eclipse.org/FAQ_How_do_I_open_an_editor_on_something_that_is_not_a_file%3F

� eclipse.dzone.com/tips/programmatically-split-editor-

� www.pajbam.com/wp-content/uploads/2008/04/cours_plugin_eclipse.pdf

� Des liens sur le Workspace (gestion de fichiers)� wiki.eclipse.org/FAQ_How_do_I_open_an_editor_on_a_file_outside_the_workspace%3F

� www.eclipsezone.com/eclipse/forums/t83786.html

� wiki.eclipse.org/index.php/EFS

� www.eclipse.org/eclipse/platform-team/docs/ABC%20of%20Platform%20Workspace.ppt

� www.eclipse.org/articles/Article-Resource-deltas/resource-deltas.html

� hexapixel.com/2009/01/12/rcp-workspaces

� www.eclipse.org/articles/Article-Mark My Words/mark-my-words.html

� www.eclipse.org/articles/Article-Builders/builders.html

� wiki.eclipse.org/FAQ_How_do_I_make_my_compiler_incremental%3F

� wiki.eclipse.org/FAQ_How_do_I_implement_an_Eclipse_builder%3F

� www.eclipsepluginsite.com/builders-natures-markers.html

Page 6: Construction d'éditeurs avec la plateforme Eclipse

6Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workbench Editors : ressources …

� Des liens sur l’amélioration d’un TextEditor� beuss.developpez.com/tutoriels/eclipse/plug-in/editor/colors

� www.eclipse.org/eclipse/platform-text/development/dev.html

� wiki.eclipse.org/FAQ_How_do_I_provide_syntax_coloring_in_an_editor%3F

� wiki.eclipse.org/FAQ_What_is_a_document_partition%3F

� wiki.eclipse.org/FAQ_How_do_I_add_Content_Assist_to_my_editor%3F

� www.eclipse.org/articles/Article-Folding-in-Eclipse-Text-Editors/folding.html

� www.ibm.com/developerworks/opensource/library/os-ecca

� www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTCompletionEditor.htm

� Des livres

� Eclipse – Building Commercial-Quality Plug-ins, 2004 - ISBN : 0-321-22847-2

� Eclipse – Rich Client Platform, 2005 – ISBN : 0-321-33461-2

Page 7: Construction d'éditeurs avec la plateforme Eclipse

7Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités : Différences entre Vue et Editeur

� Un éditeur est commun à toutes les perspectives d’une

fenêtre

� Si l’éditeur est fermé à partir d’une perspective il est fermé pour

toutes les perspectives

� Il n’est pas possible d’empiler une vue avec un éditeur

� Un éditeur n’est pas détachable

� Un éditeur a obligatoirement une barre de titre

� Un éditeur n’a pas de barre de menus et de barre d’outils

localisées, il partage avec les barres de la fenêtre

Page 8: Construction d'éditeurs avec la plateforme Eclipse

8Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités : Différences entre Vue et Editeur

� Un éditeur peut être instancié plusieurs fois pour un type

d’éditeur donné

� Une vue ne possède qu’une seule instance (cas particulier avec

l’identifiant secondaire)

� Un éditeur apparaît à un seul endroit de la page alors qu’une

vue peut être déplacée

� Un éditeur peut être dans un état « modifié », son contenu

peut ainsi être sauvegardé

� Un éditeur peut être associé à un nom de fichier ou à une

extension et cette association peut être modifiée par

l’utilisateur

Page 9: Construction d'éditeurs avec la plateforme Eclipse

9Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités : Usage de l’éditeur

� Les fausses idées concernant un éditeur …

� Editeur est dédié uniquement à l’affichage et à la manipulation du

contenu d’un fichier

� Une vue peut réaliser la même chose

� Editeur est dédié à l’affichage du texte

� Un éditeur peut aussi afficher des IHMs types formulaires (PDE)

� La vue console affiche uniquement du texte

� Quand utiliser un éditeur ?

� Quand le contenu est considéré comme l’élément central de la fenêtre.

Toutes les vues sont utilisées comme support (outline, explorer, …)

� Quand il est nécessaire de fournir des actions spécifiques pour l’édition

(sauvegarde, menu contextuel, …)

Page 10: Construction d'éditeurs avec la plateforme Eclipse

10Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comGénéralités : Editeur interne et externe

� Editeur interne

� Intégré dans une page d’une fenêtre du Workbench

� Le menu et la barre d’outils sont issus de la fenêtre du Workbench

� Editeur externe (System Editor)

� Démarré dans une fenêtre séparée au Workbench

� Après le démarrage d’un éditeur externe, le Workbench n’a plus la

main sur l’état de l’éditeur (pas de possibilité d’arrêt)

� La collaboration ne peut s’effectuer que par le système de fichier

� Editeur mixte (In-Place Editor)

� Intégré dans une page d’une fenêtre du Workbench, un éditeur

externe (intégration OLE)

� Le menu de l’éditeur externe intégré utilise le menu de la fenêtre du

Workbench

Page 11: Construction d'éditeurs avec la plateforme Eclipse

11Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comGénéralités : Editeur interne et externe

� Exemple : Utilisation d’un éditeur Word en mode « In-Place »

L’éditeur externe Word est intégré dans une page d’une WorkbenchWindow

Le menu de l’application Eclipse est complété par les éléments

du menu de Word

Page 12: Construction d'éditeurs avec la plateforme Eclipse

12Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités : Editeur par défaut

� Un éditeur par défaut est celui à utiliser en priorité si

d’autres éditeurs traitent le même type d’entrées

� Exemple : fichier xml

� Plusieurs éditeurs disponibles (texte, xml, m2eclipse, …)

� Si l’éditeur xml est utilisé comme défaut, il sera ouvert en priorité

� Lors de la définition d’un éditeur (voir extension editors), il

est possible de spécifier qu’un éditeur est par défaut

� Un éditeur est définit implicitement par défaut, si aucun

autre éditeur ne peut traiter son type d’entrée

� Si un fichier est ouvert avec un éditeur, cet éditeur ne

devient pas par défaut mais sera utilisé pour ré-ouvrir de

nouveau ce fichier

Page 13: Construction d'éditeurs avec la plateforme Eclipse

13Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comGénéralités : Carte des classes de l’éditeur

� Principales interfaces et classes pour la gestion des éditeursIWorkbenchPage

activate(IWorkbenchPart)

bringToTop(IWorkbenchPart)

findEditor(String)

getEditorReferences()

hideEditor(IEditorReference)

showEditor(IEditorReference)

IWorkbenchPartReference

getId()

getPage()

getPart(boolean)IWorkbenchSite

getPage()

getSelectionProvider()

getShell()

getWorkbenchWindow()

setSelectionProvider(ISelectionProvider)

IWorkbenchPart

createPartControl(Composite)

dispose()

getSite()

IEditorPart

getEditorSite()

getEditorInput()

init(IEditorSite, IEditorInput)

IWorkbenchPartSite

getKeyBindingService()

registerContextMenu(MenuManager, ISelectionProvider)

registerContextMenu(String, MenuManager, ISelectionProvider)

IEditorReference

getEditor(boolean)

getEditorInput()

getFactoryId()

getName()

isPinned()

WorkbenchPart

dispose()

getConfigurationElement()

getSite()

setPartName(String)

EditorPart

getEditorSite()

getEditorInput()

init(IEditorSite, IEditorInput)

IEditorSite

getActionBars()

getActionBarContributor()

EditorInput

getEditorSite()

getEditorInput()

init(IEditorSite, IEditorInput)

Dépendance

Héritage Généraliste

Spécifique à un éditeur

Page 14: Construction d'éditeurs avec la plateforme Eclipse

14Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités : Principales classes de l’éditeur

� IEditorPart : Contient le code de l’IHM de l’éditeur

� IEditorSite : Pont entre l’éditeur et le Workbench

� IEditorInput : Descripteur du contenu d’un éditeur

� IEditorDescriptor : Descripteur utilisé dans le registre des

éditeurs

� IEditorReference : Représenter une instance d’un éditeur

dans la page active

� IEditorActionBarContributor : Utilisé pour contribuer à

l’ajout d’actions dans la barre de menus et d’outils

Page 15: Construction d'éditeurs avec la plateforme Eclipse

15Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur interne par extension

� Sélectionner le point d’extension org.eclipse.ui.editors

Création d’une extension àpartir du point d’extension

org.eclipse.ui.editors

Création d’un éditeur à partir des templates Editor et

Multi-page Editor

Page 16: Construction d'éditeurs avec la plateforme Eclipse

16Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur interne par extension

� Définir les attributs de l’extension

Identifiant de l’éditeur

Nom de l’éditeur

Extensions des fichiers (ex : html) gérées par l’éditeur

Objet de type EditorPart implémentant le contenu d’un éditeur interne

Utiliser pour démarrer un éditeur externe (mutuellement

exclusif avec class)

Objet de type IEditorActionBarContributor utilisé pour ajouter des actions à la barre de menu

et à la barre d’outils

Les noms des fichiers gérés par l’éditeur

L’attribut default permet d’indiquer que cet éditeur est à

utiliser en priorité pour les fichiers dont l’extension est html ou txtUtilisation d’une police

par défaut

Page 17: Construction d'éditeurs avec la plateforme Eclipse

17Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur interne par extension

� Etendre un éditeur de type EditorPart

package eclipse.workbench.viewexample.views

public class SimpleEditor extends EditorPart {

public SimpleEditor() { }public void doSaveAs() { }

public void init(IEditorSite site, IEditorInput input) throws PartInitException {setSite(site);setInput(input);

}

public boolean isDirty() {return false;

}

public boolean isSaveAsAllowed() {return false;

}

public void createPartControl(Composite parent) {Label myLabel = new Label(parent, SWT.NONE);myLabel.setText("Simple View");

}

public void setFocus() { }public void doSave(IProgressMonitor monitor) { }

}

SimpleEditor.java du Projet EditorExample

Page 18: Construction d'éditeurs avec la plateforme Eclipse

18Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur interne par extension

� Pour utiliser cet éditeur plusieurs solutions sont à envisager

� Ouvrir un fichier au format html ou txt (File -> Open File …)

� Faire appel explicitement à la méthode openEditor à partir d’un

WorkbenchPage (voir plus tard)

� A noter que si aucun éditeur n’est défini pour une extension

donnée d’un fichier

� Ce fichier n’est pas ouvert par un éditeur Eclipse

� Un éditeur externe (System Editor) est utilisé si l’extension a été

associée à un éditeur

� Si l’éditeur d’Eclipse est défini comme éditeur par défaut, le

fichier est automatiquement ouvert dans cet éditeur

� Il est possible d’utiliser d’autres éditeurs en utilisant le

menu Open With

Page 19: Construction d'éditeurs avec la plateforme Eclipse

19Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur interne par extension

� Exemple : Ouverture du fichier pom.xml par trois éditeurs

Plusieurs éditeurs peuvent éditer ce fichier

Via l’éditeur de M2 Eclipse Via l’éditeur XML

Des éditeurs fournis par Eclipse

L’éditeur système

Via l’éditeur sytème« Firefox »

Page 20: Construction d'éditeurs avec la plateforme Eclipse

20Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur externe par extension

� Précédemment l’attribut class a permis de développer un

éditeur interne

� Pour développer des éditeurs externes il faut utiliser les

attributs launcher ou command

� A noter que class, launcher et command sont mutuellement

exclusif

� Utilisation de l’attribut launcher

� Nécessite la création d’une classe implémentant IEditorLauncher

� void open(IPath file) : appelée pour ouvrir le fichier dont le chemin

est passé en paramètre

� Utilisation de l’attribut command

� Commande du système (par exemple : notepad.exe)

� Ne pas confondre avec les commandes Eclipse !!!!

Page 21: Construction d'éditeurs avec la plateforme Eclipse

21Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur externe par extension

� Exemple : Création d’un éditeur externe via launcher

L’attribut launcher est renseigné

Si l’attribut launcher doit être renseigné, ne pas modifier les attributs class et command

Cet éditeur est associé aux fichiers dont l’extension est

extlaunch

Page 22: Construction d'éditeurs avec la plateforme Eclipse

22Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur externe par extension

� Exemple (suite) : Création d’un éditeur externe via launcher

public class SimpleEditorEditorLauncher implements IE ditorLauncher {

public void open(IPath file) {final Program findProgram = Program.findProgram("txt");boolean result = findProgram.execute(file.toFile().ge tAbsolutePath());

System.out.println("External Editor has been launche d ? : " + result);}

}

SimpleEditor.java du Projet EditorExample

Utilisation de l’API Program pour démarrer un éditeur externe

Recherche au niveau du système d’exploitation le programme associé

à l’extension txt(pour être sur d’obtenir un résultat)

Exécution du programme (notepad.exe) en donnant en paramètre le chemin du fichier

Page 23: Construction d'éditeurs avec la plateforme Eclipse

23Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur externe par extension

� Exemple (suite) : Création d’un éditeur externe via launcher

Utilisation de l’éditeur interne texte (via Open With)

Utilisation de l’éditeur externe (notepad.exe)

(également via Open With)

Page 24: Construction d'éditeurs avec la plateforme Eclipse

24Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Construction d’un éditeur externe par extension

� Exemple : Création d’un éditeur externe via command

L’attribut command est renseigné

Cet éditeur est associé aux fichiers dont l’extension est

extCommand

Si l’attribut command doit être renseigné, ne pas modifier les

attributs class et launcher

Très simple d’utilisation mais ne permet pas de définir des

paramètres dérivés

Page 25: Construction d'éditeurs avec la plateforme Eclipse

25Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

EditorPart

� La définition d’un nouvel éditeur est obtenue en héritant de la classe EditorPart

� Des méthodes abstraites doivent être implémentées

� void init(IEditorSite site, IEditorInput input) : initialise l’éditeur

� void createPartControl(Composite parent) : création de l’IHM par des composants SWT où parent est le conteneur de la vue

� void setFocus() : composant qui aura le focus lors de l’activation

� void doSave(IProgressMonitor monitor) : sauvegarde le contenu de l’éditeur

� void doSaveAs() : sauvegarde le contenu de l’éditeur dans un autre emplacement

� boolean isDirty() : indique si le contenu a changé

� boolean isSaveAsAllowed() : « Save As » est-il supporté ?

� boolean isSaveOnCloseNeeded() : La sauvegarde est-elle nécessaire avant la fermeture de l’éditeur ?

Page 26: Construction d'éditeurs avec la plateforme Eclipse

26Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

EditorPart

� Des méthodes qui peuvent être redéfinies …

� void setInitializationData(…) : appelée lors de la création de

l’extension

� String getTitleToolTip() : message pour la bulle d’aide de l’éditeur

� Des méthodes à exploiter …

� IEditorSite getEditorSite() : retourne le site de l’éditeur (étudier par la

suite)

� IEditorInput getEditorInput() : retourne l’EditorInput de l’éditeur

(étudier par la suite)

� void setPartName(String ti) : modifie directement le titre de l’éditeur

en place d’utiliser les données de l’extension

Page 27: Construction d'éditeurs avec la plateforme Eclipse

27Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

EditorPart et IEditorSite

� Le site d’un éditeur est une sorte de pont entre l’éditeur

(définit par EditorPart) et le Workbench

� Il faut voir le site comme un objet qui permet de lier l’éditeur

au contexte de l’application

� L’interface IWorkbenchSite est une abstraction d’un site

� IWorkbenchPage getPage() : la page dans laquelle l’éditeur est stockée

� Shell getShell() : la fenêtre physique d’où est contenue l’éditeur

� IWorkbenchWindow getWorkbenchWindow() : la fenêtre déclarative contenant l’éditeur

� void registerContextMenu(MenuManager mM, ISelectionProvider sP) : expose un menu vers le Workbench pour permettre son extension

ultérieur

� void setSelectionProvider(ISelectionProvider sP) : déclare un SelectionProvider (TableViewer par exemple) au service de sélection

Page 28: Construction d'éditeurs avec la plateforme Eclipse

28Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

EditorPart et IEditorSite

� L’interface IEditorSite (sous type de IWorkbenchSite) fournit

des méthodes spécifiques

� IActionBars getActionBars() : la barre d’action de l’éditeur

� IEditorActionBarContributor getActionBarContributor() : retourne un

objet IEditorActionBarContributor utilisé pour la création des actions

A l’ouverture de l’éditeur des commandes (ou actions) sont

ajoutées à la barre d’action et menu

L’ajout d’éléments dans la barre de menu

et la barre d’outils sera étudié dans la

suite

Page 29: Construction d'éditeurs avec la plateforme Eclipse

29Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

IEditorInput

� Un objet IEditorInput est un descripteur léger sur le contenu

d’un éditeur

� Il ne s’agit pas du modèle de l’éditeur mais d’une description

sur la source de l’éditeur utilisé par l’EditorPart

� A chaque création d’une nouvelle instance d’EditorPart, un

objet de type IEditorInput doit être passé en paramètre

� L’éditeur à ouvrir doit supporter l’objet IEditorInput passé en

paramètre

� Possibilité d’adapter un objet IEditorInput en autre objet

puisque l’objet est de type IAdaptable

� Exemple : adapter un CustomEditorInput en FileEditorInput de telle

sorte que CustomEditorInput soit utilisable par des éditeurs

manipulant des fichiers

Page 30: Construction d'éditeurs avec la plateforme Eclipse

30Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

IEditorInput

� Principales méthodes de IEditorInput

� boolean exists() : vérifie si l’éditeur existe

� ImageDescriptor getImageDescriptor() : retourne une image

� String getToolTipText() : retourne le texte de la bulle d’aide

� String getName() : retourne un nom

� En pratique un éditeur qui édite le contenu

d’un fichier utilise en FileEditorInput

� Contient un attribut de type File permettant d’accéder au contenu du

fichier

� Principales méthodes de FileEditorInput

� IFile getFile() : retourne le fichier contenant la source

Lors de la définition de votre propre IEditorInput redéfinissez obligatoirement

la méthode equals

Page 31: Construction d'éditeurs avec la plateforme Eclipse

31Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� Le registre des éditeurs est utilisé par le conteneur Eclipse

pour stocker l’intégralité des éditeurs créés

� Il n’existe qu’un seul registre d’éditeur géré par le Workbench

� A partir de ce registre il est possible de

� Chercher un éditeur par son identifiant

� Chercher tous les éditeurs associés à un nom de fichier

� Chercher l’éditeur par défaut par son nom

IEditorRegistry editorRegistry = PlatformUI.getWorkbe nch().getEditorRegistry();

L’interface IEditorRegistry est détaillée dans la suite

Page 32: Construction d'éditeurs avec la plateforme Eclipse

32Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� L’interface IEditorRegistry dispose des méthodes suivantes

� IEditorDescriptor findEditor(String id) : recherche un éditeur par son id

� IEditorDescriptor[] getEditors(String fileName) : retourne les éditeurs

disponibles pour un fichier donné

� IEditorDescriptor getDefaultEditor(String fileName) : retourne l’éditeur

par défaut pour un fichier donné

� boolean isSystemExternalEditorAvailable(String fileName) : vérifie s’il

existe un éditeur externe disponible pour un fichier donné

� void setDefaultEditor(String fileNameOrExt, String id) : modifie

l’éditeur par défaut suivant le nom de fichier ou l’extension

� Un objet IEditorDescriptor décrit un éditeur du point de vue

de sa déclaration (informations de l’extension)

Page 33: Construction d'éditeurs avec la plateforme Eclipse

33Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� Exemple : Modifier et accéder à l’éditeur par défaut

Deux commandes permettent de modifier l’éditeur par défaut des

fichiers de type html

La commande Launcher Editor Default associe l’éditeur SimpleExternalEditorWithLauncherId au

fichier html

Le traitement de cette commande • affiche l’ancien éditeur par défaut• affecte le nouveau éditeur par défaut• affiche enfin le nouveau éditeur par défaut

1

2

3

Page 34: Construction d'éditeurs avec la plateforme Eclipse

34Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� Exemple (suite) : Modifier et accéder à l’éditeur par défaut

public class LauncherEditorCommandHandler extends Abs tractHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IEditorRegistry editorRegistry = PlatformUI.get Workbench().getEditorRegistry();

IEditorDescriptor defaultEditor = editorRegistry.getD efaultEditor("*.html");if (defaultEditor != null) {

System.out.println(defaultEditor.getLabel());}

editorRegistry.setDefaultEditor("*.html","eclipse.w orkbench.EditorExample.SimpleExternalEditorWithLaun cherId");

defaultEditor = editorRegistry.getDefaultEditor("*.h tml");if (defaultEditor != null) {

System.out.println(defaultEditor.getLabel());}

return null;}

}

LauncherEditorCommandHandler.javadu Projet EditorExample

Récupération de l’éditeur par défaut des fichiers dont l’extension est html

Modification de l’éditeur par défaut des fichiers de type html

Page 35: Construction d'éditeurs avec la plateforme Eclipse

35Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� L’interface IEditorDescriptor décrit l’éditeur dans le registre

des éditeurs (relation avec les extensions)

� String getId() : identifiant de l’éditeur

� String getLabel() : le nom de l’éditeur

� ImageDescriptor getImageDescriptor() : image de l’éditeur

� boolean isInternal() : utilise un éditeur interne pour l’ouverture ?

� boolean isOpenExternal() : utilise un éditeur externe pour l’ouverture ?

� boolean isOpenInPlace() : utilise un éditeur externe intégré à Eclipse ?

� …

� Le registre ne donne pas accès aux instances des objets

IEditorPart (voir cycle de vie)

Page 36: Construction d'éditeurs avec la plateforme Eclipse

36Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des éditeurs

� Exemple : Interroger le registre des éditeurs

public class EditorRegistryCommandHandler extends Abs tractHandler {

@Overridepublic Object execute(ExecutionEvent event) throws Ex ecutionException {

final IEditorRegistry editorRegistry = PlatformUI.get Workbench().getEditorRegistry();

final IEditorDescriptor[] editors = editorRegistry. getEditors("*.txt");

for (IEditorDescriptor iEditorDescriptor : editors) {System.out.println(iEditorDescriptor.getLabel());

}

return null;}

}

EditorRegistryCommandHandler.javadu Projet EditorExample

Récupère les éditeurs associés àce type d’extension

Deux éditeurs sont disponibles

Page 37: Construction d'éditeurs avec la plateforme Eclipse

37Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie

� Un objet IWorkbenchPage permet de gérer le cycle de vie

des instances d’une classe IEditorPart (celle utilisée pour

programmer l’interface d’un éditeur)

� Chaque instance de type IEditorPart est associée un objet

de type IEditorReference

� Une instance IEditorReference est associée une instance IEditorPart

� Il peut exister dans une même page plusieurs instances du

même éditeur (pas d’identifiant secondaire)

� Les méthodes fournies par la page permettent généralement

d’afficher ou de cacher des éditeurs

Page 38: Construction d'éditeurs avec la plateforme Eclipse

38Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie

� Principales méthodes de IWorkbenchPage en relation avec la notion d’éditeur

� IEditorPart getActiveEditor() : l’éditeur actuellement actif

� boolean closeAllEditors(boolean save) : ferme tous les éditeurs sans

possibilité de sauvegarde si save vaut false

� boolean closeEditor(IEditorPart e, boolean save) : ferme un éditeur désigné par e

� IEditorPart findEditor(IEditorInput e) : cherche un éditeur via son IEditorInput

� IEditorPart[] getDirtyEditors() : retourne l’ensemble des éditeurs dont le contenu a changé (nécessite une sauvegarde)

� IEditorReferences[] getEditorReferences() : retourne l’ensemble des éditeurs

� IEditorPart openEditor(…) : ouvre un éditeur (détailler dans le prochain transparent)

Page 39: Construction d'éditeurs avec la plateforme Eclipse

39Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Le comportement de l’ouverture d’un éditeur est différent

selon la configuration utilisée pour la méthode openEditor

� Trois configurations différentes

� Ouvre un nouvel éditeur s’il n’existe pas un éditeur ayant un même

input (MATCH_INPUT)

� Ouvre un nouvel éditeur s’il n’existe pas un éditeur ayant un même

identifiant (MATCH_ID)

� Ouvre un nouvel éditeur même s’il existe un éditeur ayant un même

input ou un même identifiant (MATCH_NONE)

� Surcharge de la méthode openEditor

� IEditorPart openEditor(IEditorInput input, String editorID) : ouvre un éditeur s’il n’existe pas un éditeur ouvert ayant un même input

� IEditorPart openEditor(final IEditorInput input, final String editorID, final boolean activate, final int matchFlags) : ouvre un éditeur en spécifiant la configuration

Page 40: Construction d'éditeurs avec la plateforme Eclipse

40Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple : Ouvrir un éditeur pour un fichier

présent dans le Workspace

public class OpenEditorCommandHandler extends Abstrac tHandler {

@Overridepublic Object execute(ExecutionEvent event) throws Ex ecutionException {

final IWorkbenchPage activePage = PlatformUI.getWorkb ench().getActiveWorkbenchWindow().getActivePage();

ISelectionService selService = PlatformUI.getWorkbenc h().getActiveWorkbenchWindow().getSelectionService( );final ISelection selection = selService.getSelection( );if (selection instanceof TreeSelection) {

TreeSelection currentFile = (TreeSelection)selection;final IFile firstElement = (IFile)currentFile.getFirs tElement();IEditorDescriptor desc = PlatformUI.getWorkbench().ge tEditorRegistry().getDefaultEditor(firstElement.get Name());try {

activePage.openEditor(new FileEditorInput(firstElem ent), desc.getId());} catch (PartInitException e) {

e.printStackTrace();}

}

return null;}

}

OpenEditorCommandHandler.java du Projet EditorExample

Récupération de l’éditeur associé au type du fichier sélectionné(ici le fichier sample.html)

Ouverture de l’éditeur s’il n’existe pas un éditeur déjà ouvert ayant le même input

Page 41: Construction d'éditeurs avec la plateforme Eclipse

41Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir un éditeur pour un fichier présent

dans le Workspace

Les fichiers doivent être présents dans le répertoire du workspace pour être ouvert

via la méthode open(…)

L’utilisation de la méthode openEditor ne s’applique que pour

les fichiers présents dans le Workspace, sauf cas …

Page 42: Construction d'éditeurs avec la plateforme Eclipse

42Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple : Ouvrir un éditeur pour un fichier non présent

dans le Workspace (solution 1)public class OpenExternalEditorCommandHandler extend s AbstractHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {try {

IWorkspace ws = ResourcesPlugin.getWorkspace();IProject project = ws.getRoot().getProject("SimpleEdi tor");

if (!project.exists())project.create(null);

if (!project.isOpen())project.open(null);

final IWorkbenchWindow activeWorkbenchWindow = Platfo rmUI.getWorkbench().getActiveWorkbenchWindow();final Shell shell = activeWorkbenchWindow.getShell() ;

String name = new FileDialog(shell, SWT.OPEN).open() ;if (name == null)

return null;

IPath location = new Path(name);IFile file = project.getFile(location.lastSegment()) ;file.createLink(location, IResource.NONE, null);IWorkbenchPage page = activeWorkbenchWindow.getActiv ePage();if (page != null)

IEditorDescriptor desc = PlatformUI.getWorkbench().ge tEditorRegistry().getDefaultEditor(file.getName());page.openEditor(new FileEditorInput(file), desc.get Id());

} catch(Exception e) {e.printStackTrace();

}return null;

}}

OpenExternalEditorCommandHandler.javadu Projet EditorExample

Une boîte de dialogue est utilisée pour choisir un

fichier sur le système hôte

Création d’un lien entre le fichier physique et le

workspace

Utilisation de l’éditeur par défaut pour l’ouverture

Page 43: Construction d'éditeurs avec la plateforme Eclipse

43Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir un éditeur pour un fichier non

présent dans le Workspace (solution 1)

Le fichier setup.log est localisé à l’emplacement

c:\setup.log

L’icône précise qu’il s’agit d’un lien

Pas de fichier setup.logdans le répertoire du

workspace

Page 44: Construction d'éditeurs avec la plateforme Eclipse

44Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple : Ouvrir un éditeur pour un fichier non présent

dans le Workspace (solution 2)

public class OpenExternalEditorWithEFSCommandHandle r extends AbstractHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IWorkbenchWindow activeWorkbenchWindow = Platfo rmUI.getWorkbench().getActiveWorkbenchWindow();final Shell shell = activeWorkbenchWindow.getShell() ;

String name= new FileDialog(shell, SWT.OPEN).open() ;if (name == null)

return null;name = name.replace('\\','/');IFileStore fileStore = EFS.getLocalFileSystem().getSt ore(URI.create(name));if (!fileStore.fetchInfo().isDirectory() && fileSto re.fetchInfo().exists()) {

IWorkbenchPage page= activeWorkbenchWindow.getActiv ePage();try {

IDE.openEditorOnFileStore(page, fileStore);} catch (PartInitException e) {

e.printStackTrace();}

}return null;

}}

OpenExternalEditorWithEFCCommandHandler.javadu Projet EditorExample

Depuis la version Eclipse 3.3, EFS (Eclipse File System) a été défini pour

simplifier la gestion des fichiers

Utilisation de la méthode openEditorOnFileStore définie

dans la classe IDE

Page 45: Construction d'éditeurs avec la plateforme Eclipse

45Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple : Ouvrir un éditeur pour un contenu qui n’est pas

un fichier Affichage du contenu qui ne provient pas d’un fichier (une chaîne de texte)

Exemple issu de la FAQ Eclipse

http://wiki.eclipse.org/FAQ_How_do_I_open_an_editor_on_something_that_is_not_a_file%3F

Page 46: Construction d'éditeurs avec la plateforme Eclipse

46Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir un éditeur pour un contenu qui

n’est pas un fichierpublic class OpenEditorWithNoFileCommandHandler exte nds AbstractHandler {

class StringStorage implements IStorage {priva te String string;

StringStorage(String input) {this.string = input;

}

public InputStream getContents() throws CoreException {return new ByteArrayInputStream(string.getBytes());

}

public IPath getFullPath() {return null;

}

public Object getAdapter(Class adapter) {return null;

}

public String getName() {int len = Math.min(5, string.length());return string.substring(0, len).concat("...");

}

public boolean isReadOnly() {return true;

}}... // Suite dans le prochain transparent

OpenEditorWithNoFileCommandHandler.javadu projet EditorExample

Page 47: Construction d'éditeurs avec la plateforme Eclipse

47Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir un éditeur pour un contenu qui

n’est pas un fichierpublic class OpenEditorWithNoFileCommandHandler exte nds AbstractHandler {

class StringInput implements IStorageEditorInput {private IStorage storage;

StringInput(IStorage storage) {this.storage = storage;

}

public boolean exists() { return true; }

public ImageDescriptor getImageDescriptor() { return null; }

public String getName() {return storage.getName();

}

public IPersistableElement getPersistable() { return null; }

public IStorage getStorage() {return storage;

}

public String getToolTipText() {return "String-based file: " + storage.getName();

}

public Object getAdapter(Class adapter) { return nu ll; }}... // Suite dans le prochain transparent

OpenEditorWithNoFileCommandHandler.javadu projet EditorExample

Page 48: Construction d'éditeurs avec la plateforme Eclipse

48Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir un éditeur pour un contenu qui

n’est pas un fichier

public class OpenEditorWithNoFileCommandHandler exte nds AbstractHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {IWorkbenchWindow window = PlatformUI.getWorkbench().g etActiveWorkbenchWindow();

String string = "This is the text file contents";

IStorage storage = new StringStorage(string);IStorageEditorInput input = new StringInput(storage) ;IWorkbenchPage page = window.getActivePage();

if (page != null) {try {

page.openEditor(input, "org.eclipse.ui.DefaultTextE ditor");} catch (PartInitException e) {

e.printStackTrace();}

}

return null;}

OpenEditorWithNoFileCommandHandler.javadu projet EditorExample

Contenu à afficher

Définition d’un IEditorInputdédié à la gestion d’une chaîne

de caractères

Ouverture de l’éditeur qui gère l’édition et l’affichage du texte

Page 49: Construction d'éditeurs avec la plateforme Eclipse

49Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple : Ouvrir plusieurs instances d’un même éditeur

Plusieurs instances d’un même éditeur

Page 50: Construction d'éditeurs avec la plateforme Eclipse

50Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : openEditor …

� Exemple (suite) : Ouvrir plusieurs instances d’un même

éditeurpublic class OpenSeveralEditorInstances extends Abstr actHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IWorkbenchPage activePage = PlatformUI.getWorkb ench().getActiveWorkbenchWindow().getActivePage();

ISelectionService selService = PlatformUI.getWorkbenc h().getActiveWorkbenchWindow().getSelectionService( );final ISelection selection = selService.getSelection( );if (selection instanceof TreeSelection) {

TreeSelection currentFile = (TreeSelection)selection;final IFile firstElement = (IFile)currentFile.getFirs tElement();IEditorDescriptor desc =

PlatformUI.getWorkbench().getEditorRegistry().getDe faultEditor(firstElement.getName());try {

activePage.openEditor(new FileEditorInput(firstElement), desc.getId(), true, IWorkbenchPage.MATCH_NONE);

} catch (PartInitException e) {e.printStackTrace();

}}

return null;}

}

OpenSeveralEditorInstances.javadu projet EditorExample

Précise qu’il n’y a pas de comparaison entre les instances d’éditeur

Page 51: Construction d'éditeurs avec la plateforme Eclipse

51Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie

� L’interface IEditorReference permet de représenter une

instance d’un éditeur dans la page active

� String getName() : le nom de l’éditeur

� IEditorPart getEditor(boolean restore) : l’éditeur associé à cette

instance

� IEditorInput getEditorInput() : l’EditorInput associé à cette instance

� boolean isPinned() : indique si l’éditeur est épinglé (voir transparent

suivant pour explication)

� L’accès à un objet IViewReference se fait par l’intermédiaire

du Workbench Page actif

Page 52: Construction d'éditeurs avec la plateforme Eclipse

52Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : isPinned ?

� Possibilité d’ouvrir plusieurs éditeurs dans une page pouvant

aboutir à un nombre important d’éditeurs ouverts

� La plateforme Eclipse permet de restreindre le nombre

d’éditeur ouvert dans une page en fermant automatique-

ment les anciens éditeurs

� Preferences -> General -> Editors … activer l’option Close editors …

Seuls trois éditeurs doivent rester ouverts

Page 53: Construction d'éditeurs avec la plateforme Eclipse

53Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : isPinned ?

� Un éditeur ne peut être fermé automatiquement dans les

cas suivants

� si son état est dirty (contenu modifié)

� si son état est pinned (épinglé)

� Comment « épingler » un éditeur …Dés que l’option Close Editors

automatically est activée, l’action Pin Editor est disponible

Possibilité de modifier programmatiquement l’état de la

caractéristique pinned d’un éditeur

L’action Pin Editor sur l’éditeur courant active ou pas l’état épinglé

Page 54: Construction d'éditeurs avec la plateforme Eclipse

54Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie : de l’ouverture à la fermeture

� Ouverture de l’éditeur

� void init(IEditorSite site, IEditorInput input) : initialisation du

contenu de l’éditeur

� void createPartControl(Composite parent) : création de l’IHM

� Modification du contenu

� void firePropertyChange(PROP_INPUT) : déclenche un changement

� boolean isDirty() : précise s’il y a des changements

� Persistance

� void doSave(IProgressMonitor monitor) : sauvegarder le contenu

� void doSaveAs() : sauvegarder le contenu dans un autre objet

� Fermeture

� dispose() : destruction des objets

1

2

3

4

Page 55: Construction d'éditeurs avec la plateforme Eclipse

55Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : ouverture d’un éditeur

� Ouverture d’un éditeur procède à la création d’une instance

EditorPart dans le Workbench Page actif

� Ordre d’appel des méthodes de la classe de type EditorPart

� Constructeur de la classe de type EditorPart

� void init(IEditorSite site, IEditorInput input) : ne pas oublier de

stocker le site et l’input dans le traitement de cette méthode

� void createPartControl(Composite parent)

� Méthodes appelées par la plateforme Eclipse uniquement à

la création de l’instance d’un éditeur

1

2

3

Page 56: Construction d'éditeurs avec la plateforme Eclipse

56Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : éditeur en utilisation

� Tout au long de l’utilisation d’une instance d’un EditorPart,

son contenu peut évoluer

� Exemple : un texte a été modifié, une sauvegarde peut être réalisée

� La méthode isDirty() permet de retourner à la page courante

l’état de ce changement

� Si un changement est repéré, les procédures de sauvegarde

du contenu sont proposées

� La commande Save est activée

� La commande Save As est activée si la méthode isSaveAsAllowed()

retourne vraie

� La sauvegarde est proposée à l’utilisateur si la méthode

isSaveOnCloseNeeded() retourne vraie

Page 57: Construction d'éditeurs avec la plateforme Eclipse

57Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : fermeture d’un éditeur

� La sauvegarde du contenu est gérée directement par

l’éditeur dans la classe de type EditorPart

� Plusieurs méthodes sont appelées en fonction du type de

sauvegarde à réaliser

� void doSave(IProgressMonitor monitor) : appelée pour réaliser une

sauvegarde sur une ressource

� void doSaveAs() : appelée pour effectuer une sauvegarde de type

« Sauvegarder Comme »

� A la suite de la sauvegarde, il faut penser à modifier l’état

du changement retourné par la méthode isDirty()

� La fermeture d’un éditeur provoque la suppression d’une

instance de type EditorPart (méthode dispose() appelée)

Page 58: Construction d'éditeurs avec la plateforme Eclipse

58Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : show et hide

� Depuis la version Eclipse 3.5 (Galileo), une API permet de

cacher et de rendre visible un éditeur sans destruction de

ces instances

� Son utilisation reste limitée et seulement deux méthodes

sont proposées

� void hideEditor(IEditorReference) : cache un éditeur en utilisant son

EditorReference

� void showEditor(IEditorReference) : affiche un éditeur précédemment

caché

� Il n’est pas possible de récupérer la liste des éditeurs qui

sont dans un état caché

Page 59: Construction d'éditeurs avec la plateforme Eclipse

59Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : show et hide

� Exemple : Cacher et ouvrir un éditeur

public class HideEditorCommandHandler extends Abstrac tHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IWorkbenchPage activePage = PlatformUI.getWorkb ench().getActiveWorkbenchWindow().getActivePage();

final IWorkbenchPartReference reference = activePage. getReference(activePage.getActiveEditor());if (reference instanceof IEditorReference) {

activePage.hideEditor((IEditorReference)reference);Activator.getDefault().getHiddenEditors().add((IEdi torReference)reference);

}

return null;}

}

HideEditorCommandHandler.javadu projet EditorExample

Ajoute chaque référence (IEditorReference) des éditeurs à

cacher dans l’Activator

Handler utilisé pour cacher des éditeurs

L’ajout explicite des éditeurs dans l’Activator est nécessaire puisque l’API ne permet pas de connaître les éditeurs

cachés

Page 60: Construction d'éditeurs avec la plateforme Eclipse

60Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie : show et hide

� Exemple (suite) : Cacher et ouvrir un éditeur

public class ShowEditorCommandHandler extends Abstrac tHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IWorkbenchPage activePage = PlatformUI.getWorkb ench().getActiveWorkbenchWindow().getActivePage();

final List<IEditorReference> hiddenEditors = Activat or.getDefault().getHiddenEditors();if (!hiddenEditors.isEmpty()) {

activePage.showEditor(hiddenEditors.get(0));hiddenEditors.remove(0);

}return null;

}}

ShowEditorCommandHandler.javadu projet EditorExample

public class ShowAllHiddenEditorsHandler extends Abst ractHandler {

public Object execute(ExecutionEvent event) throws Ex ecutionException {final IWorkbenchPage activePage = PlatformUI.getWorkb ench().getActiveWorkbenchWindow().getActivePage();

WorkbenchPage activeWorkbencPage = (WorkbenchPage)act ivePage;

final List<IEditorReference> hiddenEditors = Activat or.getDefault().getHiddenEditors();hiddenEditors.clear();activeWorkbencPage.resetHiddenEditors();return null;

}}

ShowAllHiddenEditorsHandler.javadu projet EditorExample

Appel de showEditor pour afficher l’éditeur puis suppression dans l’Activator

Appel de resetHiddenEditors pour réafficher tous les éditeurs cachés

ou

Permet de réafficher un seul éditeur

Permet de réafficher tous les éditeurs

Page 61: Construction d'éditeurs avec la plateforme Eclipse

61Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

MultiPageEditorPart

� Un MultiPageEditorPart est un éditeur avec plusieurs pages

où chaque page peut contenir

� un éditeur (EditorPart) ou

� un composant SWT

� Un MultiPageEditorPart hérite de EditorPart et par

conséquent il se comporte comme un éditeur classique

(cycle de vie identique)

Une page contenant un éditeur

Une page contenant des composants SWT (Composite, Button, …)

Page 62: Construction d'éditeurs avec la plateforme Eclipse

62Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

MultiPageEditorPart

� Les méthodes utiles de la classe MultiPageEditorPart

� int addPage(IEditorPart editor, IEditorInput input) : ajoute un éditeur

à la dernière page et retourne l’index de la page ajoutée

� int addPage(Control p) : ajoute un composant SWT à la dernière page

et retourne l’index de la page ajoutée

� void setPageText(int index, String title) : modifie le titre de la page en

fonction de l’index donné

� Les méthodes à implémenter et à redéfinir

� void createPages() : appeler pour construire les pages

� void doSave(IProgressMonitor p) : sauvegarde de l’éditeur multiple

� void doSaveAs() : sauvegarde de type « Sauvegarder Comme »

� boolean isSaveAsAllowed() : autoriser le « Sauvegarder Comme »

� void pageChange(int new) : à redéfinir si besoin d’être notifié du

changement de page

Page 63: Construction d'éditeurs avec la plateforme Eclipse

63Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

MultiPageEditorPart

� Exemple : Un éditeur multiple avec trois pages

Une page contenant un éditeur de texte affichant le contenu

d’un fichier

Une page contenant un composite avec un bouton

permettant de choisir une police de caractères

Une dernière page contenant un composite avec un composant

StyledText permettant d’afficher chaque mot (donné par le texte de la page 1) avec une police définie par la page 2

Exemple basé sur le template fourni par la plateforme Eclipse

utilisé pour illustrer la construction d’éditeurs

Page 64: Construction d'éditeurs avec la plateforme Eclipse

64Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

MultiPageEditorPart

� Exemple (suite) : Un éditeur multiple avec trois pagespublic class MultiPageEditor extends MultiPageEditorP art implements IResourceChangeListener {

public MultiPageEditor() {super();ResourcesPlugin.getWorkspace().addResourceChangeLis tener(this);

}

protected void createPages() {createPage0();createPage1();createPage2();

}private void createPage0() {

try {editor = new TextEditor();int index = addPage(editor, getEditorInput());setPageText(index, editor.getTitle());

} catch (PartInitException e) {ErrorDialog.openError(getSite().getShell(), "Error c reating nested text editor", null, e.getStatus());

}}private void createPage2() {

...text = new StyledText(composite, SWT.H_SCROLL | SWT. V_SCROLL);int index = addPage(composite);setPageText(index, "Preview");

}

protected void pageChange(int newPageIndex) {super.pageChange(newPageIndex);if (newPageIndex == 2) sortWords();

}

// Suite dans le prochain transparent}

MultiPageEditor.javadu projet MultiPageEditorExample

Ajoute un écouteur sur les changements des ressources

Demande la création de chaque page

Ajoute un éditeur dans la page 0

Ajoute un composite dans la page 2

A chaque changement de page une action est réalisée

Page 65: Construction d'éditeurs avec la plateforme Eclipse

65Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

MultiPageEditorPart

� Exemple (suite) : Un éditeur multiple avec trois pagespublic class MultiPageEditor extends MultiPageEditorP art implements IResourceChangeListener {

public void doSave(IProgressMonitor monitor) {getEditor(0).doSave(monitor);

}

public void doSaveAs() {IEditorPart editor = getEditor(0);editor.doSaveAs();setPageText(0, editor.getTitle());setInput(editor.getEditorInput());

}

public void resourceChanged(final IResourceChangeEve nt event) {if(event.getType() == IResourceChangeEvent.PRE_CLOS E){

Display.getDefault().asyncExec(new Runnable(){public void run(){

IWorkbenchPage[] pages = getSite().getWorkbenchWind ow().getPages();for (int i = 0; i<pages.length; i++){

if(((FileEditorInput)editor.getEditorInput()).getFi le().getProject().equals(event.getResource())) {IEditorPart editorPart = pages[i].findEditor(editor.g etEditorInput());pages[i].closeEditor(editorPart,true);

}}

} });

}}

public void dispose() {ResourcesPlugin.getWorkspace().removeResourceChange Listener(this);super.dispose();

}}

Sauvegarde le contenu si des modifications ont été apportées

Si le projet est fermé, les éditeurs associés sont fermés

MultiPageEditor.javadu projet MultiPageEditorExample

Page 66: Construction d'éditeurs avec la plateforme Eclipse

66Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Diviser un éditeur

� Dans une page la zone de l’éditeur est unique et plusieurs

instances d’éditeurs peuvent cohabiter dans la zone

� L’affichage des éditeurs peut se faire

� Soit en empilant les différents éditeurs

� Soit en divisant (split) les éditeurs

� Soit de manière mixte (empiler + diviser)

� Pour diviser des éditeurs, l’utilisateur peut faire glisser un

éditeur dans la zone

� Toutefois, il n’existe pas d’API « publics » pour réaliser

cette opération de manière programmatique, il faut penser

par l’implémentation interne

Page 67: Construction d'éditeurs avec la plateforme Eclipse

67Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Diviser un éditeur

� Exemple : Diviser programmatiquement la zone de l’éditeur

Exemple issu du blog …http://swarmy.free.fr/wordpress/?p=17

La zone de l’éditeur est séparée en deux

Page 68: Construction d'éditeurs avec la plateforme Eclipse

68Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Diviser un éditeur

� Exemple (suite) : Diviser programmatiquement la zone de

l’éditeurpublic class CreateSplitEditorHandler extends Abstra ctHandler {

public Object execute(ExecutionEvent event) throws E xecutionException {IWorkbenchPage workbenchPage = PlatformUI.getWorkbenc h().getActiveWorkbenchWindow().getActivePage();IWorkbenchPart part = workbenchPage.getActivePart();PartPane partPane = ((PartSite) part.getSite()).getPa ne();LayoutPart layoutPart = partPane.getPart();

IEditorReference[] editorReferences = workbenchPage. getEditorReferences();if (editorReferences.length > 1) {

PartPane currentEditorPartPane = ((PartSite) workbenc hPage.getActiveEditor().getSite()).getPane();EditorSashContainer editorSashContainer = null;ILayoutContainer rootLayoutContainer = layoutPart.get Container();if (rootLayoutContainer instanceof LayoutPart) {

ILayoutContainer editorSashLayoutContainer = ((Layout Part) rootLayoutContainer).getContainer();if (editorSashLayoutContainer instanceof EditorSashCo ntainer) {

editorSashContainer = ((EditorSashContainer) editorS ashLayoutContainer);}

}

PartStack newPart = createStack(editorSashContainer);editorSashContainer.stack(currentEditorPartPane, ne wPart);if (rootLayoutContainer instanceof LayoutPart) {

ILayoutContainer cont = ((LayoutPart) rootLayoutConta iner).getContainer();

if (cont instanceof PartSashContainer) {// "Split" the editor area by adding the new part((PartSashContainer) cont).add(newPart);

}}

}return null;

}// Suite dans le prochain transparent ...

}

CreateSplitEditorHandler.javadu projet SplitEditorExample

Page 69: Construction d'éditeurs avec la plateforme Eclipse

69Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Diviser un éditeur

� Exemple (suite) : Diviser programmatiquement la zone de

l’éditeur

public class CreateSplitEditorHandler extends Abstra ctHandler {

...

private PartStack createStack(EditorSashContainer edi torSashContainer) {WorkbenchPage workPage = (WorkbenchPage)PlatformUI.ge tWorkbench().getActiveWorkbenchWindow().getActivePa ge();EditorStack newWorkbook = EditorStack.newEditorWorkbo ok(editorSashContainer, workbenchPage);return newWorkbook;

}}

CreateSplitEditorHandler.javadu projet SplitEditorExample

Une grande partie des APIs utilisées sont définies comme

Internal

Page 70: Construction d'éditeurs avec la plateforme Eclipse

70Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Ecouteurs (Part Listeners)

� Les modifications opérées sur un éditeur (activation, visibilité

ou l’ouverture) peuvent être écoutées (principe identique

pour les vues)

� L’activation et la création des éditeurs sont écoutables via

l’interface IPartService implémentées par IWorkbenchPage

� void addPartListener(IPartListener pl) : écouteur « 1ère » version

� void addPartListener(IPartListener2 pl) : écouteur « 2nd » version

� IWorkbenchPart getActivePart() : Part active

� IWorkbenchPartReference getActivePartReference() : Part référence

active

� L’écouteur IPartListener est à remplacer par l’interface

IPartListener2

Page 71: Construction d'éditeurs avec la plateforme Eclipse

71Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Ecouteurs (Part Listeners)

� IPartListener2 fournit les méthodes suivantes pour les

réponses aux événements sur un éditeur

� void partActivated(IWorkbenchPartReference pr) : part activée

� void partBroughtToTop(IWorkbench… pr) : part au premier plan

� void partClosed(IWorkbench… pr) : part fermée

� void partDeactivated(IWorkbench… pr) : part désactivée

� void partHidden(IWorkbench… pr) : part cachée

� void partInputChanged(IWorkbench… pr) : saisie de l’utilisateur

� void partOpened(IWorkbench… pr) : part ouverte

� void partVisible(IWorkbench… pr) : part visible

� L’écoute de certaines modifications propres aux éditeurs n’est

pas pris en compte : show/hide, instances multiples, division

d’un éditeur, …

Page 72: Construction d'éditeurs avec la plateforme Eclipse

72Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Ecouteurs (Part Listeners)

� Exemple : Ecouter les changements d’un EditorPartpublic class LifeCycleEditor extends EditorPart {

public void createPartControl(Composite parent) {...IWorkbenchPage activePage = PlatformUI. getWorkbench().getActiveWorkbenchWindow().getActivePage();activePage.addPartListener(new IPartListener2() {

@Overridepublic void partActivated(IWorkbenchPartReference par tRef) {

IWorkbenchPart part = partRef.getPart(false);if (LifeCycleEditor.this == part) {

System. out.println(".partActivated()");}

}@Overridepublic void partBroughtToTop(IWorkbenchPartReference partRef) {

IWorkbenchPart part = partRef.getPart(false);if (LifeCycleEditor.this == part) {

System. out.println(".partBroughtToTop()");}

}@Overridepublic void partClosed(IWorkbenchPartReference partRe f) {

IWorkbenchPart part = partRef.getPart(false);if (LifeCycleEditor.this == part) {

System. out.println(".partClosed()");}

}...

}}

}

LifeCycleEditor.javadu projet EditorExample

Page 73: Construction d'éditeurs avec la plateforme Eclipse

73Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et les commandes

� Lors de l’activation d’un éditeur il est possible de rendre

accessible des actions spécifiques à ce contexte

� Si l’éditeur n’est plus actif, les actions spécifiques sont

automatiquement cachées

� Exemple : ouverture d’un éditeur de texte

� Rendre accessible des actions comme copier/coller/couper …

� Deux solutions sont à envisager

� Utilisation des restrictions via les commandes (afficher une commande

selon si un éditeur est actif ou pas)

� Utilisation d’un objet IEditorActionBarContributor (à renseigner lors de

la définition de l’extension d’un éditeur)

� Dans la suite, nous utiliserons la seconde solution basée sur

l’utilisation de commandes

Page 74: Construction d'éditeurs avec la plateforme Eclipse

74Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et les commandes

� L’interface IEditorActionBarContributor permet d’ajouter des

actions dans un menu, une barre d’outils et la barre d’états

� void contributeToMenu(IMenuManager mmanager) : pour contribuer à

l’enrichissement de la barre de menu

� void contributeToStatusLine(IStatusLineManager smanager) : pour

contribuer à l’enrichissement de la barre d’états

� void contributeToToolBar(IToolBarManager tmanager) : pour

contribuer à l’enrichissement de la barre d’outils

� Dans les trois cas, possibilité d’ajouter des éléments de type

IContributionItem (CommandContributionItem)

Page 75: Construction d'éditeurs avec la plateforme Eclipse

75Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et les commandes

� Exemple : Contribuer au menu, à la barre d’outils et à la

barre d’états

Lors de l’activation de l’éditeur, des actions sont disponibles dans la barre d’outils (1), la barre d’état (2) et le menu File (3)

1

2

3

Page 76: Construction d'éditeurs avec la plateforme Eclipse

76Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et les commandes

� Exemple (suite) : Contribuer au menu, à la barre d’outils et

à la barre d’états

plugin.xml du projet EditorActionBarContributor

Objet de type EditorWithCommandActionBarContributor

Page 77: Construction d'éditeurs avec la plateforme Eclipse

77Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et les commandes

� Exemple (suite) : Contribuer au menu, à la barre d’outils et

à la barre d’états public class EditorWithCommandActionBarContributor e xtends EditorActionBarContributor {

public void contributeToMenu(IMenuManager menuManage r) {super.contributeToMenu(menuManager);CommandContributionItemParameter commandParameter = n ew CommandContributionItemParameter(

PlatformUI.getWorkbench(), "contributionitem","eclipse.workbench.editorexample.SimpleCommandId",CommandContributionItem.STYLE_PUSH);

IContributionItem ref = new CommandContributionItem( commandParameter);

IMenuManager menu = new MenuManager("Simple Editor");menuManager.prependToGroup(IWorkbenchActionConstant s.MB_ADDITIONS, menu);menuManager.findMenuUsingPath("File").add(ref);

}

public void contributeToStatusLine(IStatusLineManag er statusLineManager) {CommandContributionItemParameter commandParameter = n ew CommandContributionItemParameter(

PlatformUI.getWorkbench(), "contributionitem","eclipse.workbench.editoractionbarcontributorexampl e.samplecommandid",CommandContributionItem.STYLE_PUSH);

IContributionItem ref = new CommandContributionItem( commandParameter);statusLineManager.add(ref);

}

public void contributeToToolBar(IToolBarManager tool BarManager) {CommandContributionItemParameter commandParameter = n ew CommandContributionItemParameter(

PlatformUI.getWorkbench(), "contributionitem","eclipse.workbench.editoractionbarcontributorexampl e.samplecommandid",CommandContributionItem.STYLE_PUSH);

IContributionItem ref = new CommandContributionItem( commandParameter);toolBarManager.add(ref);

}}

EditorWithCommandActionBarContributor.javadu projet EditorActionBarContributor

Page 78: Construction d'éditeurs avec la plateforme Eclipse

78Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Généralités

� La plateforme Eclipse s’appuie sur le Workspace pour

stocker les fichiers qu’il manipule

� Le Workspace est un répertoire hiérarchique physique qui

contient une collection de ressources

� Projets, répertoires et fichiers

� Le Workspace sert également à stocker les paramètres des

plugins (répertoire .metadata)

� Paramètres définis par les préférences de l’utilisateur

� Agencement de l’espace de travail (perspectives, projets ouverts, …)

� Pourquoi discuter du Workspace ici ?

� L’éditeur manipulent essentiellement des ressources

� Besoin de notifications sur les changements des ressources

Page 79: Construction d'éditeurs avec la plateforme Eclipse

79Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Généralités

� Structure d’un Workspace Eclipse

Répertoire contenant des informations liées aux plugins

Ressources de type projet

Fichier .log utilisépour stocker les

messagesInformations liées

aux plugins

Ressources de type dossier et fichier

Page 80: Construction d'éditeurs avec la plateforme Eclipse

80Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Généralités

� Exemple : Localiser l’emplacement du Workspace

public class WorkspaceViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button location = new Button(parent, SWT.FLAT);location.setText("Workspace location ...");location.addSelectionListener(new SelectionAdapter() {

@Overridepublic void widgetSelected(SelectionEvent e) {

Location instanceLoc = Platform.getInstanceLocation( );

System.out.println(instanceLoc.getURL().toString()) ;}

});...

}}

WorkspaceViewPart.javadu projet WorkspaceExample

Page 81: Construction d'éditeurs avec la plateforme Eclipse

81Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Généralités

� Exemple : Forcer la sélection du Workspace au démarrage

d’une application Eclipse

Avec l’option -data @noDefault, la plateforme Eclipse demandera àchaque démarrage l’emplacement

du Workspace

WorkspaceExampleConfiguration.launchdu projet WorkspaceExample

Page 82: Construction d'éditeurs avec la plateforme Eclipse

82Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource

� La plateforme Eclipse fournit des APIs pour la création, la

navigation et la manipulation de ressources dans un

Workspace

� Le plugin org.eclipse.core.resources fournit ces APIs

(dépendance obligatoire)

� Des méta-données sont associées aux ressources

� Properties (session et persistent)

� Preferences

� Content types

� Linked resources (attaché un fichier à un projet qui n’est pas localisé

dans le Workspace)

� Markers (task, problem, text, bookmark)

Page 83: Construction d'éditeurs avec la plateforme Eclipse

83Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource

� Cartes des principales interfaces concernant les ressources

IResource

getName()

getParent()

getWorkspace()

getFullPath()

IContainer

members()

exists(IPath)

IProject

open(int, IProgressMonitor)

create(IProgressMonitor)

close(IProgressMonitor)

IFolder

getFile(String)

create(boolean, boolean, IProgressMonitor)

createLink(URI, int, IProgressMonitor)

delete(boolean, boolean, IProgressMonitor)

IWorkspaceRoot

getProjects()

getProject(String)

delete(boolean, boolean, IProgressMonitor)

IWorkspace

addResourceChangeListener(IResourceChangeListener)

build(int, IProgressMonitor)

isAutoBuilding()

getRoot()

IFile

create(InputStream, int, IProgressMonitor)

createLink(URI, int, IProgressMonitor)

delete(boolean, boolean, IProgressMonitor)

IPath

toFile()

Dépendance

Héritage

Page 84: Construction d'éditeurs avec la plateforme Eclipse

84Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Resource / IWorkspaceRoot

� Le Workspace est défini par l’interface IWorkspace et il n’y

a qu’un seul workspace par application Eclipse

� Pour récupérer le workspace de l’application Eclipse en cours

� IWorkspace permet l’écoute des changements sur les res-

sources d’un workspace (détaillée plus tard)

� Il permet également de récupérer un objet IWorkspaceRoot

autorisant l’accès à l’ensemble des projets

� Principales méthodes de IWorkspaceRoot

� IProject getProject(String) : récupère un projet par son nom

� IProject[] getProjects() : récupère tous les projets

IWorkspace current = ResourcesPlugin.getWorkspace();

IWorkspaceRoot currentRoot = ResourcesPlugin.getWorks pace().getRoot();

Page 85: Construction d'éditeurs avec la plateforme Eclipse

85Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Resource / IWorkspaceRoot

� Exemple : Lister l’ensemble des projets d’un Workspacepublic class WorkspaceViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button projects = new Button(parent, SWT.FLAT);projects.setText("Workspace location ...");projects.addSelectionListener(new SelectionAdapter() {

@Overridepublic void widgetSelected(SelectionEvent e) {

IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject[] projects = root.getProjects();for (IProject iProject : projects) {

System.out.println(iProject.getName());}

}});...

}}

WorkspaceViewPart.javadu projet WorkspaceExample

Page 86: Construction d'éditeurs avec la plateforme Eclipse

86Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / IProject

� L’interface IProject définit le concept de projet

� Principales caractéristiques d’un projet Eclipse

� Un projet est un conteneur et contient des dossiers et des fichiers

� Un projet peut construire des ressources

� Un projet peut avoir des références vers d’autres projets

� Un projet peut avoir une ou plusieurs natures (voir plus tard)

� Un projet contient des méta-données (IProjectDescription)

� Différentes méthodes …

� void create(IProgressMonitor) : crée du projet

� void open(IProgessMonitor) : ouvre un projet

� IProjectDescription getDescription() : récupère les méta-datas

� IFolder getFolder(String) : retourne un dossier

� IFile getFile(String) : retourne un fichier

� + méthodes fournies par IContainer

Page 87: Construction d'éditeurs avec la plateforme Eclipse

87Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / IProject

� Exemple : Manipulation de ressource IProjectpublic class WorkspaceViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button createProject = new Button(parent, SWT.FLAT);createProject.setText("Create new Project ...");createProject.addSelectionListener(new SelectionAdap ter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject project4 = root.getProject("Project 4" );try {

project4.create(null);project4.open(null);

final IProjectDescription description = project4.get Description();description.setComment("This is a simple project");final IProject project1 = root.getProject("Project 1" );final IProject project2 = root.getProject("Project 2" );

IProject[] tabProjects = {project1, project2};description.setReferencedProjects(tabProjects);

project4.setDescription(description, null);} catch (CoreException e1) {

e1.printStackTrace();}

}});...

}}

WorkspaceViewPart.javadu projet WorkspaceExample

Page 88: Construction d'éditeurs avec la plateforme Eclipse

88Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / IProject

� Les informations décrit dans IProjectDescription sont

stockées dans le fichier .project

<?xml version="1.0" encoding="UTF-8"?><projectDescription>

<name>Project 4</name>

<comment>This is a simple project</comment>

<projects><project>Project 1</project><project>Project 2</project>

</projects>

<buildSpec></buildSpec>

<natures></natures>

</projectDescription>

Nom du projet

Commentaire du projet

Liste des projets référencés

Liste des Builders

Liste des Natures Fichier .project du répertoire Project 4

Page 89: Construction d'éditeurs avec la plateforme Eclipse

89Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / IFolder

� L’interface IFolder décrit un dossier localisé dans un projet

� Un objet IFolder est un conteneur et contient des fichiers et des dossiers

� Différentes méthodes …

� void create(boolean, boolean, IProgressMonitor) : création du dossier

� IFile getFile(String) : retourne un fichier

� IFolder getFolder(String) : retour un dossier

� + méthodes fournies par IContainer

� L’interface IFile décrit un fichier

� void create(InputStream, boolean, IProgressMonitor) : création du fichier

� InputStream getContents() : retourne le contenu

� IPath getFullPath() : retourne le chemin

� + méthodes fournis par IResource

Page 90: Construction d'éditeurs avec la plateforme Eclipse

90Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / IFolder

� Exemple : Manipulation de ressources IFolder et IFilepublic class WorkspaceViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button createFolder = new Button(parent, SWT.FLAT);createFolder.setText("Create new Folder and File ... ");createFolder.addSelectionListener(new SelectionAdapt er() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject project4 = root.getProject("Project 4" );

try {final IFolder folderA = project4.getFolder("Folder A" );folderA.create(true, true, null);

IFile fileA = project4.getFile("File A.txt");fileA.create(new ByteArrayInputStream("HelloWorld fro m File A".getBytes()), true, null);

IFile fileB = folderA.getFile("File B.txt");fileB.create(new ByteArrayInputStream("HelloWorld fro m File B".getBytes()), true, null);

System.out.println(fileA.getFullPath());

} catch (CoreException e1) {e1.printStackTrace();

}}

}); ...}

}

WorkspaceViewPart.javadu projet WorkspaceExample

Page 91: Construction d'éditeurs avec la plateforme Eclipse

91Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Les propriétés (Properties) sont utilisées pour attacher des

informations (méta-données) aux ressources

� Tous les objets de type IResource sont concernés (IProject,

IFolder, IFile et IWorkspaceRoot)

� Quand une ressource est supprimée, ses propriétés sont

effacées également

� Deux types de propriétés sont à distinguer

� Propriétés de session

� Propriétés persistantes

� L’API de manipulation est fournie par l’interface IResource

Page 92: Construction d'éditeurs avec la plateforme Eclipse

92Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Propriétés de session

� Permet de sauvegarder des informations dans un couple clé / valeur

� Les valeurs peuvent être des objets

� Les propriétés sont maintenues en mémoire

� Les propriétés sont supprimées quand une ressource est supprimée

ou quand un projet ou un workspace est fermé

� Map IResource#getSessionProperties() : propriétés en session

� Propriétés de persistances

� Sauvegarde les informations physiquement sur le disque

� Les valeurs sont obligatoirement des chaînes de caractères

� Les chaînes de caractères sont prévues pour être courtes

� Les propriétés sont maintenues même au redémarrage de la

plateforme

� Map IResource#getPersistentProperties() : propriétés persistantes

Page 93: Construction d'éditeurs avec la plateforme Eclipse

93Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Exemple : Manipulation des propriétés de session

public class PropertiesViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button saveSessionPropertiesButton = new Button(pare nt, SWT.FLAT);saveSessionPropertiesButton.setText("Save Session Pr operties ...");saveSessionPropertiesButton.addSelectionListener(ne w SelectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();

final IProject project5 = root.getProject(projectNam e);

try {if (!project5.exists()) {

project5.create(null);project5.open(null);

}project5.setSessionProperty(new QualifiedName("sess ion_test", "en"), "test");

} catch (Exception e1) {e1.printStackTrace();

}}

});...

}}

PropertiesViewPart.javadu projet WorkspaceExample

Enregistrement d’une propriété« session_test » dans la session d’un projet

Si le projet est fermé, workspacerechargé ou application redémarrée, la

propriété est perdue

Page 94: Construction d'éditeurs avec la plateforme Eclipse

94Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Exemple (suite) : Manipulation des propriétés de session

public class WorkspaceViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button loadSessionPropertiesButton = new Button(pare nt, SWT.FLAT);loadSessionPropertiesButton.setText("Load Session Pr operties ...");loadSessionPropertiesButton.addSelectionListener(ne w SelectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject project5 = root.getProject(projectNam e);

try {final Map sessionProperties = project5.getSessionPro perties();System.out.println(sessionProperties.get(new Qualifi edName("session_test", "en")));

} catch (CoreException e1) {e1.printStackTrace();

}}

});...

}}

PropertiesViewPart.javadu projet WorkspaceExample

Chargement de la propriété« session_test »

Page 95: Construction d'éditeurs avec la plateforme Eclipse

95Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Exemple : Manipulation des propriétés persistances

public class PropertiesViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button savePersistentPropertiesButton = new Button(p arent, SWT.FLAT);savePersistentPropertiesButton.setText("Save Persist ence Properties ...");savePersistentPropertiesButton.addSelectionListener (new SelectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject project5 = root.getProject(projectNam e);

try {if (!project5.exists()) {

project5.create(null);}

project5.setPersistentProperty(new QualifiedName("p ersistent_test", "en"), "test");} catch (CoreException e1) {

e1.printStackTrace();}

}});

}}

PropertiesViewPart.javadu projet WorkspaceExample

Enregistrement d’une propriété« persistent_test » dans un projet en

mode persistant

Si le projet est fermé, workspacerechargé ou application redémarrée, la

propriété reste présente

Page 96: Construction d'éditeurs avec la plateforme Eclipse

96Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Properties

� Exemple (suite) : Manipulation des propriétés persistances

public class PropertiesViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button loadPersistentPropertiesButton = new Button(p arent, SWT.FLAT);loadPersistentPropertiesButton.setText("Load Persist ence Properties ...");loadPersistentPropertiesButton.addSelectionListener (new SelectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject project5 = root.getProject(projectNam e);

try {final Map persistentProperties = project5.getPersist entProperties();System.out.println(persistentProperties.get(new Qual ifiedName("persistent_test", "en")));

} catch (CoreException e1) {e1.printStackTrace();

}}

});}

}

PropertiesViewPart.javadu projet WorkspaceExample

Chargement de la propriété« persistent_test »

Page 97: Construction d'éditeurs avec la plateforme Eclipse

97Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Les markers sont un mécanisme permettant d’annoter une ressource

� Les markers peuvent s’appliquer autant sur les projets que les dossiers et les fichiers

� La plateforme Eclipse définit cinq types de markers

� Marker : annotation de base

� Task : annotation de type tâche

� Problem : annotation de type problème

� Text : annotation de type texte

� Bookmark : annotation de type favori

� Possibilité de définir ses propres markers en utilisant le point d’extension org.eclipse.core.resources.markers

� Les types de markers sont hiérarchiques et des niveaux d’héritage peuvent être définis

Page 98: Construction d'éditeurs avec la plateforme Eclipse

98Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

Markers de type Problem avec deux niveaux de sévérité : Error et Warning

� Exemple : Des Markers de types Problem et Task

Markers de type Task

Page 99: Construction d'éditeurs avec la plateforme Eclipse

99Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Un marker est défini par l’interface IMarker

� La création d’un marker est réalisé à partir d’un objet de

type IResource

� Opérations basiques (méthodes de IResource)

� IMarker createMarker(String) : création d’un marker à partir d’un

identifiant (Task, Bookmark, …)

� void deleteMarkers(String t, boolean, int) : supprime tous les markers

définis par le type t

� Principales méthodes de IMarker

� void delete() : supprimer un marker

� Une série setAttribute(String, boolean || int || Object) : permettant

d’affecter des valeurs à des attributs prédéfinis

Page 100: Construction d'éditeurs avec la plateforme Eclipse

100Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� L’interface IMarker définit un ensemble d’attributs et de

valeurs d’attributs pour les types de marker prédéfinis

� SEVERITY : niveau de sévérité (#SEVERITY_ERROR,

#SEVERITY_WARNING, #SEVERITY_INFO)

� MESSAGE : description du marker (nom d’une tâche)

� LOCATION : information pour distinguer deux markers

� PRIORITY : niveau de priorité (#PRIORITY_HIGH,

#PRIORITY_NORMAL, #PRIORITY_LOW)

� DONE : marker est considéré terminé

� CHAR_START et CHAR_END : intervalle impacté

� LINE_NUMBER : numéro de line impacté

� USER_EDITABLE : modification autorisé ou pas

Page 101: Construction d'éditeurs avec la plateforme Eclipse

101Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Exemple : Création d’une annotation de type Task

Les tâches sont visibles dans la vue Tasks

Depuis l’éditeur, une annotation précise qu’une tâche est associée à la ligne 2

Tâche annotée àune ressource de

type fichier

Page 102: Construction d'éditeurs avec la plateforme Eclipse

102Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Exemple (suite) : Création d’une annotation de type Taskpublic class MarkersViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button createTasks = new Button(parent, SWT.FLAT);createTasks.setText("Create Tasks ...");createTasks.addSelectionListener(new SelectionAdapte r() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject projectMarkers= root.getProject("Proj ect Markers");try {

if (!projectMarkers.exists()) {projectMarkers.create(null);projectMarkers.open(null);

}final IFile file = projectMarkers.getFile("file");if (!file.exists()) {

file.create(new ByteArrayInputStream("HelloWorld\nThis is a text for Markers example".getBytes()), IR esource.NONE, null);

}

IMarker createTaskMarker = file.createMarker(IMarker. TASK);createTaskMarker.setAttribute(IMarker.MESSAGE, "Sam ple Task message");createTaskMarker.setAttribute(IMarker.PRIORITY, IMa rker.PRIORITY_LOW);createTaskMarker.setAttribute(IMarker.USER_EDITABLE , false);createTaskMarker.setAttribute(IMarker.LINE_NUMBER, 2);

} catch (Exception e1) {e1.printStackTrace();

}}

});}

}

MarkersViewPart.javadu projet WorkspaceExample

Page 103: Construction d'éditeurs avec la plateforme Eclipse

103Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Exemple : Création d’une annotation de type Problem

Les problèmes sont visibles dans la vue Problems

Depuis l’éditeur, une annotation précise que des problèmes sont associés à la ligne 2

Problèmes annotés à une ressource de

type fichier

Page 104: Construction d'éditeurs avec la plateforme Eclipse

104Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Exemple (suite) : Création d’une annotation de type Problem

public class MarkersViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button createProblems = new Button(parent, SWT.FLAT) ;createProblems.createTasks.setText("Create Tasks ... ");createProblems.addSelectionListener(new SelectionAda pter() {

public void widgetSelected(SelectionEvent e) {...try {

IMarker createErrorProblemMarker = file.createMarker( IMarker.PROBLEM);createErrorProblemMarker.setAttribute(IMarker.MESSA GE, "Sample Error Problem message");createErrorProblemMarker.setAttribute(IMarker.SEVER ITY, IMarker.SEVERITY_ERROR);createErrorProblemMarker.setAttribute(IMarker.PRIOR ITY, IMarker.PRIORITY_LOW);createErrorProblemMarker.setAttribute(IMarker.LINE_ NUMBER, 2);

IMarker createWarningProblemMarker = file.createMarke r(IMarker.PROBLEM);createWarningProblemMarker.setAttribute(IMarker.MES SAGE, "Sample Warning Problem message");createWarningProblemMarker.setAttribute(IMarker.SEV ERITY, IMarker.SEVERITY_WARNING);createWarningProblemMarker.setAttribute(IMarker.PRI ORITY, IMarker.PRIORITY_HIGH);createWarningProblemMarker.setAttribute(IMarker.LIN E_NUMBER, 2);

} catch (Exception e1) {e1.printStackTrace();

}}

});}

}

MarkersViewPart.javadu projet WorkspaceExample

Page 105: Construction d'éditeurs avec la plateforme Eclipse

105Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

� Exemple : Création d’une annotation de type BookmarkDepuis l’éditeur, une annotation précise qu’un

favori est associé à la ligne 2

Les favoris sont visibles dans la vue Bookmarks

Page 106: Construction d'éditeurs avec la plateforme Eclipse

106Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Resource / Markers

public class MarkersViewPart extends ViewPart {

public void createPartControl(Composite parent) {...Button createBookmarks = new Button(parent, SWT.FLAT );createBookmarks.createTasks.setText("Create Tasks .. .");createBookmarks.addSelectionListener(new SelectionAd apter() {

public void widgetSelected(SelectionEvent e) {...try {

IMarker createErrorProblemMarker = file.createMarker( IMarker.BOOKMARK);createErrorProblemMarker.setAttribute(IMarker.MESSA GE, "Sample Bookmark message");createErrorProblemMarker.setAttribute(IMarker.LINE_ NUMBER, 2);

} catch (Exception e1) {e1.printStackTrace();

}}

});}

}

MarkersViewPart.javadu projet WorkspaceExample

� Exemple (suite) : Création d’une annotation de type

Bookmark

Page 107: Construction d'éditeurs avec la plateforme Eclipse

107Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Builder

� Un Builder (constructeur) est un objet qui manipule les

ressources d’un projet pour produire d’autres ressources

� Cette opération s’appelle un Build ou une construction

� La plateforme définit deux types de construction

� Une construction complète (full build) : manipule toutes les ressources

même si aucune modification n’a été apportée sur ces ressources

� Une construction incrémentale (incremental build) : s’appuie sur les

précédentes constructions pour traiter les ressources modifiées

� Les constructions incrémentales s’appuient sur des objets de

type IResourceDelta pour distinguer les changements d’une

ressource

� Le nettoyage d’un projet (Clean) force un builder à procéder

à une construction complète

Page 108: Construction d'éditeurs avec la plateforme Eclipse

108Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Builder

� Une construction (complète ou incrémentale) se déclenche

� De manière automatique (si l’option Build Automatically est activée)

à chaque modification opérée sur le workspace

� A la demande explicite du développeur (Build Project, Build All)

� Lors du démarrage d’un builder des artefacts peuvent être

générés

� Des ressources (projet, dossier ou des fichiers)

� Des markers (tâches, problèmes, …)

� Une ressource générée est appelée ressource dérivée

� Une construction est encapsulée dans un processus

extérieur de manière à

� éviter le blocage

� assurer l’annulation de la construction

Page 109: Construction d'éditeurs avec la plateforme Eclipse

109Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Builder / Exemple JDT

� Le projet JDT (Java Development Tool) utilise un builder

pour compiler les classes Java d’un projet

� Construction complète via JDT

� Toutes les classes Java (ressources) sont compilées

� Les fichiers .class (ressources dérivées) sont stockés dans le réper-

toire bin

� Les problèmes de compilation sont ajoutées comme des markers de

type Problem

� Construction incrémentale via JDT

� Seules les classes modifiées sont recompilées (utilisation des

IResourceDelta)

� Mise à jour de la liste des markers de type Problem

Page 110: Construction d'éditeurs avec la plateforme Eclipse

110Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Builder

� Un builder peut être déclenché explicitement via les

méthodes suivantes

� IProject#build(…) : demande un démarrage d’une construction avec

possibilité de choisir son builder (voir paramètres)

� IWorkspace#build(…) : demande un démarrage d’une construction

de tous les projets du workspace

� Les commandes utilisées dans le Workbench permettent

d’appeler directement ces méthodes

� Lors de l’appel de ces méthodes, des builders sont déclen-

chés. Si aucun builder n’a été défini aucune construction ne

sera réalisée

Page 111: Construction d'éditeurs avec la plateforme Eclipse

111Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Création d’une extension à org.eclipse.core.resources.builders

Utilisation du point d’extension org.eclipse.core.resources.builders

Template existant pour les constructeurs

Page 112: Construction d'éditeurs avec la plateforme Eclipse

112Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Edition des attributs de l’extension builders

Préciser l’identifiant de l’extension de manière à manipuler le builder par la suite

plugin.xmldu projet BuilderExample

Page 113: Construction d'éditeurs avec la plateforme Eclipse

113Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Edition des attributs de l’extension builders (suite)Précise si le constructeur est associé à

une nature (voir plus tard)

Si à vraie, déclenche une construction incrémentale même s’il

n’y a aucun changementplugin.xmldu projet BuilderExample

Page 114: Construction d'éditeurs avec la plateforme Eclipse

114Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Création de la classe du builder

Définition de la classe où sera codée le traitement du builder

plugin.xmldu projet BuilderExample

Classe de type IncrementalProjectBuilder

Page 115: Construction d'éditeurs avec la plateforme Eclipse

115Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer des paramètres au builder

Deux paramètres sont associés au builder

plugin.xmldu projet BuilderExample

Page 116: Construction d'éditeurs avec la plateforme Eclipse

116Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Classe du builder personnaliséepublic class CustomIncrementalProjectBuilder extends IncrementalProjectBuilder {

protected IProject[] build(int kind, Map args, IProg ressMonitor monitor) throws CoreException {if (kind == IncrementalProjectBuilder.FULL_BUILD) {

fullBuild(monitor);} else {

IResourceDelta delta = getDelta(getProject());if (delta == null) {

fullBuild(monitor);} else {

incrementalBuild(delta, monitor);}

}return null;

}

protected void fullBuild(final IProgressMonitor monit or) throws CoreException {try {

final IFolder folder = this.getProject().getFolder(" My Bin");if (!folder.exists()) {

folder.create(true, true, null);}

getProject().accept(new MyBuildVisitor());} catch (CoreException e) {}

}

protected void incrementalBuild(IResourceDelta delta , IProgressMonitor monitor) throws CoreException {delta.accept(new MyBuildDeltaVisitor());

}...

CustomIncrementalProjectBuilder.javadu projet BuilderExample

Selon le type de builderdes traitements

particuliers sont réalisés

Au niveau du full build un répertoire My Bin est créé

Un Visiteur est utilisé pour parcourir chaque ressource de la

construction et réaliser les opérations adéquates

Page 117: Construction d'éditeurs avec la plateforme Eclipse

117Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Classe du builder personnalisée (suite)

public class CustomIncrementalProjectBuilder extends IncrementalProjectBuilder {

class MyBuildVisitor implements IResourceVisitor {public boolean visit(IResource res) {

System.out.println("Full " + res.getName());return true;

}}

class MyBuildDeltaVisitor implements IResourceDeltaV isitor {public boolean visit(IResourceDelta res) {

System.out.println("Incremental " + res.getKind() + " " + res.getResource().getName());return true;

}}

protected void clean(IProgressMonitor monitor) throw s CoreException {final IFolder folder = this.getProject().getFolder(" My Bin");if (folder.exists()) {

folder.delete(true, null);}

}}

CustomIncrementalProjectBuilder.javadu projet BuilderExample

Ce visiteur donne accès àchaque IResource « balayée »

par le full build

Ce visiteur donne accès à chaque IResourceDelta « balayée » par

l’incremental build

La catégorie permet de savoir quelle modification a été apportée à la ressource (voir constante dans IResourceDelta)

L’opération de nettoyage efface le répertoire créé dans le full build

Page 118: Construction d'éditeurs avec la plateforme Eclipse

118Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer un builder personnalisé à un projet

public class BuilderViewPart extends ViewPart {

public void createPartControl(Composite parent) {parent.setLayout(new GridLayout());

Button createTasks = new Button(parent, SWT.FLAT);createTasks.setText("Associate Builder ...");createTasks.addSelectionListener(new SelectionAdapte r() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();

final IProject projectBuilder = root.getProject("Proj ect Builder");

try {if (!projectBuilder.exists()) {

projectBuilder.create(null);projectBuilder.open(null);

}

final IFile file = projectBuilder.getFile("file 1");if (!file.exists()) {

file.create(new ByteArrayInputStream("HelloWorld\n Th is is text for Builder examples".getBytes()), IResource.NONE, null);

}

...

BuilderViewPart.javadu projet BuilderExample

Création d’un projet et d’un fichier

Page 119: Construction d'éditeurs avec la plateforme Eclipse

119Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer un builder personnalisé à un projet (suite)

public class BuilderViewPart extends ViewPart {

public void createPartControl(Composite parent) {...

final String BUILDER_ID = "eclipse.workbench.Builde rExample.samplebuilderid";

IProjectDescription desc = projectBuilder.getDescript ion();ICommand[] commands = desc.getBuildSpec();

// Add builder to projectICommand command = desc.newCommand();command.setBuilderName(BUILDER_ID);ICommand[] newCommands = new ICommand[commands.lengt h + 1];

// Add it before other builders.System.arraycopy(commands, 0, newCommands, 1, comma nds.length);newCommands[0] = command;desc.setBuildSpec(newCommands);projectBuilder.setDescription(desc, null);

} catch (Exception e1) {e1.printStackTrace();

}}

});}

}

BuilderViewPart.javadu projet BuilderExample

Identifiant du builder = identifiant plugin + identifiant extension du builder

Page 120: Construction d'éditeurs avec la plateforme Eclipse

120Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer un builder personnalisé à un projet (suite)

Un dossier a été ajoutélors du full build

Toutes les ressources sont « visitées »

Page 121: Construction d'éditeurs avec la plateforme Eclipse

121Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer un builder personnalisé à un projet (suite)

Le contenu du fichier file1a été mis à jour

Deux ressources ont étémodifiées

Page 122: Construction d'éditeurs avec la plateforme Eclipse

122Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Builder / Définir son Builder

� Associer un builder personnalisé à un projet (suite)

Le fichier file1 a été déplacé

Des ressources ont été modifiées, ajoutée (nouveau file 1) et supprimée (ancien file 1)

Page 123: Construction d'éditeurs avec la plateforme Eclipse

123Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature

� Associer un builder à un projet doit être réalisé une seule

fois, habituellement quand le projet est créé

� La plateforme Eclipse préconise d’associer un builder à un

projet en passant par la notion de nature

� De manière plus générale une nature est utilisée également

pour créer une association entre un projet et des plugins

� En ajoutant une nature à un projet, vous précisez que des

plugins sont configurés à utiliser ce projet

� Ce mécanisme de nature peut être ainsi utilisé pour ajouter

un comportement spécifique à des projets

Page 124: Construction d'éditeurs avec la plateforme Eclipse

124Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature / Exemple JDT

� Le projet JDT (Java Development Tool) utilise une nature

pour définir des comportements spécifiques pour les projets

Java

� Fonctionnalités de la nature Java

� Tous les plugins JDT sont ainsi associés aux projets Java

� Un classpath a été configuré

� Un builder propre au langage Java est défini

� Les icônes des ressources contenant du Java sont modifiés pour les

distinguer des autres ressources

� Des actions sur les différents menus peuvent être visibles ou

masquées

Page 125: Construction d'éditeurs avec la plateforme Eclipse

125Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Création d’une extension à org.eclipse.core.resources.natures

Utilisation du point d’extension org.eclipse.core.resources.natures

Page 126: Construction d'éditeurs avec la plateforme Eclipse

126Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Edition des attributs de l’extension nature

Préciser l’identifiant de l’extension de manière à manipuler le builder par la suite

plugin.xmldu projet NatureExample

Page 127: Construction d'éditeurs avec la plateforme Eclipse

127Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Associer une nature à un projet

public class NatureViewPart extends ViewPart {public void createPartControl(Composite parent) {

parent.setLayout(new GridLayout());

Button createNature = new Button(parent, SWT.FLAT);createNature.setText("Associate Nature (add Builder by code ...");createNature.addSelectionListener(new SelectionAdapt er() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject projectNature = root.getProject("Proje ct Nature");

try {if (!projectNature.exists()) {

projectNature.create(null);projectNature.open(null);

}

final IFile file = projectNature.getFile("file 1");if (!file.exists()) {

file.create(new ByteArrayInputStream("HelloWorld\n Th is is text for Nature examples".getBytes()), IResource.NONE, null);

}...

}}

NatureViewPart.javadu projet NatureExample

Création d’un projet et d’un fichier

Page 128: Construction d'éditeurs avec la plateforme Eclipse

128Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Associer une nature à un projet (suite)

public class NatureViewPart extends ViewPart {

public void createPartControl(Composite parent) {...

IProjectDescription description = projectNature.getD escription();String[] natures = description.getNatureIds();String[] newNatures = new String[natures.length + 1];System.arraycopy(natures, 0, newNatures, 0, natures .length);newNatures[natures.length] = "eclipse.workbench.Nat ureExample.samplenatureid";

description.setNatureIds(newNatures);projectNature.setDescription(description, null);

} catch (Exception e1) {e1.printStackTrace();

}}

});}

}

NatureViewPart.javadu projet NatureExample

Identifiant de la nature = identifiant plugin + identifiant extension de la nature

Page 129: Construction d'éditeurs avec la plateforme Eclipse

129Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Création de la classe de la natureDéfinition de la classe où sera codé le traitement de la configuration de la nature vis-à-vis des projets

plugin.xmldu projet NatureExample

Classe de type IProjectNature

Page 130: Construction d'éditeurs avec la plateforme Eclipse

130Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Un objet de type IProjectNature fournit des méthodes pour

l’installation et la désinstallation d’une nature

� void configure() : configure une nature pour un projet

� void unconfigure() : dé-configure une nature

� IProject getProject() : retourne le projet associé à la nature

� void setProject(IProject project) : modifie le projet associé à la nature

� Que faire dans configure/unconfigure ?

� Installation/désinstallation d’un builder

� Création/suppression d’attributs supplémentaires

� Plusieurs projets peuvent être associés à un même type de

nature (IProjectNature)

Page 131: Construction d'éditeurs avec la plateforme Eclipse

131Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Exemple : Associer un builder à une naturepublic class CustomProjectNature implements IProject Nature {

private IProject current;

public void configure() throws CoreException {final String BUILDER_ID = "eclipse.workbench.Builde rExample.samplebuilderid";IProjectDescription desc = current.getDescription();ICommand[] commands = desc.getBuildSpec();

// Add builder to projectICommand command = desc.newCommand();command.setBuilderName(BUILDER_ID);ICommand[] newCommands = new ICommand[commands.lengt h + 1];

// Add it before other builders.System.arraycopy(commands, 0, newCommands, 1, comma nds.length);newCommands[0] = command;desc.setBuildSpec(newCommands);current.setDescription(desc, null);

}

public void deconfigure() throws CoreException {// Code permettant la suppression du builder ...

}

public IProject getProject() {return current;

}

public void setProject(IProject project) {this.current = project;

}}

CustomProjectNature.javadu projet NatureExample

IProjectDescription sert àpréciser les natures à utiliser

sur un projet

Page 132: Construction d'éditeurs avec la plateforme Eclipse

132Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comWorkspace : Nature / Définir sa nature

� Exemple : Définir l’icône d’un projet en fonction de la nature

plugin.xmldu projet NatureExample

Création de l’extension org.eclipse.ui.ide.projectNatureImages

Préciser l’identifiant de la naturepuis l’image à afficher

Nécessite que le plugin org.eclipse.ui.ide soit ajouté

comme dépendance

Page 133: Construction d'éditeurs avec la plateforme Eclipse

133Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature / Contraintes

� Des natures définies sur un projet peuvent être activées

sous certaines conditions (suivant des contraintes)

� Deux types de contraintes sont disponibles

� one-of-nature : spécifie qu’il ne peut y avoir qu’une seule nature pour

un projet

� requires-nature : spécifie qu’une nature dépend d’une autre nature et

ne peut être ajoutée à un projet que si l’autre nature est associée

également au projet

� Exemple via la contrainte requires-nature

� Un plugin ou outils ne peut être associé aux projets dont la nature

JDT est associée

� Les contraintes sont définies directement au niveau des

extensions des natures

Page 134: Construction d'éditeurs avec la plateforme Eclipse

134Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature / Contraintes

� Exemple : Définir une contrainte requires-nature

plugin.xmldu projet NatureExample

Identifiant de la nature requise (Ici il s’agit de la nature pour

gérer les projets Java)

Ajout d’un élément de type requires-nature à la définition

d’un nature

Page 135: Construction d'éditeurs avec la plateforme Eclipse

135Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature / Contraintes

� Exemple (suite) : Définir une contrainte requires-nature

public class NatureViewPart extends ViewPart {public void createPartControl(Composite parent) {

parent.setLayout(new GridLayout());

Button createRequiresNature = new Button(parent, SWT .FLAT);createRequiresNature.setText("Associate Nature (add Builder by code ...");createRequiresNature.addSelectionListener(new Select ionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkspaceRoot root = ResourcesPlugin.getWorkspace() .getRoot();final IProject projectNature = root.getProject("Proje ct Requires Nature");

try {if (!projectNature.exists()) {

projectNature.create(null);projectNature.open(null);

}

final IFile file = projectNature.getFile("file 1");if (!file.exists()) {

file.create(new ByteArrayInputStream("HelloWorld\n Th is is text for Nature examples".getBytes()), IResource.NONE, null);

}...

}}

NatureViewPart.javadu projet NatureExample

Page 136: Construction d'éditeurs avec la plateforme Eclipse

136Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Workspace : Nature / Contraintes

public class NatureViewPart extends ViewPart {

public void createPartControl(Composite parent) {...

IProjectDescription description = projectNature.getD escription();String[] natures = description.getNatureIds();String[] newNatures = new String[natures.length + 1];System.arraycopy(natures, 0, newNatures, 0, natures .length);newNatures[natures.length] = "eclipse.workbench.Nat ureExample.samplerequiresnaturesid";IStatus status = ResourcesPlugin.getWorkspace().vali dateNatureSet(newNatures);

if (status.getCode() == IStatus.OK) {description.setNatureIds(newNatures);projectNature.setDescription(description, null);

} else {System.out.println("Cannot enable this nature, natur e is required.");

}} catch (Exception e1) {

e1.printStackTrace();}

}});

}}

� Exemple (suite) : Définir une contrainte requires-nature

NatureViewPart.javadu projet NatureExample

Vérifie si les natures sont valides avant de les imposer aux projets

Comme la nature Java n’est pas associée au projet, une erreur

est retournée

Page 137: Construction d'éditeurs avec la plateforme Eclipse

137Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte

� Dans la suite, nous allons étudier en détail un éditeur qui

manipule du texte via la classe TextEditor

� Nous allons montrer comment enrichir un éditeur de texte

en ajoutant

� une coloration syntaxique

� un assistant de contenu (content assist)

� utilisation de patron

� vérification lexicale (spell checking)

� plan du contenu (outline)

� hiérarchiser du texte (folding)

� Par ailleurs, nous allons capitaliser la plupart des éléments

étudiés précédemment pour développer un exemple complet

Page 138: Construction d'éditeurs avec la plateforme Eclipse

138Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : exemple

� Définition d’un éditeur pour la sauvegarde de mot de passe

Les mots clés sont en gras La vue Outline est utilisée pour visualiser le contenu de l’éditeur

Utilisation de l’assistant de contenu pour insérer des mots clés et des templates

Page 139: Construction d'éditeurs avec la plateforme Eclipse

139Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : TextEditor par extension

� Définir un extension basée sur le point d’extension

org.eclipse.ui.editors

� Définir les attributs de l’extension

� Implémenter une classe qui hérite de TextEditor

� Fournir une icône pour dissocier l’éditeur

� Connecter le menu et la barre de menu à l’implémentation par défaut

� TextEditorActionContributor

� Ajouter les dépendances suivantes dans Require-Bundle

� org.eclipse.jface.text

� org.eclipse.ui.workbench.texteditor

� org.eclipse.ui.editors

Page 140: Construction d'éditeurs avec la plateforme Eclipse

140Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : hiérarchie du TextEditor

� Classe AbstractTextEditor

� Chercher / Remplacer, navigateur hypertexte

� Classe StatusTextEditor

� Afficher une barre d’état

� Classe AbstractDecoratedTextEditor

� Numéro de lignes, change ruler, overview ruler, surbrillance de la sélection, …

� Classe TextEditor

� L’éditeur de texte utilisé par défaut

� Toutes ces classes sont définies dans la plateforme Eclipse

via les packages org.eclipse.ui.editors…

� Nous verrons par la suite des APIs issues de la boîte à outils

JFace

Page 141: Construction d'éditeurs avec la plateforme Eclipse

141Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : SourceViewerConfiguration

� La configuration de l’affichage d’un éditeur de texte passe

par l’utilisation d’un objet de type SourceViewerConfiguration

� Coloration syntaxique

� Formatage

� Complétion automatique, …

� La classe SourceViewConfiguration réalise que très peu de

traitement, il faut passer par TextSourceViewerConfiguration

� Pour associer un SourceViewerConfiguration à un éditeur de

type texte

� setSourceViewerConfiguration(SourceViewerConfiguration s) : appeler cette méthode à la création de l’éditeur

� Au cours des fonctionnalités de notre éditeur nous découv-

rirons certaines méthodes de SourceViewerConfiguration

Page 142: Construction d'éditeurs avec la plateforme Eclipse

142Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : SourceViewerConfiguration

� Exemple : Associer un SourceViewerConfiguration à un

éditeur de texte

public class PassMemEditorPart extends AbstractDecor atedTextEditor {public PassMemEditorPart() {

super();

this.setSourceViewerConfiguration(new PassMemSourceViewerConfiguration(getSharedColor s(), getPreferenceStore()));

}}

Un SourceViewerConfigurationne s’utilise que pour les éditeurs

de type texte

Associe un SourceViewerConfiguration avec

l’éditeur

PassMemEditorPart.javades projets PassMemEditorStep…

Page 143: Construction d'éditeurs avec la plateforme Eclipse

143Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� La coloration syntaxique permet de mettre en forme des

éléments du contenu d’un texte

� Caractère, mot, phrase, paragraphe, …

� Possibilité de modifier les caractéristiques suivantes

� Couleur de fond

� Couleur de texte

� Style du texte (italique, gras, police, taille, …)

� Exemple

Page 144: Construction d'éditeurs avec la plateforme Eclipse

144Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� La coloration syntaxique est mise en place en utilisant un

objet de type IPresentationReconciler

� Un IPresentationReconciler permet de mettre à jour la mise

en forme du document lors de la saisie d’un texte

� Un objet PresentationReconciler s’appuie sur deux objets

� Damager : détermine quelle portion du texte à été modifiée et qui

doit être mise à jour (IPresentationDamager)

� Repairer : permet de savoir les styles à appliquer sur la portion de

texte qui a été modifiée (IPresentationRepairer)

� La classe DefaultDamagerRepairer implémente les interfaces

de Damager et Repairer (majorité des cas)

� Petite explication …

Page 145: Construction d'éditeurs avec la plateforme Eclipse

145Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� L’objet IPresentationReconciler coordonne le Damager et le

Repairer

� Le Damager indique au IPresentationReconciler qu’une

portion du texte a été modifiée

� La portion du texte est transférée au Repairer pour que des

styles y soient appliqués

� L’utilisation de la classe DefaultDamagerRepairer traite à la

fois les demandes de Damager et les besoins de Repairer

� Le SourceViewerConfiguration fournit la méthode suivante

� IPresentationReconciler getPresentationReconciler() : retourne un

IPresentationReconciler pour un éditeur de texte donné

Page 146: Construction d'éditeurs avec la plateforme Eclipse

146Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

IPresentationReconciler

install(…)

getDamager(…)

getRepairer(…)

� Cartes des classes concernant un PresentationReconciler

IPresentationDamager

getDamageRegion(…)IPresentationRepairer

createPresentation(…)

Dépendance

Héritage

PresentationReconciler

setDamager(…)

setRepairer(…)

DefaultDamageRepairer

ITokenScanner

nextToken(…) Etudiée dans la suite

Page 147: Construction d'éditeurs avec la plateforme Eclipse

147Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� Exemple : Définir un IPresentationReconciler dans un

SourceViewerConfigurationpublic class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private ISharedTextColors refSharedTextColors;

public PassMemSourceViewerConfiguration(ISharedText Colors pSharedTextColors,IPreferenceStore preferenceStore) {

super(preferenceStore);

this.refSharedTextColors = pSharedTextColors;}

public IPresentationReconciler getPresentationReconc iler(ISourceViewer sourceViewer) {

DefaultDamagerRepairer commentDamagerRepairer= new D efaultDamagerRepairer(getRuleBasedScanner());

PresentationReconciler reconciler= new PresentationR econciler();reconciler.setDamager(commentDamagerRepairer, IDocu ment.DEFAULT_CONTENT_TYPE);reconciler.setRepairer(commentDamagerRepairer, IDoc ument.DEFAULT_CONTENT_TYPE);

return reconciler;}

... // La suite dans les prochains transparents}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep1

Scanner étudiépar la suite

Page 148: Construction d'éditeurs avec la plateforme Eclipse

148Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� Un DefaultDamagerRepairer s’appuie sur un scanner

(ITokenScanner) pour déterminer les styles à appliquer

� Un objet ITokenScanner décompose un texte sur des

intervalles donnés et retourne des Tokens

� Un token contient le style à appliquer sur la portion du texte

� Pour déterminer quel token doit être retourné, l’objet

ITokenScanner s’appuie sur des règles Rules

� Résumé

� Un objet ITokenScanner est associé à un ensemble de Rules

� Chaque règle est associée à un Token

� Si la règle est respectée, le Token est retourné

Page 149: Construction d'éditeurs avec la plateforme Eclipse

149Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� Cartes des classes concernant Scanner et Rules

IToken

getData()

Token ITokenScanner

nextToken()

getTokenOffset()

getTokenLength()

ICharacterScanner

read()

unread()

IRule

evaluate()

RuleBasedScanner

setRules()

setDefaultReturnToken()

RuleBasedPartitionScanner

setRules()

IPredicatRule

getSuccessToken()

WhitespaceRule

NumberRule

WordRule

SingleLineRule

MultiLineRule

WordPatternRule

IWordDetector

isWordStart()

isWordPart()

IWhitespaceDetector

isWhitespace()

Dépendance

Héritage

Page 150: Construction d'éditeurs avec la plateforme Eclipse

150Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� Pour chaque règle (voir dans la suite) définie, un Token est

retourné

� Un Token est défini par l’interface IToken et une implémen-

tation par défaut est fournie par Token

� Un objet Token contient un type et un objet

� Différentes valeurs de types (indéfini, espace, fin de fichier

ou autre)

� L’objet contenu peut de type arbitraire

� String : pour donner des valeurs de partitions (voir plus tard)

� TextAttribute(Color for, Color back, int style, Font font) : défini le

style d’un texte

Page 151: Construction d'éditeurs avec la plateforme Eclipse

151Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Coloration Syntaxique

� Exemple : Construction d’objets de type Token

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private ITokenScanner getRuleBasedScanner() {Token tokenDefault = new Token(new TextAttribute(

refSharedTextColors.getColor(new RGB(0, 0, 255)), nu ll, SWT.ITALIC | SWT.BOLD));Token keywordToken = new Token(new TextAttribute(

refSharedTextColors.getColor(new RGB(0, 0, 0)), null , SWT.BOLD));Token tokenComment1 = new Token(new TextAttribute(

refSharedTextColors.getColor(new RGB(192, 192, 192)) , refSharedTextColors.getColor(new RGB(20, 20, 20)), S WT.ITALIC));

Token tokenComment2 = new Token(new TextAttribute(refSharedTextColors.getColor(new RGB(140, 140, 140)) , refharedTextColors.getColor(new RGB(200, 200, 200)), SWT.ITALIC));

...}

}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep1

Plusieurs Token ont été définis

Page 152: Construction d'éditeurs avec la plateforme Eclipse

152Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Coloration Syntaxique / WordRule

� Dans la plupart des cas, la mise en place de la coloration

syntaxique consiste à lister un ensemble de mots clés

� L’objet WordRule est utilisé dans les cas suivants

� Colorer des mots complets

� Colorer des mots qui débutent par un caractère donné

� Un objet WordRule est construit à partir

� IWordDetector : vérifie les caractères valides en début de mot et les

caractères faisant parti d’un mot (détailler dans la suite)

� Un Token par défaut utilisé par les mots non reconnus

� Un objet WordRule permet d’ajouter des mots clés via

� void addWord(String word, Token currentToken) : ajoute un mot et

un Token qui doit être retourné si le mot est découvert

Page 153: Construction d'éditeurs avec la plateforme Eclipse

153Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Coloration Syntaxique / WordRule

� L’objet IWordDetector permet de vérifier les caractères

valides en début de mot et tout au long du mot à l’aide des

méthodes

� boolean isWordStart(char c) : true s’il s’agit d’un caractère valide en

début de mot

� boolean isWordPart(char c) : true s’il s’agit d’un caractère valide en

cours de mot

� A chaque saisi d’un caractère WordRule demande à son

objet IWordDetector si le mot en cours est valide

� Si le caractère de début est découvert deux tokens peuvent

être retournés

� Le Token par défaut, puisque le mot n’est pas encore identifié

� Le Token associé au mot clé

Page 154: Construction d'éditeurs avec la plateforme Eclipse

154Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Coloration Syntaxique / WordRule

� Exemple : Définition de règles à partir de WordRule

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private static final class WordDetector implements I WordDetector {public boolean isWordPart(char c) {

return Character.isLetter(c);}

public boolean isWordStart(char c) {return c == '@';

}}

private ITokenScanner getRuleBasedScanner() {...

// Keywords.String[] keywords = {"@entry", "@login", "@password ", "@url", "@note", "@creationDate", "@expirationDa te"};

WordRule keywordRule= new WordRule(new WordDetector() , tokenDefault);

for(String current : keywords) {keywordRule.addWord(current, keywordToken);

}

...}

}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep1

Utilisation du Tokenpar défaut

La liste des mots clés àdécouvrir

Un mot clé contient uniquement des lettres et commence par @

Page 155: Construction d'éditeurs avec la plateforme Eclipse

155Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Coloration Syntaxique / WordRule

� Exemple (suite) : Définition de règles à partir de WordRule

Les mots clés ont étédécouverts

Mot clé en cours d’être découvert (utilisation du Token

par défaut)

Ce mot n’a pas été découvert

Page 156: Construction d'éditeurs avec la plateforme Eclipse

156Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Col. Synt. / (Single|Multi)LineRule

� La règle SingleLineRule définit une règle qui est satisfaite

� Débute avec une chaîne de caractères donnée

� Se termine avec une chaîne de caractères donnée

� Se termine avec la ligne

� Un caractère d’échappement est autorisé pour exprimer que

la ligne suivante est considérée comme le prolongement de

la ligne en cours

� Constructeur de SingleLineRule

� SingleLineRule(String startSeq, String endSeq, IToken tok, char esc)

� EndOfLineRule est une variante de SingleLineRule àl’exception que la règle se termine avec la ligne

� MultiLineRule propose les mêmes fonctionnalités que SingleLineRule sur plusieurs lignes

Page 157: Construction d'éditeurs avec la plateforme Eclipse

157Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Col. Synt. / (Single|Multi)LineRule

� Exemple : Définition de règles à partir de SingleLineRule et

MultiLineRulepublic class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private ITokenScanner getRuleBasedScanner() {...

// Comment.EndOfLineRule commentRule1 = new EndOfLineRule("//", tokenComment,'c');MultiLineRule commentRule2 = new MultiLineRule("/*", "*/", tokenComment, (char)0, true);...

}}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep1

Les commentaires sont identifiés

Page 158: Construction d'éditeurs avec la plateforme Eclipse

158Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Scanner

� Un Scanner s’appuie sur les règles pour déterminer quel

Token doit être retourné

� Un Scanner est défini par l’interface ITokenScanner

� La classe RuleBasedScanner est une implémentation par

défaut et permet de retourner des règles

� void setRules(IRule[] rules) : permet d’ajouter une liste de règles

� Dans la suite nous utiliserons un scanner pour gérer les

partitions via la classe RuleBasedPartitionScanner

Page 159: Construction d'éditeurs avec la plateforme Eclipse

159Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Scanner

� Exemple : Mise en place d’un scanner

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private ITokenScanner getRuleBasedScanner() {...

RuleBasedScanner passMemScanner= new RuleBasedScanne r();

// Keywords.String[] keywords = {"@entry", "@login", "@password ", "@url", "@note", "@creationDate", "@expirationDa te"};

WordRule keywordRule= new WordRule(new WordDetector() , tokenDefault);

for(String current : keywords) {keywordRule.addWord(current, keywordToken);

}

// Comment.EndOfLineRule commentRule1 = new EndOfLineRule("//", tokenComment1,'c');MultiLineRule commentRule2 = new MultiLineRule("/*", "*/", tokenComment2, (char)0, true);

IRule[] rules= {keywordRule, commentRule1, commentR ule2};passMemScanner.setRules(rules);

return passMemScanner;}

}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep1

Trois règles ont été définies et associées au scanner

Page 160: Construction d'éditeurs avec la plateforme Eclipse

160Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Modèle de texte

� Un texte est défini par un modèle de présentation IDocument

et est affiché via un ITextViewer

� Un modèle de présentation est associé à un type de fichier

(défini par IEditorInput) par un objet IDocumentProvider

� Un IDocumentProvider effectue donc la relation entre un

objet IEditorInput et un objet IDocumentProvider

� Responsabilités d’un IDocumentProvider

� Création du modèle d’annotation IAnnotationModel (markers, …)

� Création et gestion du modèle de présentation IDocument

� …

Page 161: Construction d'éditeurs avec la plateforme Eclipse

161Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Modèle de texte

� Exemple : Associer un IDocumentProvider par programme

public class PassMemEditorPart extends AbstractDecor atedTextEditor {public PassMemEditorPart() {

super();

this.setSourceViewerConfiguration(new PassMemSourceViewerConfiguration(getSharedColor s(), getPreferenceStore()));

this.setDocumentProvider(new PassDocumentProvider()) ;}

}

PassMemEditorPart.javadu projet PassMemEditorStep2

Possibilité également d’associer un IDocumentProvider par déclaration. Deux solutions différentes ne sert à

rien de les combiner

Page 162: Construction d'éditeurs avec la plateforme Eclipse

162Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Modèle de texte

� Exemple : Associer un IDocumentProvider par extension

plugin.xmldu projet PassMemEditorStep2

Pour tous les fichiers dont l’extension est .pass le IDocumentProvider est associé au

modèle de présentation

Page 163: Construction d'éditeurs avec la plateforme Eclipse

163Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Modèle de texte

� Cartes des classes concernant le modèle de présentation

IDocument

get()

getLength()

getLine…()

getDocumentPartitioner()

getLine…()

addDocumentListener()

AbstractDocument

getStore()

getTracker()

Dépendance

Héritage

IDocumentExtension3

getPartition()

getContentType()

IDocumentPartitioner

connect()

getPartition()

getContentType()

Document

IDocumentListener

documentAboutToBeChanged()

documentChanged()

Position

getOffset()

getLength()

isDeleted()

IDocumentProvider

getAnnotationModel(Object element)

getDocument(Object element)

connect(Object element)

IAnnotationModel

addAnnotation(Annotation, Position)

getAnnotationIterator()

IEditorInput

Modèle de Présentation

Modèle du domaine

Page 164: Construction d'éditeurs avec la plateforme Eclipse

164Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Les partitions (décrites par ITypedRegion) permettent de

diviser un document en plusieurs régions

� Chaque région est associée à un type de contenu

� Un partitionneur (décrit par IDocumentPartitioner) est

responsable de la division du document en plusieurs régions

� L’avantage des partitions est de pouvoir découper le

document selon les différents langages exploités

� Exemple d’un fichier Java

� Code Java

� Commentaire

� Annotation, …

Page 165: Construction d'éditeurs avec la plateforme Eclipse

165Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Le partitionnement assure une mise à jour permanente de

chaque partition lorsque le texte est modifié

� Le IDocumentProvider assure que le partitionnement est

installé

� void setupDocument(Object ele, IDocument doc) : méthode à utiliser

pour configurer le partitionnement

� Le SourceViewerConfiguration a besoin de connaître le

partitionnement et les types de contenu définis

� String getConfiguredDocumentPartitioning(ISourceViewer sv) :

retourne le partitionnement pour cette configuration

� String[] getConfiguredContentTypes(ISourceViewer sv) : retourne les

types de contenu définis dans le partitionnement

Page 166: Construction d'éditeurs avec la plateforme Eclipse

166Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Exemple : Ajouter un partitionnement

Type par défaut

Type commentaire

Deux types de contenu sont utilisés un type par défaut et un type

commentaire

12

1

2

1

2

Page 167: Construction d'éditeurs avec la plateforme Eclipse

167Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Exemple (suite) : Ajouter un partitionnement public class PassDocumentProvider extends FileDocume ntProvider {

public static final String PASS_PARTITIONING = "ecl ipse.workbench.passmemeditor.passpartitioning";

public static final String PASS_CODE = IDocument.DE FAULT_CONTENT_TYPE;public static final String PASS_COMMENT= "PASS_COMM ENT";

private static final String[] CONTENT_TYPES= {PASS_CODE,PASS_COMMENT

};

protected void setupDocument(Object element, IDocume nt document) {if (document instanceof IDocumentExtension3) {

IDocumentExtension3 ext = (IDocumentExtension3)docu ment;

IDocumentPartitioner partitioner = createPassPartitio ner();ext.setDocumentPartitioner(PASS_PARTITIONING, parti tioner);partitioner.connect(document);

}}

private IDocumentPartitioner createPassPartitioner() {EndOfLineRule commentRule1 = new EndOfLineRule("//", new Token(PASS_COMMENT),'c');MultiLineRule commentRule2 = new MultiLineRule("/*", "*/", new Token(PASS_COMMENT), (char)0, true);

IPredicateRule[] rules= { commentRule1, commentRule 2 };

RuleBasedPartitionScanner scanner= new RuleBasedPart itionScanner();scanner.setPredicateRules(rules);

return new FastPartitioner(scanner, CONTENT_TYPES);}

}

PassDocumentProvider.javadu projet PassMemEditorStep2

Identifiant du partitionnement

Associer au document le partitionneur

Connecter le partitionneurau document

Utilisation d’un scanneur spécifique pour les partitions

Page 168: Construction d'éditeurs avec la plateforme Eclipse

168Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Exemple (suite) : Ajouter un partitionnement

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

public String getConfiguredDocumentPartitioning(ISo urceViewer sourceViewer) {return PassDocumentProvider.PASS_PARTITIONING;

}

public String[] getConfiguredContentTypes(ISourceVi ewer sourceViewer) {return new String[] { PassDocumentProvider.PASS_COD E, PassDocumentProvider.PASS_COMMENT };

}

public IPresentationReconciler getPresentationReconc iler(ISourceViewer sourceViewer) {PresentationReconciler reconciler = new Presentation Reconciler();reconciler.setDocumentPartitioning(getConfiguredDoc umentPartitioning(sourceViewer));

// Partition for other.DefaultDamagerRepairer defaultDamagerRepairer = new D efaultDamagerRepairer(getDefaultRuleBasedScanner()) ;

reconciler.setDamager(defaultDamagerRepairer, PassD ocumentProvider.PASS_CODE);reconciler.setRepairer(defaultDamagerRepairer, Pass DocumentProvider.PASS_CODE);

// Partition for Comment.DefaultDamagerRepairer commentDamagerRepairer = new D efaultDamagerRepairer(getCommentRuleBasedScanner()) ;

reconciler.setDamager(commentDamagerRepairer, PassD ocumentProvider.PASS_COMMENT);reconciler.setRepairer(commentDamagerRepairer, Pass DocumentProvider.PASS_COMMENT);

return reconciler;}

... // Suite dans le prochain transparent}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep2

Utilisation de deux scanneurs distinctes

Page 169: Construction d'éditeurs avec la plateforme Eclipse

169Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Partition

� Exemple (suite) : Ajouter un partitionnement

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private ITokenScanner getCommentRuleBasedScanner() {Token tokenComment2 = new Token(new TextAttribute(re fSharedTextColors

.getColor(new RGB(140, 140, 140)), null, SWT.ITALIC) );

RuleBasedScanner commentScanner = new RuleBasedScanne r();commentScanner.setDefaultReturnToken(tokenComment2) ;return commentScanner;

}

private ITokenScanner getDefaultRuleBasedScanner() {Token tokenDefault = new Token(new TextAttribute(refS haredTextColors

.getColor(new RGB(0, 0, 255)), null, SWT.ITALIC | SW T.BOLD));Token keywordToken = new Token(new TextAttribute(refS haredTextColors

.getColor(new RGB(0, 0, 0)), null, SWT.BOLD));

RuleBasedScanner passMemScanner = new RuleBasedScanne r();

// Keywords.String[] keywords = { "@entry", "@login", "@passwor d", "@url", "@note",

"@creationDate", "@expirationDate" };WordRule keywordRule = new WordRule(new WordDetector() , tokenDefault);

for (String current : keywords) {keywordRule.addWord(current, keywordToken);

}

IRule[] rules = { keywordRule };passMemScanner.setRules(rules);

return passMemScanner;}

}

Utilisation des règles définies pour le type PASS_COMMENT

Principe déjà évoqué sans l’utilisation de partitionnement

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep2

Page 170: Construction d'éditeurs avec la plateforme Eclipse

170Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� L’assistant de contenu (Content Assist) permet de fournir

une aide contextuelle à l’utilisateur

� Selon ce contexte (texte en sélection, fraction de mot, …)

l’assistant peut proposer des solutions adaptées

� Fournir des patrons de texte (voir plus tard)

� Compléter un mot qui était en cours de saisie

� Enrichir une portion de texte sélectionné

� …

� L’aide contextuelle est disponible via la combinaison de

touche Ctrl + Espace ou en fonction d’un certain délai

d’attente

Page 171: Construction d'éditeurs avec la plateforme Eclipse

171Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple : Intégration d’un assistant de contenu

Complétion de mots clés (àdéfinir l’algorithme qui liste les propositions de la complétion)

Pour chaque mot clésélectionné, une information

peut être donnée

L’assistant de contenu est ouvert

Page 172: Construction d'éditeurs avec la plateforme Eclipse

172Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� L’objet SourceViewerConfiguration est utilisé pour déclarer

l’assistant de contenu

� IContentAssistant getContentAssistant(ISourceViewer p) : définit

l’objet IContentAssistant employé pour activer l’assistant de contenu

� Un objet IContentAssistant est utilisé pour configurer

l’assistant de contenu

� Pour chaque type de contenu un objet IContentAssistProcessor doit

être défini

� Paramètres liés à l’affichage (couleur, délai d’apparition, …)

� Des écouteurs liés au déroulement de l’assistant (début, fin, sélection

de l’élément proposé par l’assistant)

Page 173: Construction d'éditeurs avec la plateforme Eclipse

173Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple (suite) : Intégration d’un assistant de contenu

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {...public IContentAssistant getContentAssistant(final IS ourceViewer sourceViewer) {

ContentAssistant assistant= new ContentAssistant();assistant.setDocumentPartitioning(getConfiguredDocu mentPartitioning(sourceViewer));

assistant.setContentAssistProcessor(new HippiePropos alProcessor(), PassDocumentProvider.PASS_COMMENT);

PassMemCompletionProcessor processor = new PassMemCo mpletionProcessor();assistant.setContentAssistProcessor(processor, Pass DocumentProvider.PASS_CODE);assistant.setContentAssistProcessor(processor,IDocu ment.DEFAULT_CONTENT_TYPE);

// Paramètres du ContentAssistant étudiés plus tard

return assistant;}

}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep3

Un IContentAssistProcessor prédéfini dont le fonctionnement est d’identifier des mots qui

existent déjà dans les éditeurs ouverts

Défini notre propre IContentAssistProcessor(voir dans la suite)

Page 174: Construction d'éditeurs avec la plateforme Eclipse

174Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Pour que l’assistant de contenu puisse démarrer lors de

l’utilisation du raccourci CTRL + Espace il faut créer une

action de type ContentAssistAction

� Exemple : activer l’assistant de contenu via CTRL + Espace

public class PassMemEditorPart extends AbstractDecor atedTextEditor {public PassMemEditorPart() {

super();

this.setSourceViewerConfiguration(new PassMemSourceViewerConfiguration(getSharedColor s(), getPreferenceStore()));

this.setDocumentProvider(new PassDocumentProvider()) ;

}

protected void createActions() {super.createActions();

ContentAssistAction action= new ContentAssistAction( PassMemEditorMessages.getBundle(), "contentAssist." , this);action.setActionDefinitionId(ITextEditorActionDefin itionIds.CONTENT_ASSIST_PROPOSALS);setAction("ContentAssist", action);

}}

PassMemEditorPart.javadu projet PassMemEditorStep3

Page 175: Construction d'éditeurs avec la plateforme Eclipse

175Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple : Ajouter les actions d’assistant de contenu dans le

menu principalpublic class PassMemEditorActionContributor extends TextEditorActionContributor {

private RetargetTextEditorAction fContentAssist;

public PassMemEditorActionContributor() {fContentAssist = new RetargetTextEditorAction(PassMe mEditorMessages.getBundle(), "contentAssist."); fContentAssist.setActionDefinitionId(ITextEditorAct ionDefinitionIds.CONTENT_ASSIST_PROPOSALS);

}

public void contributeToMenu(IMenuManager menu) {super.contributeToMenu(menu);

IMenuManager editMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT );

if (editMenu != null) {editMenu.appendToGroup(IWorkbenchActionConstants.MB _ADDITIONS,

fContentAssist);}

}

public void setActiveEditor(IEditorPart part) {super.setActiveEditor(part);if (part instanceof ITextEditor) {

fContentAssist.setAction(getAction((ITextEditor) pa rt, "ContentAssist"));}

}}

PassMemEditorActionContributor.javadu projet PassMemEditorStep3

Page 176: Construction d'éditeurs avec la plateforme Eclipse

176Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Un objet IContentAsssistProcessor fournit un mécanisme

pour gérer la complétion de texte (ICompletionProposal)

� Différentes méthodes pour la gérer cette complétion

� ICompletionProposal[] computeCompletionProposals(ITextViewer

viewer, int offset) : pour définir les propositions de complétion

� char[] getCompletionProposalAutoActivationCharacters() : les

caractères qui déclenchent la complétion

� Dans la méthode computeCompletionProposals, il faut fournir

un algorithme qui établie une liste de propositions suivant le

contexte courant

� @e fournira les propositions @entry et @expirationDate

Page 177: Construction d'éditeurs avec la plateforme Eclipse

177Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple (suite) : Intégration d’un assistant de contenu

public class PassMemCompletionProcessor implements I ContentAssistProcessor {

public char[] getCompletionProposalAutoActivationCh aracters() {return new char[] {'@'};

}

public ICompletionProposal[] computeCompletionPropo sals(ITextViewer viewer, int offset) {IDocument document = viewer.getDocument();int currOffset = offset - 1;

String currWord = "";try {

char currChar;while (currOffset > 0 && !Character.isWhitespace(cur rChar = document.getChar(currOffset))) {

currWord = currChar + currWord;currOffset--;

}

List<String> currentSuggests = buildSuggests(currWor d);ICompletionProposal[] proposals = null;if (currentSuggests.size() > 0) {

proposals = buildProposals(currentSuggests, currWor d, offset - currWord.length());}return proposals;

} catch (BadLocationException e) {e.printStackTrace();return null;

}}

PassMemCompletionProcessor.javadu projet PassMemEditorStep3

Extrait à partir du mot courant la liste des propositions

Identifie le mot en cours de saisie

Construit à partir des propositions des objets ICompletionProposal

Le caractère @ qui permet de déclencher l’assistant de contenu

Page 178: Construction d'éditeurs avec la plateforme Eclipse

178Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple (suite) : Intégration d’un assistant de contenu

public class PassMemCompletionProcessor implements I ContentAssistProcessor {

private List<String> buildSuggests(String word) {List<String> current = new ArrayList<String>();for (int i = 0 ; i < PassMemSourceViewerConfiguratio n.KEYWORDS.length ; i++) {

if (PassMemSourceViewerConfiguration.KEYWORDS[i].st artsWith(word)) {current.add(PassMemSourceViewerConfiguration.KEYWOR DS[i]);

}}return current;

}

private ICompletionProposal[] buildProposals(List<S tring> suggestions, String replacedWord, int offset) {ICompletionProposal[] proposals = new ICompletionPr oposal[suggestions.size()];int index = 0;for (Iterator<String> i = suggestions.iterator(); i .hasNext();) {

String currSuggestion = (String) i.next();IContextInformation contextInfo = new ContextInformat ion(null, currSuggestion);proposals[index] = new CompletionProposal(currSugge stion, offset,

replacedWord.length(), currSuggestion.length(), null, currSuggestion, contextInfo,currSuggestion);

index++;}return proposals;

}...

}

PassMemCompletionProcessor.javadu projet PassMemEditorStep3

Retourne une information contextuelle par rapport à la

proposition en cours de sélection

Page 179: Construction d'éditeurs avec la plateforme Eclipse

179Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Pour afficher l’information contextuelle (partie droite) il faut

configurer l’objet IContentAssistant de cette façon

� Optionnellement si vous souhaitez paramétrer l’affichage des

informations contextuelles

� Redéfinir la méthode getInformationControlCreator() qui indiquera la

présentation à utiliser

� Fournir un IInformationPresenter qui précisera comment afficher les

informations contextuelles

assistant.setInformationControlCreator(getInformati onControlCreator(sourceViewer));

public IInformationControlCreator getInformationCont rolCreator(ISourceViewer sourceViewer) {return new IInformationControlCreator() {

public IInformationControl createInformationControl( Shell parent) {return new DefaultInformationControl(parent, presen ter);

}};

}

Page 180: Construction d'éditeurs avec la plateforme Eclipse

180Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple : Modifier l’apparence de l’information contextuellepublic class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

private DefaultInformationControl.IInformationPrese nter presenter;

public PassMemSourceViewerConfiguration(ISharedText Colors pSharedTextColors, IPreferenceStore preference Store) {super(preferenceStore);this.refSharedTextColors = pSharedTextColors;

presenter = new DefaultInformationControl.IInformat ionPresenter() {public String updatePresentation(Display display, St ring infoText,

TextPresentation presentation, int maxWidth, int maxHe ight) {StyleRange range = new StyleRange(0, 1, null, refSha redTextColors.getColor(new

RGB(220,220,220)), SWT.BOLD | SWT.ITALIC);presentation.addStyleRange(range);return infoText;

}};

}

public IContentAssistant getContentAssistant(final IS ourceViewer sourceViewer) {...assistant.setInformationControlCreator(getInformati onControlCreator(sourceViewer));

}

public IInformationControlCreator getInformationCont rolCreator(ISourceViewer sourceViewer) {return new IInformationControlCreator() {

public IInformationControl createInformationControl( Shell parent) {return new DefaultInformationControl(parent, presen ter);

}};

}...

}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep3

Le premier caractère est un gras et sa couleur de fond est modifiée

Page 181: Construction d'éditeurs avec la plateforme Eclipse

181Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Un objet IContentAsssistProcessor fournit également un

traitement pour afficher de l’information contextuelle

� L’information peut être affichée à différents cas

� A la suite d’un caractère donné (principe étudié précédemment)

� Une fois une proposition de complétion insérée dans le document

� Différentes méthodes liées à la gestion de l’information

� IContextInformation[] computeContextInformation(ITextViewer

viewer, int offset) : pour définir les informations susceptibles d’être

affichées

� char[] getContextInformationAutoActivationCharacters() : les

caractères qui déclenchent l’affichage des informations

� IContextInformationValidator getContextInformationValidator() :

défini un objet qui établie si une information doit être affichée ou pas

à la suite de la complétion

1

2

Page 182: Construction d'éditeurs avec la plateforme Eclipse

182Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple : Afficher de l’information contextuelle à la suite

d’un caractère donné

public class PassMemCompletionProcessor implements I ContentAssistProcessor {

public char[] getContextInformationAutoActivationCh aracters() {return new char[] {'?'};

}

public IContextInformation[] computeContextInformat ion(ITextViewer viewer, int offset) {ContextInformation[] contextInfos = new ContextInfor mation[PassMemSourceViewerConfiguration.KEYWORDS.le ngth];

for (int i = 0; i < contextInfos.length; i++) {contextInfos[i] = new ContextInformation(null, Pass MemSourceViewerConfiguration.KEYWORDS[i]);

}

return contextInfos;}

...}

PassMemCompletionProcessor.javadu projet PassMemEditorStep3

Affichage de l’information à la

suite du caractère -

Page 183: Construction d'éditeurs avec la plateforme Eclipse

183Editors - M. Baron - Page

keul

keul

.blo

gspo

t.comEditeur et le texte : Assistant de contenu

� Exemple : Afficher de l’information contextuelle une fois une

proposition de complétion insérée dans le documentpublic class PassMemCompletionProcessor implements I ContentAssistProcessor {

...

private ICompletionProposal[] buildProposals(List<S tring> suggestions, String replacedWord, int offset) {...for (Iterator<String> i = suggestions.iterator(); i .hasNext();) {

...IContextInformation contextInfo = new ContextInformat ion(null, currSuggestion);...

}return proposals;

}

public IContextInformation[] computeContextInformat ion(ITextViewer viewer, int offset) {ContextInformation[] contextInfos = new ContextInfor mation[PassMemSourceViewerConfiguration.KEYWORDS.le ngth];

for (int i = 0; i < contextInfos.length; i++) {contextInfos[i] = new ContextInformation(null, Pass MemSourceViewerConfiguration.KEYWORDS[i]);

}

return contextInfos;}

public IContextInformationValidator getContextInform ationValidator() {return new ContextInformationValidator(this);

}}

Le validator compare que l’information utilisée par la complétion est disponible

dans computeContextInformation

PassMemCompletionProcessor.javadu projet PassMemEditorStep3

Page 184: Construction d'éditeurs avec la plateforme Eclipse

184Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Un template permet à partir de l’assistant de contenu

d’insérer un squelette de texte

� Le contenu du texte inséré peut être complété

par des propositions de valeurs de mots

� Un template s’utilise suivant un contexte

� Une boucle while ne peut être insérée que dans du code Java

� La définition d’un template est réalisée soit

� au travers du point d’extension org.eclipse.ui.editors.template

� programmatiquement via Template et TemplateContexteType

� Privilégier la solution via extension permet

� de s’assurer d’une meilleure portabilité du code

� d’enrichir les templates existants

Page 185: Construction d'éditeurs avec la plateforme Eclipse

185Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

� Processus d’utilisation des templates depuis l’assistant de

contenu

� En fonction de la position sur

le document, identification du type

de contexte (ContextType)

� En fonction de l’identification de contexte,

récupération des templates

disponibles (TemplateStore)

� Proposition des templates à l’utilisateur

� Insertion du template dans le document

� Proposition des valeurs pour les différentes

variables (TemplateContexte)

Editeur et le texte : Template

1

2

3

4

5

Page 186: Construction d'éditeurs avec la plateforme Eclipse

186Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple : Définir un template par extension

Création d’une extension àpartir du point d’extension

org.eclipse.ui.editors.templates

Page 187: Construction d'éditeurs avec la plateforme Eclipse

187Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple (suite) : Définir un template par extension

plugin.xmldu projet PassMemEditorStep4

Définir un élément template

contextTypeId permet de préciser l’identifiant du contexte (définir plus tard)

Page 188: Construction d'éditeurs avec la plateforme Eclipse

188Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple (suite) : Définir un template par extension

plugin.xmldu projet PassMemEditorStep4

Définition de l’identifiant contextTypeId en utilisant une classe prédéfinie de la plateforme

Page 189: Construction d'éditeurs avec la plateforme Eclipse

189Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple (suite) : Définir un template par extension

plugin.xmldu projet PassMemEditorStep4

Pour le template proposé est défini le texte àinsérer. Les textes ${…} désignent des variables

Page 190: Construction d'éditeurs avec la plateforme Eclipse

190Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple (suite) : Définir un template par extension

plugin.xmldu projet PassMemEditorStep4

Pour la variable entry ces valeurs seront déterminés par un objet de type

TemplateVariableResolver

L’élément resolver nomméentryValues permet d’obtenir la liste des valeurs à proposer pour

la variable entry

Page 191: Construction d'éditeurs avec la plateforme Eclipse

191Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Les classes de type TemplateVariableResolver permettent

d’énumérer les valeurs possibles pour une variable

� Ces valeurs sont proposées après l’insertion du template

dans le document courant

� Pour retourner ces valeurs possibilité de redéfinir certaines

méthodes

� String[] resolveAll(TemplateContext context) : un ensemble de

valeurs à proposer

� String resolve(TemplateContext context) : une seule valeur à

proposer

� Un objet de type TemplateContext donne accès à l’ensemble

des variables et aux valeurs associées

Page 192: Construction d'éditeurs avec la plateforme Eclipse

192Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple (suite) : Définir un template par extension

public class TemplateEntryVariableResolver extends T emplateVariableResolver {

protected String[] resolveAll(TemplateContext contex t) {return new String[] {"twitter", "gmail"};

}}

TemplateEntryVariableResolver.javadu projet PassMemEditorStep4

Page 193: Construction d'éditeurs avec la plateforme Eclipse

193Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� La classe TemplateCompletionProcessor est un objet

IContentAssistProcessor dédié à la gestion de l’insertion de

template via l’assistant de contenu

� Différentes méthodes qui permettent de respecter le

processus d’insertion de template

� TemplateContextType getContextType(ITextViewer viewer, IRegion

region) : retourne le type de contexte en fonction de la position sur le

document

� Template[] getTemplates(String contextTypeId) : retourne une liste

de templates en fonction de l’identifiant de type de contexte

� Image getImage(Template template) : retourne une image associé à

un template

Page 194: Construction d'éditeurs avec la plateforme Eclipse

194Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple : Intégrer un template défini par extension dans un

assistant de contenu

public class PassMemTemplateProcessor extends Templa teCompletionProcessor {

protected TemplateContextType getContextType(ITextVi ewer viewer,IRegion region) {

return Activator.getDefault().getContextTypeRegistr y().getContextType(Activator.PASS_MEM_TEMPLATE_CONT EXT);}

protected Image getImage(Template template) {return Activator.getImage("template");

}

protected Template[] getTemplates(String contextType Id) {ContributionTemplateStore templateStore= Activator.g etDefault().getTemplateStore();

return templateStore.getTemplates(contextTypeId);}

}

PassMemTemplateProcessor.java du projet PassMemEditorStep4

Page 195: Construction d'éditeurs avec la plateforme Eclipse

195Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

public class Activator extends AbstractUIPlugin {private ContributionTemplateStore fTemplateStore;private ContributionContextTypeRegistry fRegistry;

public static final String PASS_MEM_TEMPLATE_CONTEX T= "eclipse.workbench.passmemeditorstep4.templateco ntextid";

private static final String TEMPLATES_PREFERENCE_KE Y= "templates";

public ContributionTemplateStore getTemplateStore() {if (fTemplateStore == null) {

fTemplateStore= new ContributionTemplateStore(getCo ntextTypeRegistry(), getPreferenceStore(), TEMPLATES_PREFERENCE_KEY);

try {fTemplateStore.load();

} catch (IOException x) {x.printStackTrace();

}}return fTemplateStore;

}

public ContributionContextTypeRegistry getContextTyp eRegistry() {if (fRegistry == null) {

fRegistry= new ContributionContextTypeRegistry();fRegistry.addContextType(PASS_MEM_TEMPLATE_CONTEXT) ;

}return fRegistry;

}...

}

� Exemple (suite) : Intégrer un template défini par extension

dans un assistant de contenu

Activator.java du projet PassMemEditorStep4

Page 196: Construction d'éditeurs avec la plateforme Eclipse

196Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple : Combiner une intégration d’un template défini par

extension et une proposition de mots cléspublic class PassMemTemplateProcessorBis extends Tem plateCompletionProcessor {

public ICompletionProposal[] computeCompletionPropo sals(ITextViewer viewer, int offset) {final ICompletionProposal[] computeCompletionPropos als = super.computeCompletionProposals(viewer, offse t);

IDocument document = viewer.getDocument();int currOffset = offset - 1;String currWord = "";try {

char currChar;while (currOffset > 0 && !Character.isWhitespace(cur rChar = document.getChar(currOffset))) {

currWord = currChar + currWord;currOffset--;

}

List<String> currentSuggests = buildSuggests(currWor d);ICompletionProposal[] proposals = null;if (currentSuggests.size() > 0) {

proposals = buildProposals(currentSuggests, currWor d, offset - currWord.length());}

ICompletionProposal[] copyOf = Arrays.copyOf(compute CompletionProposals,computeCompletionProposals.length + proposals.length );

for (int i = 0 ; i < proposals.length ; i++) {copyOf[i+computeCompletionProposals.length] = propo sals[i];

}return copyOf;

} catch (BadLocationException e) {return null;

}}}

PassMemTemplateProcessorBis.javadu projet PassMemEditorStep4

Récupère les objets ICompletionProposalliés aux templates

Page 197: Construction d'éditeurs avec la plateforme Eclipse

197Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Template

� Exemple : Intégrer un template défini programmatiquement

dans un assistant de contenupublic class PassMemTemplateProcessorBisBis implemen ts IContentAssistProcessor {

private static final String CONTEXT_ID= "eclipse.wo rkbench.passmemeditorstep4.templatecontextid"; private TemplateContextType fContextType= new Templa teContextType(

CONTEXT_ID, "Default Template Context");

private Template fTemplate= new Template("PassTemplate", // name"This Template inserts all keywords", // descriptio nCONTEXT_ID,"@entry\n${entry}\n@login\n@password\n@url\n@note\n @creationDate\n@expirationDate", // patternfalse);

public ICompletionProposal[] computeCompletionPropo sals(ITextViewer viewer, int offset) {...final ICompletionProposal[] tabTemplates = new IComp letionProposal[1];TemplateContext context= new DocumentTemplateContext (fContextType, document, offset, 0);Region region= new Region(offset, 0);TemplateProposal proposal= new TemplateProposal(fTem plate, context, region, Activator.getImage("templat e"));tabTemplates[0] = proposal;...

final ICompletionProposal[] copyOf = Arrays.copyOf(t abTemplates, tabTemplates.length + proposals.length) ;

for (int i = 0 ; i < proposals.length ; i++) {copyOf[i+tabTemplates.length] = proposals[i];

}

return copyOf;} catch (BadLocationException e) {

e.printStackTrace();return null;

}}...

}

PassMemTemplateProcessorBisBis.javadu projet PassMemEditorStep4

Page 198: Construction d'éditeurs avec la plateforme Eclipse

198Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Mise à jour

� Lors de la modification du document d’un éditeur il peut être

intéressant

� D’identifier des erreurs (orthographiques) et de les ajouter dans le

modèle d’annotation

� De construire un modèle (utilisé pour l’affichage dans Outline)

� L’écoute des changements ne peut être réalisé dans le

Thread-UI car la mise à jour est trop couteuse

� Le Reconciler fournit un Thread pour ce type de tâche

� Traitement déclenché quand l’utilisateur a fini de saisir du texte

� Interruptible quand l’utilisateur re-saisit du texte

� Autorise la synchonisation

� Implémentation par défaut : MonoReconciler

� La stratégie de traitement est définit dans IReconcilingStrategy

Page 199: Construction d'éditeurs avec la plateforme Eclipse

199Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Mise à jour

� Un objet IReconcilingStrategy est utilisé pour définir les

traitements de mise à jour d’un document

� Différentes méthodes à implémenter

� void setDocument(IDocument document) : pour connaître le

document sur lequel la stratégie s’applique

� void reconcile(IRegion partition) : déclenché à chaque modification

du document et permet de connaître la région impactée

� Dans la méthode reconcile, différents traitements peuvent

être réalisés

� Utilisation d’un moteur de vérification orthographique (Spelling

Checking) et création d’annotation SpellingAnnotation

� Utilisation d’un parser pour identifier les éléments saisis dans le texte

puis utiliser le résultat du parser pour l’affichage dans Outline

Page 200: Construction d'éditeurs avec la plateforme Eclipse

200Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple : Création d’une vue Outline personnalisée

Le contenu de l’éditeur est analysé puis affiché dans la vue Outline

La vue Outline affiche une liste d’éléments. Un élément sélectionnépermet de mettre en surbrillance la

portion sur l’éditeur

Page 201: Construction d'éditeurs avec la plateforme Eclipse

201Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple (suite) : Création d’une vue Outline personnalisée

public class PassMemSourceViewerConfiguration extend s TextSourceViewerConfiguration {

public PassMemSourceViewerConfiguration(ISharedText Colors pSharedTextColors, IPreferenceStore preference Store, PassMemEditorPart pEditor) {

super(preferenceStore);this.refSharedTextColors = pSharedTextColors;this.refEditor = pEditor;

}

public IReconciler getReconciler(ISourceViewer source Viewer) {IReconcilingStrategy strategy = new PassMemReconcile Strategy(sourceViewer, refEditor);return new MonoReconciler(strategy, false);

}

...}

PassMemSourceViewerConfiguration.javadu projet PassMemEditorStep5

Page 202: Construction d'éditeurs avec la plateforme Eclipse

202Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple (suite) : Création d’une vue Outline personnalisée

public class PassMemReconcileStrategy implements IRe concilingStrategy, IReconcilingStrategyExtension {

private IDocument fDocument;

private final PassMemEditorPart fEditor;

public PassMemReconcileStrategy(ISourceViewer pSourc eViewer, PassMemEditorPart refEditorPart) {fEditor = refEditorPart;

}

public void reconcile(IRegion partition) {PassMemModel value = new PassMemParser().parse(fDocu ment);this.fEditor.setPassMemModel(value);

}

public void reconcile(DirtyRegion dirtyRegion, IRegi on subRegion) {}

public void setDocument(IDocument document) {fDocument = document;

}

public void initialReconcile() {reconcile(new Region(0, fDocument.getLength()));

}

public void setProgressMonitor(IProgressMonitor moni tor) { }

}

PassMemReconcileStrategy.java du projet PassMemEditorStep5

Utilisation d’un parser qui analyse le document de

l’éditeur

Page 203: Construction d'éditeurs avec la plateforme Eclipse

203Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple (suite) : Création d’une vue Outline personnaliséepublic final class PassMemParser {

private IDocument fDocument;private int fLine;private int fLineCount;

public PassMemModel parse(IDocument document) {try {

fDocument= document;fLine= 0;fLineCount= fDocument.getNumberOfLines();return parsePassMem();

} catch (BadLocationException e) {return null;

}}

private PassMemModel parsePassMem() throws BadLocati onException {PassMemModel refModel = new PassMemModel();while (fLine < fLineCount) {

IRegion region= fDocument.getLineInformation(fLine);String text= fDocument.get(region.getOffset(), regi on.getLength());

for (int i = 0 ; i < PassMemSourceViewerConfiguratio n.KEYWORDS.length ; i++) {if (text.startsWith(PassMemSourceViewerConfiguratio n.KEYWORDS[i])) {

refModel.addKeywordPosition(buildKeywordPosition(te xt, PassMemSourceViewerConfiguration.KEYWORDS[i], regio n.getOffset(), refModel));

}}fLine++;

}return refModel;

}

private KeywordPosition buildKeywordPosition(String t ext, String keyword, int offset, PassMemModel pModel) {KeywordPosition refKeywordPosition = new KeywordPosit ion(keyword, offset, text.length());return refKeywordPosition;

}}

PassMemParser.java du projet PassMemEditorStep5

A chaque découverte d’un mot clé, ajout dans un

modèle

Page 204: Construction d'éditeurs avec la plateforme Eclipse

204Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple (suite) : Création d’une vue Outline personnaliséepublic class PassMemModel {

private List<KeywordPosition> keywordPositions;

public PassMemModel() {keywordPositions = new ArrayList<KeywordPosition>();

}

public void addKeywordPosition(KeywordPosition curre nt) {this.keywordPositions.add(current);

}

public List<KeywordPosition> getKeywordPositions() {return this.keywordPositions;

}}

public class KeywordPosition {private String key;private int offset;private int length;

public KeywordPosition(String key, int offset, int len gth) {this.key = key;this.offset = offset;this.length = length;

}

public String getKey() {return key;

}

public int getOffSetPosition() {return offset;

}

public int getLength() {return length;

}}

PassMemModel.java du projet PassMemEditorStep5

KeywordPosition.java du projet PassMemEditorStep5

Page 205: Construction d'éditeurs avec la plateforme Eclipse

205Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : Outline

� Exemple (suite) : Création d’une vue Outline personnaliséepublic class PassMemEditorPart extends AbstractDecor atedTextEditor {

private PassMemOutlinePage fOutlinePage;private PassMemModel fPassMemModel;...public Object getAdapter(Class required) {

if (IContentOutlinePage.class.equals(required)) {if (fOutlinePage == null)

createOutlinePage();return fOutlinePage;

}return super.getAdapter(required);

}

private void createOutlinePage() {fOutlinePage = new PassMemOutlinePage(this);fOutlinePage.addSelectionChangedListener(new ISelect ionChangedListener() {

public void selectionChanged(SelectionChangedEvent e vent) {ISelection selection= event.getSelection();if (selection instanceof IStructuredSelection) {

IStructuredSelection ss= (IStructuredSelection) sele ction;Object element= ss.getFirstElement();if (element instanceof KeywordPosition) {

KeywordPosition re= (KeywordPosition) element;selectAndReveal(re.getOffSetPosition(), re.getLengt h());

}}

}});

}

public void setPassMemModel(PassMemModel passMemMode l) {fPassMemModel = passMemModel;if (fOutlinePage != null)

fOutlinePage.updatePassMemModel(passMemModel);}public PassMemModel getPassMemModel() {

return fPassMemModel;}

}

PassMemEditorPart.java du projet PassMemEditorStep5

Page 206: Construction d'éditeurs avec la plateforme Eclipse

206Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Editeur et le texte : il reste …

� De nombreuses améliorations peuvent encore être apportées

à un composant TextEditor

� Folding : plier / déplier une zone de texte

� Spell Checking : vérification orthographique en exploitant un moteur

de vérification et un dictionnaire de mots

� Hyperlinks : ajouter des liens hypertextes dans du texte

Des informations complémentaires sur la mise en place de ces

améliorations peuvent être trouvées

www.eclipse.org/eclipse/platform-text/development/dev.html

Page 207: Construction d'éditeurs avec la plateforme Eclipse

207Editors - M. Baron - Page

keul

keul

.blo

gspo

t.com

Bilan

� Ce support de cours a exploré les différentes APIs de la

plateforme Eclipse pour la mise en place d’éditeur

� Deux types d’éditeurs sont à distinguer

� Ceux qui fournissent un composant TextEditor pour la manipulation de texte

� Ceux qui fournissent des IHMs formulaires qui facilitent l’édition des éditeurs à base de texte (complémentaires aux premiers)

� Les éditeurs permettent donc de manipuler des DSL (Domain

Specific Language)

� Des projets du domaine de la modélisation tentent de faire

abstraction de l’apprentissage des APIs et focalisent essentiellement sur la modélisation (Xtext)

� Dans le chapitre lié à la modélisation, nous reviendrons sur

ces technologies