95
Développement de clients riches : Plateforme Eclipse Mickaël BARON – 2009 (Rev. Juillet 2010) mailto:[email protected] ou mailto:[email protected] Chapitre 3 : Conception de plug Chapitre 3 : Conception de plug - - ins ins Workbench : Views

Construction de vues avec la plateforme Eclipse

Embed Size (px)

DESCRIPTION

Ce support de cours s'intéresse à détailler la construction de vues 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, étude des classes ViewPart StickyView et Category, vues multiples, registre des vues, cycle de vie, communication entre vues (en direct, le service de sélection et IAdaptable).

Citation preview

Page 1: Construction de vues avec la plateforme Eclipse

Développement de clients riches : Plateforme Eclipse

Mickaël BARON – 2009 (Rev. Juillet 2010)mailto:[email protected] ou mailto:[email protected]

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

Workbench : Views

Page 2: Construction de vues avec la plateforme Eclipse

2Views - 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 de vues avec la plateforme Eclipse

3Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Organisation du cours sur le Workbench : Views

Tous les exemples du cours sont disponibles directement à l’adressembaron.developpez.com/eclipse/views

� Construction déclarative

� ViewPart, StickyView et Category

� Vues multiples

� Registre des vues

� Cycle de vie

� Communication entre vues

Page 4: Construction de vues avec la plateforme Eclipse

4Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Déroulement du cours

� Pédagogie du cours

� Illustration avec de nombreux exemples qui sont disponibles à

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

� Des bulles d’aide tout au long du cours

� Logiciels utilisés

� Eclipse 3.4.2 Ganymede

� Pré-requis

� Connaître la boite à outils SWT, JFace

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

� Remerciements

� Developpez.com : djo.mos (Jawher MOUSSA)

� …

Ceci est une alerte

Ceci est une astuce

Page 5: Construction de vues avec la plateforme Eclipse

5Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Ressources …

� Des articles sur la construction des vues

� www.eclipse.org/articles/viewArticle/ViewArticle2.html

� www.vogella.de/articles/RichClientPlatform/article.html

� eclipsesource.com/blogs/2010/06/23/tip-how-to-detect-that-a-view-was-detached/

� Des articles sur la communication entre vues

� www.eclipse.org/articles/Article-WorkbenchSelections/article.html

� www.eclipse.org/articles/Article-Properties-View/properties-view.html

� wiki.eclipse.org/FAQ_How_do_I_find_out_what_object_is_selected%3F

� wiki.eclipse.org/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F

� 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 6: Construction de vues avec la plateforme Eclipse

6Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités

� Dans la partie précédente nous avons étudié les perspectives

qui permettent d’agencer vues et éditeurs

� Une vue est utilisée pour naviguer dans une hiérarchie

d’information, ouvrir un éditeur ou afficher des propriétés en

relation directe avec l’éditeur actif

� Cette partie sera l’occasion d’étudier en détail les construc-

tions des vues et les possibilités d’interaction

� construction d’une vue par extension

� construction de vues multiples

� construction de vues de type Sticky Views

� registre des vues

� mécanismes de communication entre les vues

Page 7: Construction de vues avec la plateforme Eclipse

7Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Généralités

IWorkbenchPage

activate(IWorkbenchPart)

bringToTop(IWorkbenchPart)

findView(String)

getViewReferences()

hideView(IViewPart)

showView(String)

IWorkbenchPartReference

getId()

getPage()

getPart(boolean)

IViewReference

getView(boolean)

isFastView()

WorkbenchPart

dispose()

getConfigurationElement()

getSite()

setPartName(String)

ViewPart

getViewSite()

init(IViewSite)

init(IViewSite, IMemento)

saveState(IMemento)

IWorkbenchPart

createPartControl(Composite)

dispose()

getSite()

IViewPart

getViewSite()

init(IViewSite)

init(IViewSite, IMemento)

saveState(IMemento)

IWorkbenchSite

getPage()

getSelectionProvider()

getShell()

getWorkbenchWindow()

setSelectionProvider(ISelectionProvider)

IWorkbenchPartSite

getKeyBindingService()

registerContextMenu(MenuManager, ISelectionProvider)

registerContextMenu(String, MenuManager, ISelectionProvider)

IViewSite

getActionBars()

� Principales interfaces et classes pour la gestion des vues

Dépendance

Héritage

Page 8: Construction de vues avec la plateforme Eclipse

8Views - M. Baron - Page

keul

keul

.blo

gspo

t.comConstruction d'une vue par extension

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

Création d’une vue àpartir du template

Sample View

Création d’une extension à partir du point d’extension org.eclipse.ui.views

Page 9: Construction de vues avec la plateforme Eclipse

9Views - M. Baron - Page

keul

keul

.blo

gspo

t.comConstruction d'une vue par extension

� Définir les attributs de l’extension

Identifiant de la vue

Nom de la vue

Objet de type ViewPartdécrivant le contenu d’une vue

Ratio pour l’ouverture de la vue en mode

FastView

Possibilité d’avoir plusieurs instances de

cette vue

Possibilité de retrouver la vue après un redémarrage

du Workbench

Page 10: Construction de vues avec la plateforme Eclipse

10Views - M. Baron - Page

keul

keul

.blo

gspo

t.comConstruction d'une vue par extension

� Etendre une vue de type ViewPart

package eclipse.workbench.viewexample.views

public class SimpleView extends ViewPart {

public SampleView() {}

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

}

public void setFocus() {}

}

SimpleView.java du Projet ViewExample

Création du contenu en utilisant des composants SWT

Page 11: Construction de vues avec la plateforme Eclipse

11Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart

� La définition d’une nouvelle vue est obtenue en héritant de

la classe ViewPart

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

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

� void setFocus() : précise le composant SWT qui aura le focus à

chaque activation de la vue

� Des méthodes qui peuvent être redéfinies (à voir plus tard)

� setInitializationData(…) : appelée lors de la création de l’extension

� init(IWorkbenchPartSite p) : appelée pour initialiser le contexte de la vue (quelle est la Shell parente, la page active, …)

� Des méthodes à exploiter

� IViewSite getViewSite() : site de la vue (étudier par la suite)

� void setPartName(String ti) : modifie le titre

Page 12: Construction de vues avec la plateforme Eclipse

12Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart

� L’implémentation de la méthode createPartControl suit un

processus assez similaire

� Modifier l’agent de placement du parent si nécessaire

� Créer un ou plusieurs composants SWT / JFace à l’intérieur du parent

� Déclarer des nouvelles actions avec la barre d’actions du site

� Déclarer un nouveau menu contextuel dans le Workbench avec le site

� Déclarer l’écoute de la sélection d’un composant avec le site

Les déclarations d’actions, d’un menu contextuel et de la sélection seront étudiés en détail dans la suite

Page 13: Construction de vues avec la plateforme Eclipse

13Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart et IViewSite

� Le site d’une vue est une sorte de pont entre la vue (définit

par ViewPart) et le Workbench

� Il faut voir le site comme un objet qui permet de lier la vue

au contexte de l’application

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

� IWorkbenchPage getPage() : la page dans laquelle la vue est stockée

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

� IWorkbenchWindow getWorkbenchWindow() : la fenêtre déclarative contenant la vue

� 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 14: Construction de vues avec la plateforme Eclipse

14Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart et IViewSite

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

des méthodes spécifiques

� IActionBars getActionBars() : la barre d’action de la vue

� String getSecondaryId() : identifiant secondaire utilisé pour gérer des

instances multiples de la vue

