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.
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);
        }
}


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();
  }
}


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();
        }
}

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();
        }
}

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();
        }
}

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;
         }
}


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);
        }
}

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);
        }
}


C'est quand même mieux avec un arbre Non ? :)

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