Syndication : Atom 1.0  RSS 2.0
Blogs des développeurs   »   Akrogen Blog

Article complet: Conception d'un Editeur Eclipse de workflow XML [step 17]

11/09/2009

Permalink 17:12:07, Catégories: Plugin Eclipse, Récapitulatif, Récapitulatif Eclipse, Frameworks, 4142 mots   French (FR) , azerr

[Eclipse][Java] Conception d'un Editeur Eclipse de workflow XML [step 17]

A l'étape du billet précédant [step16] nous avons finalisé la palette d'outils GEF qui permet de créer des states, des actions et des connections entre actions et states.

Dans ce billet je souhaitais dans un premier temps expliquer comment mettre en place la fonctionnalité "suppression de state, actions, connections" dans la page GEF Graphics, à l'aide de la touche "Suppr" ou à l'aide d'une action d'un menu contextuel. Je me suis inspiré des exemples GEF qui sont basés sur un EditorPart simple (une seule page GEF) pour intégrer cette fonctionnalité de delete dans notre editor multi page de workflow (MultiPageEditorPart) et je me suis rendu compte que nous ne pouvions pas encore mettre en place cette fonctionnalité de delete avant d'avoir régler le problème de sélection des EditPart GEF (pour ensuite les supprimer avec l'action delete). La selection d'EditPart GEF ne fonctionne pas dans notre cas car :

  1. le code générée par EMF concernant la sélection d'items (ISelectionProvider) dans l'editor multi page WorkflowEditor obstrue la selection d'un item provenant d'une autre page non générée par EMF (qui n'utilise pas ViewerPane EMF). Par exemple, dans le cas de notre editor GEF la selection d'un EditPart GEF est obstruée. Pour plus d'informations sur ce sujet, voir la section GEF GraphicalViewer - ISelectionProvider.
  2. nous sommes dans un contexte de multi page et que l'editor GEF org.eclipse.gef.ui.parts.GraphicalEditor ne fonctionne pas dans un multi page concernant le sujet de la selection d'EditPart. Nous réglerons ce problème dans le prochain billet.

Pour mettre en évidence le premier problème, mettez un point d'arrêt dans la méthode GraphicalEditor#selectionChanged(IWorkbenchPart part, ISelection selection), sélectionnez un state, action de la page GEF Graphics et vous pourrez constater que cette méthode n'est jamais appelé :

public void selectionChanged(IWorkbenchPart part, ISelection selection) { 
  // If not the active editor, ignore selection changed. 
  if (this.equals(getSite().getPage().getActiveEditor())) 
    updateActions(selectionActions); 
}

Nous expliquerons dans le prochain billet l'importance de ce code qui réagit à la selection des EditPart GEF, et qui permet de gérer les actions de delete des EditPart GEF sélectionné.

Pour expliquer le 2ème problème, il faut que le premier soit résolu et mettez ensuite un point d'arrêt à la fin de la méthode GraphicalEditor#selectionChanged(IWorkbenchPart part, ISelection selection) ( appel de updateActions) et vous pourrez constater que le point d'arrêt ne s'arrête jamais.

Pour résoudre le premier problème, je me suis appuyé sur l'excellent article Integrating EMF and GMF Generated Editors qui explique pas à pas comment intégrer un editor GEF généré par Graphical Modeling Framework (GMF) dans un multi page editor généré par EMF.

A la fin de ce billet, lorsque nous sélectionnerons un state, action, connection, cette sélection s'affichera dans la barre de statut (ce qui à ce stade ne fonctionne pas).

Vous pouvez télécharger le projet org.example.workflow_step17.zip présenté dans ce billet.

[Suite:]

EMF - MultiPageEditorPart

EMF est capable de générer à partir d'un genmodel, un editor multi page MultiPageEditorPart constitué de plusieurs pages capable de mettre à jour un modèle EMF. Un MultiPageEditorPart est un EditorPart constitué de plusieurs pages qui peuvent être :

  • un Control SWT qui peut être ajouté au multi page editor via la méthode MultiPageEditorPart#addPage(Control control). Les pages générées par EMF sont basées sur un org.eclipse.emf.common.ui.ViewerPane qui construit en interne un Control SWT (accéssible via la méthode ViewerPane#getControl()) et qui est ajouté à l'editor multi page.
  • un EditorPart (ex : notre EditorPart GEF) qui peut être ajouté au multi page editor via la méthode MultiPageEditorPart#addPage(IEditorPart editor, IEditorInput input)

Notre éditor multi page WorkflowEditor en est un exemple d'editor multi page générée par EMF. Dans l'introduction de ce billet nous avons évoqué le problème de selection d'items. Pour regler ce problème nous devons effectuer des modifications du code générée par EMF qui va suivre les étapes décrites dans l'article Integrating EMF and GMF Generated Editors. Le lien Integrating EMF / GMF editors article - comments est un commentaire effectué sur cet article qui est aussi très intéressant de lire.

L'idée générale des modifications à effectuer dans le code générée par EMF est :

  • d'utiliser un MultiPageSelectionProvider au lieu de l'implémentation de ISelectionProvider générée par EMF (le WorkflowEditor lui même).
  • Le MultiPageSelectionProvider impose le fait d'avoir des EditorPart, ce qui implique de transformer les ViewerPane EMF en EditorPart.

Dans ce billet je vais suivre les mêmes étapes que l'article Integrating EMF and GMF Generated Editors :

  • Dissecting the EMF Editor qui permettra d'utiliser des EditorPart au lieu des ViewerPane.
  • Selection Handling qui permettra d'utiliser un MultiPageSelectionProvider au lieu des WorkflowEditor qui implémente ISelectionProvider.
  • Combining the Editors qui corrigera le problème de la synchronisation de la page Selection avec la Outline.

Dissecting the EMF Editor

Ici nous allons effectuer la même chose que ce qui est expliqué dans la section Dissecting the EMF Editor de l'article GMF. L'idée est de ne plus utiliser les ViewerPane EMF mais d'utiliser les EditorPart. En effet nous souhaitons utiliser un MultiPageSelectionProvider dans notre editor, ce qui implique que chacune des pages doivent être des EditorPart (et pas des Control SWT). Le code MultiPageSelectionProvider#getSelection()

public ISelection getSelection() { 
  IEditorPart activeEditor = multiPageEditor.getActiveEditor(); 
  if (activeEditor != null) { 
  ISelectionProvider selectionProvider = activeEditor.getSite().getSelectionProvider(); 
  if (selectionProvider != null) { 
  return selectionProvider.getSelection(); 
  } 
  } 
  return StructuredSelection.EMPTY; 
}

montre que ce ISelectionProvider fonctionne qu'avec des IEditorPart.

Nous allons transformer uniquement la page Selection basée sur un ViewerPane en EditorPart. Les autres pages n'existeront plus dans notre editor. Mais nous allons quand même créer une classe de base (basé sur EditorPart) qui gère la plupart des problèmetque du ViewerPane, si jamais vous souhaitez ajouter les autres pages dans votre cas (je vous conseille de regarder l'article qui explique comment faire). Cette classe de base est identique (presque) à TopicmapEditorPart expliqué dans l'article.