Le contenu de la vue est défini par la méthode createPartControl

L’ajout d’actions se fait via le site de la vue

Sera utilisée dans la partie Vues Multiples

Page 15: Construction de vues avec la plateforme Eclipse

15Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart et IViewSite

� Exemple : accéder aux éléments du site d’une vue

package eclipse.workbench.viewexample.views

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

parent.setLayout(new GridLayout(2,true));

Button buttonLeft = new Button(parent, SWT. FLAT);buttonLeft.setText("LEFT_Button");

Button buttonRight = new Button(parent, SWT. FLAT);buttonRight.setText("RIGHT_Button");

GridData myGridData = new GridData(GridData. FILL_BOTH);myGridData.horizontalSpan = 2;viewer = new TableViewer(parent, SWT. MULTI | SWT. H_SCROLL | SWT. V_SCROLL);viewer.setContentProvider(new ViewContentProvider() );viewer.setLabelProvider(new ViewLabelProvider());viewer.getControl().setLayoutData(myGridData);viewer.setInput(this.getViewSite());

this.createActions();this.createToolBar();this.createContextMenu();

}}

SiteView.java du Projet ViewExample

Modification de l’agent de placement du parent

Construction de l’interface à partir de composants SWT

Création des actions, de la barre d’outils et du menu

contextuel

Page 16: Construction de vues avec la plateforme Eclipse

16Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

ViewPart et IViewSite

� Exemple (suite) : accéder aux éléments du site d’une vue...private void createActions() {

action1 = new Action("Action 1") {public void run() { System. out.println("Action 1 Performed"); }

};action2 = new Action("Action 2") {

public void run() { System. out.println("Action 2 Performed"); }};

}

private void createToolBar() {IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();mgr.add(this.action1);mgr.add(this.action2);

}

private void createContextMenu() {MenuManager menuMgr = new MenuManager();menuMgr.setRemoveAllWhenShown(true);menuMgr.addMenuListener(new IMenuListener() {

public void menuAboutToShow(IMenuManager mgr) {mgr.add(action1);mgr.add(new Separator());mgr.add(action2);

}});

Menu menu = menuMgr.createContextMenu(viewer.getCont rol());Viewer.getControl().setMenu(menu);getSite().registerContextMenu(menuMgr, viewer);

}

SiteView.java du Projet ViewExample

Ce menu est déclaré dans le Workbench. L’extension du menu devient possible

Page 17: Construction de vues avec la plateforme Eclipse

17Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Une Sticky View est une vue partagée à toutes les perspec-

tives d’une application Eclipse

� Une Sticky View n’est pas associée explicitement à une

perspective, la déclaration est implicite

� Lors du chargement d’une perspective, une Sticky View

déjà ouverte le reste et conserve sa position

� Un « reset » sur une perspective ne fermera pas une Sticky

View

� La fermeture d’une Sticky View ne peut se faire que par

une demande explicite (fermeture de la vue associée)

� Pour quelle occasion ?

� Cheat Sheets (aide contextualisée)

Page 18: Construction de vues avec la plateforme Eclipse

18Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Création d’une vue classique

plugin.xml du projet ViewExample

Onglet Extensions

Page 19: Construction de vues avec la plateforme Eclipse

19Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Création d’une vue classique (suite)

package eclipse.workbench.viewexample.views

public class StickyViewPart extends ViewPart {

public StickyViewPart() {}

public void createPartControl(Composite parent) {Label myCurrentLabel = new Label(parent, SWT. NONE);myCurrentLabel.setText("View used for the StickyView V iewExample series");

}

public void setFocus() {}

}

StickyViewPart.java du projet ViewExample

plugin.xml du projet ViewExample

Page 20: Construction de vues avec la plateforme Eclipse

20Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Création d’une Sticky View

Onglet Extensions

plugin.xml du projet ViewExample

Page 21: Construction de vues avec la plateforme Eclipse

21Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Association d’une vue avec une Sticky View

Vue qui sera transformée en Sticky View

Identifiant d’une vue existante

Position de la Sticky View dans les perspectives (BOTTOM,

RIGHT, LEFT, TOP)

Précise si la Sticky Viewpeut elle être fermée ?

La Sticky View peut elle être déplacée

plugin.xml du projet ViewExample

Page 22: Construction de vues avec la plateforme Eclipse

22Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Sticky View

� Exemple : une vue transformée en Sticky View

La Sticky View est visible et conserve son emplacement lors des

changements des perspectives

Projet ViewExample

Page 23: Construction de vues avec la plateforme Eclipse

23Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Category

� Une Category est un regroupement de vues utilisée pour

organiser la liste des vues dans le menu Window -> Show

View -> Other

� Possibilité d’associer une vue à une

nouvelle catégorie ou à une catégorie

déjà existante

� Les catégories sont hiérarchiques,

possibilité de spécifier à une catégorie

une catégorie parente existante

� Les catégories sont identifiées par un

identifiant unique Plusieurs catégories existantes : General, Debug,

Help, Java, …

Page 24: Construction de vues avec la plateforme Eclipse

24Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Category

� Création d’une Category

plugin.xml du projet ViewExample

Création d’une nouvelle catégorie

Identifiant de la nouvelle catégorie

Nom de la nouvelle catégorie

Parent de la catégorie (optionnelle)

Onglet Extensions

Page 25: Construction de vues avec la plateforme Eclipse

25Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Category

� Associer la vue à la catégorie plugin.xml du projet ViewExample

Onglet Extensions

La vue ViewCategory est associée à la catégorie *.ViewExample.Category

La liste des vues est accessible via le menu Window -> Show View

-> Other

La vue ViewCategory est contenu dans la catégorie

Category Example

Page 26: Construction de vues avec la plateforme Eclipse

26Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vue Détachée

� Une vue détachée est une vue affichée dans une fenêtre

autre que celle de la WorkbenchWindow

� Une vue détachée appartient toujours à sa perspective

� Pour détacher une vue, afficher le menu contextuel (bouton

droit) puis option Detached

� Au niveau des APIs de manipulation des vues détachées

c’est le grand vide …

� Savoir si une vue est détachée ?

� Pas d’écouteur pour savoir si une vue est détachée

� Solution : titre de la fenêtre est vide, quand la vue est détachée les

événements de redimensionnement sont déclenchés

� Détacher une vue

� Utilisation des APIs internes

Page 27: Construction de vues avec la plateforme Eclipse

27Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vue Détachée

� Exemple : Détecter qu’une vue est détachée

La vue Detach View est détachée

Page 28: Construction de vues avec la plateforme Eclipse

28Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vue Détachée

� Exemple (suite) : Détecter qu’une vue est détachéepublic class DetachViewPart extends ViewPart {

private Composite parent;private Label label;protected boolean isDetached;

public DetachViewPart() {}

@Overridepublic void createPartControl(Composite parent) {

this.parent = parent;parent.setLayout(new RowLayout());label = new Label(parent, SWT.NONE);parent.addControlListener(new ControlAdapter() {

@Overridepublic void controlResized(ControlEvent e) {

updateDetached();}

});updateDetached();

}

private void updateDetached() {isDetached = parent.getShell().getText().length() == 0;label.setText("View isDetached? " + isDetached);

}

...}

DetachViewPart.java du Projet ViewExample

Page 29: Construction de vues avec la plateforme Eclipse

29Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vue Détachée

� Exemple : Attacher et Détacher une vue par code

Attache ou Détache une vue selon son état Détaché ou pas

Page 30: Construction de vues avec la plateforme Eclipse

30Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vue Détachée

