/***************************************************************************** * Copyright (c) 2012 CEA LIST. * * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * CEA LIST - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.actions; /***************************************************************************** * Copyright (c) 2010 CEA LIST. * * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation * *****************************************************************************/ import java.util.ArrayList; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.commands.Command; import org.eclipse.gmf.runtime.common.ui.util.DisplayUtils; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.papyrus.commands.wrappers.GEFtoEMFCommandWrapper; import org.eclipse.papyrus.infra.emf.providers.EMFLabelProvider; import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.util.ViewServiceUtil; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IActionDelegate; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog; import org.eclipse.ui.dialogs.SelectionDialog; /** * * Super Class for the ShowHide action * */ public abstract class AbstractShowHideAction implements IActionDelegate, IWorkbenchWindowActionDelegate { /** the selected elements */ protected List<IGraphicalEditPart> selectedElements; /** the initial selection */ protected List<Object> initialSelection; /** key for the EditPolicy providing the action */ private String editPolicyKey = null; /** title for the window */ private String title = null; /** message for the window */ private String message = null; /** label provider */ private ILabelProvider labelProvider = null; /** content provider */ private ITreeContentProvider contentProvider = null; /** the list of the views to destroy */ protected List<EditPartRepresentation> viewsToDestroy; /** the list of the view to create */ protected List<EditPartRepresentation> viewsToCreate; /** the list of the {@link EditPartRepresentation} */ protected List<EditPartRepresentation> representations; /** * * Constructor. * * @param title * title for the dialog * @param message * message for the dialog * @param editPolicyKey * the EditPolicy used for this action */ public AbstractShowHideAction(String title, String message, String editPolicyKey) { this.editPolicyKey = editPolicyKey; this.title = title; this.message = message; /* for further information, see bug 302555 */ ViewServiceUtil.forceLoad(); } /** * {@inheritDoc} */ public void dispose() { // nothing here } /** * {@inheritDoc} */ public void init(IWorkbenchWindow window) { // nothing here } /** * {@inheritDoc} */ public void run(IAction action) { if(!canRun()) { return; } initAction(); buildInitialSelection(); SelectionDialog selectionDialog = getSelectionDialog(); selectionDialog.open(); if(selectionDialog.getReturnCode() == Dialog.OK) { buildShowHideElementsList(selectionDialog.getResult()); final Command command = getActionCommand(); final TransactionalEditingDomain domain = this.selectedElements.get(0).getEditingDomain(); if(command.canExecute()) { try { domain.runExclusive(new Runnable() { public void run() { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { // executing the command public void run() { domain.getCommandStack().execute(new GEFtoEMFCommandWrapper(command)); } }); } }); } catch (InterruptedException e) { Activator.log.error(e); } } } } /** * Creates and returns the selection dialog displayed by this action * * @return the created selection dialog */ protected SelectionDialog getSelectionDialog() { CheckedTreeSelectionDialog selectionDialog = new CheckedTreeSelectionDialog(DisplayUtils.getDisplay().getActiveShell(), getEditorLabelProvider(), getContentProvider()); selectionDialog.setTitle(title); selectionDialog.setMessage(message); selectionDialog.setContainerMode(true); selectionDialog.setInput(getInput()); selectionDialog.setExpandedElements(getExpandedElements()); selectionDialog.setInitialElementSelections(getInitialSelection()); return selectionDialog; } /** * Returns the list of all elements * * @return the list of all elements */ protected Object[] getExpandedElements() { List<Object> allElements = new ArrayList<Object>(); for(EditPartRepresentation current : this.representations) { allElements.add(current); allElements.addAll(current.getPossibleElement()); } return allElements.toArray(); } /** * * Test if the action can be run! Useful when we press F4 and it's the first * action in Papyrus * * @return if the action can be run or not */ public boolean canRun() { if(this.selectedElements.isEmpty()) { return false; } for(Object object : this.selectedElements) { if(!(object instanceof EditPart)) { return false; } else { EditPolicy policy = ((EditPart)object).getEditPolicy(editPolicyKey); if(policy == null) { return false; } } } return true; } /** * * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) * * @param action * the current action * @param selection * the current selection */ public void selectionChanged(IAction action, ISelection selection) { boolean enabled = false; if(editPolicyKey != null) { selectedElements = new ArrayList<IGraphicalEditPart>(); if(selection instanceof StructuredSelection) { for(Object current : ((StructuredSelection)selection).toArray()) { if(current instanceof IGraphicalEditPart) { selectedElements.add((IGraphicalEditPart)current); EditPolicy policy = ((IGraphicalEditPart)current).getEditPolicy(editPolicyKey); if(policy != null) { enabled = true; break; } } } } } if(action != null) { action.setEnabled(enabled); } } /** * Initialize * <ul> * <li>{@link #labelProvider}</li> * <li> {@link #representations}</li> * </ul> * * This method should be override by subclasses to initialize {@link #contentProvider} for example. * */ protected void initAction() { this.labelProvider = new EditPartRepresentationLabelProvider(); this.representations = new ArrayList<AbstractShowHideAction.EditPartRepresentation>(); } /** * Returns the initial selection for the Tree Dialog. * * @return The initial selection for the Tree Dialog */ public List<Object> getInitialSelection() { return this.initialSelection; } /** * Build the initial selection for the tree */ protected void buildInitialSelection() { this.initialSelection = new ArrayList<Object>(); for(EditPartRepresentation current : this.representations) { contributeToInitialSelection(initialSelection, current); } } /** * Complete the list of initial selection for the given representation and its potential children * * @param listToComplete * the list of selected elements to complete * @param representation * the edit part representation that completes the list */ protected void contributeToInitialSelection(List<Object> listToComplete, EditPartRepresentation representation) { listToComplete.addAll(representation.getInitialSelection()); List<EditPartRepresentation> children = representation.getPossibleElement(); if(children != null) { for(EditPartRepresentation child : children) { contributeToInitialSelection(listToComplete, child); } } } /** * Returns the input for the TreeDialog * * @return the input for the TreeDialog */ abstract protected List<Object> getInput(); /** * Fill the following fields with the elements to show and the elements to * hide * <ul> * <li>{@link #viewsToCreate}</li> * <li> {@link #viewsToDestroy}</li> * </ul> * * @param result * the interesting element selected in the tree */ protected void buildShowHideElementsList(Object[] result) { this.viewsToCreate = new ArrayList<EditPartRepresentation>(); this.viewsToDestroy = new ArrayList<EditPartRepresentation>(); } /** * Returns the command done by this action * * @return the command done by this action */ abstract protected Command getActionCommand(); /** * Setter for {@link #labelProvider} * * @param provider * the label provider for the tree */ protected void setEditorLabelProvider(ILabelProvider provider) { this.labelProvider = provider; } /** * Returns the label provider used by the dialog * * @return the labelProvider */ protected ILabelProvider getEditorLabelProvider() { return labelProvider; } /** * Setter for {@link #contentProvider} * * @param provider * the provider for the tree */ protected void setContentProvider(ITreeContentProvider provider) { this.contentProvider = provider; } /** * Returns the content provider for the selection dialog * * @return the contentProvider */ protected ITreeContentProvider getContentProvider() { return contentProvider; } /** * Setter for {@link #selectedElements}. When this action is called by a * popup menu, {@link #selectedElements} is filled by {@link #selectionChanged(IAction, ISelection)} When this action is called * by a Handler, {@link #selectedElements} is filled with this method * * @param selection * the current selection */ public void setSelection(List<IGraphicalEditPart> selection) { this.selectedElements = selection; } /** * Getter for {@link AbstractShowHideAction#editPolicyKey} * * @return * * {@link AbstractShowHideAction#editPolicyKey} */ public String getEditPolicyKey() { return this.editPolicyKey; } /** * * This class provides some facilities to build the action. * */ public class EditPartRepresentation { /** the editpart represented by this class */ private IGraphicalEditPart representedEditPart; /** the initial selection */ protected List<EditPartRepresentation> initialSelection; /** the possible element to show/hide */ protected List<EditPartRepresentation> elementsToSelect; /** the semantic element represented by the EditPart */ protected EObject eObject; /** parent edit part representation */ final private EditPartRepresentation parentRepresentation; /** * Constructor. * * @param representedEditPart * the represented EditPart * @param eObject * the semantic element represented by EditPartRepresentation */ public EditPartRepresentation(IGraphicalEditPart representedEditPart, EObject eObject) { this(representedEditPart, eObject, null); } /** * * Constructor. * * @param representedEditPart * the represented EditPart * @param eObject * the semantic element represented by EditPartRepresentation * @param parentRepresentation * parent representation of this edit part representation */ public EditPartRepresentation(IGraphicalEditPart representedEditPart, EObject eObject, EditPartRepresentation parentRepresentation) { this.setRepresentedEditPart(representedEditPart); this.eObject = eObject; this.parentRepresentation = parentRepresentation; initRepresentation(); } /** * Getter for {@link #representedEditPart} * * @return the represented editpart, {@link #representedEditPart} */ public IGraphicalEditPart getRepresentedEditPart() { return this.representedEditPart; } /** * Getter for {@link #eObject} * * @return {@link #eObject} */ public EObject getSemanticElement() { return this.eObject; } /** * Getter for {@link #initialSelection} * * @return {@link #initialSelection} */ public List<EditPartRepresentation> getInitialSelection() { return this.initialSelection; } /** * initialize the following fields * <ul> * <li> {@link #initialSelection}</li> * <li>{@link #elementsToSelect}</li> * </ul> */ protected void initRepresentation() { this.initialSelection = new ArrayList<EditPartRepresentation>(); this.elementsToSelect = new ArrayList<EditPartRepresentation>(); } /** * Setter for {@link #elementsToSelect} * * @return {@link #elementsToSelect} */ public List<EditPartRepresentation> getPossibleElement() { return this.elementsToSelect; } /** * Returns the parent representation of this edit part representation * * @return the parent representation of this edit part representation */ public EditPartRepresentation getParentRepresentation() { return parentRepresentation; } /** * Setter for the {@link #representedEditPart} * * @param representedEditPart * {@link #representedEditPart} */ public void setRepresentedEditPart(IGraphicalEditPart representedEditPart) { this.representedEditPart = representedEditPart; } /** * Returns the display label for this edit part representation * * @return the display label for this edit part representation */ public String getLabel() { EObject semanticElement = getSemanticElement(); if(isElementInherited()) { StringBuffer buffer = new StringBuffer(); buffer.append(getEditorLabelProvider().getText(getSemanticElement())); buffer.append(" "); buffer.append("(from "); buffer.append(getEditorLabelProvider().getText(getSemanticElement().eContainer())); buffer.append(")"); return buffer.toString(); } return getEditorLabelProvider().getText(semanticElement); } /** * Returns the display label for this edit part representation * * @return the display label for this edit part representation */ public Image getImage() { return getEditorLabelProvider().getImage(getSemanticElement()); } /** * Checks if the parent of the element linked to the given edit part representation is similar to the element of the parent representation * * @param representation * the edit part representation to check * @return <code>true</code> if the element is inherited */ protected boolean isElementInherited() { EditPartRepresentation parentRepresentation = getParentRepresentation(); if(parentRepresentation == null) { // no parent => can not be inherited return false; } // no uml element in representation, can not check if(getSemanticElement() == null) { return false; } EObject parentElement = parentRepresentation.getSemanticElement(); EObject elementOwner = getSemanticElement().eContainer(); // Null for rer.getUMLElement was already check before. if(parentElement == null || elementOwner == null) { // no element in the parent representation return false; } if(!parentElement.equals(elementOwner)) { return true; } return false; } } /** * label provider that delegates to the edit part representation the label */ protected class EditPartRepresentationLabelProvider extends LabelProvider { /** editor label provider */ protected EMFLabelProvider editorLabelProvider; /** * Constructor. */ public EditPartRepresentationLabelProvider() { this.editorLabelProvider = new EMFLabelProvider(); } /** * {@inheritDoc} */ @Override public String getText(Object element) { if(element instanceof EditPartRepresentation) { return ((EditPartRepresentation)element).getLabel(); } return editorLabelProvider.getText(element); } /** * {@inheritDoc} */ @Override public Image getImage(Object element) { if(element instanceof EditPartRepresentation) { return ((EditPartRepresentation)element).getImage(); } return editorLabelProvider.getImage(element); } } // /** // * // * EditorLabelProvider for the {@link CheckedTreeSelectionDialog} // * // */ // public class CustomEditorLabelProvider extends EditorLabelProvider { // // /** // * {@inheritDoc} // */ // @Override // public Image getImage(Object element) { // if(element instanceof EditPartRepresentation) { // element = ((EditPartRepresentation)element).getSemanticElement(); // } // return super.getImage(element); // } // // /** // * {@inheritDoc} // */ // @Override // public String getText(Object element) { // if(element instanceof CompartmentEditPartRepresentation) { // return ((CompartmentEditPartRepresentation)element).getCompartmentName(); // } else if(element instanceof EditPartRepresentation) { // EObject semanticElement = ((EditPartRepresentation)element).getSemanticElement(); // if(isElementInherited((EditPartRepresentation)element)) { // StringBuffer buffer = new StringBuffer(); // buffer.append(super.getText(semanticElement)); // buffer.append(" "); // buffer.append("(from "); // buffer.append(super.getText(((EditPartRepresentation)element).getSemanticElement().eContainer())); // buffer.append(")"); // return buffer.toString(); // } else { // return super.getText(semanticElement); // } // } // return super.getText(element); // } // } }