Créer la classe org.example.workflow.presentation.parts.AbstractWorkflowEditorPart comme suit :

package org.example.workflow.presentation.parts; 
 
import org.eclipse.core.runtime.IProgressMonitor; 
import org.eclipse.emf.common.command.BasicCommandStack; 
import org.eclipse.emf.common.notify.AdapterFactory; 
import org.eclipse.emf.edit.domain.EditingDomain; 
import org.eclipse.emf.edit.domain.IEditingDomainProvider; 
import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter; 
import org.eclipse.emf.edit.ui.dnd.LocalTransfer; 
import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; 
import org.eclipse.emf.edit.ui.provider.UnwrappingSelectionProvider; 
import org.eclipse.jface.action.IMenuListener; 
import org.eclipse.jface.action.IMenuManager; 
import org.eclipse.jface.action.MenuManager; 
import org.eclipse.jface.action.Separator; 
import org.eclipse.jface.viewers.StructuredViewer; 
import org.eclipse.swt.dnd.DND; 
import org.eclipse.swt.dnd.Transfer; 
import org.eclipse.swt.widgets.Menu; 
import org.eclipse.ui.IEditorInput; 
import org.eclipse.ui.IEditorSite; 
import org.eclipse.ui.PartInitException; 
import org.eclipse.ui.part.EditorPart; 
import org.example.workflow.presentation.WorkflowEditor; 
import org.example.workflow.presentation.WorkflowEditorPlugin; 
 