� Exemple (suite) : Attacher et Détacher une vue par codepublic class OpenDetachViewPart extends DetachViewPar t {

public OpenDetachViewPart() {}

@Overridepublic void createPartControl(Composite parent) {

super.createPartControl(parent);Button detachViewButton = new Button(parent, SWT.NONE );detachViewButton.addSelectionListener(new Selection Adapter() {

public void widgetSelected(SelectionEvent e) {IWorkbenchPage page = getSite().getPage();final IViewReference findViewReference = page.findVie wReference(

"eclipse.workbench.ViewExample.openDetachViewId");if (!isDetached) {

((WorkbenchPage) page).detachView(findViewReference );} else {

((WorkbenchPage) page).attachView(findViewReference );}

}});

detachViewButton.setText("Attach/Detach");}

...}

AttachOrDetachViewPart.java du Projet ViewExample

Réutilise la vue DetachViewPart pour

connaître l’état de la vue

Page 31: Construction de vues avec la plateforme Eclipse

31Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� Jusque là nous avons vu qu’une vue est identifiée par

un identifiant unique définie lors de la création d’une

extension (attribut id)

� Le conteneur de la plateforme Eclipse s’appuie sur cet

identifiant pour la création de l’instance de la vue

� Par conséquent, une seule instance de la vue ne peut être

créée par le conteneur de la plateforme Eclipse

� Or, il peut être intéressant d’afficher plusieurs instances

d’une même vue

� Un second identifiant est utilisé pour la création d’instances

multiples

Page 32: Construction de vues avec la plateforme Eclipse

32Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� Une vue est donc identifiée par un identifiant primaire et un

identifiant secondaire (par défaut est vide)

� Une instance d’une vue est identifiée de la manière suivante

� Pour activer la gestion des instances multiples d’une vue, il

faut modifier le paramètre allowMultiple à true

� Différentes manières de construire une instance multiple

d’une vue

Identifiant_Primaire:Identifiant_Secondaire

Identifiant primaire déclarélors de la définition de la vue

Identifiant secondaire déclaré pour chaque nouvelle instance de la vue

Page 33: Construction de vues avec la plateforme Eclipse

33Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

Identifiant primaire de la vue Multiple Instances View 1

Ne pas ajouter un identifiant secondaire lors de la définition de la vue

� Activation de la gestion multiple d’une vue

La gestion multiple de cette vue est activée

Page 34: Construction de vues avec la plateforme Eclipse

34Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� Exemple 1 : Vues multiples à partir de IPageLayout

package eclipse.workbench.viewexample.views

public class MultipleInstancesViewFactory implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {String editorAreaId = layout.getEditorArea();

layout.addView(" eclipse.workbench.ViewExample.MultipleInstanceView1:1", IPageLayout. LEFT, 0.25f, editorAreaId);

layout.addView(" eclipse.workbench.ViewExample.MultipleInstanceView1:2", IPageLayout. BOTTOM, 0.25f, editorAreaId);

}}

MultipleInstancesViewFactory.javadu projet ViewExample

Création de deux instances de la même vue

Création statique d’instances

multiples de la vue

Page 35: Construction de vues avec la plateforme Eclipse

35Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

MultipleInstancesViewFactorydu projet ViewExample

La vue Multiple Instances View 1 est instanciée deux fois

� Exemple 1 (suite) : Vues multiples à partir de IPageLayout

Page 36: Construction de vues avec la plateforme Eclipse

36Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� Exemple 2 : Vues multiples à partir de IWorkbenchPage

package eclipse.workbench.viewexample.views

public class AddSecondaryViewAction implements IWorkb enchWindowActionDelegate {private int secondaryIdCount = 0;

public AddSecondaryViewAction() { }

public void run(IAction action) {try {

PlatformUI. getWorkbench().getActiveWorkbenchWindow().getActivePage(). showView("eclipse.workbench.ViewExample.MultipleInstanceView2",Integer.toString(secondaryIdCount),IWorkbenchPage.VIEW_ACTIVATE);secondaryIdCount++;

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

}}

public void selectionChanged(IAction action, ISelecti on selection) { }

public void dispose() { }

public void init(IWorkbenchWindow window) { }}

AddSecondaryViewAction.javadu projet ViewExample

La méthode showView permet d’ajouter une vue en donnant un

identifiant secondaire

Création dynamique d’instances

multiples de la vue

Page 37: Construction de vues avec la plateforme Eclipse

37Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� Exemple 2 (suite) : Vues multiples à partir de IWorkbench…

AddSecondaryViewAction du projet ViewExample

Action permettant la création de nouvelles

instances de vue

Plusieurs instances de vue

Page 38: Construction de vues avec la plateforme Eclipse

38Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

� La création d’une vue via la méthode showView(…) varie

selon le mode de fonctionnement utilisé

� IViewPart showView(String id, String secId, int mode) throws

PartInitException : crée une vue à partir d’un identifiant primaire id,

d’un identifiant secondaire secId et d’un mode

� Différentes valeurs pour mode

� VIEW_ACTIVATE : vue est visible et a le focus

� VIEW_VISIBLE : vue visible mais n’a pas le focus

� VIEW_CREATE : vue créée mais n’a pas forcément le focus

Vues multiples

Page 39: Construction de vues avec la plateforme Eclipse

39Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Vues multiples

� A partir du code d’une ViewPart il est possible de connaître l’identifiant secondaire au travers du site de la vue via

l’interface IViewSite

� String getSecondaryId() : identifiant secondaire utilisé pour gérer des instances multiples de la vue

� Exemple : afficher l’identifiant secondaire d’une vuepackage eclipse.workbench.viewexample.views

public class MultipleInstanceViewPart2 extends ViewP art {

public MultipleInstanceViewPart2() { }

public void createPartControl(Composite parent) {Button myButton = new Button(parent, SWT. FLAT);myButton.setText("Give me the Secondary ID");myButton.addSelectionListener(new SelectionAdapter( ) {

public void widgetSelected(SelectionEvent e) {String secondaryId = getViewSite().getSecondaryId();System. out.println(secondaryId);

}});

}

public void setFocus() { }}

MultipleInstanceViewPart2.javadu projet ViewExample

Identifiant secondaire

Page 40: Construction de vues avec la plateforme Eclipse

40Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

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

pour stocker l’intégralité des vues créées (incluant

également les Sticky Views et les Categories)

� Il n’existe qu’un seul registre de vue géré par le Workbench

� A partir de ce registre il est possible de

� Chercher une vue par son identifiant

� Récupérer l’ensemble des Categories, des Sticky Views ou des Views

IViewRegistry viewRegistry = PlatformUI.getWorkbench( ).getViewRegistry();

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

Page 41: Construction de vues avec la plateforme Eclipse

41Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

� L’interface IViewRegistry dispose des méthodes suivantes

� IViewDescriptor find(String id) : recherche une vue par son id

� IViewCategory[] getCategories() : récupère l’intégralité des catégories

� IStickyViewDescriptor[] getStickyViews() : retourne l’intégralité des

Sticky Views

� IViewDescriptor[] getViews() : retourne l’intégralité des vues issues

du registre des vues

� L’interface IViewCategory représente une catégorie de vues

� String getId() : id de la catégorie

� String getLabel() : nom de la catégorie

� IPath getPath() : chemin de la catégorie (parent)

� IViewDescriptor getViews() : liste des vues

Page 42: Construction de vues avec la plateforme Eclipse

42Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

� L’interface IViewDescriptor décrit le contenu d’une vue

� String getId() : identifiant de la vue

