septembre
2009
A l’étape du billet précédant [step17] nous avons réglé le problème de la selection d’un EditPart GEF. Si vous mettez un point d’arrêt dans la méthode GraphicalEditor#selectionChanged(IWorkbenchPart part, ISelection selection), puis si vous sélectionnez un state, action de la page GEF Graphics vous pourrez constater que cette méthode est appelée :
// If not the active editor, ignore selection changed.
if (this.equals(getSite().getPage().getActiveEditor()))
updateActions(selectionActions);
}
Mais la méthode updateActions n’est jamais appelé. Nous expliquerons dans ce billet comment régler ce problème pour pouvoir ensuite implémenter les fonctionnalités de suppression :
- suppression des states/actions sélectionnés.
- suppression des connections sélectionnées.
La supppression pourra s’effectuer via :
- l’entrée de menu « Delete » accessible par le menu contextuel de la page GEF Graphics.
- la touche « Suppr ».
- l’entrée de menu « Delete » accessible par le menu global « Edit ».
Voici une copie d’écran qui affiche le menu contextuel qui permettra de supprimer un state sélectionné :
Vous pouvez télécharger le projet org.example.workflow_step18.zip présenté dans ce billet.
GEF Actions
Dans la page GEF, nous avons vu que notre modèle EMF est modifié via des Command GEF générée par nos EditPolicy installées qui réagissent à l’outil sélectionné dans la palette GEF. Une autre manière est de générer des Command GEF via des actions GEF. Ces actions GEF étendent toutes la classe org.eclipse.jface.action.Action qui sont beaucoup utilisés dans l’IDE Eclipse dans les menu (lorsque l’on clique sur un item d’un menu (ex : Copy), l’item du menu est associé à une Action JFace. La classe de base d’un editor GEF org.eclipse.gef.ui.parts.GraphicalEditor installe dans la méthode GraphicalEditor#createActions() par défaut 3 grands types d’actions GEF:
- les action de selection qui étendent org.eclipse.gef.ui.actions.SelectAction. Ce type d’action génère des Command GEF lorsque le Viewer de GraphicalEditor (GraphicalViewer) est sélectionné, comme l’action de delete.
- les action de stack qui éténdent org.eclipse.gef.ui.actions.StackAction. qui permmettent de gérer le undo, redo…
- les action de properties comme le save (je n’ai pas encore bien compris a quoi sert cette action).
DeleteAction
L’action qui nous intéresse dans notre cas est l’action de selection delete org.eclipse.gef.ui.actions.DeleteAction. Cette action réagit à la selection d’un EditPart et génère une Commande GEF de delete dans le cas ou l’EditPart sélectionné à un EditPolicy qui rèagit à sa suppression (ex : dans notre cas nous installerons un EditPolicy sur les EditPart StateTypePart, ActionTypePart et ConnectionPart pour pouvoir les supprimer.
Lorsqu’un EditPart GEF est sélectionné, une commande GEF DeleteCommand doit être instancié. Ceci est du à la méthode DeleteAction#calculateEnabled() :
Command cmd = createDeleteCommand(getSelectedObjects());
if (cmd == null)
return false;
return cmd.canExecute();
}
Cette méthode est appelée pour vérifier si l’action « Delete » doit être activée ou non. Lorsqu’un EditPart GEF action/state est sélectionné, une commande GEF DeleteCommand devra être instanciée et l’action « Delete » sera activée. L’exéction de la commande GEF DeleteCommand s’effectuera lorsque l’action DeleteAction sera lancée via sa méthode DeleteAction#run() :
execute(createDeleteCommand(getSelectedObjects()));
}
GraphicalWorkflowEditor#selectionChanged
Lorsqu’un EditPart GEF est sélectionné, la méthode DeleteAction#calculateEnabled() doit être appelé pour activer/désactiver l’action de delete en fonction de l’EditPart GEF selectionné. Cette méthode est appelé lorsqu’il y a une selection dans le viewer GEF par la méthode GraphicalEditor#updateActions(List actionIds). Le code qui permet de rafraîchir les actions de selection lors d’une selection dans le viewer de l’editor GEF se trouve dans la classe GEF GraphicalEditor :
* @see org.eclipse.ui.ISelectionListener#selectionChanged(IWorkbenchPart, ISelection)
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// If not the active editor, ignore selection changed.
if (this.equals(getSite().getPage().getActiveEditor()))
updateActions(selectionActions);
}
Cette méthode implémente l’interface org.eclipse.ui.ISelectionListener qui est appelé (théoriquement) lorsque il y a une selection effectuée sur n’importe quel éditeur du workbench Eclipse. GraphicalEditor joue le rôle d’un listener de selection en s’enregistrant dans le service de selection dans sa méthode init :
...
getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this);
...
}
Le test dans la méthode GraphicalEditor#selectionChanged :
if (this.equals(getSite().getPage().getActiveEditor()))
permet de tester si la sélection effectuée dans l’IDE Eclipse, concerne bien l’editor GEF en question. Dans un contexte ou l’editor GEF n’est pas inclus dans un multi page editor, ce code fonctionne très bien, mais qu’il l’est ce code ne sera jamais éxécuté car :
getSite().getPage().getActiveEditor()
retourne le multi page editor (dans notre cas WorkflowEditor) et pas l’editor GEF qui est inclu dans une page du multi page editor (dans notre cas GraphicalWorkflowEditor). Pour régler ce problème il faut tester si la page courante sélectionnée est bien notre editor GEF. Pour connaître la page active d’un editor, la classe de base org.eclipse.ui.part.MultiPageEditorPart (dont hérite notre multi page editor) fournit la méthode MultiPageEditorPart#getActiveEditor() mais qui est (pour je ne sais quelle raison) en protected. Pour pouvoir y accéder dans notre classe GraphicalWorkflowEditor, nous définissons une nouvelle méthode public WorkflowEditor#getActivePageEditor() comme suit :
return super.getActiveEditor();
}
Ici nous avons défini une nouvelle méthode (au lieu de surcharger la méthode MultiPageEditorPart#getActiveEditor() protected pour la rendre public) car dans la javdoc il y a :
Subclasses should not override this method
.
Nous pouvons ensuite surcharger la méthode GraphicalEditor#selectionChanged(IWorkbenchPart part, ISelection selection) dans la classe GraphicalWorkflowEditor comme suit :
// If not the active editor, ignore selection changed.
IWorkbenchPartSite site = getSite();
if (parent.equals(site.getPage().getActiveEditor())) {
// Multi page workflow editor is selected
// If not the active page editor, ignore selection changed.
WorkflowEditor workflowEditor = (WorkflowEditor)parent;
if (this.equals(workflowEditor.getActivePageEditor())) {
{
super.updateActions(super.getSelectionActions());
}
}
}
}
Mettez un point d’arrêt au debut de notre nouvelle méthode GraphicalWorkflowEditor#selectionChanged(IWorkbenchPart part, ISelection selection) et relancez le plugin. Si vous sélectionnez un state dans la page GEF, le point d’arrêt s’arrête.
Delete ActionType-StateType
Pour supprimer un state ou une action du workflow, nous allons créer une Commande GEF org.example.workflow.presentation.graphical.commands.DeleteCommand comme suit :
import java.util.List;
import org.eclipse.gef.commands.Command;
import org.example.workflow.model.ActionType;
import org.example.workflow.model.ConnectableNode;
import org.example.workflow.model.StateType;
import org.example.workflow.model.WorkflowType;
public class DeleteCommand extends Command {
private WorkflowType workflow;
private ConnectableNode connectableNode;
@Override
public void execute() {
getChildren().remove(getConnectableNode());
}
public WorkflowType getWorkflow() {
return workflow;
}
public void setWorkflow(WorkflowType workflow) {
this.workflow = workflow;
}
public ConnectableNode getConnectableNode() {
return connectableNode;
}
public void setConnectableNode(ConnectableNode connectableNode) {
this.connectableNode = connectableNode;
}
protected List getChildren() {
if (connectableNode instanceof StateType)
return workflow.getState();
if (connectableNode instanceof ActionType)
return workflow.getAction();
return null;
}
}
Cette commande GEF de delete doit être ensuite appelé via un EditPolicy qui doit étendre org.eclipse.gef.editpolicies.ComponentEditPolicy. En effet d’après la javadoc :
By default, ComponentEditPolicy understands being DELETEd from its container….
Notre command GEF DeleteCommand doit être initialisée dans la méthode ComponentEditPolicy#createDeleteCommand(GroupRequest deleteRequest) que nous allons implémenter. Créez la classe org.example.workflow.presentation.graphical.policies.WorkflowComponentEditPolicy comme suit :
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.ComponentEditPolicy;
import org.eclipse.gef.requests.GroupRequest;
import org.example.workflow.model.ConnectableNode;
import org.example.workflow.model.WorkflowType;
import org.example.workflow.presentation.graphical.commands.DeleteCommand;
public class WorkflowComponentEditPolicy extends ComponentEditPolicy {
@Override
protected Command createDeleteCommand(GroupRequest deleteRequest) {
WorkflowType parent = (WorkflowType)(getHost().getParent().getModel());
DeleteCommand deleteCmd = new DeleteCommand();
deleteCmd.setWorkflow(parent);
deleteCmd.setConnectableNode((ConnectableNode)(getHost().getModel()));
return deleteCmd;
}
}
Installez l’EditiPolicy WorkflowComponentEditPolicy dans l’EditPart Installez org.example.workflow.presentation.graphical.parts.ConnectableNodePart dans la méthode ConnectableNodePart#createEditPolicies() comme suit :
protected void createEditPolicies() {
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
new WorkflowNodeEditPolicy());
installEditPolicy(EditPolicy.COMPONENT_ROLE,
new WorkflowComponentEditPolicy());
}
Executer Commande delete
L’exéction de la commande GEF DeleteCommand s’effectuera lorsque l’action DeleteAction sera lancée via sa méthode DeleteAction#run() :
execute(createDeleteCommand(getSelectedObjects()));
}
Il nous reste donc à lancer DeleteAction#run() qui peut s’effectuer de plusieurs manières, autrement dit pouvoir supprimer un state, une action sélectionné :
- par le menu contextuel accéssible dans l’editor GEF Graphics qui propose une entrée de menu « Delete ».
- par la touche « Suppr ».
- par le menu globale accéssible dans la barre de menu standard « Edit » l’entrée de menu « Delete ».
Delete – Menu contextuel
Dans cette section nous allons associer un menu contextuel à la page GEF Graphics et nous y ajouterons une entrée « Delete ». Nous avons vu que l’action de delete GEF DeleteAction est ajouté par défaut au registry d’actions de l’editor GraphicalEditor. Pour ajouter un menu contextuel à une editor GEF, il est conseillé d’implémenter la classe abstraite GEF org.eclipse.gef.ContextMenuProvider.
Créez la classe org.example.workflow.presentation.graphical.actions.WorkflowContextMenuProvider comme suit :
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.ui.actions.ActionFactory;
public class WorkflowContextMenuProvider extends ContextMenuProvider {
private ActionRegistry actionRegistry;
public WorkflowContextMenuProvider(EditPartViewer viewer,
ActionRegistry registry) {
super(viewer);
setActionRegistry(registry);
}
public void buildContextMenu(IMenuManager menu) {
GEFActionConstants.addStandardActionGroups(menu);
IAction action = getActionRegistry().getAction(
ActionFactory.DELETE.getId());
if (action.isEnabled())
menu.appendToGroup(GEFActionConstants.GROUP_EDIT, action);
}
private ActionRegistry getActionRegistry() {
return actionRegistry;
}
public void setActionRegistry(ActionRegistry registry) {
actionRegistry = registry;
}
}
Cette classe éténd org.eclipse.gef.ContextMenuProvider et attend dans son constructeur un registry d’actions (qui sera celui de l’editor GraphicalEditor). La méthode WorkflowContextMenuProvider#buildContextMenu(IMenuManager menu) :
- appelle
GEFActionConstants.addStandardActionGroups(menu);
qui ajoute les groupes de menu standards (EDIT, UNDO, COPY…). - ajoute l’entrée de menu « Delete » dans le groupe EDIT si l’action « Delete » peut être opérationnel (si une action/state est sélectionné).
Dans les examples GEF, ils utilisent IWorkbenchActionConstants.DELETE pour rechercher l’action de delete, mais cette constante est deprecated, il faut utiliser ActionFactory.DELETE.getId() à la place.
Pour indiquer à notre editor GEF que nous souhaitons utiliser notre menu contextuel WorkflowContextMenuProvider, modifiez la méthode GraphicalWorkflowEditor#configureGraphicalViewer() comme suit :
protected void configureGraphicalViewer() {
super.configureGraphicalViewer();
GraphicalViewer viewer = getGraphicalViewer();
viewer.setEditPartFactory(WorkflowPartFactory.INSTANCE);
ContextMenuProvider provider = new WorkflowContextMenuProvider(
getGraphicalViewer(), getActionRegistry());
getGraphicalViewer().setContextMenu(provider);
getSite().registerContextMenu(
"org.example.workflow.presentation.graphical.contextmenu", //$NON-NLS-1$
provider, getGraphicalViewer());
}
Relancez le plugin, sélectionnez une action/state et ouvrez le menu contextuel (clic droit de le souris), le menu contextuel doit s’afficher avec une entré de menu « Delete » :
Si vous sélectionnez cette action « Delete », l’action/state selectionné sera ensuite supprimé.
Delete – Touche Suppr
Nous souhaitons executer l’action DeleteAction via la touche « Suppr ». Pour effectuer ceci, il suffit de mapper l’action DeleteAction (identifié par ActionFactory.DELETE.getId()) avec la touche « Suppr » (identifié par SWT.DEL). Définissez la variable de type org.eclipse.gef.KeyHandler dans GraphicalWorkflowEditor qui contiendra notre mapping :
private KeyHandler sharedKeyHandler;
Initialisez le mapping en ajoutant la méthode GraphicalWorkflowEditor#getCommonKeyHandler() :
if (sharedKeyHandler == null) {
sharedKeyHandler = new KeyHandler();
sharedKeyHandler
.put(KeyStroke.getPressed(SWT.DEL, 127, 0),
getActionRegistry().getAction(ActionFactory.DELETE.getId()));
}
return sharedKeyHandler;
}
Pour utilisez notre mapping, ajoutez a la fin de la méthode GraphicalWorkflowEditor#configureGraphicalViewer() le code suivant :
...
viewer.setKeyHandler(new GraphicalViewerKeyHandler(getGraphicalViewer()).setParent(getCommonKeyHandler()));
}
Relancez le plugin, sélectionnez une action/state puis appuyez sur la touche « Suppr » pour le supprimer.
Delete – Menu globale
Nous souhaitons maintenant mapper l’action GEF DeleteActionAction via l’entrée de menu « Delete » du menu globale standard « Edit ». Un EditorPart influe sur les actions disponibles dans la barre de menu en étendant généralement la classe org.eclipse.ui.part.EditorActionBarContributor. Cette barre de menu personnalisée pour l’editor est souvent associée « déclarativement » dans le fichier plugin.xml à l’aide de l’attribut contributorClass. Par exemple dans notre editor de workflow nous avons une entré de menu « Workflow Editor » dans la barre de menu globale qui est disponible lorsque l’editor de workflow est activé. Ce menu est gérée par la classe org.example.workflow.presentation.WorkflowActionBarContributor et est déclaré comme ceci dans le fichier plugin.xml :
<editor
...
class="org.example.workflow.presentation.WorkflowEditor"
contributorClass="org.example.workflow.presentation.WorkflowActionBarContributor">
</editor>
</extension>
GEF fournit la classe abstraite org.eclipse.gef.ui.actions.ActionBarContributor qui éténd org.eclipse.ui.part.EditorActionBarContributor et qui est conseillé d’utiliser pour des actions GEF associées à un editor GEF. Créez la classe org.example.workflow.presentation.graphical.actions.GraphicalWorkkflowActionBarContributor comme suit :
import org.eclipse.gef.ui.actions.ActionBarContributor;
import org.eclipse.gef.ui.actions.DeleteRetargetAction;
import org.eclipse.jface.action.IToolBarManager;
public class GraphicalWorkkflowActionBarContributor extends
ActionBarContributor {
protected void buildActions() {
addRetargetAction(new DeleteRetargetAction());
}
public void contributeToToolBar(IToolBarManager toolBarManager) {
}
protected void declareGlobalActionKeys() {
}
}
Le code addRetargetAction(new DeleteRetargetAction());
dans la méthode buildActions, mappe l’action de « Delete » du workbench avec l’action DeleteAction GEF.
Maintenant nous devons associer cette barre personnalisée d’actions lorsque la page GEF Graphics est activée. Les exemples GEF renseigne cette barre d’actions déclarativement via l’attribut contributorClass de l’élement XML editor du fichier plugin.xml. Dans notre cas nous ne pouvons pas faire comme ceci car nous sommes dans un contexte de multi page, ce qui signifie que les barre d’actions doivent se rafrîchir aussi en fonction de la page sélectionnée (et pas seulement au niveau de l’editor).
Pour gérer ceci nous allons suivre les explication de la section Completing Menus and Toolbars de l’article GMF ou l’idée générale est de modifier le code EMF pour pouvoir utiliser un org.eclipse.ui.part.MultiPageEditorActionBarContributor qui permet de gérer des barres d’actions selon la page activée dans un editor multi page. Actuellement, l’editor est associé à la barre d’actions org.example.workflow.presentation.WorkflowActionBarContributor qui éténd org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor
<editor
...
class="org.example.workflow.presentation.WorkflowEditor"
contributorClass="org.example.workflow.presentation.WorkflowActionBarContributor">
</editor>
</extension>
Nous allons créer la classe WorkflowMultipageActionBarContributor (comme TopicmapMultipageActionBarContributor) qui va éténdre org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor et gérer les barres d’actions de EMF et celle de GEF en fonction de la page activée.
Copiez collez la classe de l’article SubActionBarsExt dans le package org.example.workflow.presentation.
Créez la classe org.example.workflow.presentation.WorkflowMultipageActionBarContributor comme suit :
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IActionBars2;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
import org.example.workflow.presentation.graphical.GraphicalWorkflowEditor;
import org.example.workflow.presentation.graphical.actions.GraphicalWorkkflowActionBarContributor;
import org.example.workflow.presentation.parts.AbstractWorkflowEditorPart;
/**
* A special implementation of a
* <span>::CODECOLORER_BLOCK_7::</span> to switch between action bar
* contributions for tree-based editor pages and diagram editor pages.
*
* @see MultiPageEditorActionBarContributor
*/
public class WorkflowMultipageActionBarContributor extends
MultiPageEditorActionBarContributor {
private IActionBars2 myActionBars2;
private SubActionBarsExt myTreeSubActionBars;
private SubActionBarsExt myDiagramSubActionBars;
private SubActionBarsExt myActiveEditorActionBars;
private IEditorPart myActiveEditor;
private IPropertyListener myEditorPropertyChangeListener = new IPropertyListener() {
public void propertyChanged(Object source, int propId) {
if (myActiveEditorActionBars != null) {
if (myActiveEditorActionBars.getContributor() instanceof WorkflowActionBarContributor) {
((WorkflowActionBarContributor) myActiveEditorActionBars
.getContributor()).update();
}
}
}
};
@Override
public void init(IActionBars bars) {
super.init(bars);
assert bars instanceof IActionBars2;
myActionBars2 = (IActionBars2) bars;
}
@Override
public void setActiveEditor(IEditorPart part) {
if (myActiveEditor != null) {
myActiveEditor
.removePropertyListener(myEditorPropertyChangeListener);
}
super.setActiveEditor(part);
myActiveEditor = part;
if (myActiveEditor instanceof IEditingDomainProvider) {
myActiveEditor.addPropertyListener(myEditorPropertyChangeListener);
}
}
@Override
public void setActivePage(IEditorPart activeEditor) {
if (activeEditor instanceof GraphicalWorkflowEditor) {
setActiveActionBars(getDiagramSubActionBars(), activeEditor);
} else {
if (activeEditor instanceof AbstractWorkflowEditorPart) {
setActiveActionBars(getTreeSubActionBars(), activeEditor);
}
}
}
@Override
public void dispose() {
super.dispose();
if (myDiagramSubActionBars != null) {
myDiagramSubActionBars.dispose();
myDiagramSubActionBars = null;
}
if (myTreeSubActionBars != null) {
myTreeSubActionBars.dispose();
myTreeSubActionBars = null;
}
}
/**
* Switches the active action bars.
*/
private void setActiveActionBars(SubActionBarsExt actionBars,
IEditorPart activeEditor) {
if (myActiveEditorActionBars != null
&& myActiveEditorActionBars != actionBars) {
myActiveEditorActionBars.deactivate();
}
myActiveEditorActionBars = actionBars;
if (myActiveEditorActionBars != null) {
myActiveEditorActionBars.setEditorPart(activeEditor);
myActiveEditorActionBars.activate();
}
}
/**
* @return the sub cool bar manager for the tree-based editors.
*/
public SubActionBarsExt getTreeSubActionBars() {
if (myTreeSubActionBars == null) {
myTreeSubActionBars = new SubActionBarsExt(getPage(),
myActionBars2, new WorkflowActionBarContributor(),
"org.example.workflow.presentation.TreeActionContributor");
}
return myTreeSubActionBars;
}
/**
* @return the sub cool bar manager for the diagram editor.
*/
public SubActionBarsExt getDiagramSubActionBars() {
if (myDiagramSubActionBars == null) {
myDiagramSubActionBars = new SubActionBarsExt(
getPage(),
myActionBars2,
new GraphicalWorkkflowActionBarContributor(),
"org.example.workflow.presentation.graphical.actions.GraphicalWorkkflowActionBarContributor");
}
return myDiagramSubActionBars;
}
}
Pour créer cette classe j'ai repris le code de la classe TopicmapMultipageActionBarContributor que j'ai adapté à notre besoin :
<ul>
<li>utilisation de WorkflowActionBarContributor au lieu de TopicmapActionBarContributor.</li>
<li>utilisation de GraphicalWorkkflowActionBarContributor au lieu de TopicMapDiagramActionBarContributor.</li>
<li> terst effectué sur le type d'editor AbstractWorkflowEditorPart car notre multi page contient une page source:
<code>public void setActivePage(IEditorPart activeEditor) {
if (activeEditor instanceof GraphicalWorkflowEditor) {
setActiveActionBars(getDiagramSubActionBars(), activeEditor);
} else {
if (activeEditor instanceof AbstractWorkflowEditorPart) {
setActiveActionBars(getTreeSubActionBars(), activeEditor);
}
}
}
Modifiez le fichier plugin.xml pour utiliser dans notre editor WorkflowEditor, le contribution de barres d’actions WorkflowMultipageActionBarContributor au lieu de WorkflowActionBarContributor :
<editor
...
class="org.example.workflow.presentation.WorkflowEditor"
contributorClass="org.example.workflow.presentation.WorkflowMultipageActionBarContributor">
</editor>
...
Si vous relancez le plugin vous aurrez une erreur de ClassCastException sur WorkflowMultipageActionBarContributor :
Pour eviter cette erreur, modifiez la méthode WorkflowEditor#getActionBarContributor() pour récupérer de notre MultipageActionBarContributor la contribution de barres d’action concernant l’editor SelectionEditPart :
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated NOT
*/
public EditingDomainActionBarContributor getActionBarContributor() {
return (WorkflowActionBarContributor) ((WorkflowMultipageActionBarContributor) getEditorSite()
.getActionBarContributor()).getTreeSubActionBars()
.getContributor();
}
Relancez le plugin (vous n’aurrez plus d’erreur de ClassCastException), selectionnez une action/state et accéder au menu global Edit/Delete :
Cette entrée de menu est active lorsque un state/action est sélectionné. Si vous cliquez sur cette entrée de menu, le state/action sélectionné se supprime du workflow.
Si vous accédez à la page Selection et que vous tentez d’ouvrir le menu contextuel, celui-ci ne s’ouvre pas, pour remédier à ce problème, modifiez la méthode AbstractWorkflowEditorPart#menuAboutToShow(IMenuManager manager) de la classe org.example.workflow.presentation.parts.AbstractWorkflowEditorPart comme ceci :
// pass the request to show the context menu on to the parent editor
((WorkflowActionBarContributor) ((WorkflowMultipageActionBarContributor) parentEditor
.getEditorSite().getActionBarContributor())
.getTreeSubActionBars().getContributor())
.menuAboutToShow(manager);
}
Relancez le plugin, le menu contentuel dans la page Selection doit être à nouveau opérationnel :
Delete ConnectionType
Pour supprimer une connection nous allons créer une Commande GEF org.example.workflow.presentation.graphical.commands.DeleteConnectionCommand comme suit :
import org.eclipse.gef.commands.Command;
import org.example.workflow.model.ActionType;
import org.example.workflow.model.Connection;
public class DeleteConnectionCommand extends Command {
private Connection connection;
public void setConnection(Connection connection) {
this.connection = connection;
}
@Override
public void execute() {
if (connection.getSource() instanceof ActionType) {
ActionType action = (ActionType) connection.getSource();
action.setToState(null);
} else {
if (connection.getTarget() instanceof ActionType) {
ActionType action = (ActionType) connection.getTarget();
action.setFromState(null);
}
}
}
}
Cette commande GEF de delete de connections doit être ensuite appelé via un EditPolicy qui doit étendre org.eclipse.gef.editpolicies.ConnectionEditPolicy. En effet d’après la javadoc :
A model-based EditPolicy for connections… By default, ConnectionEditPolicy understands only DELETE.
Notre command GEF DeleteConnectionCommand doit être initialisée dans la méthode ConnectionEditPolicy#getDeleteCommand(GroupRequest deleteRequest) que nous allons implémenter. Créez la classe org.example.workflow.presentation.graphical.policies.WorkflowConnectionEditPolicy comme suit :
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.ConnectionEditPolicy;
import org.eclipse.gef.requests.GroupRequest;
import org.example.workflow.model.Connection;
import org.example.workflow.presentation.graphical.commands.DeleteConnectionCommand;
public class WorkflowConnectionEditPolicy extends ConnectionEditPolicy {
@Override
protected Command getDeleteCommand(GroupRequest request) {
DeleteConnectionCommand cmd = new DeleteConnectionCommand();
Connection connection = (Connection) getHost().getModel();
cmd.setConnection(connection);
return cmd;
}
}
Installez l’EditiPolicy WorkflowConnectionEditPolicy dans l’EditPart org.example.workflow.presentation.graphical.parts.ConnectionPart dans la méthode ConnectionPart#createEditPolicies() comme suit :
protected void createEditPolicies() {
installEditPolicy(EditPolicy.CONNECTION_ROLE, new WorkflowConnectionEditPolicy());
}
Relancez le plugin, sélectionnez une connection de la page GEF et supprimez la à l’aide du menu contextuel « Delete », à l’aide de la touche « Suppr » ou via le menu global « Edit/Delete ».
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