Tutorial: GEF (Graphical Editing Framework) [Part 6]
Par Jean Charles MAMMANA, mercredi 13 juin 2007 à 11:39 :: Programmation :: #15 :: rss
GEF fournit plusieurs types de vues pour un éditeur.
Jusqu'à présent on avait notre éditeur avec nos petites boites. Il serait agréable d'y ajouter une vue permettant d'afficher notre graph sous forme d'un arbre ?
Allez hop, on y va...
Jusqu'à présent on avait notre éditeur avec nos petites boites. Il serait agréable d'y ajouter une vue permettant d'afficher notre graph sous forme d'un arbre ?
Allez hop, on y va...
Il s'agit d'une vue spéciale appelé "outline".
La première chose a faire est donc d'ajouter cette vue au plugin RCP.
C'est la class Perspective qui définit les vues de notre plugin. On y ajoute notre vue.
Si on lance l'application a ce niveau, vous verrez la nouvelle vue a gauche du graph.

L'outline view possède ses propres editspart. cela permet de faire un affichage différent du graph. Mais ici ce n'est pas le cas.
On va créer tous les editparts nécessaire a cette vue ainsi que la factory associé dans un nouveau package : tutogef.part.tree .
On commence par une class de base abstraite qui sera étendu par les editparts.
Puis les editparts. On remarque ils ont exactement la même forme que ceux du graph.
Puis la factory :
Maintenant on va créer une class embedded a MyGraphicalEditor qui va s'occuper de l'outline view.
On fait quelques modifications par la même occasion pour rendre accessible le modèle et le keyHandler.
Dans "plugin.xml" il faut ajouter la dépendance a org.eclipse.ui.views Puis il ne reste plus qu'a appeler notre class embedded quand il faut. Pour cela c'est dans la methode getAdapter que cela se passe :
C'est quand même mieux avec un arbre Non ? :)

Comme d'habitude, vous pouvez télécharger le projet ICI
La première chose a faire est donc d'ajouter cette vue au plugin RCP.
C'est la class Perspective qui définit les vues de notre plugin. On y ajoute notre vue.
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(true);
layout.addStandaloneView(IPageLayout.ID_OUTLINE, true, IPageLayout.LEFT, 0.3f, editorArea);
}
}
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(true);
layout.addStandaloneView(IPageLayout.ID_OUTLINE, true, IPageLayout.LEFT, 0.3f, editorArea);
}
}
Si on lance l'application a ce niveau, vous verrez la nouvelle vue a gauche du graph.