� String getLabel() : nom

� String getDescription() : description

� float getFastViewWithRatio() : ratio

� boolean getAllowMultiple() : instances multiples ou pas

� String getCategoryPath() : chemin des catégories

� isRestorable() : vue reconstruite au redémarrage de l’application

� IViewPart createView() : création d’une instance (peu utilisé car

réalisé par le conteneur)

� Le registre des vues ne gère pas les instances IViewPart,

elles le sont au niveau de la page

Page 43: Construction de vues avec la plateforme Eclipse

43Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

� L’interface IStickyViewDescriptor représente une Sticky View

� String getId() : identifiant de la vue

� int getLocation() : position de la vue dans la WorkbenchWindow

� boolean isCloseable() : la vue peut-elle être fermée

� isMoveable() : la vue peut-elle être déplacée

Page 44: Construction de vues avec la plateforme Eclipse

44Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

� Exemple : interroger le registre des vuespackage eclipse.workbench.viewexample.views

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

...Button findView = new Button(parent, SWT. FLAT);findView.addSelectionListener(new SelectionAdapter( ) {

public void widgetSelected(SelectionEvent e) {System. out.println("- Find View -");IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry();

ViewDescriptor find = viewRegistry.find("eclipse.workbench.ViewExample.views.ViewRegistryId");

System. out.println(find.getLabel());System. out.println(find.getAllowMultiple());

}});findView.setText("Find : ViewRegistryId");

Button getCategories = new Button(parent, SWT. FLAT);getCategories.addSelectionListener(new SelectionAda pter() {

public void widgetSelected(SelectionEvent e) {System. out.println("- Get Categories -");IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry();IViewCategory[] categories = viewRegistry.getCategories();for (IViewCategory viewCategory : categories) {

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

}});getCategories.setText("Get Categories");...

}}

ViewRegistryViewPart.java du projet ViewExample

Page 45: Construction de vues avec la plateforme Eclipse

45Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Registre des vues

� Exemple (suite) : interroger le registre des vues

...Button getStickyViews = new Button(parent, SWT. FLAT);getStickyViews.addSelectionListener(new SelectionAd apter() {

public void widgetSelected(SelectionEvent e) {System. out.println("- Get Sticky Views -");IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry();IStickyViewDescriptor[] stickyViews = viewRegistry.getStickyViews();for (IStickyViewDescriptor stickyViewDescriptor : sti ckyViews) {

System. out.println(stickyViewDescriptor.getId() + stickyViewD escriptor.getLocation());}

}});getStickyViews.setText("Get Sticky Views");Button getViews = new Button(parent, SWT. FLAT);getViews.addSelectionListener(new SelectionAdapter( ) {

public void widgetSelected(SelectionEvent e) {System. out.println("- Get Views -");IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry();IViewDescriptor[] views = viewRegistry.getViews();for (IViewDescriptor viewDescriptor : views) {

System. out.println(viewDescriptor.getId());}

}});getViews.setText("Get Views");

}}

ViewRegistryViewPart.java du projet ViewExample

Page 46: Construction de vues avec la plateforme Eclipse

46Views - 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 ViewPart (celle utilisée pour

programmer l’interface d’une vue)

� Pour rappel l’agencement des objets ViewPart d’une page

est réalisé par les perspectives

� L’instance d’une ViewPart est associée à son identifiant (id)

� Il peut exister plusieurs instances d’une ViewPart dans le

cas ou dans la description de la vue, la gestion des instances

multiples est activée (id:idSecondaire)

Page 47: Construction de vues avec la plateforme Eclipse

47Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Cycle de vie

� L’interface IViewReference décrit la relation entre identifiant

et instance de ViewPart

� String getId() : identifiant primaire de la vue

� String getSecondaryId() : identifiant secondaire de la vue

� IViewPart getView(boolean restore) : référence à la ViewPart, restore

à TRUE pour tenter de la restaurer si elle n’existe pas

� boolean isFastView() : cette vue est de type FastView

� IWorkbenchPage getPage() : Workbench Page dans laquelle cette

vue est référencée

� String getPartName() : le nom à afficher

� …

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

du Workbench Page actif

Page 48: Construction de vues avec la plateforme Eclipse

48Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

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

ViewPart dans le cas où il n’existe aucune instance de

cette ViewPart dans le Workbench Page actif

� L’ouverture d’une vue déjà présente dans une perspective

rend active cette vue. Aucune nouvelle instance est créée

� L’ouverture d’une vue dans une autre perspective affiche la

vue sans re-créér une nouvelle instance (les ViewPart sont

partagées dans les perspectives)

� Dans le cas des vues avec instances multiples, la stratégie

d’ouverture est identique sauf qu’il peut exister plusieurs

instances d’une même ViewPart

Page 49: Construction de vues avec la plateforme Eclipse

49Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

Ouverture de la vue SimpleViewdans la perspective Resource

Création d’une instance de la classe SimpleView.java du

projet ViewExample stockée dans la page courante

La vue SimpleView n’a jamais encore été ouverte

� Démonstration …

Page 50: Construction de vues avec la plateforme Eclipse

50Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

La vue SimpleView est déjàouverte dans la perspective

Resource

La vue SimpleView est ajoutée à la perspective

SimplePerspective

Comme une instance àSimpleView existe, aucune autre instance n’est créée

� Démonstration (suite) …

Page 51: Construction de vues avec la plateforme Eclipse

51Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

� Lors de l’analyse de la classe ViewPart seules les méthodes

createPartControl(…) et setFocus() avaient été étudiées

� D’autres méthodes sont fournies et appelées par le conte-

neur (suivant un ordre donné) pour instancier la ViewPart

� Constructeur de la classe

� void setInitializationData(IConfigurationElement, String, Object) : les

informations de l’extension sont passées en paramètre permettant

de connaître le titre, le nom, l’image, …

� void init(IViewSite) : initialise l’instance avec le site

� void init(IViewSite, IMemento) : idem sauf que l’objet IMemento

permet de restaurer un état (voir fermeture d’une vue)

� void createPartControl(Composite) : pour programmer l’IHM

� Méthodes appelées uniquement à la création de l’instance

1

2

3

4

5

Page 52: Construction de vues avec la plateforme Eclipse

52Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

� Exemple : accès aux informations de l’extension d’une vue

public class OpenLifeCycle extends ViewPart {

public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {super.setInitializationData(cfig, propertyName, data);

System.out.println(cfig.getAttribute("name"));}

public OpenLifeCycle() {}

public void createPartControl(Composite parent) {}

public void setFocus() {}

}

OpenLifeCycle du projet ViewExample

Récupération des informations de l’extension utilisée par la création de

cette vue

Page 53: Construction de vues avec la plateforme Eclipse

53Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – ouverture d’une vue

� A l’ouverture, la vue passe par différents états

� Opened : lors de la création de l’instance d’une ViewPart

� Visible : la vue est visible

� Activated : la vue a le focus

La vue SimpleView a été ajoutée par le menu Show View

Les différents états de la vue : Opened -> Visible -> Activated

Page 54: Construction de vues avec la plateforme Eclipse

54Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – fermeture d’une vue

� Lors de la fermeture d’une vue dans une perspective le

Workbench Page vérifie si cette vue est également présente

dans d’autres perspectives

� Présente : la vue est cachée

� Non présente : la référence ViewPart est disposée

� Quand une référence ViewPart est disposée, elle est suppri-

mée de la liste des IViewReference du Workbench Page

� Une nouvelle référence doit être créée pour ré-ouvrir la vue

