juillet
2009
A l’étape du billet précédant [step5] notre éditeur de workflow est constitué de pages UI (générées par EMF.Edit) et d’une page source (basée sur un StructuredTextEditor WST). Dans ce billet, nous allons ajouter une page graphique à notre éditeur de workflow en utilisant le projet GEF. La page graphique permettra de gérer graphiquement :
la description du workflow XML :
<state name="state1" />
<state name="state2" />
<action fromState="state1" toState="state2" name="action1" />
</workflow>
A la fin du billet nous aurons initialisé une page graphique Graphics vierge (avec une palette d’outils vide) basée sur GEF :
Vous pouvez télécharger le projet org.example.workflow_step6.zip présenté dans ce billet.
GEF – Graphical Editing Framework
Le projet GEF qui signifie Graphical Editing Framework fournit un framework qui permet de développer son propre éditeur graphique complexe permettant de gérér (graphiquement) son modèle (modèle Java, EMF, DOM XML..). Dans notre cas le modèle géré sera notre instance EMF WorkflowType.
Lorsque j’ai démarré GEF, je ne savais pas par où commencer, et il m’a fallu un temps considérable pour assimiler le framework (et j’ai encore beaucoup à apprendre) dù à sa grande richesse de fonctionnalités. Si vous êtes débutant en GEF je vous conseille de lire les tutoriaux en francais sur GEF sur le blog de Psykokwak. Il décrit pas à pas comment développer un éditeur graphique basé sur GEF dans une application RCP. La partie modèle se base sur un POJO simple et la partie sérialisation du modèle n’est pas spécialement traité, par contre il montre tout ce que peut fournir GEF. Je vous conseille vivement de lire ces billets pour comprendre les différents composants de GEF (GraphicalEditor, PaletteRoot…).
Dans mes billets je vais moi aussi tenter d’expliquer GEF en décrivant pas à pas à comment développer la page graphique de l’éditeur de workflow.
La documentation officiel de GEF propose plusieurs articles sur lequels je me suis appuyé :
- A Shape Diagram Editor : exemple qui explique comment développer un éditeur d’un diagrame de shapes basé sur un modèle Java Shape (POJO).
- Using GEF with EMF : exemple qui reprend A Shape Diagram Editor pour avoir un modèle Shape EMF.
Mais je vous avoue que j’ai du lire plusieurs fois ces articles et mettre les mains dans le code pour comprendre les principes de GEF. GEF est un super framework mais qui demande beaucoup d’investissements (comme EMF ou d’autres frameworks).
Initialisation page Graphics
Dans ce billet nous allons initialiser la page GEF en :
- ajoutant la dépendance à GEF.
- ajoutant la page graphique à l’éditeur à l’aide de la classe GraphicalWorkflowEditor.
Dependances GEF
ajouter la dépendance org.eclipse.gef au projet org.example.workflow.editor.
Classe GraphicalWorkflowEditor
GEF fournit la classe abstraite org.eclipse.gef.ui.parts.GraphicalEditor qui éténd la classe abstraite org.eclipse.ui.part.EditorPart (classe de base pour les éditeurs). Au lieu d’étendre directement GraphicalEditor nous allons éténdre GraphicalEditorWithFlyoutPalette (qui éténd GraphicalEditor) pour bénéficier d’une palette d’outils. Un outil permet de manipuler le graphique (ex : sélection de figures du graphique) ou de modifier le modèle (outil de création de figures).
Dans la dernière section GraphicalEditor, vous pourrez voir une copie d’écran pour chaque implémentation de GraphicalEditor fournit par GEF.
Créer la classe org.example.workflow.presentation.graphical.GraphicalWorkflowEditor comme suit :
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
public class GraphicalWorkflowEditor extends GraphicalEditorWithFlyoutPalette {
@Override
protected PaletteRoot getPaletteRoot() {
return null;
}
@Override
public void doSave(IProgressMonitor monitor) {
}
}
La classe GraphicalEditorWithFlyoutPalette impose d’implémenter les méthodes GraphicalEditorWithFlyoutPalette#getPaletteRoot() et GraphicalEditorWithFlyoutPalette#doSave(IProgressMonitor monitor) qui a ce stade sont implémentées basiquement.
Ajouter la méthode createAndAddGraphicalPage dans WorkflowEditor :
GraphicalWorkflowEditor graphicalPage = new GraphicalWorkflowEditor();
try {
int index = addPage(graphicalPage, getEditorInput());
setPageText(index, "Graphics");
} catch (PartInitException e) {
e.printStackTrace();
}
}
Appeler la méthode createAndAddGraphicalPage dans la méthode WorkflowEditor#createPages() (juste avant la construction de la page source) :
@Override
public void createPages() {
...
// Add graphical page
createAndAddGraphicalPage();
// Add source page
createAndAddSourcePage();
...
}
...
private void createAndAddGraphicalPage() {
GraphicalWorkflowEditor graphicalPage = new GraphicalWorkflowEditor();
try {
int index = addPage(graphicalPage, getEditorInput());
setPageText(index, "Graphics");
} catch (PartInitException e) {
e.printStackTrace();
}
}
...
Relancez le plugin et vous aurrez l’erreur suivante :
Le ligne de code 236 de la classe GraphicalEditor qui pose problème est la suivante :
return getEditDomain().getCommandStack();
}
protected DefaultEditDomain getEditDomain() {
return editDomain;
}
Comme on peut le voir, le problème vient du fait que le champs editDomain est null (pour plus d’information sur EditDomain voir section GEF – EditDomain). Il faut donc l’initialiser à travers notre classe GraphicalWorkflowEditor . Pour cela ajouter le constructeur de GraphicalWorkflowEditor comme suit :
super.setEditDomain(new DefaultEditDomain(this));
}
Ce qui donne :
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
public class GraphicalWorkflowEditor extends GraphicalEditorWithFlyoutPalette {
public GraphicalWorkflowEditor() {
super.setEditDomain(new DefaultEditDomain(this));
}
@Override
protected PaletteRoot getPaletteRoot() {
return null;
}
@Override
public void doSave(IProgressMonitor monitor) {
}
}
Relancez le plugin et vous aurrez une page GEF vide avec la palette :
GEF – EditDomain
Nous avons vu qu’il est impératif de définir L’org.eclipse.gef.EditDomain de GEF à la classe de base GEF GraphicalEditor. Mais a quoi sert cette instance? L’EditDomain de GEF permet de collecter l’état d’un éditeur GEF :
- EditDomain#getCommandStack() : retourne la stack de commandes qui contient des commandes GEF.
- EditDomain#getActiveTool() : retourne l’outil org.eclipse.gef.Tool actif (outil sélectionné dans la palette). Un outil de sélection (pour sélectionner des figures du graphique), outil de création de figures sont des exemples d’outils que la palette peut contenir.
ATTENTION!!! Il ne faut pas confondre stack de commandes GEF org.eclipse.gef.commands.CommandStack qui est une classe, avec stack de commandes EMF org.eclipse.emf.common.command.CommandStack qui est une interface. Elles ont le même rôle mais n’utilisent pas les mêmes structures.
Une stack de commandes GEF org.eclipse.gef.commands.CommandStack contient des commandes GEF de type org.eclipse.gef.commands.Command. CommandStack#execute(org.eclipse.gef.commands.Command command) permet d’executer une commande GEF. Dans le cas d’un outil de création de figures, cet outil créé une commande GEF de création de figure et l’ajoute à la stack de commande GEF via la méthode execute. La stack de commande GEF permet ainsi de gérer le undo/redo (comme EMF.Edit).
GraphicalEditor & Palette
Comme nous l’avons vu précédemment, la classe de base de GEF pour un éditeur graphique est GraphicalEditor. GEF fournit 2 autres implementations GraphicalEditorWithPalette et GraphicalEditorWithFlyoutPalette qui éténdent GraphicalEditor. En d’autres termes pour créer un éditeur graphique on peut étendre :
- org.eclipse.gef.ui.parts.GraphicalEditor :
L’utilisation de cette classe permet d’avoir une zone graphique uniquement.
- org.eclipse.gef.ui.parts.GraphicalEditorWithPalette :
L’utilisation de cette classe permet par défaut d’avoir une zone graphique à droite de l’éditeur et une palette d’outils (outil de sélection, de création de figures…) à gauche de la l’éditeur.
- org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette :
L’utilisation de cette classe permet d’avoir par défaut une zone graphique à droite de l’éditeur et une palette d’outils à droite de la l’éditeur. La palette peut être cachée en cliquant sur le petit triangle à coté du libéllé Palette.
12 Commentaires + Ajouter un commentaire
Articles récents
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step5]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step4]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step3]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step2]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step1]
Commentaires récents
- Conception d’un Editeur Eclipse de workflow XML [step 0] dans
- Conception d’un Editeur Eclipse de workflow XML [step 19] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
Bonjour,
Merci bcp Angelo,
Bonne continuitation
Bonjour,
Je n’ai jamais fait de GMF donc je ne pourrais pas vous donner de réponses pertinentes. Je pense que c’est faisable mais je ne pense pas que ca soit facile. J’en ai pas mal sué pour intégrer EMF+GEF+WST. Je pense que GMF ca sera pareil.
L’idée que j’ai de GMF est que le modèle est géré uniquement avec des outils graphiques et que l’on ne s’amuse pas a saisir le contenu XML (XMI généralement) du modèle. Il y a selon moi un projet qui manque dans Eclipse : « la synchronisation d’un modèle EMF avec un editeur Text XML » (peut être XText pourrait marcher?). WST-SSE gère cette problématique mais je trouve qu’elle n’est pas très propre (devoir coder ses Translator sont une chose qui « casse » la modélisation EMF, WST ne peut pas être utilisé (je croies) dans une application RCP….). De plus ca ne m »a pas été très facile de l’intégrer avec GEF.
Bon courage
Angelo
Bonjour Angelo,
Oui c’est normal j’avaias lu que vous etes passer sur autre chose, je voudrais juste savoir si le plugin wst fonctionne avec GMF.
Merci encore
Mahmoud
Bonjour,
Cela fait très longtemps que je ne me suis pas plongé dans le code ce tutorial. Je ne pourrais pas vous aider plus. Bon courage.
Angelo
Bonjour Angelo,
merci pour ces tuto, ils m’ont permis d’avoir des idées plus clair. cela dit j’ai essayé d’utiliser StructuredTextEditor pour le fameau exemple de mindmap mais j’arrive pas à échapper à l’erreur suivante:
An error has occurred. See error log for more details.
org.eclipse.wst.sse.ui.StructuredTextEditor cannot be cast to org.eclipse.emf.edit.domain.IEditingDomainProvider
je crois aue l’erruer vient de cette classe : SubActionBarsExt mais j’ai pas pu faire mieux ):
des idées sur comment je peux détourner ce probleme?
d’accord je vais chercher si cette solution me convient.
Merci
Ok je comprends mieux. Je ne suis pas sur mais je pense qu’il faut utiliser SWT SashForm pour faire ca.
Bon courage.
Angelo
ce que je cherche c’est d’avoir dans un même onglet ,le code source et la partie graphique.
par exemple dans cette image: on trouve dans le même onglet(Design dans notre cas) la page graphique et au dessous la page source.
Merci
De que je voies dans la copie d’ecran, c’est qu’il y a un onglet « design » (qui est la page Source dans mon cas) et un onglet « preview » (qui est la page Graphics dans mon cas). Moi j’ai affiche la page Graphics avant la page Source. Ce que tu souhaite faire, c’est afficher la page Source avant Graphics? Si c’est cela il faut modifier dans la methode createPages l’ordre des appels des methodes createAndAdd*.
Mais bon je ne suis pas sur que ca soit vraiment ca ta question. Ma reponse est trop simple.
Angelo
Bonjour Angelo,
voilà une interface (éditeur html) qui ressemble à ce que je cherche.
http://www.eclipsetotale.com/img/art7-pagedesigner.png
Merci encore pour votre disponibilité.
Bonjour snatiz87,
Merci de tes encouragements. Je n’ai pas bien compris ta question. La page graphique et source sont déja dans le même onglets, non?
Angelo
Bonjour Angelo,
Merci beaucoup pour ce très bon tuto.
est ce qu’il est possible de mettre la page source et la page graphique dans un même onglet.
car je voie c’est mieux de les mettre dans le même onglet.
sous cette forme
——————-
| page graphique |
——————-
| page source |
——————-
ou bien
——— ———–
| page | page |
| source | graphique|
——— ———–
Merci d’avance.