L'outline view possède ses propres editspart. cela permet de faire un affichage différent du graph. Mais ici ce n'est pas le cas.
On va créer tous les editparts nécessaire a cette vue ainsi que la factory associé dans un nouveau package : tutogef.part.tree .
On commence par une class de base abstraite qui sera étendu par les editparts.
public abstract class AppAbstractTreeEditPart extends AbstractTreeEditPart implements
PropertyChangeListener {
public void activate() {
super.activate();
((Node) getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
((Node) getModel()).removePropertyChangeListener(this);
super.deactivate();
}
}
PropertyChangeListener {
public void activate() {
super.activate();
((Node) getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
((Node) getModel()).removePropertyChangeListener(this);
super.deactivate();
}
}
Puis les editparts. On remarque ils ont exactement la même forme que ceux du graph.
public class EntrepriseTreeEditPart extends AppAbstractTreeEditPart {
protected List<Node> getModelChildren() {
return ((Entreprise)getModel()).getChildrenArray();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
protected List<Node> getModelChildren() {
return ((Entreprise)getModel()).getChildrenArray();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
public class ServiceTreeEditPart extends AppAbstractTreeEditPart {
protected List<Node> getModelChildren() {
return ((Service)getModel()).getChildrenArray();
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.COMPONENT_ROLE,new AppDeletePolicy());
}
public void refreshVisuals(){
Service model = (Service)getModel();
setWidgetText(model.getName());
setWidgetImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
protected List<Node> getModelChildren() {
return ((Service)getModel()).getChildrenArray();
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.COMPONENT_ROLE,new AppDeletePolicy());
}
public void refreshVisuals(){
Service model = (Service)getModel();
setWidgetText(model.getName());
setWidgetImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
public class EmployeTreeEditPart extends AppAbstractTreeEditPart{
protected List<Node> getModelChildren() {
return ((Employe)getModel()).getChildrenArray();
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.COMPONENT_ROLE,new AppDeletePolicy());
}
public void refreshVisuals(){
Employe model = (Employe)getModel();
setWidgetText(model.getName()+" "+model.getPrenom());
setWidgetImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_DEF_VIEW));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
protected List<Node> getModelChildren() {
return ((Employe)getModel()).getChildrenArray();
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.COMPONENT_ROLE,new AppDeletePolicy());
}
public void refreshVisuals(){
Employe model = (Employe)getModel();
setWidgetText(model.getName()+" "+model.getPrenom());
setWidgetImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_DEF_VIEW));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(Node.PROPERTY_ADD)) refreshChildren();
if(evt.getPropertyName().equals(Node.PROPERTY_REMOVE)) refreshChildren();
}
}
Puis la factory :
public class AppTreeEditPartFactory implements EditPartFactory {
@Override
public EditPart createEditPart(EditPart context, Object model) {
EditPart part = null;
if (model instanceof Entreprise)
part = new EntrepriseTreeEditPart();
else if (model instanceof Service)
part = new ServiceTreeEditPart();
else if (model instanceof Employe)
part = new EmployeTreeEditPart();
if (part != null)
part.setModel(model);
return part;
}
}
@Override
public EditPart createEditPart(EditPart context, Object model) {
EditPart part = null;
if (model instanceof Entreprise)
part = new EntrepriseTreeEditPart();
else if (model instanceof Service)
part = new ServiceTreeEditPart();
else if (model instanceof Employe)
part = new EmployeTreeEditPart();
if (part != null)
part.setModel(model);
return part;
}
}
Maintenant on va créer une class embedded a MyGraphicalEditor qui va s'occuper de l'outline view.
On fait quelques modifications par la même occasion pour rendre accessible le modèle et le keyHandler.
public class MyGraphicalEditor extends GraphicalEditor {
(...)
private Entreprise model;
private KeyHandler keyHandler;
protected class OutlinePage extends ContentOutlinePage{
private SashForm sash;
public OutlinePage() {
super(new TreeViewer());
}
public void createControl(Composite parent) {
sash = new SashForm(parent, SWT.VERTICAL);
getViewer().createControl(sash);
getViewer().setEditDomain(getEditDomain());
getViewer().setEditPartFactory(new AppTreeEditPartFactory());
getViewer().setContents(model);
getSelectionSynchronizer().addViewer(getViewer());
}
public void init(IPageSite pageSite) {
super.init(pageSite);
// On hook les actions de l'editeur sur la toolbar
IActionBars bars = getSite().getActionBars();
bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), getActionRegistry().getAction(ActionFactory.UNDO.getId()));
bars.setGlobalActionHandler(ActionFactory.REDO.getId(), getActionRegistry().getAction(ActionFactory.REDO.getId()));
bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), getActionRegistry().getAction(ActionFactory.DELETE.getId()));
bars.updateActionBars();
// On associe les raccourcis clavier de l'editeur a l'outline
getViewer().setKeyHandler(keyHandler);
}
public Control getControl() {
return sash;
}
public void dispose() {
getSelectionSynchronizer().removeViewer(getViewer());
super.dispose();
}
}
(...)
protected void initializeGraphicalViewer() {
GraphicalViewer viewer = getGraphicalViewer();
model = CreateEntreprise();
viewer.setContents(model);
}
(...)
protected void configureGraphicalViewer() {
(...)
keyHandler = new KeyHandler();
keyHandler.put(
KeyStroke.getPressed(SWT.DEL, 127, 0),
getActionRegistry().getAction(ActionFactory.DELETE.getId()));
keyHandler.put(
KeyStroke.getPressed('+', SWT.KEYPAD_ADD, 0),
getActionRegistry().getAction(GEFActionConstants.ZOOM_IN));
keyHandler.put(
KeyStroke.getPressed('-', SWT.KEYPAD_SUBTRACT, 0),
getActionRegistry().getAction(GEFActionConstants.ZOOM_OUT));
viewer.setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.NONE), MouseWheelZoomHandler.SINGLETON);
viewer.setKeyHandler(keyHandler);
}
}
(...)
private Entreprise model;
private KeyHandler keyHandler;
protected class OutlinePage extends ContentOutlinePage{
private SashForm sash;
public OutlinePage() {
super(new TreeViewer());
}
public void createControl(Composite parent) {
sash = new SashForm(parent, SWT.VERTICAL);
getViewer().createControl(sash);
getViewer().setEditDomain(getEditDomain());
getViewer().setEditPartFactory(new AppTreeEditPartFactory());
getViewer().setContents(model);
getSelectionSynchronizer().addViewer(getViewer());
}
public void init(IPageSite pageSite) {
super.init(pageSite);
// On hook les actions de l'editeur sur la toolbar
IActionBars bars = getSite().getActionBars();
bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), getActionRegistry().getAction(ActionFactory.UNDO.getId()));
bars.setGlobalActionHandler(ActionFactory.REDO.getId(), getActionRegistry().getAction(ActionFactory.REDO.getId()));
bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), getActionRegistry().getAction(ActionFactory.DELETE.getId()));
bars.updateActionBars();
// On associe les raccourcis clavier de l'editeur a l'outline
getViewer().setKeyHandler(keyHandler);
}
public Control getControl() {
return sash;
}
public void dispose() {
getSelectionSynchronizer().removeViewer(getViewer());
super.dispose();
}
}
(...)
protected void initializeGraphicalViewer() {
GraphicalViewer viewer = getGraphicalViewer();
model = CreateEntreprise();
viewer.setContents(model);
}
(...)
protected void configureGraphicalViewer() {
(...)
keyHandler = new KeyHandler();
keyHandler.put(
KeyStroke.getPressed(SWT.DEL, 127, 0),
getActionRegistry().getAction(ActionFactory.DELETE.getId()));
keyHandler.put(
KeyStroke.getPressed('+', SWT.KEYPAD_ADD, 0),
getActionRegistry().getAction(GEFActionConstants.ZOOM_IN));
keyHandler.put(
KeyStroke.getPressed('-', SWT.KEYPAD_SUBTRACT, 0),
getActionRegistry().getAction(GEFActionConstants.ZOOM_OUT));
viewer.setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.NONE), MouseWheelZoomHandler.SINGLETON);
viewer.setKeyHandler(keyHandler);
}
}
Dans "plugin.xml" il faut ajouter la dépendance a org.eclipse.ui.views Puis il ne reste plus qu'a appeler notre class embedded quand il faut. Pour cela c'est dans la methode getAdapter que cela se passe :
public class MyGraphicalEditor extends GraphicalEditor {
(...)
public Object getAdapter(Class type) {
if (type == ZoomManager.class)
return ((ScalableRootEditPart) getGraphicalViewer().getRootEditPart()).getZoomManager();
if (type == IContentOutlinePage.class) {
return new OutlinePage();
}
return super.getAdapter(type);
}
}
(...)
public Object getAdapter(Class type) {
if (type == ZoomManager.class)
return ((ScalableRootEditPart) getGraphicalViewer().getRootEditPart()).getZoomManager();
if (type == IContentOutlinePage.class) {
return new OutlinePage();
}
return super.getAdapter(type);
}
}
C'est quand même mieux avec un arbre Non ? :)

Comme d'habitude, vous pouvez télécharger le projet ICI

Commentaires
1. Le lundi 14 avril 2008 à 11:20, par Fabien
2. Le mardi 15 avril 2008 à 16:13, par Tyco
Ajouter un commentaire