public abstract class AbstractWorkflowEditorPart extends EditorPart implements IMenuListener, IEditingDomainProvider { 
 
   protected WorkflowEditor parentEditor; 
    
   public AbstractWorkflowEditorPart(WorkflowEditor parent) { 
   super(); 
   this.parentEditor = parent; 
   } 
    
   protected static String getString(String key) { 
   return WorkflowEditorPlugin.INSTANCE.getString(key); 
   } 
 
   public EditingDomain getEditingDomain() { 
   return parentEditor.getEditingDomain(); 
   } 
 
   protected BasicCommandStack getCommandStack() { 
   return ((BasicCommandStack)getEditingDomain().getCommandStack()); 
   } 
    
   protected AdapterFactory getAdapterFactory() { 
   return parentEditor.getAdapterFactory(); 
   } 
    
   protected void createContextMenuFor(StructuredViewer viewer) { 
   MenuManager contextMenu = new MenuManager("#PopUp"); 
   contextMenu.add(new Separator("additions")); 
   contextMenu.setRemoveAllWhenShown(true); 
   contextMenu.addMenuListener(this); 
   Menu menu= contextMenu.createContextMenu(viewer.getControl()); 
   viewer.getControl().setMenu(menu); 
   getSite().registerContextMenu(contextMenu, new UnwrappingSelectionProvider(viewer)); 
 
   int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; 
   Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() }; 
   viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer)); 
   viewer.addDropSupport(dndOperations, transfers, new EditingDomainViewerDropAdapter(getEditingDomain(), viewer)); 
   } 
    
   @Override 
   public void doSave(IProgressMonitor monitor) { 
   // nothing to do here - this is handled by the parent editor 
   } 
 
   @Override 
   public void doSaveAs() { 
   // nothing to do here - this is handled by the parent editor 
   } 
 
   @Override 
   public void init(IEditorSite site, IEditorInput input) throws PartInitException { 
   setSite(site); 
   setInput(input); 
   } 
 
   @Override 
   public boolean isDirty() { 
   return getCommandStack().isSaveNeeded();  
   } 
 
   @Override 
   public boolean isSaveAsAllowed() { 
   return true; 
   } 
 
   public void menuAboutToShow(IMenuManager manager) { 
   // pass the request to show the context menu on to the parent editor 
   ((IMenuListener)parentEditor.getEditorSite().getActionBarContributor()).menuAboutToShow(manager); 
   } 
    
   public abstract void setInput(Object input); 
 
 
}

Créer la classe org.example.workflow.presentation.parts.SelectionEditorPart comme suit :

package org.example.workflow.presentation.parts; 
 
import org.eclipse.emf.edit.ui.celleditor.AdapterFactoryTreeEditor; 
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; 
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; 
import org.eclipse.jface.viewers.TreeViewer; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.FillLayout; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Tree; 
import org.example.workflow.presentation.WorkflowEditor; 
 
public class SelectionEditorPart extends AbstractWorkflowEditorPart { 
 
  protected TreeViewer viewer; 
 
  public SelectionEditorPart(WorkflowEditor parent) { 
    super(parent); 
  } 
 
  @Override 
  public void createPartControl(Composite parent) { 
 
    viewer = new TreeViewer(parent, SWT.MULTI); 
    Tree tree = viewer.getTree(); 
    tree.setLayoutData(new FillLayout()); 
 
    viewer.setContentProvider(new AdapterFactoryContentProvider( 
        getAdapterFactory())); 
    viewer.setLabelProvider(new AdapterFactoryLabelProvider( 
        getAdapterFactory())); 
 
    new AdapterFactoryTreeEditor(tree, getAdapterFactory()); 
 
    createContextMenuFor(viewer); 
    getEditorSite().setSelectionProvider(viewer); 
  } 
 