Page 55: Construction de vues avec la plateforme Eclipse

55Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCycle de vie – fermeture d’une vue

� D’autres méthodes sont appelées par le conteneur (suivant

un ordre donné) lors de la fermeture d’une vue

� void saveState(IMemento memento) : appelée uniquement quand

l’application Eclipse doit être fermée. Cette méthode n’est pas appelée

s’il n’existe pas de vue ouverte (référence n’existe pas)

� void dispose() : suppression de la référence quand la vue doit être

disposée

� A la fermeture, la vue passe par différents états

� Deactivated : la vue n’a plus le focus

� Hidden : la vue est cachée

� Closed : l’instance de la vue est disposée

Page 56: Construction de vues avec la plateforme Eclipse

56Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues

� Dans tous les exemples que nous avons étudiés nous

n’avons encore jamais échangé d’information entre vues

� Informations à partager

� Des attributs d’une classe ViewPart

� Sélection courante d’une TableViewer

� Et pourtant, la plateforme Eclipse fournit un ensemble de

mécanismes pour faciliter la communication entre vues

� Nous étudions dans cette partie ces mécanismes

� Communication directe entre des ViewParts

� Communication à partir des écouteurs de vues

� Service de sélection

� Le patron Adaptateur via IAdaptable

Page 57: Construction de vues avec la plateforme Eclipse

57Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (en direct …)

� Le premier mécanisme consiste à récupérer l’instance d’une

ViewPart à partir de l’identifiant de sa vue

� Une classe ViewPart spécialisée peut éventuellement

disposer d’attributs ou d’un modèle de données à partager

� Le registre des vues ne permet pas de récupérer des

instances de ViewPart puisque ces instances sont gérées au niveau de la page (voir cycle de vie)

� Il faut passer par la page active pour récupérer cette

instance de ViewPart en fonction de l’identifiant de la vue

IWorkbenchPage page = PlatformUI. getWorkbench().getActiveWorkbenchWindow().getActivePage();

IViewPart viewPart = page.findViewReference(String id ).getView(true);

Récupération de la page active

Récupération de l’instance ViewPart d’une vue en fonction de son identifiant par rapport à la page active

Page 58: Construction de vues avec la plateforme Eclipse

58Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (en direct …)

� Exemple : communication entre deux instances ViewPartpackage eclipse.workbench.linkviewexample.views

public class LinkView2 extends ViewPart {

private String familyName;private String firstName;

public LinkView2() { }

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

Label nameLabel = new Label(parent, SWT. NONE);nameLabel.setText("Family Name");Label fnameLabel = new Label(parent, SWT. NONE);fnameLabel.setText("First Name");final Text nameText = new Text(parent, SWT. BORDER);nameText.addModifyListener(new ModifyListener() {

public void modifyText(ModifyEvent e) {familyName = nameText.getText();

}});final Text fnameText = new Text(parent, SWT. BORDER);fnameText.addModifyListener(new ModifyListener() {

public void modifyText(ModifyEvent e) {firstName = fnameText.getText();

}});

}...

}

LinkView2.java du projet LinkViewExample

Attribut spécifique à la classe LinkView2.java

Perspective Link Direct

Page 59: Construction de vues avec la plateforme Eclipse

59Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (en direct …)

� Exemple (suite) : communication entre deux instances …

package eclipse.workbench.linkviewexample.views

public class LinkView1 extends ViewPart {

public void createPartControl(Composite parent) {Button getLinkView2DataButton = new Button(parent, S WT.FLAT);getLinkView2DataButton.addSelectionListener(new Sel ectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();IViewPart findView =

activePage.findViewReference("eclipse.workbench.LinkViewExample.views.linkviewid2");

if (findView != null) {String familyName = ((LinkView2)findView).getFamilyN ame();String firstName = ((LinkView2)findView).getFirstNam e();System. out.println(familyName + " " + firstName);

} else {System. out.println("Instance de vue non créée");

}}});getLinkView2DataButton.setText("Retrieve information from LinkView2");

}

...}

LinkView1.java du projet LinkViewExample

Page 60: Construction de vues avec la plateforme Eclipse

60Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (en direct …)

� Comme les instances ViewPart sont gérées au niveau de la

page, il se peut que des instances d’une vue ne soient pas

encore créées

� Par conséquent il existe un couplage fort entre ViewPart

� Le scénario suivant peut se produire

� Une vue identifiée par id1 (dans le contenu de sa ViewPart) souhaite

accéder à une instance ViewPart d’une vue identifiée par id2

� Si la vue id2 n’a pas été créée (par exemple par encore visible dans

une perspective) l’instance de sa ViewPart sera null

� La vue id1 ne pourra pas accéder aux informations de la ViewPart de

id2 tant que la création n’a pas été réalisée

� Le problème se complexifie si les vues gère les instances

multiples

Page 61: Construction de vues avec la plateforme Eclipse

61Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (en direct …)

� Exemple : communication entre deux instances ViewPart

package eclipse.workbench.linkviewexample.views

public class MultipleLinkView extends ViewPart {

public void createPartControl(Composite parent) {Button getLinkView2DataButton = new Button(parent, S WT.FLAT);getLinkView2DataButton.addSelectionListener(new Sel ectionAdapter() {

public void widgetSelected(SelectionEvent e) {IWorkbenchPage activePage = PlatformUI. getWorkbench().getActiveWorkbenchWindow().getActivePage();IViewPart findView =

activePage.findViewReference("eclipse.workbench.LinkViewExample.views.linkviewid2","1").getView(true);

if (findView != null) {String familyName = ((LinkView2)findView).getFamilyN ame();String firstName = ((LinkView2)findView).getFirstNam e();System. out.println(familyName + " " + firstName);

} else {System. out.println("Instance de vue non créée");

}}});getLinkView2DataButton.setText("Retrieve information from LinkView2");

}

...}

MultipleLinkView.java du projet LinkViewExample

Récupération de l’instance d’une

ViewPart par rapport àl’identifiant primaire et

secondaire

Page 62: Construction de vues avec la plateforme Eclipse

62Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (Part Listeners)

� Une vue peut subir des modifications comme l’activation,

l’ouverture ou la visibilité et permet d’effectuer des

changements à la réponse des événements

� L’activation et la création des vues peuvent être écoutées 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 63: Construction de vues avec la plateforme Eclipse

63Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (Part Listeners)

� IPartListener2 fournit les méthodes suivantes pour les

