/***************************************************************************** * Copyright (c) 2009 Atos Origin. * * * 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: * Emilien Perico (Atos Origin) emilien.perico@atosorigin.com - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.infra.services.controlmode.action; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.ui.EMFEditUIPlugin; import org.eclipse.emf.edit.ui.action.ControlAction; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.papyrus.commands.CheckedOperationHistory; import org.eclipse.papyrus.infra.core.resource.AbstractBaseModel; import org.eclipse.papyrus.infra.core.resource.IModel; import org.eclipse.papyrus.infra.core.resource.ModelSet; import org.eclipse.papyrus.infra.core.resource.ModelUtils; import org.eclipse.papyrus.infra.core.resource.notation.NotationModel; import org.eclipse.papyrus.infra.core.resource.uml.UmlModel; import org.eclipse.papyrus.infra.core.utils.EditorUtils; import org.eclipse.papyrus.infra.services.controlmode.commands.ControlCommand; import org.eclipse.papyrus.infra.services.controlmode.util.ControlModeUtil; import org.eclipse.papyrus.infra.widgets.toolbox.notification.NotificationRunnable; import org.eclipse.papyrus.infra.widgets.toolbox.notification.Type; import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.IContext; import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; /** * An action to control a papyrus resource. */ public class PapyrusControlAction extends ControlAction { /** * Instantiates a new papyrus control action. * * @param domain * the domain */ public PapyrusControlAction(EditingDomain domain) { super(domain); setDescription(EMFEditUIPlugin.INSTANCE.getString("_UI_Control_menu_item_description")); setToolTipText("Split the model into an external model"); } /** * {@inheritDoc} */ @Override public boolean isEnabled() { return ControlModeUtil.canControl(eObject); } /** * Checks if a specified element gets a diagram * * @param eObject * @return true if a diagram exists */ private boolean getDiagram(EObject eObject) { Resource modelResource = eObject.eResource(); if(modelResource != null) { // only check for diagrams in the relative notation resource (same name as the opened resource) Resource notationResource = modelResource.getResourceSet().getResource(modelResource.getURI().trimFileExtension().appendFileExtension(NotationModel.NOTATION_FILE_EXTENSION), true); if(notationResource != null) { for(EObject o : notationResource.getContents()) { if(o instanceof Diagram) { EObject element = ((Diagram)o).getElement(); if(element != null && (element.equals(eObject) || EcoreUtil.isAncestor(this.eObject, element))) { return true; } } } } } return false; } /** * {@inheritDoc} */ @Override public boolean updateSelection(IStructuredSelection selection) { boolean result = false; this.selection = selection; if(selection.size() == 1) { Object object = AdapterFactoryEditingDomain.unwrap(selection.getFirstElement()); if(object instanceof IAdaptable) { object = ((IAdaptable)object).getAdapter(EObject.class); } // Check whether the selected object is controllable result = domain.isControllable(object); if(result) { eObject = (EObject)object; } else { eObject = null; } } return result; } /** * {@inheritDoc} */ @Override public void run() { // check if object selection is in the current model set. If not, warn the user and disable action ModelSet modelSet = ModelUtils.getModelSet(); if(modelSet != null) { IModel umlModel = modelSet.getModel(UmlModel.MODEL_ID); boolean enableControl = false; if(eObject != null && umlModel instanceof AbstractBaseModel) { enableControl = ((AbstractBaseModel)umlModel).getResource().equals(eObject.eResource()); } if(!enableControl) { NotificationBuilder.createAsyncPopup("You must perform control action from the resource:\n" + eObject.eResource().getURI().trimFileExtension().toString() + " for this element").setType(Type.INFO).run(); return; } if(!getDiagram(eObject)) { NotificationBuilder.createAsyncPopup("The selected package must contain a diagram to perform control action").setType(Type.INFO).run(); return; } Resource controlledModel = getControlledResource(); if(controlledModel == null) { return; } try { ControlCommand transactionalCommand = new ControlCommand(EditorUtils.getTransactionalEditingDomain(), controlledModel, eObject, "Control", null); IStatus status = CheckedOperationHistory.getInstance().execute(transactionalCommand, new NullProgressMonitor(), null); if(status.isOK()) { notifySave(); } else { NotificationBuilder.createErrorPopup(status.getMessage()).setTitle("Unable to control").run(); } } catch (ExecutionException e) { MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_InvalidURI_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_CannotCreateResource")); EMFEditUIPlugin.INSTANCE.log(e); } } } /** * Display asynchronous popup to inform user about the control action */ protected void notifySave() { new NotificationBuilder().setMessage("Your element has been controlled.\nYou need to save your model to see modifications in your workspace.\nDo you want to save ?").addAction(new NotificationRunnable() { public void run(IContext context) { try { Display.getDefault().syncExec(new Runnable() { public void run() { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().doSave(new NullProgressMonitor()); } }); } catch (Exception e) { e.printStackTrace(); } } public String getLabel() { return "Save"; } }).setTemporary(true).setAsynchronous(true).setType(Type.INFO).setDelay(2000).run(); } /** * Instantiates a ControlResourceDialog and gets the controlled resource * * @return the controlled resource */ private Resource getControlledResource() { org.eclipse.papyrus.infra.services.controlmode.ui.ControlResourceDialog dialog = new org.eclipse.papyrus.infra.services.controlmode.ui.ControlResourceDialog(Display.getDefault().getActiveShell(), getEditingDomain(), eObject.eResource(), getElementName(eObject)); int returnCode = dialog.open(); Resource resource = null; if(returnCode == Window.OK) { resource = dialog.getControlResource(); if(resource == null || !resource.getURI().isPlatformResource()) { MessageDialog.openWarning(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_InvalidURI_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_CannotCreateResource")); resource = null; } } return resource; } /** * Gets the specified object name, a default name if not found * * @param obj * @return the element name */ private String getElementName(EObject eObject) { EStructuralFeature nameFeature = getLabelFeature(eObject.eClass()); if(nameFeature != null) { Object value = eObject.eGet(nameFeature); if(value != null) { return value.toString(); } } // Default file name to use for the controlled resource if no appropriate "name" was found // on the controlled element. return "Unknown"; } /** * Copied from org.eclipse.emf.edit.provider.ReflectiveItemProvider and slightly modified to * return null if no likely candidate is found. * * @param eClass * @return the EStructuralFeature for the class */ protected EStructuralFeature getLabelFeature(EClass eClass) { EAttribute result = null; for(EAttribute eAttribute : eClass.getEAllAttributes()) { if(!eAttribute.isMany() && eAttribute.getEType().getInstanceClass() != FeatureMap.Entry.class) { if("name".equalsIgnoreCase(eAttribute.getName())) { result = eAttribute; break; } else if(eAttribute.getEAttributeType().getInstanceClass() == String.class && result != null && result.getEAttributeType().getInstanceClass() != String.class) { result = eAttribute; } } } return result; } }