  @Override 
  public void setFocus() { 
    viewer.getTree().setFocus(); 
  } 
 
  @Override 
  public void setInput(Object input) { 
    viewer.setInput(input); 
  } 
 
}

Cette classe gère la même chose que la page Selection basé sur un ViewerPane.

Dans la classe WorkflowEditor, définissez un champs selectionEditorPart

private SelectionEditorPart selectionEditorPart;

Dans la méthode WorkflowEditor#createPages() supprimez tout le code qui utilise les ViewerPane et remplacez le par le code suivant :

@Override 
public void createPages() { 
  // Creates the model from the editor input 
  // 
  createModel(); 
 
  // Only creates the other pages if there is something that can be edited 
  // 
  if (!getEditingDomain().getResourceSet().getResources().isEmpty()) { 
      int pageIndex; 
 
    try { 
      // Create a page for the selection tree view. 
      // 
      selectionEditorPart = new SelectionEditorPart(this); 
      pageIndex = addPage(selectionEditorPart, getEditorInput()); 
      setPageText(pageIndex, getString("_UI_SelectionPage_label")); 
      selectionEditorPart.setInput(getEditingDomain() 
          .getResourceSet()); 
    } catch (PartInitException e) { 
      e.printStackTrace(); 
    } 
 
    // Add graphical page 
    createAndAddGraphicalPage(); 
    // Add source page 
    createAndAddSourcePage(); 
...

Nous pouvons maintenant supprimer les méthodes WorkflowEditor#setCurrentViewerPane(ViewerPane viewerPane) et WorkflowEditor#setFocus(). La ré-implementation de WorkflowEditor#isDirty() peut être aussi enlevée.

Selection Handling

A cette étape si vous relancez le plugin et que vous sélectionnez un state, action dans le Treeview de la page Selection, la vue Properties n'est pas rafraîchit correctement. La selection d'items ne fonctionnent plus. Ici nous allons effectuer la même chose que ce qui est expliqué dans la section Selection Handling de l'article GMF. L'idée est d'utiliser un MultiPageSelectionProvider en tant que ISelectionProvider au lieu du WorkflowEditor lui même (qui implémente ISelectionProvider).

Dans la classe WorkflowEditor, ajoutez le champs de type org.eclipse.ui.part.MultiPageSelectionProvider :

private MultiPageSelectionProvider selectionProvider;

Modifiez le constructueur de WorkflowEditor comme suit :

public WorkflowEditor() { 
  super(); 
  initializeEditingDomain(); 
   selectionProvider = new MultiPageSelectionProvider(this); 
   selectionProvider.addSelectionChangedListener(new ISelectionChangedListener() { 
   public void selectionChanged(SelectionChangedEvent event) { 
   setStatusLineManager(event.getSelection()); 
   } 
   }); 
}

Ce code permet d'instancier le MultiPageSelectionProvider. Un listener est branché dessus pour détecter les changement de selection (ex : selection d'un item du Treeview de la page Selection, selection d'un EditPart GEF) et afficher le resultat de la selection dans la barre de statut (en bas à gauche du workbench).

WorkflowEditor ne doit plus implémenter ISelectionProvider :

public class WorkflowEditor extends MultiPageEditorPart implements 
    IEditingDomainProvider, IMenuListener, IViewerProvider, IGotoMarker { 
...

Maintenant nous pouvons supprimer tout le code qui implémente l'interface ISelectionProvider : supprimez les champs selectionChangedListener, selectionChangedListeners et editorSelection et supprimez les méthodes WorkflowEditor#addSelectionChangedListener(ISelectionChangedListener listener) WorkflowEditor#removeSelectionChangedListener(ISelectionChangedListener listener), WorkflowEditor#getSelection() et WorkflowEditor#setSelection(ISelection selection).

Commentez dans la méthode WorkflowEditor#handleChangedResources() le code suivant :

//if (AdapterFactoryEditingDomain.isStale(editorSelection)) { 
//setSelection(StructuredSelection.EMPTY); 
//}

L'utilisation du ISelectionProvider s'effectue via le IEditorSite. Modifiez le code de la méthode WorkflowEditor#init(IEditorSite site, IEditorInput editorInput) pour pouvoir utiliser notre MultiPageSelectionProvider :

public void init(IEditorSite site, IEditorInput editorInput) { 
... 
site.setSelectionProvider(selectionProvider); 
... 
}

Pour information, Un EditorPart possède un org.eclipse.ui.IEditorSite qui joue le rôle d'interface entre le workbench et un editor part. IEditorSite est accessible via la méthode EditorPart#getSite() (plus exactement WorkbenchPart#getSite()). C'est à travers IEditorSite que l'on renseigne par exemple :

  • les menu contextuels (registerContextMenu) disponibles dans l'EditorPart.
  • les actions disponibles (getActionBars) dans le menu globale du workbench (lorsque l'editor est sélectionné).
  • le fournisseur de selection org.eclipse.jface.viewers.ISelectionProvider de l'editor via la méthode EditorPart#setSelectionProvider(ISelectionProvider provider).

Modifiez la méthode WorkflowEditor#handleActivate() pour pouvoir utiliser notre MultiPageSelectionProvider :

protected void handleActivate() { 
  // Recompute the read only state. 
  // 
  if (editingDomain.getResourceToReadOnlyMap() != null) { 
    editingDomain.getResourceToReadOnlyMap().clear(); 
 
    // Refresh any actions that may become enabled or disabled. 
    // 
    selectionProvider.setSelection(selectionProvider.getSelection()); 
  } 
...

Modifiez WorkflowEditor#setCurrentViewer(Viewer viewer) qui n'a plus besoin de gérer la selection (branchement/débranchement des listener ISelectionChangedListener) :

public void setCurrentViewer(Viewer viewer) { 
  if (currentViewer != viewer) { 
  currentViewer = viewer; 
  } 
}

Relancez le plugin et assurez vous que la vue Outline n'est pas ouverte, maintenant lorsque vous sélectionnez un EditPart GEF dans la page Graphics, la selection de ce dernier doit s'afficher dans le barre de statut :

Vous pouvez aussi vérifier que lorsque vous sélectionnez un item du Treeview dans la page Selection, la selection doit aussi s'afficher dans la barre de statut.

Combining the Editors

Ouvrez la vue Outline via le menu Window/Show view/Outline, mettez vous sur la page Selection, puis sélectionnez un item de la Outline. Le Treeview de la page Selection, n'est pas synchronisé avec la vue Outline :

Le problème vient de la méthode WorkflowEditor#handleContentOutlineSelection() qui teste entre autre si la variable currentViewerPane n'est pas null. Dans notre cas elle est toujours null (car elle était mise à jour par le code générée que nous avons supprimé).

Ici nous allons effectuer la même chose que ce qui est expliqué dans la section Combining the Editors de l'article GMF

Pour régler ce problème, supprimez le champs currentViewerPane

//protected ViewerPane currentViewerPane;

et modifiez le code comme suit :

public void handleContentOutlineSelection(ISelection selection) { 
  if (!selection.isEmpty() && selection instanceof IStructuredSelection) {  
   List selectedElements = ((IStructuredSelection) selection).toList();  
    if (getActiveEditor() == selectionEditorPart) { 
      // If the selection viewer is active, we want it to select the  
     // same selection as this selection.  
     //  
     selectionProvider.setSelection(new StructuredSelection(  
     selectedElements));  
    } 
    else { 
      if (getActiveEditor() instanceof AbstractWorkflowEditorPart) { 
        // For any other viewer, set the input directly.  
       ((AbstractWorkflowEditorPart) getActiveEditor()).setInput(selectedElements.get(0));  
      } 
    } 
  } 
}

Ce code gère la selection de la page Selection et des autres pages qui hériterait de AbstractWorkflowEditorPart. Ici nous ne gerons ni la page source, ni la page Graphics. Relancez le plugin et vous pourrez constater que la Treeview de la page Selection est synchronisée avec le Treeview de la vue Outline :

GEF - Selection EdiPart

Les modifications de code sont finies dans ce billet. Dans cette section je vais tenter d'expliquer le problème de selection d'EditPart GEF avec le code générée par EMF.

GEF GraphicalViewer - ISelectionProvider

Nous avons modifié le code pour utiliser MultiPageSelectionProvider (et plus que WorkflowEditor implémente ISelectionProvider). Mais pourquoi devons nous faire ca? Ici je vais tenter d'expliquer pourquoi l'utilisation de MultiPageSelectionProvider règle le problème de selection des EditPart GEF.

Lorsqu'un EditPart GEF est sélectionné (clic de la souris sur un state, action, connection de la page Graphics GEF), le viewer GEF GraphicalViewer associé à l'editor GEF GraphicalEditor est capable de détecter l'EditPart sélectionné et notifie les listeners qui ont été préalablement enregistrés qu'un/plusieurs EditPart a/ont été sélectionnés. Le viewer GEF joue le rôle d'un fournisseur de sélection (il implémente l'interface org.eclipse.jface.viewers.ISelectionProvider) sur lequel on peut brancher des listeners org.eclipse.jface.viewers.ISelectionChangedListener qui souhaitent être informés des EditPart sélectionnés.

La méthode qui nous intéresse pour comprendre le probléme de selection dans GEF engendré par le code générée EMF est AbstractEditPartViewer#fireSelectionChanged() de la classe org.eclipse.gef.ui.parts.AbstractEditPartViewer :

protected void fireSelectionChanged() { 
  Object listeners[] = selectionListeners.toArray(); 
  SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); 
  for (int i = 0; i < listeners.length; i++) 
    ((ISelectionChangedListener)listeners[i]) 
      .selectionChanged(event); 
}

Cette méthode est appelée dès qu'un ou plusieurs EditPart GEF sont sélectionnés et appelle pour chacun des listeners qui implémente la méthode ISelectionChangedListener#selectionChanged(SelectionChangedEvent event) de l'interface ISelectionChangedListener. Si vous mettez un point d'arrêt dans la méthode AbstractEditPartViewer#fireSelectionChanged(), vous pourrez constater que 2 listeners ISelectionChangedListener sont enregistrés :

  • org.eclipse.gef.ui.parts.SelectionSynchronizer : qui d'après la javadoc GEF est utilisé pour synchroniser les selection entre plusieurs viewer GEF (ce qui n'est pas notre cas).
  • org.eclipse.ui.part.MultiPageEditorSite : qui est l'IEditorSite de notre multi page editor. Plus exactement c'est la méthode privée MultiPageEditorSite#getSelectionChangedListener() qui joue le rôle de listener.

Le listener qui nous intéresse est le deuxième (MultiPageEditorSite). Voici le code de MultiPageEditorSite#getSelectionChangedListener() :

private ISelectionChangedListener getSelectionChangedListener() { 
  if (selectionChangedListener == null) { 
    selectionChangedListener = new ISelectionChangedListener() { 
      public void selectionChanged(SelectionChangedEvent event) { 
        MultiPageEditorSite.this.handleSelectionChanged(event); 
      } 
    }; 
  } 
  return selectionChangedListener; 
}

Lorsqu'une selection d'un EditPart GEF est effectuée, le méthode MultiPageEditorSite#handleSelectionChanged de la classe MultiPageEditorSite est appelée. Voici son code :

protected void handleSelectionChanged(SelectionChangedEvent event) { 
  ISelectionProvider parentProvider = getMultiPageEditor().getSite() 
      .getSelectionProvider(); 
  if (parentProvider instanceof MultiPageSelectionProvider) { 
    SelectionChangedEvent newEvent = new SelectionChangedEvent( 
        parentProvider, event.getSelection()); 
    MultiPageSelectionProvider prov = (MultiPageSelectionProvider) parentProvider; 
    prov.fireSelectionChanged(newEvent); 
  } 
}

Le test qui nous intéresse est

if (parentProvider instanceof MultiPageSelectionProvider) ...

Il vérifie que le fournisseur de sélection du multi page editor (dans notre cas WorkflowEditor) est de type MultiPageSelectionProvider. Ce test n'est jamais vrai avec le code générée par EMF car le fournisseur de selection le multi page WorkflowEditor lui-même. En effet si on regarde le code générée par EMF de notre multi page editor WorkflowEditor, cette dernière implémente ISelectionProvider

public class WorkflowEditor 
  extends MultiPageEditorPart 
  implements IEditingDomainProvider, ISelectionProvider, IMenuListener, IViewerProvider, IGotoMarker { 
...

et indique que le fournisseur de selection de son IEditorSite (qui est un MultiPageEditorSite) est lui-même dans la méthode WorkflowEditor#init(IEditorSite site, IEditorInput editorInput) :

public void init(IEditorSite site, IEditorInput editorInput) { 
  ... 
  site.setSelectionProvider(this); 
  ... 

Par défaut un MultiPageEditorPart utilise un MultiPageSelectionProvider mais le code générée par EMF n'utilise pas de MultiPageSelectionProvider ce qui rtend obsolète la sélection des EditPart GEF.

GEF GraphicalEditor - ISelectionChangedListener

Après avoir modifiez le code pour pouvoir utiliser un MultiPageSelectionProvider, mettez un point d'arrêt dans la méthode GraphicalEditor#selectionChanged#selectionChanged(IWorkbenchPart part, ISelection selection), et vous pourrez constater que le point d'arrêt s'arrête :

Si on regarde la trace on peut voir que la méthode MultiPageSelectionProvider#fireSelectionChanged() est appelé qui appelle la méthode MultiPageSelectionProvider#fireEventChange(final SelectionChangedEvent event, Object[] listeners) :

public void fireSelectionChanged(final SelectionChangedEvent event) { 
  Object[] listeners = this.listeners.getListeners(); 
  fireEventChange(event, listeners); 
}

La méthode fireEventChange :

private void fireEventChange(final SelectionChangedEvent event, Object[] listeners) { 
  for (int i = 0; i < listeners.length; ++i) { 
  final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i]; 
  SafeRunner.run(new SafeRunnable() { 
  public void run() { 
  l.selectionChanged(event); 
  } 
  }); 
  } 
}

itère sur la liste des listeners enregistrés.

Le listener qui nous intéresse est le service de selection (AbstractSelectionService) qui est enregistré dans les listeners et qui appelle la méthode GraphicalEditor#selectionChanged#selectionChanged(IWorkbenchPart part, ISelection selection),.

GEF utilise le service de selection. Le GraphicalViewer GEF jour le rôle du fournisseur de selection ISelectionProvider et l'editor GEF GraphicalEditor jour le rôle du consommateur de selection (ISelectionChangedListener). Ce dernier s'abonne au service de selection dans sa méthode init :

public void init(IEditorSite site, IEditorInput input) throws PartInitException { 
  ... 
  getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this); 
  ... 
}

Pour plus d'information sur l'utilisation du service de selection je vous conseille de lire l'article Eclipse Workbench: Using the Selection Service.

L'editor GEF GraphicalEditor enregistre le fournisseur de selection GraphicalViewer via le MultiPageEditorSite comme ceci :

protected void hookGraphicalViewer() { 
  getSelectionSynchronizer().addViewer(getGraphicalViewer()); 
  getSite().setSelectionProvider(getGraphicalViewer()); 
}

Social Bookmarking:

                                     

Commentaires, Pingbacks:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0
Commentaire de: ecoplm [Membre]
Hello,

Plus personne pour les commentaires? Y-a-t-il une suite? Passionnant et motivant pour un développement durable... J'ai un projet en vue sur ces bases et|ou GMF.

@+ Eric
Permalien 16/12/2009 @ 23:31
Commentaire de: azerr [Membre]
Bonjour Eric,

> Plus personne pour les commentaires?
Que veux tu dire?

> Y-a-t-il une suite?
Pour l'instant ca n'est pas prévu. J'ai tenté de balayer la plupart des sujets pour concevoir un éditeur XML basique (il en reste encore plein, mais je pense que ca donne un point de départ). Aujourd'hui, je suis en plein rédaction des billets intitulés "Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM" sur mon nouveau blog http://angelozerr.wordpress.com/

> Passionnant et motivant pour un développement durable...

Merci. Mais je n'ai pas la science infuse et il n efaut pas hésiter de critiquer les billets si il y a des choses incohérentes.

> J'ai un projet en vue sur ces bases et|ou GMF.
Projet passionnant! Je reverais de travailler sur un tel projet. GMF je l'ai un peu étudié mais je pense qu'avant de faire du GMF il faut connaitre EMF et GEF. GMF me semble une boite noire et cel am'a fait un peu peur. Je n'ai jamais vu de vrais plugins basés sur GMF, du moins un plugin qui a une page source XML qui se synchronise avec la pge graphique. Je ne sais pas si SSE est facile à intégrer dans GMF.

Angelo
Permalien 17/12/2009 @ 09:18
Commentaire de: ecoplm [Membre]
Bonjour Angelo,

C'était noël, merci pour tes réponses.

> Plus personne pour les commentaires?
Que veux tu dire? Malgré l'intérêt indéniable des tes billets, je ne vois que très peu de mails...


Bref... en fait j'en suis au step 3, petit soucis avec les extensions workflow xml class start(BundleContext context) throws Exception... & stop ça marche pas... N'étant pas expert d'eclipse, je commence à m'y retrouver.

J'utilise Eclipse Modeling Tools - Build id: 20090920-1017 sous ubuntu server 804LTS > virtualbox > windows xppsp3. Pb de version?

J'ai téléchargé tes zip aux steps suivants mais ça coince

Mon objectif est de générer les PLM métiers (d'où l'intérêt pour l'édition graphique de workflow) en mode serveur php basé sur un (des) annuaire(s) LDAP.

@ bientôt, Eric.

Permalien 28/12/2009 @ 17:32
Commentaire de: azerr [Membre]
Bonsoir Eric,

> C'était noël, merci pour tes réponses.
de rien.

> Que veux tu dire? Malgré l'intérêt indéniable des tes billets, je ne vois que très peu de mails...
Oui je sais, le sujet editeur XML ne doit pas etre beaucoup abordé.

> J'utilise Eclipse Modeling Tools - Build id: 20090920-1017 sous ubuntu server 804LTS > virtualbox > windows xppsp3. Pb de version?
Je susi sous windows je ne peux pas t'aider la.

C'est quoi ton erreur? Ta stacktrace?

> Mon objectif est de générer les PLM métiers (d'où l'intérêt pour l'édition graphique de workflow) en mode serveur php basé sur un (des) > annuaire(s) LDAP.
Super interessant comme sujet.

Angelo


Permalien 28/12/2009 @ 17:43
Commentaire de: nd786mar1 [Membre]
Bonjour,
la sélection des éléments GEF marche parfaitement, mais ça fait presque une semaine que j'essaye de faire marcher la fonctionnalité suivante: lorsqu'on clique sur un élément graphique GEF la property view affichera ses propriétés correspondantes.
avez vous une idéé sur cela.
Merci d'avance.
Permalien 04/04/2010 @ 16:18
Commentaire de: azerr [Membre]
Bonsoir nd786mar1,

Le code généré par EMF, génère deja le code qui permet de gérer la property view. Cependant je ne sais pas si les modifications que j'ai explique dans les billets ne pose pas de problèmes? Il faudrait que tu regardes deja le code genere par EMF et verifie que ca marche puis voir ce que j'ai du modifier (pour gerer GEF et la selection des figures) pour voir si ca ne pose pas de problème. Il va falloir debugger pas a pas les sources d'eclipse (ce que je faisais) pour bien comprendre.

Bon courage.

Angelo
Permalien 05/04/2010 @ 18:23

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Akrogen Blog

Catégories


Rechercher

<  Février 2012  >
Lun Mar Mer Jeu Ven Sam Dim
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29        

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web