réponses aux événements sur la vue (

� 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

� Malheureusement certaines méthodes sont manquantes

comme : vue détachée, vue transformée en Fast View, vue

dockée …

Page 64: Construction de vues avec la plateforme Eclipse

64Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (Part Listeners)

� Exemple : écouter les changements d’une ViewPartpackage eclipse.workbench.ipartserviceexample.views

public class PartListenerViewPart extends ViewPart {

public void createPartControl(Composite parent) {parent.setLayout(new GridLayout(1, false));Label myLabel = new Label(parent, SWT. NONE);myLabel.setText("Listened View");IWorkbenchPage activePage = PlatformUI. getWorkbench().getActiveWorkbenchWindow().getActivePage();activePage.addPartListener(new IPartListener2() {

@Overridepublic void partActivated(IWorkbenchPartReference partRef) {

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

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

}@Overridepublic void partBroughtToTop(IWorkbenchPartReference partRef) {

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

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

}@Overridepublic void partClosed(IWorkbenchPartReference partRef) {

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

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

}} ...

}

PartListenerViewPart.java du projet IPartServiceExample

Liste des méthodes déclenchées lors de l’écoute de la ViewPart

Page 65: Construction de vues avec la plateforme Eclipse

65Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Le service de sélection permet à des vues d’avertir la plate-

forme Eclipse qu’une sélection sur des objets a été réalisée

� Exemple : vues Package Explorer et Properties

Le changement de sélection d’un fichier provoque la modification de la vue Properties

Page 66: Construction de vues avec la plateforme Eclipse

66Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Toutes modifications de sélection réalisées par les fournis-

seurs (Provider) sont transmises aux écouteurs (Listener)

� Le service de sélection est unique pour chaque Workbench

Window

� Il fonctionne à la manière d’un Bus où tout fournisseur peut

se connecter et où tout écouteur peut s’abonner

Instance unique par Workbench Window

Des fournisseurs existants de la plateforme

Des écouteurs existants de la plateforme

Des fournisseurs spécifiques

Page 67: Construction de vues avec la plateforme Eclipse

67Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� L’écouteur reçoit des informations liées à la sélection

� L’origine de la sélection (le fournisseur)

� Les informations de la sélection (les objets)

� Les informations de la sélection sont de deux natures

� Une liste d’objets (une ligne d’un composant TableViewer)

� Une zone de texte (un bloc de texte d’un éditeur)

� La structure de données est définie par l’interface ISelection(vue dans la partie Composants Additionnels avec Java)

Page 68: Construction de vues avec la plateforme Eclipse

68Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Un fournisseur doit implémenter l’interface ISelectionProvider

� Tous les composants Viewer de JFace sont des fournisseurs

de sélection

� void addSelectionChangedListener(ISelectionChangedListener) : ajout

d’un écouteur sur la sélection courante

� ISelection getSelection() : récupère la sélection courante

� void setSelection(ISelection) : modifie la sélection courante

� Toutefois, cette sélection est locale au composant Viewer

� Pour la diffuser au service de sélection il est nécessaire de

connecter un objet ISelectionProvider au Workbench

getSite().setSelectionProvider(tableViewer);

Site de la ViewPartcontenant le Viewer

Objet ISelectionProvider àconnecter au service de sélection

Page 69: Construction de vues avec la plateforme Eclipse

69Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Différents types de données de sélections en fonction du

type de composant Viewer

� ComboViewer

� ListViewer

� TreeViewer

� CheckboxTreeViewer

� TableViewer

� CheckboxTableViewer

� TextViewer

� SourceViewer

� ProjectionViewer

IStructuredSelection

IStructuredSelection

IStructuredSelection, ITreeSelection

IStructuredSelection, ITreeSelection

IStructuredSelection

IStructuredSelection

ITextSelection, IMarkSelection

ITextSelection, IMarkSelection

ITextSelection, IMarkSelection

Page 70: Construction de vues avec la plateforme Eclipse

70Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Chaque Workbench Window fournit un service de sélection de type ISelectionService

� Le service de sélection fournit les méthodes suivantes

� ISelection getSelection() : récupère la dernière sélection active

� ISelection getSelection(String partId) : récupère la sélection de la ViewPart définie par partId

� void addSelectionListener(ISelectionListener listener) : ajoute un écouteur sur les changements de sélection (voir transparent suivant)

� void addSelectionListener(String partId, ISelectionListener listener) : ajoute un écouteur sur les changements de la sélection d’une vue

� void addPostSelectionListener(ISelectionListener listener) : ajoute un écouteur sur des changements finaux

� Exemple ListViewer : l’écouteur ne sera averti qu’après un certaindélai de manière à éviter les sélections multiples

ISelectionService selService = getSite().getWorkbench Window().getSelectionService()

Page 71: Construction de vues avec la plateforme Eclipse

71Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� L’interface ISelectionListener fournit une seule méthode

� public void selectionChanged(IWorkbenchPart part, ISelection s) :

déclenchée lors du changement de la sélection courante

� L’interface INullSelectionListener (étend ISelectionListener)

ne fournit aucune méthode (Interface de marquage), elle

est utilisée dans les cas d’une non sélection

� Activation d’une ViewPart non connectée au service de sélection

� Toutes les vues et éditeurs du Workbench Window sont fermées

Page 72: Construction de vues avec la plateforme Eclipse

72Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Exemple : 1 vue productrice, 1 vue consommatrice

package eclipse.workbench.linkviewexample.views

public class ProviderViewPart extends ViewPart {

private TableViewer viewer;

public void createPartControl(Composite parent) {viewer = new TableViewer(parent, SWT. MULTI | SWT. H_SCROLL | SWT. V_SCROLL);viewer.setContentProvider(new ViewContentProvider() );viewer.setLabelProvider(new ViewLabelProvider());viewer.setInput(getViewSite());

this.getSite().setSelectionProvider(viewer);}

...}

ProviderViewPart.java du projet LinkViewExample

Connexion du SelectionProvider(viewer) au service de sélection

Page 73: Construction de vues avec la plateforme Eclipse

73Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Exemple (suite) : 1 vue productrice, 1 vue consommatricepackage eclipse.workbench.linkviewexample.views

public class ListenerViewPart extends ViewPart {

private Label listenerLabel;

public void createPartControl(Composite parent) {parent.setLayout(new GridLayout(1, false));listenerLabel = new Label(parent, SWT. NONE);

this.getSite().getWorkbenchWindow().getSelectionService().addSelectionListener("eclipse.workbench.LinkViewExample.views.ProviderViewPartId", new ISelectionListener() {

public void selectionChanged(IWorkbenchPart part, ISelection selection) {if (selection == null) {

return;}

if (selection instanceof IStructuredSelection) {IStructuredSelection structuredSelection = (IStructuredSelection)selection;Object firstElement = structuredSelection.getFirstElement();if (firstElement != null) {

listenerLabel.setText(firstElement.toString());listenerLabel.getParent().pack();

}}

}});

}...

}

ListenerViewPart.java du projet LinkViewExample

Ecouteur sur la sélection de la vue ProviderViewPartId

Utile pour redimensionner le parent

Récupération du service de sélection du Workbench Window

Page 74: Construction de vues avec la plateforme Eclipse

74Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Exemple : plusieurs TableViewers d’une ViewPart connectés

au service de sélection

Une vue contient deux composants TableViewer

Une vue utilisée pour écouter les changements de sélection de la vue

Multiple Providers

Utilisation de la classe SelectionProviderIntermediatepermettant de déléguer un SelectionProvider d’une

ViewPart au service de sélection

www.eclipse.org/articles/Article-WorkbenchSelections/article.html

Page 75: Construction de vues avec la plateforme Eclipse

75Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

� Exemple (suite) : plusieurs TableViewers d’une ViewPart

connectés au service de sélection

Communication entre vues (Selection Service)

package eclipse.workbench.multipleprovidersexample

public class MultipleProvidersViewPart extends ViewPa rt {

private Label listenerLabel;

public void createPartControl(Composite parent) {final SelectionProviderIntermediate selectionProvider = new SelectionProviderIntermediate();

viewer1 = new TableViewer(parent, SWT. MULTI | SWT. H_SCROLL | SWT. V_SCROLL);viewer1.setContentProvider(new ViewContentProvider( ));viewer1.setLabelProvider(new ViewLabelProvider());viewer1.setInput(getViewSite());

viewer2 = new TableViewer(parent, SWT. MULTI | SWT. H_SCROLL | SWT. V_SCROLL);viewer2.setContentProvider(new ViewContentProvider( ));viewer2.setLabelProvider(new ViewLabelProvider());viewer2.setInput(getViewSite());

this.getSite().setSelectionProvider(selectionProvider);

...}...

}

MultipleProvidersViewPart.java du projet MultipleProvidersExample

SelectionProvider « maison » utilisé pour connecter dynamiquement le Viewer de

la ViewPart au service de sélection

Le reste du code est présentédans la suite

Page 76: Construction de vues avec la plateforme Eclipse

76Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

� Exemple (suite) : plusieurs TableViewers d’une ViewPart

connectés au service de sélection

Communication entre vues (Selection Service)

package eclipse.workbench.multipleprovidersexample

public class SelectionProviderIntermediate implement s IPostSelectionProvider {private final ListenerList selectionListeners = new Li stenerList();private final ListenerList postSelectionListeners = ne w ListenerList();private ISelectionProvider delegate;

public void setSelectionProviderDelegate(ISelectionP rovider newDelegate) {if (delegate == newDelegate) { return; }if (delegate != null) {

delegate.removeSelectionChangedListener(selectionLi stener);if (delegate instanceof IPostSelectionProvider) {

((IPostSelectionProvider)delegate).removePostSelect ionChangedListener(postSelectionListener);}

}delegate = newDelegate;if (newDelegate != null) {

newDelegate.addSelectionChangedListener(selectionLi stener);if (newDelegate instanceof IPostSelectionProvider) {

((IPostSelectionProvider)newDelegate).addPostSelectionChangedListener(postSelectionListener);}fireSelectionChanged(newDelegate.getSelection());firePostSelectionChanged(newDelegate.getSelection() );

}}...

}

SelectionProviderIntermediate.java du projet MultipleProvidersExample inspirée de

www.eclipse.org/articles/Article-WorkbenchSelections/article.html

Chaque SelectionProviderdélégué est écouté

Page 77: Construction de vues avec la plateforme Eclipse

77Views - M. Baron - Page

keul

keul

.blo

gspo

t.com

Communication entre vues (Selection Service)

� Exemple (suite) : plusieurs TableViewers d’une ViewPart

connectés au service de sélection

package eclipse.workbench.multipleprovidersexample

public class MultipleProvidersViewPart extends ViewPa rt {

private Label listenerLabel;

public void createPartControl(Composite parent) {... // Voir précédent transparent

viewer1.addSelectionChangedListener(new ISelectionC hangedListener() {public void selectionChanged(SelectionChangedEvent ev ent) {

selectionProvider.setSelectionProviderDelegate(viewer1);}

});

viewer2.addSelectionChangedListener(new ISelectionC hangedListener() {public void selectionChanged(SelectionChangedEvent ev ent) {

selectionProvider.setSelectionProviderDelegate(viewer2);}

});...

}...

}

Suite de MultipleProvidersViewPart.javadu projet MultipleProvidersExample

A chaque changement de sélection d’un TableViewer modification du SelectionProvider via la classe de

délégation

Page 78: Construction de vues avec la plateforme Eclipse

78Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Précédemment nous avons étudié le service de sélection

qui permet de récupérer la sélection courante ISelection

� Pour rappel un objet de type ISelection « véhicule » l’objet

modèle d’un composant viewer

� Un écouteur du service de sélection (généralement une vue)

doit interpréter l’objet véhiculé pour le traduire en un objet

exploitable

� Inconvénients : couplage fort

� L’écouteur (la vue) doit connaître le type de l’objet véhiculé

� Nécessite une adaptation de l’écouteur à chaque nouveau type

d’objet véhiculé

� Dans certains, il n’est pas possible de modifier le code de l’écouteur

car il peut s’agir d’une vue de la plateforme : vue Properties

Page 79: Construction de vues avec la plateforme Eclipse

79Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

La vue Properties n’écoutent que les objets de type

IPropertySource

La vue Package Explorer manipule des objets d’un certains type

La vue Multiple Providers fournit des objets de type

String

ServiceSélection

Les objets de la vue Package Explorer sont adaptés en type

IPropertySource

Les objets de la vue Multiple Providers ne sont pas

consommés car la vue Propertiesne traite que les objets de type

IPropertySource

Objets consommés par

la vue Properties

Page 80: Construction de vues avec la plateforme Eclipse

80Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� L’écouteur ne doit manipuler que des objets dont il a

connaissance

� Exemple : la vue Properties ne peut manipuler que des objets de

type IPropertySource

� La transformation des objets du producteur en objet

écouteur utilise la patron de conception : adaptateur

� Nous allons montrer dans la suite comment exploiter le

service de sélection de manière à réduire le couplage entre

l’écouteur et le producteur

� Pour ce faire trois approches seront étudiées appliqué à un

exemple commun

Page 81: Construction de vues avec la plateforme Eclipse

81Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Exemple : carnet d’adresse avec informations de création et

de mise à jour

Un composant ListVieweraffiche la liste des noms du carnet d’adresse

La vue Properties affiche des informations complémentaires

lorsque un contact est sélectionné

Page 82: Construction de vues avec la plateforme Eclipse

82Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Exemple (suite) : carnet d’adresse avec informations de

création et de mise à jour

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

...final ListViewer contactsList = new ListViewer(contai ner, SWT. BORDER);contactsList.setLabelProvider(new ListLabelProvider ());contactsList.setContentProvider(new ContentProvider ());contactsList.setInput(Activator. getDefault().getContactManager());getViewSite().setSelectionProvider(contactsList);

}

class ContentProvider implements IStructuredContentPr ovider {public Object[] getElements(Object inputElement) {

Manager contactManager = (Manager) inputElement;return contactManager.contacts();

}...

}

class ListLabelProvider extends LabelProvider {public String getText(Object element) {

Contact contact = (Contact) element;return contact.getName();

}...

}}

Vue définie par ContactView.javacommune aux trois approches

Page 83: Construction de vues avec la plateforme Eclipse

83Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Exemple (suite) : carnet d’adresse avec informations de

création et de mise à jour

public class ContactManager {List<Contact> contacts;

public ContactManager() {this.contacts = new ArrayList<Contact>();

Contact contact = new Contact("Mickael BARON", "1 ru e des Eclipses");contact.setProperty("Created", "2008/04/05 11:44");contact.setProperty("Updated", "2008/04/05 11:53");this.contacts.add(contact);

contact = new Contact("Tom STORY", "11 rue du Pixar ");contact.setProperty("Created", "2008/04/05 15:21");contact.setProperty("Updated", "2008/04/07 09:48");this.contacts.add(contact);

contact = new Contact("Sarah PRINCESSE", "32 rue de s Goonies");contact.setProperty("Created", "2008/04/06 10:34");this.contacts.add(contact);

}

public Contact[] contacts() {return (Contact[])this.contacts.toArray(new Contact [0]);

}}

Fabrique des contacts définie par ContactManager.java commune aux trois approches

Page 84: Construction de vues avec la plateforme Eclipse

84Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Exemple (suite) : carnet d’adresse avec informations de

création et de mise à jour public class Contact {

private String address;private String name;private Map<String, Object> properties;

public Contact(String name, String address) {this.name = name; this.address = address;

}

public String getAddress() { return this.address; }public String getName() { return this.name; }

public synchronized Map<String, Object> getPropertie s() {if (this.properties == null) {

return Collections. emptyMap();}return new HashMap<String, Object>(this.properties) ;

}

public synchronized void setProperty(String key, Seri alizable value) {if (this.properties == null) {

this.properties = new HashMap<String, Object>();}this.properties.put(key, value);

}... // Le reste est spécifique à chaque approche, à v oir dans la suite

}

Classe Contact.java qui décrit l’objet envoyé lors d’une sélection

Page 85: Construction de vues avec la plateforme Eclipse

85Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� La première approche consiste à typer l’objet du producteur

du type de l’objet manipulé par l’écouteur

� Avantage

� Très simple à mettre en œuvre

� Inconvénients

� Le producteur connaît le type de l’objet du producteur

� Si plusieurs écouteurs avec des types différents nécessite plusieurs

implémentations (à condition que l’écouteur fournit une interface)

� Si nouvelle adaptation, nécessite de modifier le code du producteur

Page 86: Construction de vues avec la plateforme Eclipse

86Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 1 : typer l’objet du producteur du type de l’objet

manipulé par l’écouteurpackage eclipse.workbench.iadaptableexample1;

public class Contact implements IPropertySource {... // Voir code commun

public Object getEditableValue() { return null ; }

public IPropertyDescriptor[] getPropertyDescriptors() {List<PropertyDescriptor> descriptors = new ArrayList<PropertyDescriptor>();

Map<String, Object> properties = this .getProperties();for (String key : properties.keySet()) {

PropertyDescriptor descriptor = new PropertyDescriptor(key, key);descriptor.setAlwaysIncompatible( true );descriptors.add(descriptor);

}return descriptors.toArray( new IPropertyDescriptor[0]);

}

public Object getPropertyValue(Object id) {Map<String, Object> properties = this .getProperties();return properties.get(id);

}

public boolean isPropertySet(Object id) { return false ; }public void resetPropertyValue(Object id) { }public void setPropertyValue(Object id, Object value) { }

}

Classe Contact.java du projet IAdaptableExample1

La vue Properties ne consomme que des objets de

type IPropertySource

Page 87: Construction de vues avec la plateforme Eclipse

87Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� La première approche consiste à typer l’objet du producteur

du type de l’objet manipulé par l’écouteur

� Avantage

� Très simple à mettre en œuvre

� Inconvénients

� Le producteur connaît le type de l’objet du producteur

� Si plusieurs écouteurs avec des types différents nécessite plusieurs

implémentations (à condition que l’écouteur fournit une interface)

� Si nouvelle adaptation, nécessite de modifier le code du producteur

Page 88: Construction de vues avec la plateforme Eclipse

88Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� La deuxième approche consiste à implémenter l’interface IAdaptable

� Object getAdapter(Class adapter) : une adaptation est demandée du type défini par adapter. Le retour est un objet adapté du type du producteur vers le type adapter (écouteur)

� Démarche de développement : en fonction du type du paramètre adapter déléguer l’adaptation à un objet de type adapter

� Avantage

� La gestion de plusieurs types objets est facilitée car il ne s’agit plus d’héritage mais de délégation

� Inconvénients

� Le producteur connaît le type de l’objet du producteur

� Si nouvelle adaptation, nécessite de modifier le code du producteur

Page 89: Construction de vues avec la plateforme Eclipse

89Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 2 : utilisation de IAdaptable avec couplage avec le

type de l’écouteur

package eclipse.workbench.iadaptableexample2;

public class Contact implements IAdaptable {... // Voir code commun

public Object getAdapter(Class adapter) {if (adapter == IPropertySource.class) {

return new ContactPropertySourceAdapter(this);} else {

return null;}

}}

Classe Contact.java du projet IAdaptableExample2

La vue Properties exploite le patron de conception adaptateur pour adapter un objet Contact en

IPropertySource

La classe ContactPropertySourceAdapter est

de type IPropertySource

Page 90: Construction de vues avec la plateforme Eclipse

90Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 2 (suite) : utilisation de IAdaptable avec couplage

avec le type de l’écouteur package eclipse.workbench.iadaptableexample2;public class ContactPropertySourceAdapter implements IPropertySource {

private Contact contact;public ContactPropertySourceAdapter(Contact contact ) { this.contact = contact; }public Object getEditableValue() { return this; }

public IPropertyDescriptor[] getPropertyDescriptors () {List<PropertyDescriptor> descriptors = new ArrayList <PropertyDescriptor>();

Map<String, Object> properties = this.contact.getPro perties();for (String key : properties.keySet()) {

PropertyDescriptor descriptor = new PropertyDescripto r(key, key);descriptor.setAlwaysIncompatible(true);descriptors.add(descriptor);

}return descriptors.toArray(new IPropertyDescriptor[ 0]);

}

public Object getPropertyValue(Object id) {Map<String, Object> properties = this.contact.getPro perties();return properties.get(id);

}

public boolean isPropertySet(Object id) { return fal se; }public void resetPropertyValue(Object id) {}public void setPropertyValue(Object id, Object value ) {}

}

Classe ContactPropertySourceAdapter.javadu projet IAdaptableExample2

Code spécifique àIPropertySource découplé

de l’objet Contact

Page 91: Construction de vues avec la plateforme Eclipse

91Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� La troisième approche consiste à passer par une extension

pour réaliser l’adaptateur

� L’extension permet de définir

� Le type à adapter (l’objet du producteur)

� La fabrique des objets utilisée pour convertir le type du producteur

dans les types des écouteurs

� La liste des types des écouteurs que la fabrique peut adapter

� Avantage

� L’adaptation en un type donné devient en partie déclarative

� L’adaptation peut être réalisée en dehors du code du producteur

� Inconvénient

� Pas simple à première vue, mais nous allons y remédier …

Page 92: Construction de vues avec la plateforme Eclipse

92Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 3 : utilisation de IAdaptable sans couplage avec le

type de l’écouteur

package eclipse.workbench.iadaptableexample3;

public class Contact implements IAdaptable {... // Voir code commun

public Object getAdapter(Class adapter) {return Platform.getAdapterManager().getAdapter(this, adapter);

}}

Classe Contact.java du projet IAdaptableExample3

La demande d’adaptation est déléguée à Platform

L’objet du producteur n’est plus couplé aux objets des

écouteurs

L’implémentation àl’interface IAdaptable n’est

pas obligatoire

Page 93: Construction de vues avec la plateforme Eclipse

93Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 3 (suite) : utilisation de IAdaptable sans couplage

avec le type de l’écouteur

Utilisation du point d’extension org.eclipse.core.runtime.adapters

Page 94: Construction de vues avec la plateforme Eclipse

94Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 3 (suite) : utilisation de IAdaptable sans couplage

avec le type de l’écouteur

Onglet Extensions

Défini le type à adapter

La fabrique des objets utilisée pour

convertir le type du producteur dans les

types des écouteurs

Liste des types des écouteurs

Page 95: Construction de vues avec la plateforme Eclipse

95Views - M. Baron - Page

keul

keul

.blo

gspo

t.comCommunication entre vues (IAdaptable)

� Approche 3 (suite) : utilisation de IAdaptable sans couplage

avec le type de l’écouteur

package eclipse.workbench.iadaptableexample3;

public class ContactAdapterFactory implements IAdapte rFactory {

private static final Class[] TYPES = { IPropertySource.class };

public Object getAdapter(Object adaptableObject, Class adapterType) {if (adapterType == IPropertySource.class) {

if (adaptableObject instanceof Contact) {return new ContactPropertySourceAdapter((Contact) adaptableObject);

}}return null;

}

public Class[] getAdapterList() {return TYPES;

}}

Classe ContactAdapterFactory.java du projet IAdaptableExample3

La fabrique des objets utilisée pour

convertir le type du producteur dans les

types des écouteurs

Classe équivalente à celle du projet

IAdaptableExample2