diff options
Diffstat (limited to 'plugins/infra')
108 files changed, 6075 insertions, 959 deletions
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java index e08edd9824b..15b64868042 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java @@ -1,7 +1,7 @@ /*****************************************************************************
* Copyright (c) 2008, 2013 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
@@ -97,15 +97,15 @@ import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; * implementation allows to register editors and context separately. An editor
* should specify which context it need to run. This multi diagram editor allows
* to show editor side by side in one or more sash windows.
- *
+ *
* The real implementation for the generic type T of SashMultiPageEditorPart is
* actually di2.Diagram
- *
+ *
* @author cedric dumoulin
* @author <a href="mailto:jerome.benois@obeo.fr">Jerome Benois</a>
* @author <a href="mailto:thomas.szadel@atosorigin.com">Thomas Szadel</a>
* Refactoring.
- *
+ *
* TODO : remove GMF dependency !
*/
public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implements IMultiDiagramEditor, ITabbedPropertySheetPageContributor, IGotoMarker {
@@ -149,9 +149,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* This method is called when the editor input is changed from the
* ISaveAndDirtyService.
- *
+ *
* @see org.eclipse.papyrus.infra.core.lifecycleevents.IEditorInputChangedListener#editorInputChanged(org.eclipse.ui.part.FileEditorInput)
- *
+ *
* @param fileEditorInput
*/
@Override
@@ -163,9 +163,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* The isDirty flag has changed, reflect its new value
- *
+ *
* @see org.eclipse.papyrus.infra.core.lifecycleevents.IEditorInputChangedListener#isDirtyChanged()
- *
+ *
*/
@Override
public void isDirtyChanged() {
@@ -176,8 +176,8 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen @Override
public void run() {
// editor can be null if this object has been finalized, but
- // still queued in the asyncExec queue.
- // This can happen if the editor is disposed, but some run still in
+ // still queued in the asyncExec queue.
+ // This can happen if the editor is disposed, but some run still in
// the exec queue.
// When the method is executed asynchronously, the object is already finalized, and so
// editor is null.
@@ -268,7 +268,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Get the contentOutlineRegistry. Create it if needed.
- *
+ *
* @return the contentOutlineRegistry
*/
protected ContentOutlineRegistry getContentOutlineRegistry() {
@@ -288,7 +288,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Returns the service registry associated to the editor.
- *
+ *
* @return the servicesRegistry The registry.
*/
@Override
@@ -301,7 +301,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Create the ServicesRegistry.
- *
+ *
* @return
*/
private ServicesRegistry createServicesRegistry() {
@@ -320,7 +320,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Do nothing as we create the provider before any calls to this method.
* Should not be called by subclasses.
- *
+ *
* @see org.eclipse.papyrus.infra.core.sasheditor.editor.AbstractMultiPageSashEditor#createPageProvider()
*/
@Override
@@ -330,14 +330,14 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Create the pageContentProvider.
- *
+ *
* Removed since 0.10.0
- *
+ *
* @param pageFactory
* @param diResource
* Resource used to load/save the SashModel.
- *
- *
+ *
+ *
*/
// protected ISashWindowsContentProvider createPageProvider(IPageModelFactory pageFactory, Resource diResource, TransactionalEditingDomain editingDomain) {
//
@@ -352,7 +352,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen * Get The {@link IPageMngr} used to add, open, remove or close a diagram in
* the SashWindow. This method is available as soon as the {@link CoreMultiDiagramEditor#init(IEditorSite, IEditorInput)} method is
* called.
- *
+ *
* @return
*/
protected IPageManager getIPageManager() throws IllegalStateException {
@@ -365,7 +365,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Get the ActionBarContributorRegistry. Creates it if necessary.
- *
+ *
* @return
*/
protected ActionBarContributorRegistry getActionBarContributorRegistry() {
@@ -389,7 +389,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Create the ActionBarContributorRegistry.
- *
+ *
* @return
*/
private ActionBarContributorRegistry createActionBarContributorRegistry() {
@@ -397,10 +397,10 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen }
/**
- *
- *
+ *
+ *
* @param adapter
- *
+ *
* @return
*/
@SuppressWarnings("rawtypes")
@@ -493,6 +493,11 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen @Override
public void run() {
+ //Because we are asynchronous, the editor may already have been disposed
+ //(Especially in the case of tests running in the UI Thread)
+ if(servicesRegistry == null) {
+ return;
+ }
getLifecycleManager().firePostDisplay(CoreMultiDiagramEditor.this);
}
});
@@ -628,6 +633,10 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen }
private InternalEditorLifecycleManager getLifecycleManager() {
+ //I've been disposed
+ if(servicesRegistry == null) {
+ return null;
+ }
try {
return (InternalEditorLifecycleManager)servicesRegistry.getService(EditorLifecycleManager.class);
} catch (ServiceException ex) {
@@ -739,9 +748,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides getPropertySheetPage.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor#getPropertySheetPage()
*/
public IPropertySheetPage getPropertySheetPage() {
@@ -752,7 +761,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* @see org.eclipse.papyrus.infra.core.sasheditor.editor.AbstractMultiPageSashEditor#dispose()
- *
+ *
*/
@Override
public void dispose() {
@@ -819,9 +828,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides doSave.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
@@ -845,9 +854,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides doSaveAs.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.ui.part.EditorPart#doSaveAs()
*/
@Override
@@ -858,9 +867,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides isSaveAsAllowed.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
*/
@Override
@@ -870,9 +879,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides getContributorId.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
*/
@Override
@@ -887,9 +896,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides getDiagram.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart#getDiagram()
*/
// public org.eclipse.gmf.runtime.notation.Diagram getDiagram() {
@@ -926,9 +935,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides getDiagramGraphicalViewer.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart#getDiagramGraphicalViewer()
*/
// public IDiagramGraphicalViewer getDiagramGraphicalViewer() {
@@ -942,9 +951,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Overrides getEditingDomain.
- *
+ *
* {@inheritDoc}
- *
+ *
* @see org.eclipse.emf.edit.domain.IEditingDomainProvider#getEditingDomain()
*/
public EditingDomain getEditingDomain() {
@@ -953,7 +962,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Throws an UnsupportedOperationException.
- *
+ *
* @see org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor#getDiagramEditDomain()
*/
// public DiagramEditDomain getDiagramEditDomain() {
@@ -964,9 +973,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen /**
* Change the editor input.<BR>
* <U>Note</U>: that method should be called within the UI-Thread.
- *
+ *
* @see org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor#setEditorInput(org.eclipse.ui.IEditorInput)
- *
+ *
* @param newInput
* The new input
* @deprecated Not used anymore
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java new file mode 100644 index 00000000000..8c266376d1c --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.core.resource; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; + +import com.google.common.base.Optional; + + +/** + * An optional extension interface for {@linkplain IReadOnlyHandler read-only handlers} that support making files writable. + */ +public interface IReadOnlyHandler2 extends IReadOnlyHandler { + + /** + * Queries whether I can make the resources indicated by the given URIs writable. + * + * @param uris + * indicate a set of resources (presumed read-only) + * @return a {@linkplain Optional#isPresent() present} boolean indicating either that I can make the resources writable or that I handle these + * kinds of resources and they cannot be made writable; an {@linkplain Optional#absent() absent} value, otherwise + */ + Optional<Boolean> canMakeWritable(URI[] uris); + + /** + * Queries whether I can make the given {@code object} writable. + * + * @param object + * a model element (presumed read-only) + * @return a {@linkplain Optional#isPresent() present} boolean indicating either that I can make the {@code object writable or that I handle its + * kind of resources and it cannot be made writable; an {@linkplain Optional#absent() absent} value, otherwise + */ + Optional<Boolean> canMakeWritable(EObject object); +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IRollbackStatus.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IRollbackStatus.java new file mode 100644 index 00000000000..8451f1ce2c6 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IRollbackStatus.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.core.resource; + +import java.util.Collection; + +import org.eclipse.core.runtime.IStatus; + + +/** + * A specialized status that indicates that execution of a command was rolled back. Additional context that it provides includes model elements that + * triggered rollback. + */ +public interface IRollbackStatus extends IStatus { + + /** A {@linkplain IStatus#getCode() status code} indicating that the reason for the rollback could not be determined or is otherwise unclassified. */ + int UNKNOWN_REASON = 0; + + /** A {@linkplain IStatus#getCode() status code} indicating that rollback occurred because of an uncaught exception in command execution. */ + int UNCAUGHT_EXCEPTION = 1; + + /** A {@linkplain IStatus#getCode() status code} indicating that rollback occurred to revert modifications to an object that is read-only. */ + int READ_ONLY_OBJECT = 2; + + /** + * Queries the set of objects (if known) that caused the rollback, such as because they are are {@linkplain #READ_ONLY_OBJECT read-only}. + * + * @return the set (possibly empty, but not {@code null}) of objects that caused the rollback + */ + Collection<?> getCausalObjects(); +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java index ab35daa7cf7..fcfbae771dd 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java @@ -1,7 +1,7 @@ /***************************************************************************** * Copyright (c) 2008, 2013 CEA LIST and others. * - * + * * 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 @@ -61,7 +61,7 @@ import com.google.common.base.Optional; /** * This class is used to manage a set of {@link IModel}. - * + * * <h2>>Usage</h2> * <ul> * <li>First, register associated model. A loader can be used.</li> @@ -69,16 +69,16 @@ import com.google.common.base.Optional; * <li>Then, it is possible to get associated models</li> * <li>Finally, call save()</li> * </ul> - * + * * Please note that indirectly referenced models are loaded on demand. If a * model contains a cross reference towards another model (e.g. an import in * case of UML) the referenced resource does not appear initially in the set. * However, it is added once the referenced model is resolved. - * + * * TODO Modify ModelSetSnippet in order to inform them of model addition. - * + * * @author cedric dumoulin - * + * */ public class ModelSet extends ResourceSetImpl { @@ -115,18 +115,18 @@ public class ModelSet extends ResourceSetImpl { */ protected Set<URI> toDeleteOnSave = new HashSet<URI>(); - /** list of listeners of resources to know if the resource are loaded or not */ + /** list of listeners of resources to know if the resource are loaded or not */ protected ArrayList<IResourceLoadStateListener> resourceLoadStateListeners; /** map of resource loaded in the resource set, with resource as the key and a boolean indicating if the resource is loaded or not has the valuer */ protected Map<Resource, Boolean> resourcesToLoadState = new HashMap<Resource, Boolean>(); - - + + /** - * + * * Constructor. - * + * */ public ModelSet() { registerModel(additional); @@ -144,7 +144,7 @@ public class ModelSet extends ResourceSetImpl { * Register the specified model under its associated key. The key is defined * in the model itself. It is usually the model type from * (ModelPackage.eCONTENT_TYPE). - * + * * @param model * the model */ @@ -164,7 +164,7 @@ public class ModelSet extends ResourceSetImpl { /** * Get a model by its key. TODO throw an exception if not found. - * + * * @param key * the key * @return the model @@ -175,7 +175,7 @@ public class ModelSet extends ResourceSetImpl { /** * Get a model by its key. TODO throw an exception if not found. - * + * * @param key * the key * @return the model @@ -213,7 +213,8 @@ public class ModelSet extends ResourceSetImpl { throw e; } } - return setResourceOptions(r); + + return r != null && r.isLoaded() ? r : setResourceOptions(r); } @Override @@ -246,7 +247,7 @@ public class ModelSet extends ResourceSetImpl { /** * @deprecated please use {@link #getAssociatedResource(EObject, String, boolean)} instead - * + * * @param modelElement * @param associatedResourceExtension * @return @@ -258,7 +259,7 @@ public class ModelSet extends ResourceSetImpl { /** * @deprecated please use {@link #getAssociatedResource(Resource, String, boolean)} instead - * + * * @param modelResource * @param associatedResourceExtension * @return @@ -270,7 +271,7 @@ public class ModelSet extends ResourceSetImpl { /** * Retrieve and load the associated resource which have the given extension. - * + * * @param modelElement * @param associatedResourceExtension * @param loadOnDemand @@ -286,7 +287,7 @@ public class ModelSet extends ResourceSetImpl { /** * Retrieve and load the associated resource which have the given extension. - * + * * @param modelResource * @param associatedResourceExtension * @param loadOnDemand @@ -305,7 +306,7 @@ public class ModelSet extends ResourceSetImpl { /** * This method is called by getResource, createResource and demandLoad before returning * the resource to the caller so we can set options on the resource. - * + * * @param r * , can be null * @return the same resource for convenience @@ -326,7 +327,7 @@ public class ModelSet extends ResourceSetImpl { /** * Create the transactional editing domain. - * + * * @return the transactional editing domain */ public synchronized TransactionalEditingDomain getTransactionalEditingDomain() { @@ -342,7 +343,7 @@ public class ModelSet extends ResourceSetImpl { /** * @return the filenameWithoutExtension - * + * * @deprecated Use the {@link #getURIWithoutExtension()} API, instead. */ @Deprecated @@ -387,11 +388,11 @@ public class ModelSet extends ResourceSetImpl { /** * Create all the associated models. This creates the models, regardless if * they already exist. - * + * * @param newFile * The file from which path is extracted to create the new * resources - * + * * @deprecated Use the {@link #createModels(URI)} API, instead. */ @Deprecated @@ -402,7 +403,7 @@ public class ModelSet extends ResourceSetImpl { /** * Create all the associated models. This creates the models, regardless if * they already exist. - * + * * @param newFile * The file from which path is extracted to create the new * resources @@ -424,9 +425,9 @@ public class ModelSet extends ResourceSetImpl { /** * Create the model specified by the identifiers. Other models are * untouched, unless they are sharing something with specified models. - * + * * This creates the models, regardless if they already exist. - * + * * @param newFile * The file from which path is extracted to create the new * resources @@ -448,7 +449,7 @@ public class ModelSet extends ResourceSetImpl { /** * Load only the specified model. ModelSetSnippets are not called. Model is * loaded using the ModelSet Path. - * + * * @param modelIdentifier * the model identifier * @param file @@ -468,7 +469,7 @@ public class ModelSet extends ResourceSetImpl { /** * Import only the specified model. ModelSetSnippets are not called. - * + * * @param modelIdentifier * the model identifier * @param file @@ -489,7 +490,7 @@ public class ModelSet extends ResourceSetImpl { /** * Load all the associated models from a handle on one of the associated * file. - * + * * @param file * The file to load (no matter the extension) * @deprecated Use the {@link #loadModels(URI)} API, instead. @@ -506,7 +507,7 @@ public class ModelSet extends ResourceSetImpl { /** * Load all the associated models from a URI identifying one of the associated * files. - * + * * @param uri * The URI to load (no matter the extension) */ @@ -517,7 +518,7 @@ public class ModelSet extends ResourceSetImpl { ModelMultiException exceptions = null; List<IModel> orderedModelsForLoading = getOrderedModelsForLoading(); - + // Walk all registered models for(IModel model : orderedModelsForLoading) { // Try to load each model. Catch exceptions in order to load other @@ -544,8 +545,9 @@ public class ModelSet extends ResourceSetImpl { } /** - * Returns the models to be loaded, in order according to their dependencies - * @return the models to be loaded, in order according to their dependencies + * Returns the models to be loaded, in order according to their dependencies + * + * @return the models to be loaded, in order according to their dependencies */ protected List<IModel> getOrderedModelsForLoading() { return ModelUtils.getOrderedModelsForLoading(models); @@ -555,14 +557,14 @@ public class ModelSet extends ResourceSetImpl { * Import specified models into the ModelSet. The models are imported using * the specified IFile. After import, the models are associated with the * ModelSet Path. - * + * * @param modelIdentifiers * The model to import from the specified IFile. * @param file * The IFile used to import the model. * @throws ModelException * If an error occur during import. - * + * * @deprecated Use the {@link #importModels(ModelIdentifiers, URI)} API, instead */ @Deprecated @@ -575,7 +577,7 @@ public class ModelSet extends ResourceSetImpl { * Import specified models into the ModelSet. The models are imported using * the specified IFile. After import, the models are associated with the * ModelSet Path. - * + * * @param modelIdentifiers * The model to import from the specified IFile. * @param file @@ -602,14 +604,14 @@ public class ModelSet extends ResourceSetImpl { * Import only the specified model. ModelSetSnippets are not called. An * import can be performed after model are loaded. Normally, it should not * be done before a model is loaded. - * + * * @param modelIdentifier * the model identifier * @param file * the file * @throws ModelException * @returns The loaded model. - * + * * @deprecated Use the {@link #importModel(String, URI)} API, instead. */ @Deprecated @@ -622,7 +624,7 @@ public class ModelSet extends ResourceSetImpl { * Import only the specified model. ModelSetSnippets are not called. An * import can be performed after model are loaded. Normally, it should not * be done before a model is loaded. - * + * * @param modelIdentifier * the model identifier * @param file @@ -655,7 +657,7 @@ public class ModelSet extends ResourceSetImpl { /** * Save the resources. - * + * * @param monitor * The monitor. * @throws IOException @@ -728,19 +730,19 @@ public class ModelSet extends ResourceSetImpl { protected void handleResourcesToDelete() { Iterator<URI> uriIterator = getResourcesToDeleteOnSave().iterator(); while(uriIterator.hasNext()) { - URI uri = (URI)uriIterator.next(); - - if (validateDeleteResource(uri)) { - if (deleteResource(uri)) { + URI uri = uriIterator.next(); + + if(validateDeleteResource(uri)) { + if(deleteResource(uri)) { uriIterator.remove(); } } } } - + protected boolean validateDeleteResource(URI uri) { boolean result = true; - + Resource resource = getResource(uri, false); if(resource != null) { String warMessage = "The resource " + resource.getURI().lastSegment() + " was about to deleted but was still contained in the resource set. The will not be deleted"; @@ -748,19 +750,19 @@ public class ModelSet extends ResourceSetImpl { result = false; } - + return result; } - + protected boolean deleteResource(URI uri) { boolean result = false; - + try { getURIConverter().delete(uri, null); result = true; } catch (IOException e) { Activator.log.error(e); - + // hope it's a file that we can delete from the workspace! IFile file = getFile(uri); if(file != null && file.exists()) { @@ -772,19 +774,19 @@ public class ModelSet extends ResourceSetImpl { } } } - + return result; } /** * Finds the file corresponding to the specified URI, using a URI converter * if necessary (and provided) to normalize it. - * + * * @param uri * a URI * @param converter * an optional URI converter (may be <code>null</code>) - * + * * @return the file, if available in the workspace */ protected IFile getFile(URI uri) { @@ -838,12 +840,12 @@ public class ModelSet extends ResourceSetImpl { /** * The resources are already loaded, but we want to save them under another * name. - * + * * @param path * the path * @throws IOException * Signals that an I/O exception has occurred. - * + * * @deprecated Use the {@link #saveAs(URI)} API, instead. */ @Deprecated @@ -854,7 +856,7 @@ public class ModelSet extends ResourceSetImpl { /** * The resources are already loaded, but we want to save them under another * name. - * + * * @param path * the path * @throws IOException @@ -882,8 +884,8 @@ public class ModelSet extends ResourceSetImpl { snippets.performDispose(this); snippets.clear(); - - // FIXME RS: handle the unload ordering as indicated in the model extension point + + // FIXME RS: handle the unload ordering as indicated in the model extension point // Walk all registered models for(IModel model : models.values()) { if(!(model instanceof AdditionalResourcesModel)) { @@ -926,16 +928,18 @@ public class ModelSet extends ResourceSetImpl { /** * Obtains my internal API adapter. - * + * * @return my internal API adapter */ public Internal getInternal() { return new Internal() { + @Override public void setPrimaryModelResourceURI(URI uri) { setURIWithoutExtension(uri.trimFileExtension()); } + @Override public void registerModel(IModel model, boolean force) { if(force) { doRegisterModel(model); @@ -949,7 +953,7 @@ public class ModelSet extends ResourceSetImpl { /** * Add a {@link IModelSetSnippet}. A snippet allows to add code that will * perform additional operations on the ModelSet. - * + * * @param snippet * The snippet to add. */ @@ -959,11 +963,11 @@ public class ModelSet extends ResourceSetImpl { /** * A list of {@link IModelSetSnippet}. - * + * * Used by Models to maintain their list of Snippets. - * + * * @author cedric dumoulin - * + * */ public class ModelSetSnippetList extends ArrayList<IModelSetSnippet> { @@ -972,7 +976,7 @@ public class ModelSet extends ResourceSetImpl { /** * Call the start method on all registered snippets. - * + * * @param modelsManager * The model that is starting */ @@ -984,7 +988,7 @@ public class ModelSet extends ResourceSetImpl { /** * Call the start method on all registered snippets. - * + * * @param modelsManager * The model that is stopping */ @@ -1003,10 +1007,10 @@ public class ModelSet extends ResourceSetImpl { /** * Sets the {@link ModelSet}'s primary resource URI. - * + * * @param uri * the URI - * + * * @see ModelSet#createModels(URI) * @see ModelSet#saveAs(URI) */ @@ -1015,7 +1019,7 @@ public class ModelSet extends ResourceSetImpl { /** * Register a model with the option to force it (in case a more specific * implementation of the model is already registered). - * + * * @param model * a model to register * @param force @@ -1025,7 +1029,7 @@ public class ModelSet extends ResourceSetImpl { } /** - * + * * @param target */ public void saveCopy(IPath targetPathWithoutExtension) { @@ -1045,36 +1049,37 @@ public class ModelSet extends ResourceSetImpl { model.saveCopy(targetPathWithoutExtension, targetMap); } } - + public boolean addResourceLoadStateListener(IResourceLoadStateListener listener) { return resourceLoadStateListeners.add(listener); } - + public boolean removeResourceLoadStateListener(IResourceLoadStateListener listener) { return resourceLoadStateListeners.remove(listener); } - + public void notifyResourceLoadState(Resource resource, boolean newState) { - if(resourceLoadStateListeners !=null) { + if(resourceLoadStateListeners != null) { for(IResourceLoadStateListener listener : resourceLoadStateListeners) { try { listener.notifyLoadStateChanged(resource, newState); - } catch(Throwable e) { + } catch (Throwable e) { Activator.log.error(e); } } } } - + public boolean isUserModelResource(URI uri) { return uri.isPlatformResource() || uri.isFile(); } - + public class ResourceAddRemoveTracker implements Adapter { /** * {@inheritDoc} */ + @Override public void notifyChanged(Notification notification) { // if notification = add, add many or remove/remove many resource(s) to list of resources, process.. if(RESOURCE_SET__RESOURCES == notification.getFeatureID(ResourceSet.class)) { @@ -1083,33 +1088,34 @@ public class ModelSet extends ResourceSetImpl { Object object = notification.getNewValue(); if(object instanceof Resource) { resourcesToLoadState.put(((Resource)object), ((Resource)object).isLoaded()); - } + } break; case Notification.REMOVE: object = notification.getNewValue(); if(object instanceof Resource) { - resourcesToLoadState.remove(((Resource)object)); - } + resourcesToLoadState.remove((object)); + } break; case Notification.ADD_MANY: - + break; - + case Notification.REMOVE_MANY: - + + break; + + default: + // nothing to do break; - - default: - // nothing to do - break; } - + } } /** * {@inheritDoc} */ + @Override public Notifier getTarget() { return ModelSet.this; } @@ -1117,6 +1123,7 @@ public class ModelSet extends ResourceSetImpl { /** * {@inheritDoc} */ + @Override public void setTarget(Notifier newTarget) { // nothing here } @@ -1124,9 +1131,10 @@ public class ModelSet extends ResourceSetImpl { /** * {@inheritDoc} */ + @Override public boolean isAdapterForType(Object type) { return false; } - + } } diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/NestingTransactionalCommandStack.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/NestingTransactionalCommandStack.java new file mode 100644 index 00000000000..87976894389 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/NestingTransactionalCommandStack.java @@ -0,0 +1,263 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST and others. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - adapted for self-nesting behaviour + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.core.resource; + +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.CompoundCommand; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.RollbackException; +import org.eclipse.emf.transaction.impl.InternalTransaction; +import org.eclipse.emf.transaction.impl.TransactionalCommandStackImpl; +import org.eclipse.emf.transaction.util.ConditionalRedoCommand; + + +public class NestingTransactionalCommandStack extends TransactionalCommandStackImpl { + + private NestingTransactionalCommandStack childCommandStack; + + private final boolean nested; + + private boolean executing; + + public NestingTransactionalCommandStack() { + this(false); + } + + protected NestingTransactionalCommandStack(boolean nested) { + this.nested = nested; + } + + protected NestingTransactionalCommandStack getTopMostCommandStack() { + if(childCommandStack == null) { + return this; + } + return childCommandStack.getTopMostCommandStack(); + } + + protected void startNestedTransaction(Command command) { + if(childCommandStack != null) { + //Forwards to the current stack + childCommandStack.startNestedTransaction(command); + } else { + //Start a new nested transaction in a new nested Stack + childCommandStack = new NestingTransactionalCommandStack(true); + childCommandStack.setEditingDomain(getDomain()); + + childCommandStack.execute(command); + } + } + + public void commit() { + if(childCommandStack != null) { + disposeLastCommandStack(); + } + } + + private boolean disposeLastCommandStack() { + if(childCommandStack == null) { + //I'm the last command stack + dispose(); + return true; + } + + //Propagates + if(childCommandStack.disposeLastCommandStack()) { + childCommandStack = null; + } + + return false; + } + + public void rollback() { + if(childCommandStack != null) { + while(canUndo()) { + undo(); + } + disposeLastCommandStack(); + } + } + + @Override + public void execute(Command command) { + if(childCommandStack == null) { + if(!executing) { + executing = true; + + try { + super.execute(command); + } finally { + executing = false; + } + } else { + // Re-entrant command execution goes on a nested stack + try { + startNestedTransaction(command); + commit(); + } catch (OperationCanceledException e) { + rollback(); + // Propagate + throw e; + } + } + } else { + childCommandStack.execute(command); + } + } + + @Override + protected void handleError(Exception exception) { + if(nested && (exception instanceof RollbackException)) { + //A nested transaction rolled back + RollbackException rbe = (RollbackException)exception; + if(rbe.getStatus().getSeverity() == IStatus.CANCEL) { + // Propagate + throw new OperationCanceledException(); + } + } + + if(exception instanceof OperationCanceledException) { + rollback(); + // Propagate + throw (OperationCanceledException)exception; + } else { + super.handleError(exception); + } + } + + @Override + public Command getMostRecentCommand() { + if(childCommandStack == null) { + return super.getMostRecentCommand(); + } else { + return childCommandStack.getMostRecentCommand(); + } + } + + @Override + public Command getRedoCommand() { + if(childCommandStack == null) { + return super.getRedoCommand(); + } else { + return childCommandStack.getRedoCommand(); + } + } + + @Override + public Command getUndoCommand() { + if(childCommandStack == null) { + return super.getUndoCommand(); + } else { + return childCommandStack.getUndoCommand(); + } + } + + @Override + public void undo() { + if(childCommandStack == null) { + super.undo(); + } else { + childCommandStack.undo(); + } + } + + @Override + public boolean canUndo() { + if(childCommandStack == null) { + return super.canUndo(); + } else { + return childCommandStack.canUndo(); + } + } + + @Override + public boolean canRedo() { + if(childCommandStack == null) { + return super.canRedo(); + } else { + return childCommandStack.canRedo(); + } + } + + @Override + public void redo() { + if(childCommandStack == null) { + super.redo(); + } else { + childCommandStack.redo(); + } + } + + @Override + protected void doExecute(Command command, Map<?, ?> options) throws InterruptedException, RollbackException { + InternalTransaction tx = createTransaction(command, options); + boolean completed = false; + + try { + basicExecute(command); + + // new in EMF 2.4: AbortExecutionException can cause the + // command not to be added to the undo stack + completed = mostRecentCommand == command; + + // commit the transaction now + tx.commit(); + } catch (OperationCanceledException e) { + // snuff the exception, because this is expected (user asked to + // cancel the model change). We will rollback, below + if(nested) { + // Propagate to the nesting context + throw e; + } + } finally { + if((tx != null) && (tx.isActive())) { + // roll back (some exception, possibly being thrown now or + // an operation cancel, has occurred) + rollback(tx); + handleRollback(command, null); + } else { + // the transaction has already incorporated the triggers + // into its change description, so the recording command + // doesn't need them again + if(!(command instanceof RecordingCommand) && completed) { + Command triggerCommand = tx.getTriggers(); + + if(triggerCommand != null) { + // replace the executed command by a compound of the + // original and the trigger commands + CompoundCommand compound = new ConditionalRedoCommand.Compound(); + compound.append(mostRecentCommand); + compound.append(triggerCommand); + mostRecentCommand = compound; + commandList.set(top, mostRecentCommand); + } + } + } + } + } + + @Override + protected void basicExecute(Command command) { + try { + super.basicExecute(command); + } catch (OperationCanceledException e) { + // Ensure disposal of the command (when handleException() propagates a cancel, we will miss the chance) + command.dispose(); + throw e; + } + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/RollbackStatus.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/RollbackStatus.java new file mode 100644 index 00000000000..256de09aa96 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/RollbackStatus.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.core.resource; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.transaction.RollbackException; + +import com.google.common.collect.ImmutableSet; + + +/** + * An useful default implementation of the {@link IRollbackStatus} interface. + * Rollback is always an {@linkplain IStatus#ERROR error} condition, so the constructors do not require the severity. + */ +public class RollbackStatus extends Status implements IRollbackStatus { + + private final Set<?> causalObjects; + + /** + * Initializes me with the source bundle ID, reason code, and message. + * + * @param pluginId + * the source bundle ID + * @param reason + * the {@linkplain IRollbackStatus#UNKNOWN_REASON reason code} indicating why rollback occurred + * @param message + * the human-readable message + */ + public RollbackStatus(String pluginId, int reason, String message) { + this(pluginId, reason, message, null, null); + } + + /** + * Initializes me with the source bundle ID, reason code, and message. + * + * @param pluginId + * the source bundle ID + * @param reason + * the {@linkplain IRollbackStatus#UNKNOWN_REASON reason code} indicating why rollback occurred + * @param message + * the human-readable message + * @param exception + * an exception that somehow caused the rollback to occur + */ + public RollbackStatus(String pluginId, int reason, String message, Throwable exception) { + this(pluginId, reason, message, null, exception); + } + + /** + * Initializes me with the source bundle ID, reason code, and message. + * + * @param pluginId + * the source bundle ID + * @param reason + * the {@linkplain IRollbackStatus#UNKNOWN_REASON reason code} indicating why rollback occurred + * @param message + * the human-readable message + * @param causalObjects + * the objects that caused the rollback (may be {@code null} if not needed) + */ + public RollbackStatus(String pluginId, int reason, String message, Iterable<?> causalObjects) { + this(pluginId, reason, message, causalObjects, null); + } + + /** + * Initializes me with the source bundle ID, reason code, and message. + * + * @param pluginId + * the source bundle ID + * @param reason + * the {@linkplain IRollbackStatus#UNKNOWN_REASON reason code} indicating why rollback occurred + * @param message + * the human-readable message + * @param causalObjects + * the objects that caused the rollback (may be {@code null} if not needed) + * @param exception + * an exception that somehow caused the rollback to occur + */ + public RollbackStatus(String pluginId, int reason, String message, Iterable<?> causalObjects, Throwable exception) { + super(IStatus.ERROR, pluginId, reason, message, exception); + + this.causalObjects = (causalObjects == null) ? Collections.emptySet() : ImmutableSet.copyOf(causalObjects); + } + + @Override + public Collection<?> getCausalObjects() { + return causalObjects; + } + + /** + * Dig through a possibly {@linkplain #isMultiStatus() multi} status to get a rollback status out of it. + * + * @param status + * a status + * + * @return the embedded rollback status, if any (which could be the {@code status}, itself, in the simplest case) + */ + public static IRollbackStatus findRollbackStatus(IStatus status) { + IRollbackStatus result = null; + + if(status != null) { + if(status instanceof IRollbackStatus) { + result = (IRollbackStatus)status; + } else if(status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for(int i = 0; (result == null) && (i < children.length); i++) { + result = findRollbackStatus(children[i]); + } + } + + if((result == null) && (status.getException() instanceof RollbackException)) { + // The RollbackStatus may be rolled up in a generic Status created from the RollbackException that originally carried it + result = findRollbackStatus(((RollbackException)status.getException()).getStatus()); + } + } + + return result; + } + + // + // Nested types + // + + public static class Multi extends MultiStatus implements IRollbackStatus { + + private IRollbackStatus rollback; + + public Multi(String pluginId, int code, IStatus[] newChildren, String message, Throwable exception) { + super(pluginId, code, newChildren, message, exception); + } + + public Multi(String pluginId, int code, String message, Throwable exception) { + super(pluginId, code, message, exception); + } + + IRollbackStatus getRollback() { + if(rollback == null) { + rollback = findRollbackStatus(this); + } + + return rollback; + } + + @Override + public Collection<?> getCausalObjects() { + IRollbackStatus rollback = getRollback(); + return (rollback == null) ? Collections.emptySet() : rollback.getCausalObjects(); + } + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/TransactionalEditingDomainManager.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/TransactionalEditingDomainManager.java index 845968f067a..73dd38fc2da 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/TransactionalEditingDomainManager.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/TransactionalEditingDomainManager.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2011-2012 Atos.
+ * Copyright (c) 2011, 2014 Atos, CEA, and others.
*
- *
* 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
@@ -9,6 +8,7 @@ *
* Contributors:
* Mathieu Velten mathieu.velten@atos.net - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.resource;
@@ -99,7 +99,8 @@ public class TransactionalEditingDomainManager { // NotifyingWorkspaceCommandStack stack = new NotifyingWorkspaceCommandStack(CheckedOperationHistory.getInstance());
// stack.setResourceUndoContextPolicy(IResourceUndoContextPolicy.DEFAULT);
- TransactionalEditingDomain result = new TransactionalEditingDomainImpl(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE), resourceSet);
+ NestingTransactionalCommandStack stack = new NestingTransactionalCommandStack();
+ TransactionalEditingDomain result = new TransactionalEditingDomainImpl(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE), stack, resourceSet);
WorkspaceEditingDomainFactory.INSTANCE.mapResourceSet(result);
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModel.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModel.java index 994e4a145ca..ebfd4abe0f2 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModel.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModel.java @@ -1,19 +1,16 @@ /**
- *
+ *
*/
package org.eclipse.papyrus.infra.core.resource.sasheditor;
-import java.util.Map;
-
-import org.eclipse.emf.ecore.xmi.XMIResource;
-import org.eclipse.papyrus.infra.core.resource.AbstractBaseModel;
-import org.eclipse.papyrus.infra.core.resource.IModel;
/**
* @author dumoulin
- *
+ *
+ * @deprecated Use {@link SashModel} instead
*/
-public class DiModel extends AbstractBaseModel implements IModel {
+@Deprecated
+public class DiModel {
/**
* File extension used for notation.
@@ -30,38 +27,4 @@ public class DiModel extends AbstractBaseModel implements IModel { */
public static final String MODEL_ID = "org.eclipse.papyrus.infra.core.resource.sasheditor.SashModel"; //$NON-NLS-1$
- /**
- * Get the file extension used for this model.
- *
- * @see org.eclipse.papyrus.infra.core.resource.AbstractBaseModel#getModelFileExtension()
- *
- * @return
- */
- @Override
- protected String getModelFileExtension() {
- return MODEL_FILE_EXTENSION;
- }
-
- /**
- * Get the identifier used to register this model.
- *
- * @see org.eclipse.papyrus.infra.core.resource.AbstractBaseModel#getIdentifier()
- *
- * @return
- */
- @Override
- public String getIdentifier() {
- return MODEL_FILE_EXTENSION;
- }
-
- @Override
- protected Map<Object, Object> getSaveOptions() {
- Map<Object, Object> saveOptions = super.getSaveOptions();
-
- saveOptions.put(XMIResource.OPTION_USE_XMI_TYPE, Boolean.FALSE);
- saveOptions.put(XMIResource.OPTION_SAVE_TYPE_INFORMATION, Boolean.FALSE);
-
- return saveOptions;
- }
-
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModelUtils.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModelUtils.java index b909472e632..3c410693165 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModelUtils.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModelUtils.java @@ -1,5 +1,5 @@ /**
- *
+ *
*/
package org.eclipse.papyrus.infra.core.resource.sasheditor;
@@ -11,16 +11,16 @@ import org.eclipse.papyrus.infra.core.resource.ModelSet; /**
* Set of utility methods linked to Di resource.
- *
+ *
* @author cedric dumoulin
- *
+ *
*/
public class DiModelUtils {
/**
* Returns the related di file. Warning : this method is here for historical
* reasons. It should be removed asap.
- *
+ *
* @param file
* A file (di, model or notation).
* @return The associated DI file.
@@ -32,11 +32,11 @@ public class DiModelUtils { return null;
}
IFile diFile;
- if(DiModel.DI_FILE_EXTENSION.equalsIgnoreCase(file.getFileExtension())) {
+ if(SashModel.MODEL_FILE_EXTENSION.equalsIgnoreCase(file.getFileExtension())) {
diFile = file;
} else {
// Find the correct file
- IPath diPath = file.getFullPath().removeFileExtension().addFileExtension(DiModel.DI_FILE_EXTENSION);
+ IPath diPath = file.getFullPath().removeFileExtension().addFileExtension(SashModel.MODEL_FILE_EXTENSION);
diFile = file.getParent().getFile(diPath.makeRelativeTo(file.getParent().getFullPath()));
}
return diFile;
@@ -44,12 +44,12 @@ public class DiModelUtils { /**
* Returns the DI Resource associated to the model set. May be null.
- *
+ *
* @param modelSet
* @return
*/
public static Resource getDiResource(ModelSet modelSet) {
- IModel diModel = modelSet.getModel(DiModel.MODEL_ID);
+ IModel diModel = modelSet.getModel(SashModel.MODEL_ID);
if(diModel instanceof SashModel) {
return ((SashModel)diModel).getResource();
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/EMFHelper.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/EMFHelper.java index 9c6337f672d..d8d8a0790b0 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/EMFHelper.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/EMFHelper.java @@ -1,6 +1,6 @@ /*****************************************************************************
* Copyright (c) 2010, 2013 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
@@ -10,7 +10,7 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - filter out EObjects that are Resources (CDO)
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
- *
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.core.utils;
@@ -23,17 +23,17 @@ import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; /**
* @deprecated Please use {@link org.eclipse.papyrus.infra.emf.utils.EMFHelper} instead
- * (which inherit this one) for architectural reason.
+ * (which inherit this one) for architectural reason.
*/
@Deprecated
public class EMFHelper {
/**
* Gets the usages.
- *
+ *
* @param source
* the source
- *
+ *
* @return the usages or null if there is no usages
*/
public static Collection<Setting> getUsages(EObject source) {
@@ -56,7 +56,7 @@ public class EMFHelper { }
}
- return crossReferencer.getInverseReferences(source, true);
+ return crossReferencer.getInverseReferences(source, false);
}
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml index 9fce2312a6b..9fe993c7ac9 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml @@ -5,6 +5,11 @@ <extension
point="org.eclipse.papyrus.infra.emf.readonly.readOnlyHandler">
<readOnlyHandler
+ class="org.eclipse.papyrus.infra.emf.readonly.ReferencedModelReadOnlyHandler"
+ id="org.eclipse.papyrus.infra.emf.readonly.ReferencedModelReadOnlyHandler"
+ priority="15">
+ </readOnlyHandler>
+ <readOnlyHandler
class="org.eclipse.papyrus.infra.emf.readonly.FSReadOnlyHandler"
id="org.eclipse.papyrus.infra.emf.readonly.FSReadOnlyHandler"
priority="10">
@@ -106,7 +111,7 @@ class="org.eclipse.papyrus.infra.emf.readonly.ReadOnlyTester"
id="org.eclipse.papyrus.infra.emf.readonly.tester"
namespace="org.eclipse.papyrus.infra.emf.readonly.tester"
- properties="isReadOnly"
+ properties="isReadOnly,canMakeWritable"
type="org.eclipse.jface.viewers.IStructuredSelection">
</propertyTester>
</extension>
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java index 91c9168e20a..e378e43c022 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 Atos
+ * Copyright (c) 2013, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@ *
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -17,11 +18,11 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.domain.EditingDomain;
-import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import com.google.common.base.Optional;
-public abstract class AbstractReadOnlyHandler implements IReadOnlyHandler {
+public abstract class AbstractReadOnlyHandler implements IReadOnlyHandler2 {
private EditingDomain editingDomain;
@@ -49,4 +50,18 @@ public abstract class AbstractReadOnlyHandler implements IReadOnlyHandler { return Optional.absent();
}
+ /**
+ * By default, we do not handle writability of these resources.
+ */
+ public Optional<Boolean> canMakeWritable(URI[] uris) {
+ return Optional.absent();
+ }
+
+ public Optional<Boolean> canMakeWritable(EObject object) {
+ Resource res = object.eResource();
+ if((res != null) && (res.getURI() != null)) {
+ return canMakeWritable(new URI[]{ res.getURI() });
+ }
+ return Optional.absent();
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ControlledResourceTracker.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ControlledResourceTracker.java new file mode 100644 index 00000000000..34212fe77d5 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ControlledResourceTracker.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.readonly; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.TransactionalEditingDomainEvent; +import org.eclipse.emf.transaction.TransactionalEditingDomainListener; +import org.eclipse.emf.transaction.util.TransactionUtil; + +/** + * A resource-set listener that tracks controlled resource connectivity structure. It adds controlled-resource links immediately that they occur + * and removes them after a transaction has committed that removes them. This makes it reasonably efficient to determine that a referenced model + * is logically a component of the referencing model and thus not to be treated as read-only. The transactional nature of updates to this mapping + * is necessary to ensure that the ephemeral states during controlling and uncontrolling a sub-model don't fool the editing domain into thinking + * we're making changes to a read-only resource, triggering roll-back. + */ +class ControlledResourceTracker extends AdapterImpl implements TransactionalEditingDomainListener { + + private Map<URI, URI> unitMap = new HashMap<URI, URI>(); + + private Map<URI, URI> pending; + + /** + * Obtains the single tracker instance associated with the specified editing {@code domain}. + * + * @param domain + * an editing domain + * + * @return its tracker + */ + static ControlledResourceTracker getInstance(EditingDomain domain) { + ControlledResourceTracker result = null; + + for(Object next : domain.getResourceSet().eAdapters()) { + if(next instanceof ControlledResourceTracker) { + result = (ControlledResourceTracker)next; + break; + } + } + + if(result == null) { + result = new ControlledResourceTracker(domain); + } + + return result; + } + + private ControlledResourceTracker(EditingDomain domain) { + domain.getResourceSet().eAdapters().add(this); + + if(domain instanceof TransactionalEditingDomain) { + TransactionUtil.getAdapter((TransactionalEditingDomain)domain, TransactionalEditingDomain.Lifecycle.class).addTransactionalEditingDomainListener(this); + } + + // commit the initial discovery + commit(); + } + + /** + * Queries the URI of the resource in the root unit of the model of the same kind as the given potential sub-model unit. + * + * @param uri + * the URI of a resource that potentially is in a sub-model unit + * + * @return the URI of the corresponding resource in the model's root unit, which could be the same {@code uri} if this is the root unit + */ + URI getRootResourceURI(URI uri) { + URI result = uri.trimFileExtension(); + + for(URI parent = get(result); parent != null; parent = get(parent)) { + if(parent != null) { + result = parent; + } + } + + return (uri.fileExtension() == null) ? result : result.appendFileExtension(uri.fileExtension()); + } + + private URI get(URI potentialUnit) { + URI result = unitMap.get(potentialUnit); + + if((result == null) && (pending != null)) { + // Look here, too, in case the current transaction is adding the relationship + result = pending.get(potentialUnit); + } + + return result; + } + + private void ensurePending() { + if(pending == null) { + pending = new HashMap<URI, URI>(unitMap); + } + } + + private void map(URI controlledUnit, URI parentUnit) { + ensurePending(); + pending.put(controlledUnit.trimFileExtension(), parentUnit.trimFileExtension()); + } + + private void unmap(URI controlledUnit) { + ensurePending(); + pending.remove(controlledUnit.trimFileExtension()); + } + + private void commit() { + if(pending != null) { + unitMap = pending; + pending = null; + } + } + + private void rollback() { + pending = null; + } + + // + // Adapter protocol + // + + @Override + public void setTarget(Notifier newTarget) { + if(newTarget instanceof ResourceSet) { + // Discover existing resources + for(Resource next : ((ResourceSet)newTarget).getResources()) { + addAdapter(next); + } + } else if(newTarget instanceof Resource) { + handleResource((Resource)newTarget); + } + } + + protected void addAdapter(Notifier notifier) { + notifier.eAdapters().add(this); + } + + protected void removeAdapter(Notifier notifier) { + notifier.eAdapters().remove(this); + } + + @Override + public void unsetTarget(Notifier oldTarget) { + if(oldTarget instanceof ResourceSet) { + for(Resource next : ((ResourceSet)oldTarget).getResources()) { + removeAdapter(next); + } + } + } + + /** + * Discover existing parent-unit relationship in a resource. + */ + protected void handleResource(Resource resource) { + if(!resource.getContents().isEmpty()) { + EObject root = resource.getContents().get(0); + EObject container = ((InternalEObject)root).eInternalContainer(); + if(container != null) { + // Found cross-resource containment + URI parentURI = container.eIsProxy() ? ((InternalEObject)container).eProxyURI().trimFragment() : container.eResource().getURI(); + if(parentURI != null) { + map(resource.getURI(), parentURI); + } + } + } + } + + @Override + public void notifyChanged(Notification msg) { + Object notifier = msg.getNotifier(); + + if(notifier instanceof ResourceSet) { + switch(msg.getFeatureID(ResourceSet.class)) { + case ResourceSet.RESOURCE_SET__RESOURCES: + switch(msg.getEventType()) { + case Notification.ADD: + addAdapter((Resource)msg.getNewValue()); + break; + case Notification.ADD_MANY: + for(Object next : (Collection<?>)msg.getNewValue()) { + addAdapter((Resource)next); + } + break; + case Notification.SET: + removeAdapter((Resource)msg.getOldValue()); + addAdapter((Resource)msg.getNewValue()); + break; + case Notification.REMOVE: + removeAdapter((Resource)msg.getOldValue()); + break; + case Notification.REMOVE_MANY: + for(Object next : (Collection<?>)msg.getOldValue()) { + removeAdapter((Resource)next); + } + break; + } + break; + } + } else if(notifier instanceof Resource) { + switch(msg.getFeatureID(Resource.class)) { + case Resource.RESOURCE__CONTENTS: + switch(msg.getEventType()) { + case Notification.ADD: + case Notification.ADD_MANY: + // Only process the resource when the first root is added + if(msg.getPosition() == 0) { + handleResource((Resource)notifier); + } + break; + case Notification.SET: + // Only process the resource when the first root is replaced + if(msg.getPosition() == 0) { + Resource resource = (Resource)notifier; + unmap(resource.getURI()); + handleResource(resource); + } + break; + case Notification.REMOVE: + case Notification.REMOVE_MANY: + // Only process the resource when the first root is removed + if(msg.getPosition() == 0) { + unmap(((Resource)msg.getNotifier()).getURI()); + } + break; + } + } + } + } + + // + // TransactionalEditingDomainListener protocol + // + + public void transactionClosed(TransactionalEditingDomainEvent event) { + if(event.getTransaction().getStatus().getSeverity() >= IStatus.ERROR) { + // Transaction rolled back + rollback(); + } else { + // Transaction committed + commit(); + } + } + + public void editingDomainDisposing(TransactionalEditingDomainEvent event) { + removeAdapter(event.getSource().getResourceSet()); + } + + public void transactionStarting(TransactionalEditingDomainEvent event) { + // pass + } + + public void transactionInterrupted(TransactionalEditingDomainEvent event) { + // pass + } + + public void transactionStarted(TransactionalEditingDomainEvent event) { + // pass + } + + public void transactionClosing(TransactionalEditingDomainEvent event) { + // pass + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java index 3f8957536bf..f035f201423 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 Atos Origin.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and otherw.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,10 +9,13 @@ *
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.resources.IFile;
@@ -27,7 +30,7 @@ import org.eclipse.swt.widgets.Display; import com.google.common.base.Optional;
-public class FSReadOnlyHandler extends AbstractReadOnlyHandler {
+public class FSReadOnlyHandler extends AbstractReadOnlyHandler {
public FSReadOnlyHandler(EditingDomain editingDomain) {
super(editingDomain);
@@ -54,32 +57,42 @@ public class FSReadOnlyHandler extends AbstractReadOnlyHandler { public Optional<Boolean> makeWritable(final URI[] uris) {
final AtomicBoolean doEnableWrite = new AtomicBoolean();
- Display.getCurrent().syncExec(new Runnable() {
-
- public void run() {
- String message = "Do you want to remove read only flag on those files ?\n\n";
- for(URI uri : uris) {
- IFile file = getFile(uri);
- if(file != null && file.isReadOnly()) {
- message += file.getName() + "\n";
+
+ // We can't make a file writable if it already is (there are read-only handlers that treat files that
+ // are filesystem-writable as read-only for other reasons)
+ Collection<IFile> readOnlyFiles = new ArrayList<IFile>(uris.length);
+ for(int i = 0; i < uris.length; i++) {
+ IFile file = getFile(uris[i]);
+ if((file != null) && file.isReadOnly()) {
+ readOnlyFiles.add(file);
+ }
+ }
+
+ if (!readOnlyFiles.isEmpty()) {
+ Display.getCurrent().syncExec(new Runnable() {
+
+ public void run() {
+ String message = "Do you want to remove read only flag on those files ?\n\n";
+ for(URI uri : uris) {
+ IFile file = getFile(uri);
+ if(file != null && file.isReadOnly()) {
+ message += file.getName() + "\n";
+ }
}
+ doEnableWrite.set(MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Enable Write", message));
}
- doEnableWrite.set(MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Enable write", message));
- }
- });
-
+ });
+ }
+
if(doEnableWrite.get()) {
Boolean ok = true;
- for(URI uri : uris) {
- IFile file = getFile(uri);
- if(file != null && file.isReadOnly()) {
- try {
- ResourceAttributes att = file.getResourceAttributes();
- att.setReadOnly(false);
- file.setResourceAttributes(att);
- } catch (CoreException e) {
- ok = false;
- }
+ for(IFile file : readOnlyFiles) {
+ try {
+ ResourceAttributes att = file.getResourceAttributes();
+ att.setReadOnly(false);
+ file.setResourceAttributes(att);
+ } catch (CoreException e) {
+ ok = false;
}
}
return Optional.of(ok);
@@ -88,4 +101,22 @@ public class FSReadOnlyHandler extends AbstractReadOnlyHandler { }
}
+ /**
+ * I can make workspace resources writable.
+ */
+ @Override
+ public Optional<Boolean> canMakeWritable(URI[] uris) {
+ Optional<Boolean> result = Optional.absent();
+
+ for(int i = 0; (!result.isPresent() || result.get()) && (i < uris.length); i++) {
+ if(uris[i].isPlatformResource()) {
+ result = Optional.of(true);
+ } else if(uris[i].isFile()) {
+ // We don't make non-workspace (external but local) files writable
+ result = Optional.of(false);
+ }
+ }
+
+ return result;
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java index 3beab6d2fac..de7b67ec2eb 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011, 2013 Atos Origin, CEA, and others.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -10,17 +10,39 @@ * Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - Support object-level read/write controls (CDO)
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.NotificationFilter;
+import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalCommandStack;
+import org.eclipse.emf.transaction.impl.InternalTransaction;
+import org.eclipse.emf.transaction.impl.TransactionChangeRecorder;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.IRollbackStatus;
+import org.eclipse.papyrus.infra.core.resource.RollbackStatus;
+import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
+import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
+import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDomainImpl {
@@ -40,6 +62,127 @@ public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDom public boolean isReadOnly(EObject eObject) {
return ReadOnlyManager.getReadOnlyHandler(this).isReadOnly(eObject).get();
}
+
+ @Override
+ protected TransactionChangeRecorder createChangeRecorder(ResourceSet rset) {
+ // Ensure that the ControlledResourceTracker gets in ahead of the change recorder so that it processes
+ // notifications pertaining to sub-model unit structure, first, to ensure correct determination of
+ // read-only state for cross-model-referenced objects
+ ControlledResourceTracker.getInstance(this);
+
+ return doCreateChangeRecorder(rset);
+ }
+
+ protected TransactionChangeRecorder doCreateChangeRecorder(ResourceSet rset) {
+ return new TransactionChangeRecorder(this, rset) {
+ @Override
+ protected void appendNotification(Notification notification) {
+ // Append to the transaction first
+ super.appendNotification(notification);
+
+ if (!NotificationFilter.READ.matches(notification)) {
+ // Check whether we are modifying a read-only object
+ assertNotReadOnly(notification.getNotifier());
+ }
+ }
+ };
+ }
+
+ protected void assertNotReadOnly(Object object) {
+ InternalTransaction tx = getActiveTransaction();
+
+ // If there's no transaction, then there will be nothing to roll back. And if it's unprotected, let the client do whatever.
+ // And, of course, don't interfere with rollback!
+ if((tx != null) && !tx.isRollingBack() && !Boolean.TRUE.equals(tx.getOptions().get(Transaction.OPTION_UNPROTECTED))) {
+ boolean readOnly;
+
+ // Check for Resource first because CDO resources *are* EObjects
+ if(object instanceof Resource) {
+ Resource.Internal resource = (Resource.Internal)object;
+ if(resource.isLoading()) {
+ // We must be able to modify read-only resources in order to load them
+ return;
+ }
+ readOnly = isReadOnly(resource) && !makeWritable(resource);
+ } else if(object instanceof EObject) {
+ EObject eObject = (EObject)object;
+ readOnly = isReadOnly(eObject) && !makeWritable(eObject);
+ } else {
+ // If it's not an EMF-managed object, we don't care
+ readOnly = false;
+ }
+
+ if(readOnly) {
+ String message = "Attempt to modify object(s) in a read-only model."; //$NON-NLS-1$
+ Collection<?> offenders = Collections.singleton(object);
+ tx.abort(new RollbackStatus(Activator.PLUGIN_ID, IRollbackStatus.READ_ONLY_OBJECT, message, offenders));
+ }
+ }
+ }
+
+ protected boolean makeWritable(Resource resource) {
+ URI[] uris = getCompositeModelURIs(resource.getURI());
+ IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(this);
+
+ if(handler instanceof IReadOnlyHandler2) {
+ if(!((IReadOnlyHandler2)handler).canMakeWritable(uris).or(false)) {
+ return false;
+ }
+ }
+
+ return handler.makeWritable(uris).get();
+ }
+
+ protected boolean makeWritable(EObject object) {
+ boolean result;
+
+ URI uri = EcoreUtil.getURI(object);
+
+ // If it's a workspace resource, we don't have to worry about object-level read-only state
+ if(uri.isPlatformResource()) {
+ result = makeWritable(object.eResource());
+ } else {
+ IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(this);
+
+ if((handler instanceof IReadOnlyHandler2) && !((IReadOnlyHandler2)handler).canMakeWritable(object).or(false)) {
+ result = false;
+ } else {
+ result = handler.makeWritable(object).get();
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Obtains the complete set of URIs for members of the composite model resource of which the given URI is one member.
+ *
+ * @param memberURI a member of a composite Papyrus model
+ *
+ * @return the complete set of member resources (which could just be the original {@code memberURI})
+ */
+ protected URI[] getCompositeModelURIs(URI memberURI) {
+ URI[] result = null;
+
+ if(memberURI.isPlatformResource()) {
+ // We don't have object-level read-only state in the workspace (perhaps in CDO repositories)
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(memberURI.trimFragment().toPlatformString(true)));
+ if((file != null) && file.exists()) {
+ IPapyrusFile composite = PapyrusModelHelper.getPapyrusModelFactory().createIPapyrusFile(file);
+ Set<URI> memberURIs = new HashSet<URI>();
+ for(IFile member : OneFileUtils.getAssociatedFiles(composite)) {
+ memberURIs.add(URI.createPlatformResourceURI(member.getFullPath().toString(), true));
+ }
+ result = memberURIs.toArray(new URI[memberURIs.size()]);
+ }
+ }
+
+ if(result == null) {
+ result = new URI[]{ memberURI };
+ }
+
+ return result;
+ }
@Override
public void dispose() {
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainProvider.java index 19233543070..d9fe778ec6d 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainProvider.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainProvider.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2011 Atos Origin.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
- *
* 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
@@ -9,6 +8,7 @@ *
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -19,6 +19,7 @@ import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.workspace.IResourceUndoContextPolicy;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.papyrus.commands.CheckedOperationHistory;
+import org.eclipse.papyrus.commands.NestingNotifyingWorkspaceCommandStack;
import org.eclipse.papyrus.commands.NotifyingWorkspaceCommandStack;
import org.eclipse.papyrus.infra.core.resource.ITransactionalEditingDomainProvider;
@@ -32,7 +33,7 @@ import org.eclipse.papyrus.infra.core.resource.ITransactionalEditingDomainProvid public class PapyrusROTransactionalEditingDomainProvider implements ITransactionalEditingDomainProvider {
public TransactionalEditingDomain createTransactionalEditingDomain(ResourceSet resourceSet) {
- NotifyingWorkspaceCommandStack stack = new NotifyingWorkspaceCommandStack(CheckedOperationHistory.getInstance());
+ NotifyingWorkspaceCommandStack stack = new NestingNotifyingWorkspaceCommandStack(CheckedOperationHistory.getInstance());
stack.setResourceUndoContextPolicy(IResourceUndoContextPolicy.DEFAULT);
TransactionalEditingDomain result = new PapyrusROTransactionalEditingDomain(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE), stack, resourceSet);
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java index 779bf21b8f6..f09bd0e39df 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011, 2013 Atos Origin, CEA, and others.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -10,6 +10,7 @@ * Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - support non-IFile resources and object-level permissions (CDO)
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -28,12 +29,13 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import com.google.common.base.Optional;
@SuppressWarnings("deprecation")
-public class ReadOnlyManager implements IReadOnlyHandler {
+public class ReadOnlyManager implements IReadOnlyHandler2 {
//Using a WeakHashMap leads to a Memory Leak, because only the Key is weak.
//The IReadOnlyHandler typically has a reference to its editingDomain,
@@ -184,10 +186,11 @@ public class ReadOnlyManager implements IReadOnlyHandler { Optional<Boolean> isRO = orderedHandlersArray[i].anyReadOnly(uris);
if(isRO.isPresent() && isRO.get()) {
Optional<Boolean> result = orderedHandlersArray[i].makeWritable(uris);
- // makeWritable should provide an answer since anyReadOnly returned a positive value
- // if no answer consider it fails
+ // makeWritable should provide an answer since anyReadOnly returned a positive value.
+ // If no answer consider it a failure
if(!result.isPresent() || !result.get()) {
finalResult = false;
+ break;
}
}
}
@@ -212,6 +215,46 @@ public class ReadOnlyManager implements IReadOnlyHandler { return Optional.of(finalResult);
}
+
+ public Optional<Boolean> canMakeWritable(URI[] uris) {
+ Boolean result = false;
+
+ for(int i = 0; (i < orderedHandlersArray.length); i++) {
+ if(orderedHandlersArray[i] instanceof IReadOnlyHandler2) {
+ IReadOnlyHandler2 h2 = (IReadOnlyHandler2)orderedHandlersArray[i];
+ if (h2.anyReadOnly(uris).or(false)) {
+ // Only ask a handler about making writable what it considers to be read-only
+ Optional<Boolean> canMakeWritable = h2.canMakeWritable(uris);
+ if(canMakeWritable.isPresent()) {
+ result = canMakeWritable.get();
+ break;
+ }
+ }
+ }
+ }
+
+ return Optional.of(result);
+ }
+
+ public Optional<Boolean> canMakeWritable(EObject object) {
+ Boolean result = false;
+
+ for(int i = 0; (i < orderedHandlersArray.length); i++) {
+ if(orderedHandlersArray[i] instanceof IReadOnlyHandler2) {
+ IReadOnlyHandler2 h2 = (IReadOnlyHandler2)orderedHandlersArray[i];
+ if (h2.isReadOnly(object).or(false)) {
+ // Only ask a handler about making writable what it considers to be read-only
+ Optional<Boolean> canMakeWritable = h2.canMakeWritable(object);
+ if(canMakeWritable.isPresent()) {
+ result = canMakeWritable.get();
+ break;
+ }
+ }
+ }
+ }
+
+ return Optional.of(result);
+ }
private static final class HandlerAdapter extends AbstractReadOnlyHandler {
@@ -242,4 +285,4 @@ public class ReadOnlyManager implements IReadOnlyHandler { return delegateResult ? Optional.<Boolean> absent() : Optional.of(Boolean.FALSE);
}
}
-}
+}
\ No newline at end of file diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java index b65196de99d..03a5388e717 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 Atos Origin.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,14 +9,17 @@ *
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
+import java.util.Set;
import org.eclipse.core.commands.operations.IOperationApprover2;
import org.eclipse.core.commands.operations.IOperationHistory;
@@ -26,13 +29,17 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.workspace.AbstractEMFOperation;
+import org.eclipse.emf.workspace.EMFCommandOperation;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.ICompositeCommand;
import org.eclipse.gmf.runtime.common.core.internal.command.ICommandWithSettableResult;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
@@ -52,10 +59,9 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 { public IStatus proceedExecuting(IUndoableOperation operation, IOperationHistory history, IAdaptable info) {
HashSet<URI> filesToCheckForLock = new HashSet<URI>();
- if(operation instanceof ICommand) {
- ICommand command = (ICommand)operation;
- List<IFile> affectedFiles = command.getAffectedFiles();
-
+ Set<IFile> affectedFiles = getAffectedFiles(operation);
+
+ if(!affectedFiles.isEmpty()) {
for(IFile affectedFile : affectedFiles) {
if(affectedFile == null)
continue;
@@ -71,14 +77,18 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 { IPath path = affectedFile.getRawLocation();
if(path == null) {
// cancel if we can't find the file
- setCommandResult(command, Status.CANCEL_STATUS);
+ if(operation instanceof ICommand) {
+ setCommandResult((ICommand)operation, Status.CANCEL_STATUS);
+ }
return Status.CANCEL_STATUS;
}
File file = path.toFile();
if(file != null && file.exists() && !file.canWrite()) {
// cancel if we find a read-only file outside the
// workspace
- setCommandResult(command, Status.CANCEL_STATUS);
+ if(operation instanceof ICommand) {
+ setCommandResult((ICommand)operation, Status.CANCEL_STATUS);
+ }
return Status.CANCEL_STATUS;
}
}
@@ -130,4 +140,54 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 { }
}
+ protected Set<IFile> getAffectedFiles(IUndoableOperation operation) {
+ Set<IFile> result = getAffectedFiles(operation, null);
+ return (result == null) ? Collections.<IFile> emptySet() : result;
+ }
+
+ protected Set<IFile> getAffectedFiles(IUndoableOperation operation, Set<IFile> result) {
+ if(operation instanceof ICommand) {
+ result = appendFiles(result, ((ICommand)operation).getAffectedFiles());
+ } else if(operation instanceof GMFtoEMFCommandWrapper) {
+ result = getAffectedFiles(((GMFtoEMFCommandWrapper)operation).getGMFCommand(), result);
+ } else if(operation instanceof EMFCommandOperation) {
+ result = getAffectedFiles(((EMFCommandOperation)operation).getCommand(), result);
+ }
+
+ return result;
+ }
+
+ private Set<IFile> appendFiles(Set<IFile> result, Collection<IFile> files) {
+ if((files != null) && !files.isEmpty()) {
+ if(result == null) {
+ result = new HashSet<IFile>(files);
+ } else {
+ result.addAll(files);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Dig into an EMF command to find wrapped GMF commands and get their affected files. As commands are generally provided by GMF edit-helpers, this
+ * should turn up useful results.
+ *
+ * @param command
+ * a command to mine for affected files
+ * @param result
+ * an accumulator of affected files
+ * @return the {@code result} if it already exists, a non-empty set containing affected files, or {@code null}
+ */
+ protected Set<IFile> getAffectedFiles(Command command, Set<IFile> result) {
+ if(command instanceof CompoundCommand) {
+ for(Command next : ((CompoundCommand)command).getCommandList()) {
+ // accumulate affected files
+ result = getAffectedFiles(next, result);
+ }
+ } else if(command instanceof GMFtoEMFCommandWrapper) {
+ result = getAffectedFiles(((GMFtoEMFCommandWrapper)command).getGMFCommand(), result);
+ }
+
+ return result;
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java index 5e2dadd3410..eaef7d7c325 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011, 2013 Atos Origin, CEA, and others.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -10,6 +10,7 @@ * Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -21,33 +22,69 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.emf.utils.BusinessModelResolver;
+import com.google.common.base.Objects;
+
public class ReadOnlyTester extends PropertyTester {
public static final String IS_READ_ONLY = "isReadOnly"; //$NON-NLS-1$
+ public static final String CAN_MAKE_WRITABLE = "canMakeWritable"; //$NON-NLS-1$
+
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
- if (IS_READ_ONLY.equals(property) && receiver instanceof IStructuredSelection) {
- IStructuredSelection selection = (IStructuredSelection)receiver;
-
- Iterator<?> it = selection.iterator();
- while (it.hasNext()) {
- Object obj = it.next();
- Object businessObject = BusinessModelResolver.getInstance().getBusinessModel(obj);
-
- if (businessObject instanceof EObject) {
- EObject eObject = (EObject) businessObject;
- Resource resource = eObject.eResource();
- if ((resource != null) && (resource.getResourceSet() != null)) {
- return ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(resource.getResourceSet()))
- .isReadOnly(eObject).get();
- }
+ if(receiver instanceof IStructuredSelection) {
+ Iterator<?> objects = ((IStructuredSelection)receiver).iterator();
+
+ if(IS_READ_ONLY.equals(property)) {
+ return testIsReadOnly(objects, asBoolean(expectedValue));
+ } else if(CAN_MAKE_WRITABLE.equals(property)) {
+ return canMakeWritable(objects, asBoolean(expectedValue));
+ }
+ }
+
+ return false;
+ }
+
+ protected Boolean asBoolean(Object expectedValue) {
+ // true is the implied expected value for booleans
+ return (expectedValue instanceof Boolean) ? (Boolean)expectedValue : true;
+ }
+
+ protected boolean testIsReadOnly(Iterator<?> objects, Boolean expectedValue) {
+ while(objects.hasNext()) {
+ Object businessObject = BusinessModelResolver.getInstance().getBusinessModel(objects.next());
+
+ if(businessObject instanceof EObject) {
+ EObject eObject = (EObject)businessObject;
+ Resource resource = eObject.eResource();
+ if((resource != null) && (resource.getResourceSet() != null)) {
+ return Objects.equal(ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(resource.getResourceSet())).isReadOnly(eObject).get(), expectedValue);
}
}
}
-
+
return false;
}
+ protected boolean canMakeWritable(Iterator<?> objects, Boolean expectedValue) {
+ while(objects.hasNext()) {
+ Object businessObject = BusinessModelResolver.getInstance().getBusinessModel(objects.next());
+
+ if(businessObject instanceof EObject) {
+ EObject eObject = (EObject)businessObject;
+ Resource resource = eObject.eResource();
+ if((resource != null) && (resource.getResourceSet() != null)) {
+ IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(resource.getResourceSet()));
+ boolean isAlreadyOrCanMakeWritable = !handler.isReadOnly(eObject).or(false) //
+ || ((handler instanceof IReadOnlyHandler2) && ((IReadOnlyHandler2)handler).canMakeWritable(eObject).or(false));
+ return Objects.equal(isAlreadyOrCanMakeWritable, expectedValue);
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java new file mode 100644 index 00000000000..6d909461712 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.readonly; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.URIConverter; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler; +import org.eclipse.papyrus.infra.core.resource.ModelSet; +import org.eclipse.papyrus.infra.emf.readonly.internal.messages.Messages; +import org.eclipse.swt.widgets.Display; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; + + +/** + * A {@linkplain IReadOnlyHandler read-only handler} for objects in referenced models, which by default shouldn't be editable in the context of the + * model referencing them. + */ +public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler { + + private final ControlledResourceTracker controlledResourceTracker; + + private final Set<URI> readableReferencedModels = new HashSet<URI>(); + + private boolean interactive = true; + + public ReferencedModelReadOnlyHandler(EditingDomain editingDomain) { + super(editingDomain); + + controlledResourceTracker = ControlledResourceTracker.getInstance(editingDomain); + } + + /** + * Queries whether I interact with the user to confirm making resources writable. I am interactive by default. + * + * @return whether I am interactive + */ + public boolean isInteractive() { + return interactive; + } + + /** + * Sets whether I interact with the user to confirm making resources writable. + * + * @param interactive + * whether I am interactive + */ + public void setInteractive(boolean interactive) { + this.interactive = interactive; + } + + public Optional<Boolean> anyReadOnly(URI[] uris) { + Optional<Boolean> result = Optional.absent(); + + final URIConverter converter = getEditingDomain().getResourceSet().getURIConverter(); + + for(int i = 0; i < uris.length; i++) { + // Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level + URI next = uris[i].trimFragment(); + + // If the resource doesn't exist, then it can't be opened in some other editor, so + // we needn't be concerned about editing it in the context of a referencing model + if(!readableReferencedModels.contains(next.trimFileExtension()) && isNotModelSetMainModel(next) && converter.exists(next, null)) { + result = Optional.of(true); + break; + } + } + + return result; + } + + @Override + public Optional<Boolean> canMakeWritable(URI[] uris) { + Optional<Boolean> result = Optional.absent(); + + for(int i = 0; i < uris.length; i++) { + // Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level + URI next = uris[i].trimFragment(); + + if(isNotModelSetMainModel(next)) { + result = Optional.of(true); + } else { + // If it's not something I handle, then bomb + result = Optional.of(false); + break; + } + } + + return result; + } + + public Optional<Boolean> makeWritable(URI[] uris) { + Optional<Boolean> result = Optional.absent(); + + final List<URI> toMakeWritable = new ArrayList<URI>(uris.length); + + for(int i = 0; i < uris.length; i++) { + // Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level + URI next = uris[i].trimFragment(); + + if(isNotModelSetMainModel(next)) { + toMakeWritable.add(next); + } + } + + if(!toMakeWritable.isEmpty()) { + final boolean[] enableWrite = { !isInteractive() }; + + if(isInteractive()) { + Display.getCurrent().syncExec(new Runnable() { + + public void run() { + StringBuilder message = new StringBuilder(Messages.ReferencedModelReadOnlyHandler_promptMsg); + for(URI uri : toMakeWritable) { + String path; + if(uri.isPlatformResource()) { + path = uri.toPlatformString(true); + } else if(uri.isFile()) { + path = uri.toFileString(); + } else { + path = uri.toString(); + } + + message.append(path); + message.append("\n"); //$NON-NLS-1$ + } + enableWrite[0] = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), Messages.ReferencedModelReadOnlyHandler_promptTitle, message.toString()); + } + }); + } + + if(enableWrite[0]) { + for(URI next : toMakeWritable) { + readableReferencedModels.add(next.trimFileExtension()); + } + } + + result = Optional.of(enableWrite[0]); + } + + return result; + } + + protected boolean isNotModelSetMainModel(URI uri) { + // Default to false result because, if the context is not a ModelSet, the question doesn't make sense and we should not restrict editing + boolean result = false; + + ResourceSet rset = getEditingDomain().getResourceSet(); + if(rset instanceof ModelSet) { + ModelSet modelSet = (ModelSet)rset; + uri = resolveRootResourceURI(modelSet, uri); + + result = modelSet.isUserModelResource(uri) && !Objects.equal(modelSet.getURIWithoutExtension(), uri.trimFileExtension()); + } + + return result; + } + + /** + * Trace a potential controlled unit's root resource. + * + * @param modelSet + * the contextual model-set + * @param uri + * a resource URI + * + * @return the corresponding root resource URI, which is just the original {@code uri} if either it isn't a controlled unit or we cannot tell + */ + protected URI resolveRootResourceURI(ModelSet modelSet, URI uri) { + return controlledResourceTracker.getRootResourceURI(uri); + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java index f90850f4ff1..8d6dd98630c 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2011 Atos Origin
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
- *
* 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
@@ -9,6 +8,7 @@ *
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly.handlers;
@@ -23,11 +23,13 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyManager;
import org.eclipse.papyrus.infra.emf.utils.BusinessModelResolver;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
@@ -82,4 +84,11 @@ public class EnableWriteCommandHandler extends AbstractHandler { }
return null;
}
+
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ EObject selected = getSelectedElement();
+ EditingDomain domain = (selected == null) ? null : EMFHelper.resolveEditingDomain(selected);
+ setBaseEnabled((domain != null) && EMFHelper.canMakeWritable(selected, domain));
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/Messages.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/Messages.java new file mode 100644 index 00000000000..4e1141a773d --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/Messages.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.readonly.internal.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * This is the Messages type. Enjoy. + */ +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.emf.readonly.internal.messages.messages"; //$NON-NLS-1$ + + public static String ReferencedModelReadOnlyHandler_promptMsg; + + public static String ReferencedModelReadOnlyHandler_promptTitle; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/messages.properties b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/messages.properties new file mode 100644 index 00000000000..92baf6bdc1c --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/messages.properties @@ -0,0 +1,14 @@ +# +# Copyright (c) 2014 CEA and others. +# +# 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: +# Christian W. Damus (CEA) - Initial API and implementation +# + +ReferencedModelReadOnlyHandler_promptMsg=Do you want to make these referenced library model files writable?\n\n +ReferencedModelReadOnlyHandler_promptTitle=Enable Write diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF index 7650aed5854..d2c37127ece 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF @@ -24,6 +24,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="0.2.0",
org.eclipse.papyrus.emf.facet.custom.core;bundle-version="0.4.0"
Export-Package: org.eclipse.papyrus.infra.emf,
+ org.eclipse.papyrus.infra.emf.adapters,
org.eclipse.papyrus.infra.emf.commands,
org.eclipse.papyrus.infra.emf.databinding,
org.eclipse.papyrus.infra.emf.dialog,
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/plugin.xml b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/plugin.xml index a5a77a29959..201411fb724 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/plugin.xml +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/plugin.xml @@ -1,5 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
+<!--
+ Copyright (c) 2012, 2014 CEA and others.
+
+ 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 - Initial API and implementation
+ Christian W. Damus (CEA) - bug 323802
+
+-->
<plugin>
<extension
point="org.eclipse.papyrus.infra.core.service">
@@ -17,6 +30,10 @@ <extension
point="org.eclipse.papyrus.infra.services.labelprovider.labelProvider">
<labelProvider
+ priority="110"
+ provider="org.eclipse.papyrus.infra.emf.providers.ResourceFilteredLabelProvider">
+ </labelProvider>
+ <labelProvider
priority="100"
provider="org.eclipse.papyrus.infra.emf.providers.EMFFilteredLabelProvider">
</labelProvider>
@@ -41,6 +58,15 @@ id="org.eclipse.papyrus.infra.emf.page">
</metamodelType>
</metamodel>
+ <metamodel
+ nsURI="http://www.eclipse.org/emf/2002/Ecore">
+ <adviceBinding
+ id="org.eclipse.papyrus.infra.emf.readOnlyAdvice"
+ class="org.eclipse.papyrus.infra.emf.advice.ReadOnlyObjectEditAdvice"
+ typeId="*"
+ inheritance="none">
+ </adviceBinding>
+ </metamodel>
</extension>
<extension
point="org.eclipse.gmf.runtime.emf.type.core.elementTypeBindings">
@@ -57,5 +83,15 @@ </elementType>
</binding>
</extension>
+ <extension
+ point="org.eclipse.core.runtime.adapters">
+ <factory
+ adaptableType="org.eclipse.emf.ecore.EObject"
+ class="org.eclipse.papyrus.infra.emf.adapters.EObjectAdapterFactory">
+ <adapter
+ type="org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor">
+ </adapter>
+ </factory>
+ </extension>
</plugin>
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/EObjectAdapterFactory.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/EObjectAdapterFactory.java new file mode 100644 index 00000000000..e16b485fc3b --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/EObjectAdapterFactory.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.adapters; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.papyrus.infra.emf.dialog.NestedEditingDialogContext; +import org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor; + + +/** + * This is the EObjectAdapterFactory type. Enjoy. + */ +public class EObjectAdapterFactory implements IAdapterFactory { + + private final Class<?>[] adapterTypes = { IAtomicOperationExecutor.class }; + + public EObjectAdapterFactory() { + super(); + } + + public Object getAdapter(Object adaptable, @SuppressWarnings("rawtypes") Class adapterType) { + Object result = null; + + if(adaptable instanceof EObject) { + if(adapterType == IAtomicOperationExecutor.class) { + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain((EObject)adaptable); + if(domain == null) { + ResourceSet rset = NestedEditingDialogContext.getInstance().getResourceSet(); + if(rset != null) { + domain = TransactionUtil.getEditingDomain(rset); + } + } + if(domain != null) { + result = new EMFAtomicOperationExecutor(domain); + } + } + } + + return result; + } + + @SuppressWarnings("rawtypes") + public Class[] getAdapterList() { + return adapterTypes; + } + + // + // Nested types + // + + private static final class EMFAtomicOperationExecutor extends IAtomicOperationExecutor.Default { + + private final TransactionalEditingDomain domain; + + EMFAtomicOperationExecutor(TransactionalEditingDomain domain) { + this.domain = domain; + } + + @Override + public void execute(final Runnable operation, String label) { + domain.getCommandStack().execute(new RecordingCommand(domain, label) { + + @Override + protected void doExecute() { + operation.run(); + } + }); + } + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/ResourceSetRootsAdapter.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/ResourceSetRootsAdapter.java new file mode 100644 index 00000000000..99ebd3839aa --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/ResourceSetRootsAdapter.java @@ -0,0 +1,107 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.emf.adapters;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EContentAdapter;
+
+/**
+ * An EMF Adapter which listens on Resource Set root elements
+ *
+ * @author Camille Letavernier
+ *
+ */
+public abstract class ResourceSetRootsAdapter extends EContentAdapter {
+
+ @Override
+ public void notifyChanged(Notification msg) {
+ switch(msg.getEventType()) {
+ case Notification.ADD:
+ case Notification.ADD_MANY:
+ case Notification.REMOVE:
+ case Notification.REMOVE_MANY:
+ case Notification.UNSET:
+ doNotify(msg);
+ break;
+ }
+
+ super.notifyChanged(msg);
+ }
+
+ @Override
+ protected void setTarget(ResourceSet target) {
+ if(target instanceof ResourceSet) {
+ ResourceSet resourceSet = target;
+ if(!resourceSet.eAdapters().contains(this)) {
+ addAdapter(resourceSet);
+ }
+ }
+ super.setTarget(target);
+ }
+
+ @Override
+ protected void setTarget(Resource target) {
+ //Ignore
+ }
+
+ @Override
+ protected void setTarget(EObject target) {
+ //Ignore
+ }
+
+ @Override
+ protected void unsetTarget(EObject target) {
+ //Ignore
+ }
+
+ @Override
+ protected void unsetTarget(Resource target) {
+ //Ignore
+ }
+
+ @Override
+ protected void addAdapter(Notifier notifier) {
+ super.addAdapter(notifier);
+ }
+
+ @Override
+ protected void removeAdapter(Notifier notifier) {
+ super.removeAdapter(notifier);
+ }
+
+ @Override
+ protected void unsetTarget(ResourceSet target) {
+ if(target != null) {
+ removeAdapter(target);
+ }
+ super.unsetTarget(target);
+ }
+
+ @Override
+ protected void handleContainment(Notification notification) {
+ if(notification.getEventType() == Notification.ADD || notification.getEventType() == Notification.ADD_MANY) {
+ //Do not propagate listeners to EObjects. We're only interested on events on the ResourceSet (Add/remove resources) and Resources (Add/remove EObjects)
+ if(notification.getNotifier() == getTarget()) {
+ super.handleContainment(notification);
+ }
+ } else {
+ super.handleContainment(notification);
+ }
+ }
+
+ protected abstract void doNotify(Notification msg);
+
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/advice/ReadOnlyObjectEditAdvice.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/advice/ReadOnlyObjectEditAdvice.java new file mode 100644 index 00000000000..5c7c1b62fb4 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/advice/ReadOnlyObjectEditAdvice.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.advice; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand; +import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyReferenceRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.DuplicateElementsRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientReferenceRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + + +/** + * Advice that vetoes edits that would modify objects that are read-only and could not reasonably be made writable. + */ +public class ReadOnlyObjectEditAdvice extends AbstractEditHelperAdvice { + + public ReadOnlyObjectEditAdvice() { + super(); + } + + protected boolean isContainerUneditable(IEditCommandRequest request, EObject object) { + boolean result = false; + EObject container = object.eContainer(); + + if(container == null) { + // Resource root. Is the resource editable? + Resource resource = object.eResource(); + result = (resource != null) && isUneditable(request, resource); + } else { + result = isUneditable(request, container); + } + + return result; + } + + protected boolean isUneditable(IEditCommandRequest request, EObject object) { + boolean result = false; + + EditingDomain domain = request.getEditingDomain(); + if(EMFHelper.isReadOnly(object, domain)) { + // Check whether we have some means of making it writable + result = !EMFHelper.canMakeWritable(object, domain); + } + + return result; + } + + protected boolean isUneditable(IEditCommandRequest request, Resource resource) { + boolean result = false; + + EditingDomain domain = request.getEditingDomain(); + if(EMFHelper.isReadOnly(resource, domain)) { + // Check whether we have some means of making it writable + result = !EMFHelper.canMakeWritable(resource, domain); + } + + return result; + } + + protected ICommand getRefusal() { + return UnexecutableCommand.INSTANCE; + } + + @Override + protected ICommand getBeforeCreateCommand(CreateElementRequest request) { + EObject container = request.getContainer(); + + if((container != null) && isUneditable(request, container)) { + return getRefusal(); + } + + return super.getBeforeCreateCommand(request); + } + + @Override + protected ICommand getBeforeCreateRelationshipCommand(CreateRelationshipRequest request) { + EObject container = request.getContainer(); + + if((container != null) && isUneditable(request, container)) { + return getRefusal(); + } + + if(isUneditable(request, request.getSource())) { + return getRefusal(); + } + // Assume that the target (as in most cases) will not have an inverse reference to the new relationship + + return super.getBeforeCreateRelationshipCommand(request); + } + + @Override + protected ICommand getBeforeDestroyElementCommand(DestroyElementRequest request) { + EObject container = request.getContainer(); + + if((container != null) && isUneditable(request, container)) { + return getRefusal(); + } + // Cross-resource containment to a read-only resource? Unlikely. Don't need to look at the object-to-be-destroyed + + return super.getBeforeDestroyElementCommand(request); + } + + @Override + protected ICommand getBeforeDestroyReferenceCommand(DestroyReferenceRequest request) { + EObject container = request.getContainer(); + + // Simple case is when the owner object is read-only + if((container != null) && isUneditable(request, container)) { + return getRefusal(); + } + + // Handle the case where the reference has an opposite + EReference ref = request.getContainingFeature(); + if(ref.getEOpposite() != null) { + // The object being removed will have its inverse reference removed, also + EObject referenced = request.getReferencedObject(); + if((referenced != null) && isUneditable(request, referenced)) { + return getRefusal(); + } + } + + return super.getBeforeDestroyReferenceCommand(request); + } + + @Override + protected ICommand getBeforeDuplicateCommand(DuplicateElementsRequest request) { + List<?> elements = request.getElementsToBeDuplicated(); + + // Elements are duplicated in their containers, so the container must not be read-only + for(EObject next : Iterables.filter(elements, EObject.class)) { + EObject container = next.eContainer(); + if((container != null) && isUneditable(request, container)) { + return getRefusal(); + } + } + + return super.getBeforeDuplicateCommand(request); + } + + @Override + protected ICommand getBeforeMoveCommand(MoveRequest request) { + // Is any of the former containers read-only? + for(EObject next : Iterables.filter(request.getElementsToMove().keySet(), EObject.class)) { + if(isContainerUneditable(request, next)) { + return getRefusal(); + } + } + + if(isUneditable(request, request.getTargetContainer())) { + return getRefusal(); + } + + return super.getBeforeMoveCommand(request); + } + + @Override + protected ICommand getBeforeReorientRelationshipCommand(ReorientRelationshipRequest request) { + EObject relationship = request.getRelationship(); + + // Simple case is when the owner object is read-only + if((relationship != null) && isUneditable(request, relationship)) { + return getRefusal(); + } + + // Assume that changing the target would not affect the target object because it would not have an inverse reference + if(request.getDirection() == ReorientRequest.REORIENT_SOURCE) { + if(isUneditable(request, request.getOldRelationshipEnd())) { + return getRefusal(); + } + if(isUneditable(request, request.getNewRelationshipEnd())) { + return getRefusal(); + } + } + + return super.getBeforeReorientRelationshipCommand(request); + } + + @Override + protected ICommand getBeforeReorientReferenceRelationshipCommand(ReorientReferenceRelationshipRequest request) { + EObject owner = request.getReferenceOwner(); + + // Simple case is when the owner object is read-only + if((owner != null) && isUneditable(request, owner)) { + return getRefusal(); + } + + // Assume that changing the target would not affect the target object because it would not have an inverse reference + if(request.getDirection() == ReorientRequest.REORIENT_SOURCE) { + if(isUneditable(request, request.getOldRelationshipEnd())) { + return getRefusal(); + } + if(isUneditable(request, request.getNewRelationshipEnd())) { + return getRefusal(); + } + } + + return super.getBeforeReorientReferenceRelationshipCommand(request); + } + + @Override + protected ICommand getBeforeSetCommand(SetRequest request) { + // Simple case of read-only element + if(isUneditable(request, request.getElementToEdit())) { + return getRefusal(); + } + + if(request.getFeature() instanceof EReference) { + EReference ref = (EReference)request.getFeature(); + if(ref.getEOpposite() != null) { + // Objects on the opposite end must not be read-only + Collection<EObject> affectedOpposites = getAffectedOpposites(request.getElementToEdit(), ref, request.getValue()); + if(!affectedOpposites.isEmpty()) { + for(EObject next : affectedOpposites) { + if(isUneditable(request, next)) { + return getRefusal(); + } + } + } + } else if(ref.isContainment()) { + // Current container of any object must not change if it is read-only (and different from new container) + EObject owner = request.getElementToEdit(); + Object value = request.getValue(); + if(value instanceof Collection<?>) { + for(EObject next : Iterables.filter((Collection<?>)value, EObject.class)) { + if((next.eContainer() != owner) && isContainerUneditable(request, next)) { + return getRefusal(); + } + } + } else if(request.getValue() instanceof EObject) { + if(isContainerUneditable(request, (EObject)value)) { + return getRefusal(); + } + } + } + } + + return null; + } + + /** + * Obtains the objects that will be changed by means of the opposite "handshaking" of the given reference of a {@code source} object getting a new + * value. + */ + protected Collection<EObject> getAffectedOpposites(EObject source, EReference refWithOpposite, Object newValue) { + Collection<EObject> result; + + if(refWithOpposite.isMany()) { + if((newValue == null) || ((newValue instanceof Collection<?>) && ((Collection<?>)newValue).isEmpty())) { + // Removing all current references (and, hence, their inverses) + result = getReferencedObjects(source, refWithOpposite); + } else { + // The symmetric difference of currently- and to-be-referenced objects will change + Set<EObject> current = Sets.newHashSet(getReferencedObjects(source, refWithOpposite)); + Set<EObject> future = (newValue instanceof Collection<?>) ? ImmutableSet.copyOf(Iterables.filter((Collection<?>)newValue, EObject.class)) : Collections.singleton((EObject)newValue); + result = ImmutableList.copyOf(Sets.symmetricDifference(current, future)); + } + } else { + Object current = source.eGet(refWithOpposite); + if(current != newValue) { + // The current value will lose its inverse reference and the new value will gain one + if(current == null) { + result = Collections.singletonList((EObject)newValue); + } else if(newValue == null) { + result = Collections.singleton((EObject)current); + } else { + result = ImmutableList.of((EObject)current, (EObject)newValue); + } + } else { + // No objects will change + result = Collections.emptyList(); + } + } + + return result; + } + + /** + * Obtains the objects referenced by a {@code source} object via a particular {@code reference}. + */ + private Collection<EObject> getReferencedObjects(EObject source, EReference reference) { + Collection<EObject> result; + + Object current = source.eGet(reference); + if(current instanceof Collection<?>) { + result = ImmutableList.copyOf(Iterables.filter((Collection<?>)current, EObject.class)); + } else if(current != null) { + result = Collections.singletonList((EObject)current); + } else { + result = Collections.emptyList(); + } + + return result; + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/databinding/EMFObservableList.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/databinding/EMFObservableList.java index 6af566f79ad..beb832a0015 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/databinding/EMFObservableList.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/databinding/EMFObservableList.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.databinding;
@@ -17,6 +19,7 @@ import java.util.List; import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.ObservableList;
import org.eclipse.emf.common.command.Command;
@@ -41,7 +44,7 @@ import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; * @author Camille Letavernier
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
-public class EMFObservableList extends ObservableList implements ICommitListener, IChangeListener {
+public class EMFObservableList extends ObservableList implements ICommitListener, IChangeListener, IObserving {
/**
* The list of commands that haven't been executed yet
@@ -106,6 +109,10 @@ public class EMFObservableList extends ObservableList implements ICommitListener }
}
+ public Object getObserved() {
+ return source;
+ }
+
@Override
public synchronized void dispose() {
if(concreteList instanceof IObservableList) {
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/dialog/NestedEditingDialogContext.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/dialog/NestedEditingDialogContext.java new file mode 100644 index 00000000000..813e5524574 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/dialog/NestedEditingDialogContext.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.dialog; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; + +/** + * A tracker of nested editing-dialog context information required by various components that have no direct access to the context. + */ +public class NestedEditingDialogContext { + + private static final NestedEditingDialogContext INSTANCE = new NestedEditingDialogContext(); + + private final ThreadLocal<Integer> nesting = new ThreadLocal<Integer>(); + + private final ThreadLocal<ResourceSet> resourceSet = new ThreadLocal<ResourceSet>(); + + public static NestedEditingDialogContext getInstance() { + return INSTANCE; + } + + /** + * Queries whether the current editing dialog is nested in (created by) a higher-level dialog editing some other object. + * + * @return whether the current thread is presenting a nested editing dialog + */ + public boolean isNested() { + Integer depth = nesting.get(); + return (depth != null) && (depth.intValue() > 0); + } + + /** + * Signals entry of an editing dialog context (the current thread is now presenting a dialog). Must be matched by a subsequent + * call to {@linkplain #exit() exit} the context. + * + * @see #exit() + */ + public void enter() { + Integer depth = nesting.get(); + if((depth == null) || (depth.intValue() < 1)) { + depth = 1; + } else { + depth = depth.intValue() + 1; + } + nesting.set(depth); + } + + /** + * Signals the end of an editing dialog context (the current thread is no longer presenting a dialog). Must match an earlier + * call to {@linkplain #enter() enter} the context. + * + * @see #enter() + */ + public void exit() { + Integer depth = nesting.get(); + if(depth != null) { + if(depth.intValue() <= 1) { + depth = null; + } else { + depth = depth.intValue() - 1; + } + nesting.set(depth); + } + } + + /** + * Obtains the resource set in the editing-dialog context of the current thread. + * + * @return the current contextual resource set + */ + public ResourceSet getResourceSet() { + return resourceSet.get(); + } + + /** + * Determines, if possible, the resource set containing the given {@code context} object being edited and pushes it onto the + * current thread's context stack. + * + * @param context + * the object currently being edited in a dialog + * + * @return the resource set that was previously the context (which may be the same as the new one being pushed). This + * must be {@linkplain #pop(ResourceSet) popped} from the context subsequently + * + * @see #pop(ResourceSet) + */ + public ResourceSet push(Object context) { + final ResourceSet previous = resourceSet.get(); + + if(context instanceof EObject) { + Resource res = ((EObject)context).eResource(); + if(res != null) { + ResourceSet current = res.getResourceSet(); + if(current != null) { + // put it in context + resourceSet.set(current); + } + } + } + + return previous; + } + + /** + * Pops the current resource set from the context, restoring the given resource set that was returned by a previous {@linkplain #push(Object) + * push}, even if it was {@code null}. + * + * @param previous + * a resource set returned by an earlier push (may be {@code null}) + * + * @see #push(Object) + */ + public void pop(ResourceSet previous) { + if(previous == null) { + resourceSet.remove(); + } else { + resourceSet.set(previous); + } + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/Messages.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/Messages.java index d5a4308186d..6e02b835316 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/Messages.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/Messages.java @@ -1,15 +1,18 @@ -/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
- *
- *
+ +/*************************************************************
+ * Copyright (c) 2012, 2014 CEA and others.
+ *
* 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:
- * Patrick Tessier (CEA LIST) - Initial API and implementation
- /*****************************************************************************/
+ * Vincent Lorenzo (CEA LIST) - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
+ */
+ package org.eclipse.papyrus.infra.emf.messages;
import org.eclipse.osgi.util.NLS;
@@ -18,7 +21,20 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.emf.messages.messages"; //$NON-NLS-1$
+ public static String ResourceFilteredLabelProvider_local;
+
+ public static String ResourceFilteredLabelProvider_localExt;
+
+ public static String ResourceFilteredLabelProvider_system;
+
+ public static String ResourceFilteredLabelProvider_systemExt;
+
+ public static String ResourceFilteredLabelProvider_workspace;
+
+ public static String ResourceFilteredLabelProvider_workspaceExt;
+
public static String UnsetCommand_UnsetCommand;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/messages.properties b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/messages.properties index b5119e19f07..7a50929b818 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/messages.properties +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/messages.properties @@ -1 +1,20 @@ +#
+# Copyright (c) 2012, 2014 CEA and others.
+#
+# 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) - Initial API and implementation
+# Christian W. Damus (CEA) - bug 323802
+#
+
+ResourceFilteredLabelProvider_local=Local model file "{0}"
+ResourceFilteredLabelProvider_localExt=Local model file "{0}" ({1} component)
+ResourceFilteredLabelProvider_system=System resource "{0}"
+ResourceFilteredLabelProvider_systemExt=Resource "{0}"
+ResourceFilteredLabelProvider_workspace=Workspace model file "{0}"
+ResourceFilteredLabelProvider_workspaceExt=Workspace model file "{0}" ({1} component)
UnsetCommand_UnsetCommand=Unset Command
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/providers/ResourceFilteredLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/providers/ResourceFilteredLabelProvider.java new file mode 100644 index 00000000000..b776f51de5a --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/providers/ResourceFilteredLabelProvider.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.emf.providers; + +import java.io.IOException; +import java.util.Map; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ContentHandler; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.URIConverter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.emf.Activator; +import org.eclipse.papyrus.infra.emf.messages.Messages; +import org.eclipse.papyrus.infra.services.labelprovider.service.IFilteredLabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.PlatformUI; + +/** + * A label provider for EMF {@link Resource}s. + */ +public class ResourceFilteredLabelProvider extends EMFLabelProvider implements IFilteredLabelProvider { + + private ResourceManager images; + + public boolean accept(Object element) { + return element instanceof Resource; + } + + @Override + public void dispose() { + if(images != null) { + images.dispose(); + images = null; + } + + super.dispose(); + } + + @Override + public String getText(Object element) { + return (element instanceof Resource) ? getText((Resource)element) : super.getText(element); + } + + protected String getText(Resource resource) { + String result; + + URI uri = resource.getURI(); + + if(uri.isPlatformResource()) { + String ext = uri.fileExtension(); + if(ext == null) { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_workspace, uri.toPlatformString(true)); + } else { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_workspaceExt, uri.toPlatformString(true), uri.fileExtension()); + } + } else if(uri.isFile()) { + String ext = uri.fileExtension(); + if(ext == null) { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_local, uri.toFileString()); + } else { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_localExt, uri.toFileString(), uri.fileExtension()); + } + } else if(uri.isHierarchical()) { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_system, uri.lastSegment()); + } else { + result = NLS.bind(Messages.ResourceFilteredLabelProvider_systemExt, uri.toString()); + } + + return result; + } + + @Override + public Image getImage(Object element) { + return (element instanceof Resource) ? getImage((Resource)element) : super.getImage(element); + } + + protected Image getImage(Resource resource) { + URI uri = resource.getURI(); + URIConverter converter = (resource.getResourceSet() == null) ? URIConverter.INSTANCE : resource.getResourceSet().getURIConverter(); + + IContentType contentType = null; + try { + Map<String, ?> description = converter.contentDescription(uri, null); + contentType = (description.get(ContentHandler.CONTENT_TYPE_PROPERTY) == null) ? null : Platform.getContentTypeManager().getContentType((String)description.get(ContentHandler.CONTENT_TYPE_PROPERTY)); + } catch (IOException e) { + Activator.log.error(e); + } + + IEditorDescriptor[] editors; + if(contentType != null) { + editors = PlatformUI.getWorkbench().getEditorRegistry().getEditors(uri.lastSegment(), contentType); + } else { + editors = PlatformUI.getWorkbench().getEditorRegistry().getEditors(uri.lastSegment()); + } + + ImageDescriptor result = null; + for(int i = 0; (result == null) && (i < editors.length); i++) { + result = editors[0].getImageDescriptor(); + } + + return convert(result); + } + + protected Image convert(ImageDescriptor descriptor) { + Image result = null; + + if(descriptor != null) { + if(images == null) { + images = new LocalResourceManager(JFaceResources.getResources()); + } + + result = (Image)images.get(descriptor); + } + + return result; + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java index d187e7bbdc6..20553b3c9bc 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010, 2013 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -10,6 +10,7 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - filter out EObjects that are Resources (CDO)
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.utils;
@@ -41,11 +42,13 @@ import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.emf.facet.custom.ui.CustomizedContentProviderUtils;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers;
import org.eclipse.papyrus.infra.emf.Activator;
@@ -500,6 +503,48 @@ public class EMFHelper { }
/**
+ * Tests if an object that is read only could possibly be made writable by some means (file system attributes, team provider hook, database
+ * permissions, etc.)
+ *
+ * @param eObject
+ * an object that is assumed to be read-only
+ * @param domain
+ * the editing domain context of the {@link eObject}
+ * @return
+ * whether the {@code eObject} could be made writable
+ */
+ public static boolean canMakeWritable(final EObject eObject, final EditingDomain domain) {
+ if(domain != null) {
+ Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
+ if(handler instanceof IReadOnlyHandler2) {
+ return ((IReadOnlyHandler2)handler).canMakeWritable(eObject).or(false);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if a resource that is read only could possibly be made writable by some means (file system attributes, team provider hook, database
+ * permissions, etc.)
+ *
+ * @param resource
+ * a resource that is assumed to be read-only
+ * @param domain
+ * the editing domain context of the {@link resource}
+ * @return
+ * whether the {@code resource} could be made writable
+ */
+ public static boolean canMakeWritable(final Resource resource, final EditingDomain domain) {
+ if(domain != null) {
+ Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
+ if(handler instanceof IReadOnlyHandler2) {
+ return ((IReadOnlyHandler2)handler).canMakeWritable(new URI[] { resource.getURI() }).or(false);
+ }
+ }
+ return false;
+ }
+
+ /**
* Tests if the given EStructuralFeature is required (ie. should always
* have a value)
*
@@ -741,4 +786,42 @@ public class EMFHelper { }
return result;
}
+
+ /**
+ * Returns the given element, reloaded into the resource set of the context element,
+ * or the source element itself if not possible.
+ *
+ * Use this method for e.g. loading an element from a shared resource set into another resource set
+ * (Apply a registered profile/library, drop an element from the project explorer, ...)
+ *
+ * @param element
+ * @param contextElement
+ * @return
+ */
+ public static <T extends EObject> T reloadIntoContext(T element, EObject contextElement) {
+ ResourceSet sourceResourceSet = getResourceSet(element);
+ ResourceSet loadingContext = getResourceSet(contextElement);
+
+ if(sourceResourceSet == loadingContext || loadingContext == null) {
+ return element;
+ }
+
+ URI sourceURI = EcoreUtil.getURI(element);
+ EObject result = loadingContext.getEObject(sourceURI, true);
+
+ return (T)result;
+ }
+
+ /**
+ * Returns the resourceSet owning this eObject, or null if it is detached
+ *
+ * @param eObject
+ */
+ public static ResourceSet getResourceSet(EObject eObject) {
+ if(eObject == null || eObject.eResource() == null) {
+ return null;
+ }
+
+ return eObject.eResource().getResourceSet();
+ }
}
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/MultipleStylableElement.xwt b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/MultipleStylableElement.xwt index 208f3a1d236..40dbfbfbce4 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/MultipleStylableElement.xwt +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/MultipleStylableElement.xwt @@ -8,5 +8,5 @@ <Composite.layout>
<GridLayout numColumns="1"></GridLayout>
</Composite.layout>
- <css:ResetStyleWidget input="{Binding}"></css:ResetStyleWidget>
+ <css:ResetStyleWidget input="{Binding}" property="CSS:PapyrusCSSStyle:cssStyle"></css:ResetStyleWidget>
</Composite>
\ No newline at end of file diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleDiagram.xwt b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleDiagram.xwt index 64704634d72..5d97981f0a2 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleDiagram.xwt +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleDiagram.xwt @@ -18,7 +18,7 @@ <Composite.layout>
<GridLayout></GridLayout>
</Composite.layout>
- <css:ResetStyleWidget input="{Binding}"></css:ResetStyleWidget>
+ <css:ResetStyleWidget input="{Binding}" property="CSS:PapyrusCSSStyle:cssStyle"></css:ResetStyleWidget>
</Composite>
<Composite>
<Composite.layout>
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleStylableElement.xwt b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleStylableElement.xwt index b4b4f789285..827e0614086 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleStylableElement.xwt +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleStylableElement.xwt @@ -11,7 +11,7 @@ <Composite.layout>
<GridLayout></GridLayout>
</Composite.layout>
- <css:ResetStyleWidget input="{Binding}"></css:ResetStyleWidget>
+ <css:ResetStyleWidget input="{Binding}" property="CSS:PapyrusCSSStyle:cssStyle"></css:ResetStyleWidget>
</Composite>
<Composite>
<Composite.layout>
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/widgets/ResetStyleWidget.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/widgets/ResetStyleWidget.java index 470316e7202..f0955ffb7ee 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/widgets/ResetStyleWidget.java +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/widgets/ResetStyleWidget.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.properties.widgets;
@@ -27,6 +29,8 @@ public class ResetStyleWidget implements SelectionListener { private DataSource input;
+ private String propertyPath;
+
public ResetStyleWidget(Composite parent, int style) {
button = new Button(parent, SWT.PUSH);
button.addSelectionListener(this);
@@ -65,9 +69,28 @@ public class ResetStyleWidget implements SelectionListener { public void setInput(DataSource input) {
this.input = input;
+ checkInput();
}
public DataSource getInput() {
return input;
}
+
+ public String getProperty() {
+ return propertyPath;
+ }
+
+ public void setProperty(String property) {
+ this.propertyPath = property;
+ checkInput();
+ }
+
+ protected void checkInput() {
+ if((propertyPath != null) && (input != null)) {
+ button.setEnabled(input.isEditable(propertyPath));
+ } else {
+ button.setEnabled(true); // For compatibility with XWT models that don't specify the property
+ }
+ }
+
}
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.theme/theme/papyrus_theme.css b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.theme/theme/papyrus_theme.css index 8e651a55605..6ac50b4d5c2 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.theme/theme/papyrus_theme.css +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.theme/theme/papyrus_theme.css @@ -123,3 +123,6 @@ ParametricDiagram [appliedStereotypes~=ConstraintProperty] { elementIcon:false;
}
+Label {
+ elementIcon: false;
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/configuration/DefaultDirectEditorConfiguration.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/configuration/DefaultDirectEditorConfiguration.java index c7649f1c542..d2a446bea1c 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/configuration/DefaultDirectEditorConfiguration.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/configuration/DefaultDirectEditorConfiguration.java @@ -84,7 +84,7 @@ public class DefaultDirectEditorConfiguration implements IDirectEditorConfigurat * {@inheritDoc}
*/
public String getTextToEdit(Object objectToEdit) {
- return "";
+ return ""; //$NON-NLS-1$
}
/**
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/definition/DirectEditorExtensionPoint.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/definition/DirectEditorExtensionPoint.java index c435b7dc7d2..10ab10ed615 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/definition/DirectEditorExtensionPoint.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/definition/DirectEditorExtensionPoint.java @@ -71,10 +71,15 @@ public class DirectEditorExtensionPoint { // Read configuration elements for the current extension for(IConfigurationElement configElement : configElements) { - DirectEditorExtensionPoint proxy = parseDirectEditorConfiguration(configElement); + try { + DirectEditorExtensionPoint proxy = parseDirectEditorConfiguration(configElement); - if(proxy != null) { - directEditorExtensionPoints.add(proxy); + if(proxy != null) { + directEditorExtensionPoints.add(proxy); + } + } catch (Throwable ex) { + Activator.log.error(ex); + continue; } } // end of configElements loop diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.properties b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.properties index 7b616a5ac05..7324564d6df 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.properties +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.properties @@ -1,5 +1,5 @@ #################################################################################
-# Copyright (c) 2011 Atos.
+# Copyright (c) 2011, 2014 Atos, CEA, and others.
# 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
@@ -7,6 +7,10 @@ #
# Contributors:
# Vincent Hemery - Initial API and implementation
+# Christian W. Damus (CEA) - bug 323802
+#
##################################################################################
pluginName=Papyrus Commands Tools (Incubation)
providerName=Eclipse Modeling Project
+
+historyListeners-extpt=Operation History Listeners
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.xml b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.xml index f8f60be4ccb..98f0fc190ef 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.xml +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.xml @@ -2,6 +2,8 @@ <?eclipse version="3.4"?>
<plugin>
<extension-point id="operationApprover" name="operationApprover" schema="schema/operationApprover.exsd"/>
+ <extension-point id="historyListeners" name="%historyListeners-extpt" schema="schema/historyListeners.exsd"/>
+
<extension
point="org.eclipse.ui.handlers">
<handler
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/schema/historyListeners.exsd b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/schema/historyListeners.exsd new file mode 100644 index 00000000000..16f042831a6 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/schema/historyListeners.exsd @@ -0,0 +1,91 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.papyrus.infra.gmfdiag.commands" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appinfo> + <meta.schema plugin="org.eclipse.papyrus.infra.gmfdiag.commands" id="historyListeners" name="historyListeners"/> + </appinfo> + <documentation> + Registration of history listeners to be attached to the operation history used by the Papyrus GMF diagrams (and transactional editing domains in general). + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appinfo> + <meta.element /> + </appinfo> + </annotation> + <complexType> + <sequence> + <element ref="historyListener" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appinfo> + <meta.attribute translatable="true"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="historyListener"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + The Java class implementing of the history listener. + </documentation> + <appinfo> + <meta.attribute kind="java" basedOn=":org.eclipse.core.commands.operations.IOperationHistoryListener"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appinfo> + <meta.section type="since"/> + </appinfo> + <documentation> + 1.0 + </documentation> + </annotation> + + + + + <annotation> + <appinfo> + <meta.section type="copyright"/> + </appinfo> + <documentation> + Copyright (c) 2014 CEA and others. + +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 + </documentation> + </annotation> + +</schema> diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/CheckedOperationHistory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/CheckedOperationHistory.java index 5973347c169..179be3fdc44 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/CheckedOperationHistory.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/CheckedOperationHistory.java @@ -9,7 +9,7 @@ *
* Contributors:
* Mathieu Velten (Atos) - Initial API and implementation
- * Christian W. Damus (CEA) - bug 357250
+ * Christian W. Damus (CEA) - bug 357250, bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.commands;
@@ -80,8 +80,8 @@ public class CheckedOperationHistory implements IOperationHistory { if("operationApprover".equals(elem.getName())) { //$NON-NLS-1$
try {
ApproverPriorityPair approverPriorityPair = new ApproverPriorityPair();
- approverPriorityPair.approver = (IOperationApprover2)elem.createExecutableExtension("class");
- approverPriorityPair.priority = Integer.parseInt(elem.getAttribute("priority"));
+ approverPriorityPair.approver = (IOperationApprover2)elem.createExecutableExtension("class"); //$NON-NLS-1$
+ approverPriorityPair.priority = Integer.parseInt(elem.getAttribute("priority")); //$NON-NLS-1$
approverPriorityPairs.add(approverPriorityPair);
} catch (Exception e) {
@@ -101,6 +101,8 @@ public class CheckedOperationHistory implements IOperationHistory { private CheckedOperationHistory() {
history = OperationHistoryFactory.getOperationHistory();
+
+ addRegisteredListeners(history);
}
/*
@@ -218,6 +220,21 @@ public class CheckedOperationHistory implements IOperationHistory { return history.redo(context, monitor, info);
}
+ private static void addRegisteredListeners(IOperationHistory history) {
+ IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor(Activator.PLUGIN_ID, "historyListeners"); //$NON-NLS-1$
+
+ for(IConfigurationElement elem : configElements) {
+ if("historyListener".equals(elem.getName())) { //$NON-NLS-1$
+ try {
+ IOperationHistoryListener listener = (IOperationHistoryListener)elem.createExecutableExtension("class"); //$NON-NLS-1$
+ history.addOperationHistoryListener(listener);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in instantiation of operation history listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
// all the following methods are pure delegation
public IStatus undoOperation(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStack.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStack.java new file mode 100644 index 00000000000..d35ce4035e3 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStack.java @@ -0,0 +1,231 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST and others. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - adapted for self-nesting behaviour + * + *****************************************************************************/ +package org.eclipse.papyrus.commands; + +import org.eclipse.core.commands.operations.IOperationHistory; +import org.eclipse.core.commands.operations.IUndoContext; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.transaction.RollbackException; + + +public class NestingNotifyingWorkspaceCommandStack extends NotifyingWorkspaceCommandStack { + + private NestingNotifyingWorkspaceCommandStack childCommandStack; + + private final boolean nested; + + private boolean executing; + + protected IUndoContext defaultUndoContext; + + public NestingNotifyingWorkspaceCommandStack(IOperationHistory history) { + this(false, history, null); + } + + protected NestingNotifyingWorkspaceCommandStack(boolean nested, IOperationHistory history, IUndoContext defaultUndoContext) { + super(history); + this.nested = nested; + this.defaultUndoContext = defaultUndoContext; + } + + protected NestingNotifyingWorkspaceCommandStack(boolean nested, IOperationHistory history) { + this(nested, history, computeNestedUndoContext()); + } + + private static IUndoContext computeNestedUndoContext() { + return new IUndoContext() { + + public boolean matches(IUndoContext context) { + return context == this; + } + + public String getLabel() { + return "Nested Undo Context"; + } + }; + } + + @Override + public IUndoContext getDefaultUndoContext() { + if(defaultUndoContext == null) { + return super.getDefaultUndoContext(); + } + return defaultUndoContext; + } + + protected NestingNotifyingWorkspaceCommandStack getTopMostCommandStack() { + if(childCommandStack == null) { + return this; + } + return childCommandStack.getTopMostCommandStack(); + } + + protected void startNestedTransaction(Command command) { + if(childCommandStack != null) { + //Forwards to the current stack + childCommandStack.startNestedTransaction(command); + } else { + //Start a new nested transaction in a new nested Stack + childCommandStack = createNestedCommandStack(getOperationHistory()); + childCommandStack.setEditingDomain(getDomain()); + + childCommandStack.execute(command); + } + } + + protected NestingNotifyingWorkspaceCommandStack createNestedCommandStack(IOperationHistory history) { + return new NestingNotifyingWorkspaceCommandStack(true, history); + } + + public void commit() { + if(childCommandStack != null) { + disposeLastCommandStack(); + } + } + + private boolean disposeLastCommandStack() { + if(childCommandStack == null) { + //I'm the last command stack + dispose(); + return true; + } + + //Propagates + if(childCommandStack.disposeLastCommandStack()) { + childCommandStack = null; + } + + return false; + } + + public void rollback() { + if(childCommandStack != null) { + while (canUndo()) { + undo(); + } + disposeLastCommandStack(); + } + } + + @Override + public void execute(Command command) { + if(childCommandStack == null) { + if(!executing) { + executing = true; + + try { + super.execute(command); + } finally { + executing = false; + } + } else { + // Re-entrant command execution goes on a nested stack + try { + startNestedTransaction(command); + commit(); + } catch (OperationCanceledException e) { + rollback(); + // Propagate + throw e; + } + } + } else { + childCommandStack.execute(command); + } + } + + @Override + protected void handleError(Exception exception) { + if (nested && (exception instanceof RollbackException)) { + //A nested transaction rolled back + RollbackException rbe = (RollbackException) exception; + if (rbe.getStatus().getSeverity() == IStatus.CANCEL) { + // Propagate + throw new OperationCanceledException(); + } + } + + if (exception instanceof OperationCanceledException) { + rollback(); + } else { + super.handleError(exception); + } + } + + @Override + public Command getMostRecentCommand() { + if(childCommandStack == null) { + return super.getMostRecentCommand(); + } else { + return childCommandStack.getMostRecentCommand(); + } + } + + @Override + public Command getRedoCommand() { + if(childCommandStack == null) { + return super.getRedoCommand(); + } else { + return childCommandStack.getRedoCommand(); + } + } + + @Override + public Command getUndoCommand() { + if(childCommandStack == null) { + return super.getUndoCommand(); + } else { + return childCommandStack.getUndoCommand(); + } + } + + @Override + public void undo() { + if(childCommandStack == null) { + super.undo(); + } else { + childCommandStack.undo(); + } + } + + @Override + public boolean canUndo() { + if(childCommandStack == null) { + return super.canUndo(); + } else { + return childCommandStack.canUndo(); + } + } + + @Override + public boolean canRedo() { + if(childCommandStack == null) { + return super.canRedo(); + } else { + return childCommandStack.canRedo(); + } + } + + @Override + public void redo() { + if(childCommandStack == null) { + super.redo(); + } else { + childCommandStack.redo(); + } + } + +} diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NotifyingWorkspaceCommandStack.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NotifyingWorkspaceCommandStack.java index 854f1a86d94..da6fbbfae6d 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NotifyingWorkspaceCommandStack.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NotifyingWorkspaceCommandStack.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2011, 2013 Atos, CEA, and others.
+ * Copyright (c) 2011, 2014 Atos, CEA, and others.
*
- *
* 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
@@ -11,6 +10,7 @@ * Mathieu Velten (Atos) - Initial API and implementation
* Arthur Daussy (Atos) - 363826: [Model Explorer] Drag and drop and undo, incorrect behavior
* Christian W. Damus (CEA) - 404220: Add contexts for tracking objects changed by operations (CDO)
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.commands;
@@ -181,7 +181,7 @@ implements IWorkspaceCommandStack { }
// Documentation copied from the method specification
- public final IUndoContext getDefaultUndoContext() {
+ public IUndoContext getDefaultUndoContext() {
return defaultContext;
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/META-INF/MANIFEST.MF b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/META-INF/MANIFEST.MF index 747f030d3d1..2df85a9ff59 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/META-INF/MANIFEST.MF +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/META-INF/MANIFEST.MF @@ -52,7 +52,10 @@ Require-Bundle: org.eclipse.emf.edit.ui;bundle-version="2.5.0", org.eclipse.gmf.tooling.runtime,
com.ibm.icu,
org.eclipse.papyrus.emf.facet.custom.core;bundle-version="0.4.0",
- org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="0.4.0"
+ org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="0.4.0",
+ org.eclipse.papyrus.infra.services.decoration;bundle-version="1.0.0",
+ org.eclipse.papyrus.infra.services.markerlistener;bundle-version="1.0.0",
+ org.eclipse.papyrus.uml.tools
Bundle-Vendor: %providerName
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/icons/shortcut.gif b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/icons/shortcut.gif Binary files differnew file mode 100644 index 00000000000..c8ebb3156a8 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/icons/shortcut.gif diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml index 7021ed3753b..fff597c93c0 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml @@ -1,184 +1,206 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?eclipse version="3.0"?> +<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin>
+ <extension-point id="nestedEditor" name="NestedEditor" schema="schema/nestedEditor.exsd"/>
+ <extension-point id="initializeView" name="initializeView" schema="schema/initializeView.exsd"/>
+ <extension-point id="shapeProvider" name="ShapeProvider" schema="schema/shapeProvider.exsd"/>
+ <extension-point id="notationTypesMapping" name="notationTypesMapping" schema="schema/notationTypesMapping.exsd"/>
+ <extension-point id="svgPostProcessors" name="svgPostProcessors" schema="schema/svgPostProcessors.exsd"/>
+ <extension-point id="pasteCommandProvider" name="pasteCommandProvider" schema="schema/pasteCommandProvider.exsd"/>
-<plugin> - <extension-point id="nestedEditor" name="NestedEditor" schema="schema/nestedEditor.exsd"/> - <extension-point id="initializeView" name="initializeView" schema="schema/initializeView.exsd"/> - <extension-point id="shapeProvider" name="ShapeProvider" schema="schema/shapeProvider.exsd"/> - <extension-point id="notationTypesMapping" name="notationTypesMapping" schema="schema/notationTypesMapping.exsd"/> - <extension-point id="svgPostProcessors" name="svgPostProcessors" schema="schema/svgPostProcessors.exsd"/> - <extension-point id="pasteCommandProvider" name="pasteCommandProvider" schema="schema/pasteCommandProvider.exsd"/> - -<extension - point="org.eclipse.ui.handlers"> - <handler - class="org.eclipse.papyrus.infra.gmfdiag.common.handler.RefreshHandler" - commandId="org.eclipse.ui.file.refresh"> - <activeWhen> - <with - variable="activePartId"> - <equals - value="org.eclipse.papyrus.infra.core.papyrusEditor"> - </equals> - </with> - </activeWhen> - </handler> -</extension> -<extension - point="org.eclipse.ui.menus"> - <menuContribution - allPopups="false" - locationURI="toolbar:org.eclipes.papyrus.menu.toolbar"> - <command - commandId="org.eclipse.ui.file.refresh" - icon="icons/refresh.gif" - label="Refresh" - style="push" - tooltip="Refresh the current diagram"> - <visibleWhen - checkEnabled="false"> - <with - variable="activeEditorId"> - <equals - value="org.eclipse.papyrus.infra.core.papyrusEditor"> - </equals> - </with> - </visibleWhen> - </command> - </menuContribution> -</extension> -<extension - point="org.eclipse.ui.preferencePages"> - <page - category="org.eclipse.papyrus.infra.core.sasheditor.preferences.generalcategory" - class="org.eclipse.papyrus.infra.gmfdiag.common.preferences.ConnectionToolPreferencePage" - id="org.eclipse.papyrus.infra.gmfdiag.common.connectionTools" - name="Connection Tools"> - </page> -</extension> -<extension - point="org.eclipse.core.runtime.preferences"> - <initializer - class="org.eclipse.papyrus.infra.gmfdiag.common.preferences.ConnectionToolPreferenceInitializer"> - </initializer> +<extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ class="org.eclipse.papyrus.infra.gmfdiag.common.handler.RefreshHandler"
+ commandId="org.eclipse.ui.file.refresh">
+ <activeWhen>
+ <with
+ variable="activePartId">
+ <equals
+ value="org.eclipse.papyrus.infra.core.papyrusEditor">
+ </equals>
+ </with>
+ </activeWhen>
+ </handler>
+</extension>
+<extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ allPopups="false"
+ locationURI="toolbar:org.eclipes.papyrus.menu.toolbar">
+ <command
+ commandId="org.eclipse.ui.file.refresh"
+ icon="icons/refresh.gif"
+ label="Refresh"
+ style="push"
+ tooltip="Refresh the current diagram">
+ <visibleWhen
+ checkEnabled="false">
+ <with
+ variable="activeEditorId">
+ <equals
+ value="org.eclipse.papyrus.infra.core.papyrusEditor">
+ </equals>
+ </with>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+</extension>
+<extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.eclipse.papyrus.infra.core.sasheditor.preferences.generalcategory"
+ class="org.eclipse.papyrus.infra.gmfdiag.common.preferences.ConnectionToolPreferencePage"
+ id="org.eclipse.papyrus.infra.gmfdiag.common.connectionTools"
+ name="Connection Tools">
+ </page>
+</extension>
+<extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer
+ class="org.eclipse.papyrus.infra.gmfdiag.common.preferences.ConnectionToolPreferenceInitializer">
+ </initializer>
+</extension>
+ <extension
+ point="org.eclipse.papyrus.infra.core.model">
+ <model
+ classname="org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel"
+ description="Model for notation">
+ </model>
+ </extension>
+
+
+ <extension
+ point="org.eclipse.emf.ecore.extension_parser">
+ <parser
+ class="org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory"
+ type="notation">
+ </parser>
+ </extension>
+<extension
+ point="org.eclipse.papyrus.infra.core.service">
+ <serviceFactory
+ classname="org.eclipse.papyrus.infra.gmfdiag.common.undocontext.UndoContextServiceFactory"
+ description="The shared IUndoContext used to tag command in the CommandStack"
+ id="org.eclipse.core.commands.operations.IUndoContext"
+ priority="1"
+ startKind="lazy">
+ <dependsOn
+ serviceKeyRef="org.eclipse.emf.transaction.TransactionalEditingDomain">
+ </dependsOn>
+ </serviceFactory>
+ <service
+ classname="org.eclipse.papyrus.infra.gmfdiag.common.DefaultGraphicalEditorSupport"
+ description="The default diagram editor support implementation."
+ id="org.eclipse.papyrus.infra.gmfdiag.common.IGraphicalEditorSupport"
+ priority="1"
+ startKind="lazy">
+ </service>
+ </extension>
+<extension
+ point="org.eclipse.papyrus.infra.services.labelprovider.labelProvider">
+ <labelProvider
+ priority="40"
+ provider="org.eclipse.papyrus.infra.gmfdiag.common.providers.NotationFilteredLabelProvider">
+ </labelProvider>
+</extension>
+<extension
+ point="org.eclipse.gmf.runtime.diagram.ui.decoratorProviders">
+ <decoratorProvider
+ class="org.eclipse.papyrus.infra.gmfdiag.common.providers.ShapeDecoratorProvider">
+ <Priority
+ name="Lowest">
+ </Priority>
+ </decoratorProvider>
+</extension>
+<extension
+ point="org.eclipse.core.runtime.adapters">
+ <factory
+ adaptableType="org.eclipse.gmf.runtime.notation.Diagram"
+ class="org.eclipse.papyrus.infra.gmfdiag.common.adapter.DiagramAdapterFactory">
+ <adapter
+ type="org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.IOpenable">
+ </adapter>
+ </factory>
+</extension>
+
+<!-- ElementType bindings for diagram duplication with paste command -->
+ <extension
+ point="org.eclipse.gmf.runtime.emf.type.core.elementTypes">
+ <metamodel
+ nsURI="http://www.eclipse.org/emf/2002/Ecore">
+ <adviceBinding
+ class="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice"
+ id="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice"
+ inheritance="none"
+ typeId="*">
+ </adviceBinding>
+ </metamodel>
+ </extension>
+
+<extension point="org.eclipse.gmf.runtime.emf.type.core.elementTypeBindings">
+
+ <!-- Bindings declaration -->
+ <binding context="org.eclipse.papyrus.infra.services.edit.TypeContext">
+ <advice ref="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice" />
+ </binding>
+</extension>
+<extension
+ point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ class="org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramPropertyTester"
+ id="org.eclipse.papyrus.infra.gmfdiag.common.diagram.tester"
+ namespace="org.eclipse.papyrus.infra.gmfdiag.common.diagram.tester"
+ properties="isDiagramEditor"
+ type="org.eclipse.jface.viewers.IStructuredSelection">
+ </propertyTester>
+ <propertyTester
+ class="org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramPropertyTester"
+ id="org.eclipse.papyrus.infra.gmfdiag.common.diagram.context.tester"
+ namespace="org.eclipse.papyrus.infra.gmfdiag.common.diagram.context.tester"
+ properties="isGmfDiagramContextActive"
+ type="java.util.Collection">
+ </propertyTester> +</extension>
+<extension
+ point="org.eclipse.papyrus.infra.gmfdiag.common.shapeProvider">
+ <shapeProvider
+ class="org.eclipse.papyrus.infra.gmfdiag.common.providers.StyleBasedShapeProvider"
+ description="Provides shapes based on the applied styles."
+ id="org.eclipse.papyrus.infra.gmfdiag.common.providers.StyleBasedShapeProvider"
+ name="StyleBasedShapeProvider">
+ <Priority
+ name="Low"></Priority>
+ </shapeProvider>
+</extension>
+<extension
+ point="org.eclipse.papyrus.infra.gmfdiag.common.notationTypesMapping">
+ <mapping
+ humanReadableType="symbol"
+ type="compartment_shape_display">
+ </mapping>
</extension> - <extension - point="org.eclipse.papyrus.infra.core.model"> - <model - classname="org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel" - description="Model for notation"> - </model> - </extension> - - - <extension - point="org.eclipse.emf.ecore.extension_parser"> - <parser - class="org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory" - type="notation"> - </parser> - </extension> -<extension - point="org.eclipse.papyrus.infra.core.service"> - <serviceFactory - classname="org.eclipse.papyrus.infra.gmfdiag.common.undocontext.UndoContextServiceFactory" - description="The shared IUndoContext used to tag command in the CommandStack" - id="org.eclipse.core.commands.operations.IUndoContext" - priority="1" - startKind="lazy"> - <dependsOn - serviceKeyRef="org.eclipse.emf.transaction.TransactionalEditingDomain"> - </dependsOn> - </serviceFactory> - <service - classname="org.eclipse.papyrus.infra.gmfdiag.common.DefaultGraphicalEditorSupport" - description="The default diagram editor support implementation." - id="org.eclipse.papyrus.infra.gmfdiag.common.IGraphicalEditorSupport" - priority="1" - startKind="lazy"> - </service> - </extension> <extension - point="org.eclipse.papyrus.infra.services.labelprovider.labelProvider"> - <labelProvider - priority="40" - provider="org.eclipse.papyrus.infra.gmfdiag.common.providers.NotationFilteredLabelProvider"> - </labelProvider> + point="org.eclipse.papyrus.infra.services.decoration.decorationSpecificFunctions"> + <client + class="org.eclipse.papyrus.infra.gmfdiag.common.decoration.ExternalReferenceDecoration" + decorationType="org.eclipse.papyrus.infra.gmfdiag.common.externalref"> + </client> </extension> <extension - point="org.eclipse.gmf.runtime.diagram.ui.decoratorProviders"> - <decoratorProvider - class="org.eclipse.papyrus.infra.gmfdiag.common.providers.ShapeDecoratorProvider"> + point="org.eclipse.gmf.runtime.diagram.ui.editpolicyProviders"> + <editpolicyProvider + class="org.eclipse.papyrus.infra.gmfdiag.common.providers.ExternalReferenceEditPolicyProvider"> <Priority name="Lowest"> </Priority> - </decoratorProvider> -</extension> -<extension - point="org.eclipse.core.runtime.adapters"> - <factory - adaptableType="org.eclipse.gmf.runtime.notation.Diagram" - class="org.eclipse.papyrus.infra.gmfdiag.common.adapter.DiagramAdapterFactory"> - <adapter - type="org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.IOpenable"> - </adapter> - </factory> -</extension> - -<!-- ElementType bindings for diagram duplication with paste command --> - <extension - point="org.eclipse.gmf.runtime.emf.type.core.elementTypes"> - <metamodel - nsURI="http://www.eclipse.org/emf/2002/Ecore"> - <adviceBinding - class="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice" - id="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice" - inheritance="none" - typeId="*"> - </adviceBinding> - </metamodel> - </extension> - -<extension point="org.eclipse.gmf.runtime.emf.type.core.elementTypeBindings"> - - <!-- Bindings declaration --> - <binding context="org.eclipse.papyrus.infra.services.edit.TypeContext"> - <advice ref="org.eclipse.papyrus.infra.gmfdiag.common.advice.GMFDiagramDuplicateEditHelperAdvice" /> - </binding> -</extension> -<extension - point="org.eclipse.core.expressions.propertyTesters"> - <propertyTester - class="org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramPropertyTester" - id="org.eclipse.papyrus.infra.gmfdiag.common.diagram.tester" - namespace="org.eclipse.papyrus.infra.gmfdiag.common.diagram.tester" - properties="isDiagramEditor" - type="org.eclipse.jface.viewers.IStructuredSelection"> - </propertyTester> - <propertyTester - class="org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramPropertyTester" - id="org.eclipse.papyrus.infra.gmfdiag.common.diagram.context.tester" - namespace="org.eclipse.papyrus.infra.gmfdiag.common.diagram.context.tester" - properties="isGmfDiagramContextActive" - type="java.util.Collection"> - </propertyTester> -</extension> -<extension - point="org.eclipse.papyrus.infra.gmfdiag.common.shapeProvider"> - <shapeProvider - class="org.eclipse.papyrus.infra.gmfdiag.common.providers.StyleBasedShapeProvider" - description="Provides shapes based on the applied styles." - id="org.eclipse.papyrus.infra.gmfdiag.common.providers.StyleBasedShapeProvider" - name="StyleBasedShapeProvider"> - <Priority - name="Low"></Priority> - </shapeProvider> -</extension> + </editpolicyProvider> +</extension>
<extension
- point="org.eclipse.papyrus.infra.gmfdiag.common.notationTypesMapping">
- <mapping
- humanReadableType="symbol"
- type="compartment_shape_display">
- </mapping>
+ point="org.eclipse.papyrus.infra.gmfdiag.commands.historyListeners">
+ <historyListener
+ class="org.eclipse.papyrus.infra.gmfdiag.common.listener.RollbackNotificationHistoryListener">
+ </historyListener>
</extension>
-</plugin> +</plugin>
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/advice/GMFDiagramDuplicateEditHelperAdvice.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/advice/GMFDiagramDuplicateEditHelperAdvice.java index 202080c4135..7868a3d49df 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/advice/GMFDiagramDuplicateEditHelperAdvice.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/advice/GMFDiagramDuplicateEditHelperAdvice.java @@ -1,6 +1,6 @@ /*****************************************************************************
* Copyright (c) 2011 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
@@ -24,7 +24,6 @@ import java.util.Set; import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.resource.Resource;
@@ -41,10 +40,9 @@ import org.eclipse.gmf.runtime.emf.type.core.requests.DuplicateElementsRequest; import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
-import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
+import org.eclipse.papyrus.infra.core.resource.sasheditor.SashModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
import org.eclipse.papyrus.infra.core.services.ServiceException;
-import org.eclipse.papyrus.infra.core.utils.EditorUtils;
import org.eclipse.papyrus.infra.emf.commands.IPapyrusDuplicateCommandConstants;
import org.eclipse.papyrus.infra.emf.utils.BusinessModelResolver;
import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResource;
@@ -70,7 +68,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic Set<Object> duplicatedObjects = ((Set<Object>)additional);
EObject object = getDuplicatedEObject(request);
- if(object == null || object.eResource()==null) {
+ if(object == null || object.eResource() == null) {
return super.getBeforeDuplicateCommand(request);
}
@@ -142,7 +140,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Returns the EObject to be duplicated
- *
+ *
* @return the EObject to be duplicated
*/
protected EObject getDuplicatedEObject(DuplicateElementsRequest request) {
@@ -168,7 +166,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Constructs a new duplicate EObjects command with the specified label and
* list of EObjects.
- *
+ *
* @param editingDomain
* the editing domain through which model changes are made
* @param label
@@ -184,7 +182,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Constructs a new duplicate EObjects command with the specified label and
* list of EObjects.
- *
+ *
* @param editingDomain
* the editing domain through which model changes are made
* @param label
@@ -204,7 +202,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic * list of EObjects. Also sets the list of affected files to be the files,
* where the targetContainer is stored. Target container specifies the
* eObject into which the duplicated eObjects will be added.
- *
+ *
* @param editingDomain
* the editing domain through which model changes are made
* @param label
@@ -235,15 +233,15 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic EObject duplicateDiagram = copier.get(diagramToDuplicate);
Resource targetResource = getNotationResourceForDiagram(((Diagram)duplicateDiagram).getElement(), getEditingDomain());
Resource diTargetResource = getDiResourceForDiagram(((Diagram)duplicateDiagram).getElement(), getEditingDomain());
-
+
if(targetResource != null) {
targetResource.getContents().add(duplicateDiagram);
-
- if(diTargetResource !=null) {
+
+ if(diTargetResource != null) {
try {
- IPageManager pageManager = ServiceUtilsForResource.getInstance().getIPageManager(diTargetResource);
- pageManager.addPage(duplicateDiagram);
- } catch(ServiceException e) {
+ IPageManager pageManager = ServiceUtilsForResource.getInstance().getIPageManager(diTargetResource);
+ pageManager.addPage(duplicateDiagram);
+ } catch (ServiceException e) {
Activator.log.error(e);
}
} else {
@@ -255,11 +253,11 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic if(targetResource != null) {
Activator.log.error("It was not possible to find the Resource with the source diagram", null);
targetResource.getContents().add(duplicateDiagram);
- if(diTargetResource !=null) {
+ if(diTargetResource != null) {
try {
- IPageManager pageManager = ServiceUtilsForResource.getInstance().getIPageManager(diTargetResource);
- pageManager.addPage(duplicateDiagram);
- } catch(ServiceException e) {
+ IPageManager pageManager = ServiceUtilsForResource.getInstance().getIPageManager(diTargetResource);
+ pageManager.addPage(duplicateDiagram);
+ } catch (ServiceException e) {
Activator.log.error(e);
}
} else {
@@ -279,7 +277,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Returns the notation resource where to add the new diagram
- *
+ *
* @param eObject
* the semantic object linked to the diagram or the diagram itself.
* @param domain
@@ -295,25 +293,27 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic } else {
semanticObject = (EObject)object;
}
-
+
Resource containerResource = semanticObject.eResource();
- if(containerResource == null) {
+ if(containerResource == null) {
return null;
}
// retrieve the model set from the container resource
ResourceSet resourceSet = containerResource.getResourceSet();
-
+
if(resourceSet instanceof ModelSet) {
ModelSet modelSet = (ModelSet)resourceSet;
Resource destinationResource = modelSet.getAssociatedResource(semanticObject, NotationModel.NOTATION_FILE_EXTENSION, true);
return destinationResource;
- } else throw new RuntimeException("Resource Set is not a ModelSet or is null");
+ } else {
+ throw new RuntimeException("Resource Set is not a ModelSet or is null");
+ }
}
-
+
/**
* Returns the di resource where to add the new diagram
- *
+ *
* @param eObject
* the semantic object linked to the diagram or the diagram itself.
* @param domain
@@ -328,21 +328,23 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic } else {
semanticObject = (EObject)object;
}
-
+
Resource containerResource = semanticObject.eResource();
- if(containerResource == null) {
+ if(containerResource == null) {
return null;
}
// retrieve the model set from the container resource
ResourceSet resourceSet = containerResource.getResourceSet();
-
+
if(resourceSet instanceof ModelSet) {
ModelSet modelSet = (ModelSet)resourceSet;
- Resource destinationResource = modelSet.getAssociatedResource(semanticObject, DiModel.DI_FILE_EXTENSION, true);
+ Resource destinationResource = modelSet.getAssociatedResource(semanticObject, SashModel.MODEL_FILE_EXTENSION, true);
return destinationResource;
- } else throw new RuntimeException("Resource Set is not a ModelSet or is null");
+ } else {
+ throw new RuntimeException("Resource Set is not a ModelSet or is null");
+ }
}
-
+
/**
* Copier for diagrams, where only views and internal references are duplicated, not the semantic elements themselves.
*/
@@ -356,7 +358,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Creates a new {@link DiagramCopier}
- *
+ *
* @param semanticObjects
* list of semantic objects already copied, to which new views should be related.
*/
@@ -366,7 +368,7 @@ public class GMFDiagramDuplicateEditHelperAdvice extends AbstractEditHelperAdvic /**
* Overrides the get to look in the map of duplicated semantic objects in case the element was not found in this map
- *
+ *
* {@inheritDoc}
*/
@Override
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/databinding/custom/AbstractCustomStyleObservableValue.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/databinding/custom/AbstractCustomStyleObservableValue.java index af7a984bf13..406b4a0f6cf 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/databinding/custom/AbstractCustomStyleObservableValue.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/databinding/custom/AbstractCustomStyleObservableValue.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,11 +8,14 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.common.databinding.custom;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.core.databinding.observable.value.ValueDiff;
import org.eclipse.emf.common.command.Command;
@@ -31,7 +34,7 @@ import org.eclipse.papyrus.uml.tools.databinding.CommandBasedObservableValue; * @author Camille Letavernier
*
*/
-public abstract class AbstractCustomStyleObservableValue extends AbstractObservableValue implements CommandBasedObservableValue, IChangeListener {
+public abstract class AbstractCustomStyleObservableValue extends AbstractObservableValue implements CommandBasedObservableValue, IChangeListener, IObserving {
protected View source;
@@ -104,6 +107,11 @@ public abstract class AbstractCustomStyleObservableValue extends AbstractObserva public Command getCommand(Object value) {
return new CustomStyleValueCommand(source, value, styleClass, styleFeature, styleName);
}
+
+ @Override
+ public Object getObserved() {
+ return source;
+ }
@Override
public void dispose() {
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceDecoration.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceDecoration.java new file mode 100644 index 00000000000..09e5a6d68af --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceDecoration.java @@ -0,0 +1,70 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.decoration;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.papyrus.infra.gmfdiag.common.Activator;
+import org.eclipse.papyrus.infra.services.decoration.IDecorationSpecificFunctions;
+import org.eclipse.papyrus.infra.services.decoration.util.Decoration.PreferedPosition;
+import org.eclipse.papyrus.infra.services.decoration.util.IPapyrusDecoration;
+import org.eclipse.papyrus.infra.services.markerlistener.IPapyrusMarker;
+
+/**
+ * A Decorator for GMF Shapes, which is displayed when the graphical container is different
+ * from the semantic container (i.e. highlight external references / imported elements)
+ *
+ * It is associated to the {@link ExternalReferenceMarker}
+ *
+ * @author Camille Letavernier
+ */
+public class ExternalReferenceDecoration implements IDecorationSpecificFunctions {
+
+ @Override
+ public MarkChildren supportsMarkerPropagation() {
+ //This marker should not be propagated
+ return null;
+ }
+
+ @Override
+ public IPapyrusDecoration markerPropagation(EList<IPapyrusDecoration> childDecorations) {
+ //This marker should not be propagated
+ return null;
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptorForGE(IPapyrusMarker marker) {
+ return org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImageDescriptor(Activator.ID, "icons/shortcut.gif"); //$NON-NLS-1$
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptorForME(IPapyrusMarker marker) {
+ //This decorator only applies to GMF elements
+ return null;
+ }
+
+ @Override
+ public PreferedPosition getPreferedPosition(IPapyrusMarker marker) {
+ return PreferedPosition.NORTH_EAST;
+ }
+
+ @Override
+ public String getMessage(IPapyrusMarker marker) {
+ return "This element is imported";
+ }
+
+ @Override
+ public int getPriority(IPapyrusMarker marker) {
+ return 0;
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceMarker.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceMarker.java new file mode 100644 index 00000000000..ee3084b585d --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceMarker.java @@ -0,0 +1,135 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.decoration;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
+import org.eclipse.papyrus.infra.services.markerlistener.IPapyrusMarker;
+
+/**
+ * An IPapyrusMarker for GMF Shapes, which is activated when the graphical container is different
+ * from the semantic container (i.e. highlight external references / imported elements)
+ *
+ * This marker is volatile (created/deleted by EditPolicies on EditParts). It cannot be removed directly by the user
+ *
+ * @author Camille Letavernier
+ *
+ * @see {@link org.eclipse.papyrus.infra.gmfdiag.common.decoration.ExternalReferenceDecoration}
+ * @see {@link org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.ExternalReferenceEditPolicy}
+ */
+public class ExternalReferenceMarker implements IPapyrusMarker {
+
+ public static final String MARKER_TYPE = "org.eclipse.papyrus.infra.gmfdiag.common.externalref"; //$NON-NLS-1$
+
+ protected View notationElement;
+
+ public ExternalReferenceMarker(View notationElement) {
+ this.notationElement = notationElement;
+ }
+
+ @Override
+ public Resource getResource() {
+ return notationElement.eResource();
+ }
+
+ @Override
+ public EObject getEObject() {
+ return notationElement;
+ }
+
+ @Override
+ public boolean exists() {
+ return NotationHelper.isExternalRef(notationElement);
+ }
+
+ @Override
+ public String getType() throws CoreException {
+ return MARKER_TYPE;
+ }
+
+ @Override
+ public String getTypeLabel() throws CoreException {
+ return "External reference";
+ }
+
+ @Override
+ public void delete() throws CoreException {
+ //Do nothing: the user cannot manually remove the marker
+ }
+
+
+ ///
+ //The marker doesn't have any attribute: default implementation does nothing
+ ///
+
+ @Override
+ public Object getAttribute(String name) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public String getAttribute(String name, String defaultValue) {
+ return defaultValue;
+ }
+
+ @Override
+ public boolean getAttribute(String name, boolean defaultValue) {
+ return defaultValue;
+ }
+
+ @Override
+ public int getAttribute(String name, int defaultValue) {
+ return defaultValue;
+ }
+
+ @Override
+ public Map<String, ?> getAttributes() throws CoreException {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isSubtypeOf(String type) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) throws CoreException {
+ //Nothing
+ }
+
+ @Override
+ public void setAttribute(String name, String value) throws CoreException {
+ //Nothing
+ }
+
+ @Override
+ public void setAttribute(String name, boolean value) throws CoreException {
+ //Nothing
+ }
+
+ @Override
+ public void setAttribute(String name, int value) throws CoreException {
+ //Nothing
+ }
+
+ @Override
+ public void setAttributes(Map<String, ?> attributes) throws CoreException {
+ //Nothing
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/ConnectionEditPart.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/ConnectionEditPart.java index 8c916fd9450..4b51871b97b 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/ConnectionEditPart.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/ConnectionEditPart.java @@ -1,6 +1,6 @@ /*****************************************************************************
* 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
@@ -44,6 +44,16 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen */
protected static final String LINE_DASH_GAP = "lineDashGap";
+ /**
+ * Minimum length of dashes for dashed connectors
+ */
+ protected static final int LINE_DASH_MIN_LENGTH = 2;
+
+ /**
+ * Minimum length of the gapas between dashes
+ */
+ protected static final int LINE_GAP_MIN_LENGTH = 2;
+
public ConnectionEditPart(View view) {
super(view);
}
@@ -56,14 +66,14 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen super.refresh();
IFigure figure = this.getFigure();
Object model = this.getModel();
- if (figure instanceof PapyrusEdgeFigure && model instanceof Connector) {
- Connector connector = (Connector) model;
- PapyrusEdgeFigure edge = (PapyrusEdgeFigure) figure;
- String lineStyle = extract((StringValueStyle) connector.getNamedStyle(NotationPackage.eINSTANCE.getStringValueStyle(), LINE_STYLE));
- int lineDashLength = extract((IntValueStyle) connector.getNamedStyle(NotationPackage.eINSTANCE.getIntValueStyle(), LINE_DASH_LENGTH));
- int lineDashGap = extract((IntValueStyle) connector.getNamedStyle(NotationPackage.eINSTANCE.getIntValueStyle(), LINE_DASH_GAP));
- if (lineStyle != null) {
- setupLineStyle(edge, lineStyle, connector.getLineWidth(), lineDashLength, lineDashGap);
+ if(figure instanceof PapyrusEdgeFigure && model instanceof Connector) {
+ Connector connector = (Connector)model;
+ PapyrusEdgeFigure edge = (PapyrusEdgeFigure)figure;
+ String lineStyle = extract((StringValueStyle)connector.getNamedStyle(NotationPackage.eINSTANCE.getStringValueStyle(), LINE_STYLE));
+ int lineDashLength = extract((IntValueStyle)connector.getNamedStyle(NotationPackage.eINSTANCE.getIntValueStyle(), LINE_DASH_LENGTH));
+ int lineDashGap = extract((IntValueStyle)connector.getNamedStyle(NotationPackage.eINSTANCE.getIntValueStyle(), LINE_DASH_GAP));
+ if(lineStyle != null) {
+ setupLineStyle(edge, lineStyle, connector.getLineWidth(), lineDashLength < LINE_DASH_MIN_LENGTH ? LINE_DASH_MIN_LENGTH : lineDashLength, lineDashGap < LINE_GAP_MIN_LENGTH ? LINE_GAP_MIN_LENGTH : lineDashGap);
} else {
edge.resetStyle();
}
@@ -72,13 +82,13 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen /**
* Extracts the primitive value from the given style
- *
+ *
* @param style
- * The style
+ * The style
* @return The primitive value
*/
private String extract(StringValueStyle style) {
- if (style == null || style.getStringValue() == null || style.getStringValue().isEmpty()) {
+ if(style == null || style.getStringValue() == null || style.getStringValue().isEmpty()) {
return null;
}
return style.getStringValue();
@@ -86,13 +96,13 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen /**
* Extracts the primitive value from the given style
- *
+ *
* @param style
- * The style
+ * The style
* @return The primitive value
*/
private int extract(IntValueStyle style) {
- if (style == null) {
+ if(style == null) {
return 0;
}
return style.getIntValue();
@@ -100,37 +110,37 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen /**
* Setups the line style of the edge according to the given CSS style
- *
+ *
* @param edge
- * The shape to setup
+ * The shape to setup
* @param style
- * The CSS style
+ * The CSS style
* @param originalWidth
- * Original width of the connector
+ * Original width of the connector
* @param lineDashLength
- * Length of the dashes
+ * Length of the dashes
* @param lineDashGap
- * Length of the gap between dashes
+ * Length of the gap between dashes
*/
private void setupLineStyle(PapyrusEdgeFigure edge, String style, int originalWidth, int lineDashLength, int lineDashGap) {
- if ("none".equals(style)) {
+ if("none".equals(style)) {
edge.resetStyle();
} else {
- if ("hidden".equals(style)) {
+ if("hidden".equals(style)) {
edge.setLineStyle(Graphics.LINE_SOLID);
edge.setLineWidth(0);
edge.setVisible(false);
- } else if ("dotted".equals(style)) {
+ } else if("dotted".equals(style)) {
edge.setLineStyle(Graphics.LINE_DOT);
edge.setLineWidth(originalWidth);
- } else if ("dashed".equals(style)) {
+ } else if("dashed".equals(style)) {
edge.setLineStyle(Graphics.LINE_CUSTOM);
edge.setLineWidth(originalWidth);
- edge.setLineDash(new int[] { lineDashLength, lineDashGap });
- } else if ("solid".equals(style)) {
+ edge.setLineDash(new int[]{ lineDashLength, lineDashGap });
+ } else if("solid".equals(style)) {
edge.setLineStyle(Graphics.LINE_SOLID);
edge.setLineWidth(originalWidth);
- } else if ("double".equals(style)) {
+ } else if("double".equals(style)) {
edge.setLineWidth(originalWidth * 2);
}
}
@@ -139,9 +149,9 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen /**
- *
+ *
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart#createDefaultEditPolicies()
- *
+ *
*/
@Override
protected void createDefaultEditPolicies() {
@@ -149,4 +159,10 @@ public abstract class ConnectionEditPart extends ConnectionNodeEditPart implemen installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE, new PapyrusConnectionEndEditPolicy());
}
+ @Override
+ protected void refreshVisuals() {
+ super.refreshVisuals();
+ refreshLineWidth();
+ installRouter();
+ }
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/IControlParserForDirectEdit.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/IControlParserForDirectEdit.java new file mode 100644 index 00000000000..e4445f56796 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/IControlParserForDirectEdit.java @@ -0,0 +1,32 @@ +/***************************************************************************** + * Copyright (c) 2014 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: + * Ansgar Radermacher (CEA LIST) - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.gmfdiag.common.editpart; + +import org.eclipse.gmf.runtime.common.ui.services.parser.IParser; + + +/** + * Direct editors install their own parser. The objective of this interface is + * to reset a parser within an edit part, once a direct editor is stopped. + * This will restore the original parser + */ +public interface IControlParserForDirectEdit { + /** + * install a new parser + * @param parser + */ + public void setParser(IParser parser); +} + diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ExternalReferenceEditPolicy.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ExternalReferenceEditPolicy.java new file mode 100644 index 00000000000..3e73b38c62b --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ExternalReferenceEditPolicy.java @@ -0,0 +1,121 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.editpolicies;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.GraphicalEditPolicyEx;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.gmfdiag.common.Activator;
+import org.eclipse.papyrus.infra.gmfdiag.common.decoration.ExternalReferenceMarker;
+import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.ServiceUtilsForEditPart;
+import org.eclipse.papyrus.infra.services.decoration.DecorationService;
+import org.eclipse.papyrus.infra.services.markerlistener.IPapyrusMarker;
+
+/**
+ * A generic EditPolicy which applies {@link ExternalReferenceMarker} to EditParts when they have been imported
+ * (According to {@link NotationHelper#isExternalRef(View)}
+ *
+ * @author Camille Letavernier
+ *
+ */
+//Rely on the GraphicalEditPolicyEx, which is less expensive than adding a listener to detect changes in the containment tree
+@SuppressWarnings("restriction")
+public class ExternalReferenceEditPolicy extends GraphicalEditPolicyEx {
+
+ /**
+ * The Edit Policy Role/ID
+ */
+ public static final Object EDIT_POLICY_ROLE = Activator.ID + ".externalReferenceDecorator"; //$NON-NLS-1$
+
+ /**
+ * Last known value for isExternalReference
+ */
+ protected boolean isExternalReference = false;
+
+ protected DecorationService decorationService;
+
+ protected IPapyrusMarker marker;
+
+ protected Adapter listener;
+
+ @Override
+ public void activate() {
+ super.activate();
+
+ try {
+ decorationService = ServiceUtilsForEditPart.getInstance().getService(DecorationService.class, getHost());
+ refresh();
+ } catch (ServiceException ex) {
+ Activator.log.error(ex);
+ }
+ }
+
+ @Override
+ public void refresh() {
+ if(getView() == null) {
+ return;
+ }
+ if(decorationService == null) {
+ return;
+ }
+
+ //Add or remove the decoration when the current value is different from the last known value
+ if(NotationHelper.isExternalRef(getView()) != isExternalReference) {
+ isExternalReference = !isExternalReference;
+ if(isExternalReference) {
+ decorationService.addDecoration(getMarker(), getView());
+ } else {
+ decorationService.removeDecoration(getMarker().toString());
+ }
+ //We need to call refresh again, so that the decorator gets display.
+ //We shouldn't end up with a StackOverFlow, because we arrive here only when the "isExternalRef" value changes
+ getHost().refresh();
+ }
+ }
+
+ /**
+ * Returns the marker instance. It is never null
+ *
+ * @return
+ */
+ protected IPapyrusMarker getMarker() {
+ if(marker == null) {
+ marker = new ExternalReferenceMarker(getView());
+ }
+ return marker;
+ }
+
+ /**
+ * Return the view associated to this edit policy
+ *
+ * @return
+ */
+ protected View getView() {
+ return (View)getHost().getModel();
+ }
+
+ @Override
+ public void deactivate() {
+ super.deactivate();
+
+ if(marker != null && decorationService != null) {
+ //Remove the marker from the View to avoid duplication
+ decorationService.removeDecoration(getMarker().toString());
+ isExternalReference = false;
+ }
+
+ marker = null;
+ decorationService = null;
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/PapyrusResizableShapeEditPolicy.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/PapyrusResizableShapeEditPolicy.java index f5c83a5c8c4..134a94ffbf3 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/PapyrusResizableShapeEditPolicy.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/PapyrusResizableShapeEditPolicy.java @@ -13,27 +13,34 @@ *****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.common.editpolicies;
+import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.tools.ResizeTracker;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableShapeEditPolicy;
+import org.eclipse.papyrus.infra.gmfdiag.common.snap.ResizeTrackerWithPreferences;
/**
- *
+ *
* See Bug 424943 ResizableEditPolicy#getResizeCommand duplicates request ignoring some request values
- * TODO : remove this class when the bug will be fixed
+ *
*/
public class PapyrusResizableShapeEditPolicy extends ResizableShapeEditPolicy {
/**
+ * See Bug 424943 ResizableEditPolicy#getResizeCommand duplicates request ignoring some request values
+ * TODO : remove this override when the bug will be fixed
+ *
* Returns the command contribution for the given resize request. By
* default, the request is re-dispatched to the host's parent as a {@link org.eclipse.gef.RequestConstants#REQ_RESIZE_CHILDREN}. The
* parent's edit policies determine how to perform the resize based on the
* layout manager in use.
- *
+ *
* @param request
* the resize request
* @return the command contribution obtained from the parent
*/
+
@Override
protected Command getResizeCommand(ChangeBoundsRequest request) {
ChangeBoundsRequest req = new ChangeBoundsRequest(REQ_RESIZE_CHILDREN);
@@ -56,4 +63,16 @@ public class PapyrusResizableShapeEditPolicy extends ResizableShapeEditPolicy { return getHost().getParent().getCommand(req);
}
+ /**
+ *
+ * @see org.eclipse.gef.editpolicies.ResizableEditPolicy#getResizeTracker(int)
+ *
+ * @param direction
+ * @return
+ */
+ @Override
+ protected ResizeTracker getResizeTracker(int direction) {
+ return new ResizeTrackerWithPreferences((GraphicalEditPart)getHost(), direction);
+ }
+
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ShapeCompartmentEditPolicy.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ShapeCompartmentEditPolicy.java index 88fea4dcf86..a1120a7e39a 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ShapeCompartmentEditPolicy.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ShapeCompartmentEditPolicy.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 2014 CEA LIST and others.
*
- *
* 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
@@ -9,19 +8,14 @@ *
* Contributors:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.common.editpolicies;
-import java.util.HashMap;
-import java.util.Map;
-
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
-import org.eclipse.emf.transaction.impl.InternalTransaction;
-import org.eclipse.emf.transaction.impl.InternalTransactionalEditingDomain;
import org.eclipse.gef.editpolicies.GraphicalEditPolicy;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
@@ -35,6 +29,7 @@ import org.eclipse.papyrus.infra.gmfdiag.common.commands.SetNodeVisibilityComman import org.eclipse.papyrus.infra.gmfdiag.common.editpart.IShapeCompartmentEditPart;
import org.eclipse.papyrus.infra.gmfdiag.common.service.shape.NotificationManager;
import org.eclipse.papyrus.infra.gmfdiag.common.service.shape.ShapeService;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafe;
import org.eclipse.swt.widgets.Display;
/**
@@ -121,68 +116,15 @@ public class ShapeCompartmentEditPolicy extends GraphicalEditPolicy implements N */
protected void executeShapeCompartmentCreation(final IGraphicalEditPart editPart) {
try {
- // getEditingDomain(editPart).runExclusive(new Runnable() {
-
- /**
- * {@inheritDoc}
- */
- // public void run() {
- Display.getCurrent().syncExec(new Runnable() {
-
- /**
- * {@inheritDoc}
- */
- public void run() {
- //boolean isVisible = hasToDisplayCompartment(editPart.getNotationView());
- CreateShapeCompartmentViewCommand command = new CreateShapeCompartmentViewCommand(getEditingDomain(editPart), "Create Compartment", "Command that creates the compartment displaying shapes", editPart.getNotationView(), /* isVisible */false);
- Map<String, Boolean> options = new HashMap<String, Boolean>();
- //options.put(Transaction.OPTION_UNPROTECTED, Boolean.TRUE);
- try {
- //This should not change the command stack, as this transaction will only manipulate transient views. Create a transaction manually, if needed
- InternalTransactionalEditingDomain editingDomain = (InternalTransactionalEditingDomain)editPart.getEditingDomain();
- InternalTransaction activeTransaction = editingDomain.getActiveTransaction();
- if(activeTransaction != null && activeTransaction.isActive()) {
- if(activeTransaction.isReadOnly()) {
- //We're in a read-only active transaction (e.g. post-commit).
- //Typical case: We create a new gmf::View in a transaction.
- //The transaction has been committed, and the edit part is being created during the post-commit
- //post-commit is read-only. We cannot create a read-write transaction in this state, so we need
- //to deactive the read-only transaction first.
-
- try {
- //Deactivate the read-only transaction
- editingDomain.deactivate(activeTransaction);
-
- //Start a new read-write transaction
- InternalTransaction it = editingDomain.startTransaction(false, options);
- command.execute();
- it.commit();
- } finally {
- //Reactive the read-only transaction
- editingDomain.activate(activeTransaction);
- }
-
- } else {
- //We're already in an active read-write transaction. Simply execute the command
- //Never happens?
- command.execute();
- }
- } else {
- //We're not in a transaction. Start a new read-write transaction
- //Typical case: opening the diagram
- InternalTransaction it = editingDomain.startTransaction(false, options);
- command.execute();
- it.commit();
- }
-
- } catch (Exception e) {
- Activator.log.error(e);
- }
- // editPart.getEditingDomain().getCommandStack().execute(command);
- }
- });
- // }
- // });
+ //boolean isVisible = hasToDisplayCompartment(editPart.getNotationView());
+ TransactionalEditingDomain domain = getEditingDomain(editPart);
+ CreateShapeCompartmentViewCommand command = new CreateShapeCompartmentViewCommand(domain, "Create Compartment", "Command that creates the compartment displaying shapes", editPart.getNotationView(), /* isVisible */false);
+ try {
+ //This should not change the command stack, as this transaction will only manipulate transient views. Create a transaction manually, if needed
+ GMFUnsafe.write(domain, command);
+ } catch (Exception e) {
+ Activator.log.error(e);
+ }
} catch (Exception e) {
Activator.log.error(e);
}
@@ -261,32 +203,19 @@ public class ShapeCompartmentEditPolicy extends GraphicalEditPolicy implements N * the stereotype application
*/
protected void setVisibility(final View view, final boolean isVisible) {
- try {
- final GraphicalEditPart editPart = (GraphicalEditPart)getHost();
- editPart.getEditingDomain().runExclusive(new Runnable() {
-
- public void run() {
- Display.getCurrent().asyncExec(new Runnable() {
-
- public void run() {
- SetNodeVisibilityCommand setCommand = new SetNodeVisibilityCommand(editPart.getEditingDomain(), view, isVisible);
- //use to avoid to put it in the command stack
- Map<String, Boolean> options = new HashMap<String, Boolean>();
- options.put(Transaction.OPTION_UNPROTECTED, Boolean.TRUE);
- try {
- InternalTransaction it = ((InternalTransactionalEditingDomain)editPart.getEditingDomain()).startTransaction(false, options);
- setCommand.execute();
- it.commit();
- } catch (Exception e) {
- Activator.log.error(e);
- }
- }
- });
+ final GraphicalEditPart editPart = (GraphicalEditPart)getHost();
+ Display.getCurrent().asyncExec(new Runnable() {
+
+ public void run() {
+ SetNodeVisibilityCommand setCommand = new SetNodeVisibilityCommand(editPart.getEditingDomain(), view, isVisible);
+ //use to avoid to put it in the command stack
+ try {
+ GMFUnsafe.write(editPart.getEditingDomain(), setCommand);
+ } catch (Exception e) {
+ Activator.log.error(e);
}
- });
- } catch (Exception e) {
- Activator.log.error(e);
- }
+ }
+ });
}
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/XYLayoutWithConstrainedResizedEditPolicy.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/XYLayoutWithConstrainedResizedEditPolicy.java index 87d508506f5..aa77b8fa7f1 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/XYLayoutWithConstrainedResizedEditPolicy.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/XYLayoutWithConstrainedResizedEditPolicy.java @@ -86,24 +86,26 @@ public class XYLayoutWithConstrainedResizedEditPolicy extends XYLayoutEditPolicy double spacing = drep.getGridSpacing();
final double max_value = spacing * 20;
final SnapToHelper helper = (SnapToHelper)getHost().getAdapter(SnapToHelper.class);
- final LayoutHelper layoutHelper = new LayoutHelper();
- while(add < max_value) {//we define a max value to do test
- Rectangle LOCAL_BOUNDS = BOUNDS.getCopy();
- LOCAL_BOUNDS.translate(add, add);
- Rectangle tmp_rect = getBoundsOffest(req, LOCAL_BOUNDS, viewDescriptor);
- final PrecisionRectangle resultRect = new PrecisionRectangle(tmp_rect);
- resultRect.setWidth(-1);
- resultRect.setHeight(-1);
- PrecisionPoint res1 = new PrecisionPoint(tmp_rect.getLocation());
- helper.snapPoint(request, PositionConstants.NORTH_WEST, res1.getPreciseCopy(), res1);
- final Point pt = layoutHelper.validatePosition(getHostFigure(), resultRect.setLocation(res1));
- if(couldBeSnaped) {
- if(pt.equals(resultRect.getLocation())) {
- rect.setLocation(resultRect.getLocation());
- break;
- } else {
- add += spacing;
- continue;
+ if(helper != null) {
+ final LayoutHelper layoutHelper = new LayoutHelper();
+ while(add < max_value) {//we define a max value to do test
+ Rectangle LOCAL_BOUNDS = BOUNDS.getCopy();
+ LOCAL_BOUNDS.translate(add, add);
+ Rectangle tmp_rect = getBoundsOffest(req, LOCAL_BOUNDS, viewDescriptor);
+ final PrecisionRectangle resultRect = new PrecisionRectangle(tmp_rect);
+ resultRect.setWidth(-1);
+ resultRect.setHeight(-1);
+ PrecisionPoint res1 = new PrecisionPoint(tmp_rect.getLocation());
+ helper.snapPoint(request, PositionConstants.NORTH_WEST, res1.getPreciseCopy(), res1);
+ final Point pt = layoutHelper.validatePosition(getHostFigure(), resultRect.setLocation(res1));
+ if(couldBeSnaped) {
+ if(pt.equals(resultRect.getLocation())) {
+ rect.setLocation(resultRect.getLocation());
+ break;
+ } else {
+ add += spacing;
+ continue;
+ }
}
}
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/helper/NotationHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/helper/NotationHelper.java index 57f97aa5bb9..7d783690bec 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/helper/NotationHelper.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/helper/NotationHelper.java @@ -1,6 +1,6 @@ /*****************************************************************************
* 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
@@ -47,4 +47,42 @@ public class NotationHelper { }
return null;
}
+
+ /**
+ * Tests whether the given View is a reference to an external element.
+ * A view is an external reference if its graphical container is different from its semantic
+ * container (i.e. self.element.eContainer() != self.primaryView.eContainer().element)
+ *
+ * @param diagramElement
+ * @return
+ */
+ public static boolean isExternalRef(View diagramElement) {
+ if(diagramElement == null) {
+ return false;
+ }
+
+ View primaryView = SemanticElementHelper.findTopView(diagramElement);
+ if(primaryView == null) {
+ return false;
+ }
+
+ EObject semanticElement = primaryView.getElement();
+
+ if(semanticElement == null) {
+ return false;
+ }
+
+ EObject parentView = primaryView.eContainer();
+ if(!(parentView instanceof View)) {
+ return false;
+ }
+
+ EObject parentSemanticElement = ((View)parentView).getElement();
+ if(parentSemanticElement == null) {
+ return false;
+ }
+
+ //Relax the constraints for elements displayed on themselves (e.g. Frame in Composite Structure Diagram)
+ return parentSemanticElement != semanticElement.eContainer() && parentSemanticElement != semanticElement;
+ }
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/listener/RollbackNotificationHistoryListener.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/listener/RollbackNotificationHistoryListener.java new file mode 100644 index 00000000000..b14056758e8 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/listener/RollbackNotificationHistoryListener.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.gmfdiag.common.listener; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.commands.operations.IOperationHistoryListener; +import org.eclipse.core.commands.operations.IUndoableOperation; +import org.eclipse.core.commands.operations.OperationHistoryEvent; +import org.eclipse.core.commands.operations.TriggeredOperations; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.core.resource.IRollbackStatus; +import org.eclipse.papyrus.infra.core.resource.RollbackStatus; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.emf.providers.EMFLabelProvider; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResource; +import org.eclipse.papyrus.infra.gmfdiag.common.messages.Messages; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.ui.statushandlers.IStatusAdapterConstants; +import org.eclipse.ui.statushandlers.StatusAdapter; +import org.eclipse.ui.statushandlers.StatusManager; + + +/** + * An operation history listener that detects execution failures due to transaction rollback and presents dialogs to explain. + */ +public class RollbackNotificationHistoryListener implements IOperationHistoryListener { + + public RollbackNotificationHistoryListener() { + super(); + } + + public void historyNotification(OperationHistoryEvent event) { + switch(event.getEventType()) { + case OperationHistoryEvent.OPERATION_NOT_OK: + final long now = System.currentTimeMillis(); + + IRollbackStatus rollback = RollbackStatus.findRollbackStatus(event.getStatus()); + if(rollback == null) { + // Failure of a TriggeredOperations results in an event without a status + rollback = findRollbackStatus(event.getOperation()); + } + + if(rollback != null) { + Collection<?> causalObjects = rollback.getCausalObjects(); + Collection<String> labels = getObjectLabels(causalObjects); + + String message; + switch(rollback.getCode()) { + case IRollbackStatus.UNCAUGHT_EXCEPTION: + message = labels.isEmpty() ? Messages.RollbackNotificationHistoryListener_exception : NLS.bind(Messages.RollbackNotificationHistoryListener_exceptionWithCause, labels); + break; + case IRollbackStatus.READ_ONLY_OBJECT: + message = labels.isEmpty() ? Messages.RollbackNotificationHistoryListener_readOnly : NLS.bind(Messages.RollbackNotificationHistoryListener_readOnlyWithCause, labels); + break; + default: + message = labels.isEmpty() ? Messages.RollbackNotificationHistoryListener_unknown : NLS.bind(Messages.RollbackNotificationHistoryListener_unknownWithCause, labels); + break; + } + + // Eclipse doesn't seem to use the status adapter explanation property, so we must create a new status with our message + StatusAdapter adapter = new StatusAdapter(new Status(rollback.getSeverity(), rollback.getPlugin(), rollback.getCode(), message, rollback.getException())); + adapter.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, Messages.RollbackNotificationHistoryListener_title); + adapter.setProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY, now); + + StatusManager.getManager().handle(adapter, StatusManager.SHOW); + } + break; + } + } + + protected List<String> getObjectLabels(Iterable<?> objects) { + List<String> result = new ArrayList<String>(); + ILabelProvider labels = null; + + try { + for(Object next : objects) { + if(labels == null) { + try { + LabelProviderService labelService = null; + if(next instanceof EObject) { + labelService = ServiceUtilsForEObject.getInstance().getService(LabelProviderService.class, (EObject)next); + } else if(next instanceof Resource) { + labelService = ServiceUtilsForResource.getInstance().getService(LabelProviderService.class, (Resource)next); + } + + if(labelService != null) { + labels = labelService.getLabelProvider(); + } + } catch (ServiceException e) { + // not in an editor context. Fine + labels = new EMFLabelProvider(); + } + } + + if(labels != null) { + result.add(labels.getText(next)); + } + } + } finally { + if(labels != null) { + labels.dispose(); + } + } + + return result; + } + + protected IRollbackStatus findRollbackStatus(IUndoableOperation operation) { + IRollbackStatus result = null; + + if(operation instanceof ICommand) { + CommandResult commandResult = ((ICommand)operation).getCommandResult(); + if(commandResult != null) { + result = RollbackStatus.findRollbackStatus(commandResult.getStatus()); + } + } else if(operation instanceof TriggeredOperations) { + // We can't get the children out of a generic ICompositeOperation, and from this one only the initial triggering operation + return findRollbackStatus(((TriggeredOperations)operation).getTriggeringOperation()); + } + + return result; + } +} diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/Messages.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/Messages.java index 912f239aac2..f12616652e3 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/Messages.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/Messages.java @@ -1,15 +1,16 @@ -/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
- *
- *
+/****************************************
+ * Copyright (c) 2013, 2014 CEA and others.
+ *
* 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:
- * Patrick Tessier (CEA LIST) - Initial API and implementation
- /*****************************************************************************/
+ * Vincent Lorenzo (CEA LIST) - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
+ */
package org.eclipse.papyrus.infra.gmfdiag.common.messages;
import org.eclipse.osgi.util.NLS;
@@ -18,11 +19,26 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.gmfdiag.common.messages.messages"; //$NON-NLS-1$
+ public static String RollbackNotificationHistoryListener_exception;
+
+ public static String RollbackNotificationHistoryListener_exceptionWithCause;
+
+ public static String RollbackNotificationHistoryListener_readOnly;
+
+ public static String RollbackNotificationHistoryListener_readOnlyWithCause;
+
+ public static String RollbackNotificationHistoryListener_title;
+
+ public static String RollbackNotificationHistoryListener_unknown;
+
+ public static String RollbackNotificationHistoryListener_unknownWithCause;
+
public static String UnitsUtils_Centimeters;
public static String UnitsUtils_Inches;
public static String UnitsUtils_Pixels;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/messages.properties b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/messages.properties index 1d8adde52ab..700f3e214d5 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/messages.properties +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/messages.properties @@ -1,3 +1,23 @@ +#
+# Copyright (c) 2013, 2014 CEA and others.
+#
+# 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) - Initial API and implementation
+# Christian W. Damus (CEA) - bug 323802
+#
+
+RollbackNotificationHistoryListener_exception=The operation was rolled back due to an uncaught exception.
+RollbackNotificationHistoryListener_exceptionWithCause=The operation was rolled back due to an uncaught exception relating to the following objects: {0}
+RollbackNotificationHistoryListener_readOnly=The operation was rolled back because it modified read-only objects.
+RollbackNotificationHistoryListener_readOnlyWithCause=The operation was rolled back because it modified read-only objects: {0}
+RollbackNotificationHistoryListener_title=Operation Rolled Back
+RollbackNotificationHistoryListener_unknown=The operation was rolled back for an unknown reason.
+RollbackNotificationHistoryListener_unknownWithCause=The operation was rolled back for an unknown reason relating to the following objects: {0}
UnitsUtils_Centimeters=Centimeters
UnitsUtils_Inches=Inches
UnitsUtils_Pixels=Pixels
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java index 1ff44b8c5a6..81b39f9a956 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java @@ -142,6 +142,9 @@ public class PreferencesConstantsHelper { public final static String DRAW_CONNECTION_POINT_CONSTANT = "drawConnectionPoint"; //$NON-NLS-1$
+ public final static String INVERT_BINDING_FOR_DEFAULT_RESIZE_AND_CONSTRAINED_RESIZE_CONSTANT = "invertBindingForDefaultResizeAndConstrainedResize"; //$NON-NLS-1$
+
+
/**
* A preference of type COLOR FILL
*/
@@ -308,12 +311,21 @@ public class PreferencesConstantsHelper { * A preference to view the page break on the diagram
*/
public static final int VIEW_PAGE_BREAK = GRID_LINE_STYLE + 1;
-
+
/**
* A preference to draw big point when 2 links have a common part
*/
- public static final int DRAW_CONNECTION_POINT = VIEW_PAGE_BREAK +1;
+ public static final int DRAW_CONNECTION_POINT = VIEW_PAGE_BREAK + 1;
+ /**
+ * A Papyrus preference to define the if the default resize action is constrained or not.
+ * if the preference is <code>false</code>
+ * <ul>
+ * <li>default resize is not constraint</li>
+ * <li>resize + SHIFT is constrained</li>
+ * </ul>
+ */
+ public static final int INVERT_BINDING_FOR_DEFAULT_RESIZE_AND_CONSTRAINED_RESIZE = DRAW_CONNECTION_POINT + 1;
/**
* Get the preference constant used to store the preference of an element.
@@ -428,7 +440,7 @@ public class PreferencesConstantsHelper { break;
case VIEW_PAGE_BREAK:
sb.append(VIEW_PAGE_BREAK_CONSTANT);
- break; + break;
default:
break;
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/ExternalReferenceEditPolicyProvider.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/ExternalReferenceEditPolicyProvider.java new file mode 100644 index 00000000000..a210921bf6c --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/ExternalReferenceEditPolicyProvider.java @@ -0,0 +1,55 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.providers;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gmf.runtime.common.core.service.AbstractProvider;
+import org.eclipse.gmf.runtime.common.core.service.IOperation;
+import org.eclipse.gmf.runtime.diagram.ui.services.editpolicy.CreateEditPoliciesOperation;
+import org.eclipse.gmf.runtime.diagram.ui.services.editpolicy.IEditPolicyProvider;
+import org.eclipse.gmf.runtime.notation.Shape;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.ExternalReferenceEditPolicy;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.ServiceUtilsForEditPart;
+
+/**
+ * The EditPolicyProvider for {@link ExternalReferenceEditPolicy} It provides an {@link ExternalReferenceEditPolicy} for Papyrus edit parts, when the
+ * ServicesRegistry is available
+ * This edit policy in only installed on Shapes (Graphical Edges are typically owned by the Diagram, which makes it difficult
+ * to determine whether they are imported or not)
+ *
+ * @author Camille Letavernier
+ */
+public class ExternalReferenceEditPolicyProvider extends AbstractProvider implements IEditPolicyProvider {
+
+ @Override
+ public boolean provides(IOperation operation) {
+ if(operation instanceof CreateEditPoliciesOperation) {
+ CreateEditPoliciesOperation createOperation = (CreateEditPoliciesOperation)operation;
+ try {
+ if(ServiceUtilsForEditPart.getInstance().getServiceRegistry(createOperation.getEditPart()) != null) {
+ return createOperation.getEditPart().getModel() instanceof Shape;
+ }
+ } catch (ServiceException ex) {
+ //Do nothing: the services registry is not available.
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void createEditPolicies(EditPart editPart) {
+ editPart.installEditPolicy(ExternalReferenceEditPolicy.EDIT_POLICY_ROLE, new ExternalReferenceEditPolicy());
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/BorderNodeSnapHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/BorderNodeSnapHelper.java new file mode 100644 index 00000000000..503f835fce8 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/BorderNodeSnapHelper.java @@ -0,0 +1,36 @@ +/*****************************************************************************
+ * Copyright (c) 2014 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
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.snap;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.SnapToHelper;
+
+/**
+ *
+ * Snap Helper with default behavior for BorderNode (snap only on the center of the figrue
+ * TODO PapyrusDragBorderNodeEditPartTrackerEx should use me
+ */
+public class BorderNodeSnapHelper extends NodeSnapHelper {
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param helper
+ * @param figureToSnapBounds
+ */
+ public BorderNodeSnapHelper(SnapToHelper helper, Rectangle figureToSnapBounds) {
+ super(helper, figureToSnapBounds, false, false, true);
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/NodeSnapHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/NodeSnapHelper.java new file mode 100644 index 00000000000..329b6229324 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/NodeSnapHelper.java @@ -0,0 +1,459 @@ +/*****************************************************************************
+ * Copyright (c) 2013 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
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.gmfdiag.common.snap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.SnapToHelper;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.tools.DragEditPartsTracker;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToHelperUtil;
+
+/**
+ *
+ * this class allows to determine the best location for a node on the grid
+ *
+ * Adapted code from DragEditPartsTrackerEx
+ * TODO : PapyrusDragEditPartTracker should use me
+ */
+@SuppressWarnings("restriction")
+public class NodeSnapHelper {
+
+ /**
+ * if true, we snap on the four corner of the figures
+ */
+ protected final boolean snapOnCorners;
+
+ /**
+ * if true, we snap on the four middle side of the figures
+ */
+ protected final boolean snapOnMiddles;
+
+ /**
+ * if true, we snap on the center of the figure
+ */
+ protected final boolean snapOnCenter;
+
+ /**
+ * the snap helper to use
+ */
+ private SnapToHelper helper;
+
+ /**
+ * the bounds of the figure to snap
+ */
+ private Rectangle figureToSnapBounds;
+
+ /**
+ * the compoundSourceRectangle, see {@link DragEditPartsTracker} for further informations
+ */
+ private Rectangle compoundSourceRectangle;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param helper
+ * the snap helper
+ * @param figureToSnapBounds
+ * the bounds of the figure to snap
+ *
+ */
+ public NodeSnapHelper(final SnapToHelper helper, final Rectangle figureToSnapBounds) {
+ this(helper, figureToSnapBounds, figureToSnapBounds);
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param helper
+ * the snap helper
+ * @param figureToSnapBounds
+ * the bounds of the figure to snap
+ * @param compoundSourceRectangle
+ * see {@link DragEditPartsTracker} for further informations
+ */
+ public NodeSnapHelper(final SnapToHelper helper, final Rectangle figureToSnapBounds, final Rectangle compoundSourceRectangle) {
+ this(helper, figureToSnapBounds, compoundSourceRectangle, true, false, false);
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param helper
+ * @param figureToSnapBounds
+ * @param snapOnCorners
+ * @param snapOnMiddles
+ * @param snapOnCenter
+ */
+ public NodeSnapHelper(final SnapToHelper helper, final Rectangle figureToSnapBounds, final boolean snapOnCorners, final boolean snapOnMiddles, final boolean snapOnCenter) {
+ this(helper, figureToSnapBounds, figureToSnapBounds, snapOnCorners, snapOnMiddles, snapOnCenter);
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param helper
+ * @param figureToSnapBounds
+ * @param compoundSourceRectangle
+ * @param snapOnCorners
+ * @param snapOnMiddles
+ * @param snapOnCenter
+ */
+ public NodeSnapHelper(final SnapToHelper helper, final Rectangle figureToSnapBounds, final Rectangle compoundSourceRectangle, final boolean snapOnCorners, final boolean snapOnMiddles, final boolean snapOnCenter) {
+ this.helper = helper;
+ this.figureToSnapBounds = figureToSnapBounds;
+ this.compoundSourceRectangle = compoundSourceRectangle;
+ this.snapOnCorners = snapOnCorners;
+ this.snapOnMiddles = snapOnMiddles;
+ this.snapOnCenter = snapOnCenter;
+ }
+
+ /**
+ * This method can be overridden by clients to customize the snapping
+ * behavior.
+ *
+ * @param request
+ * the <code>ChangeBoundsRequest</code> from which the move delta
+ * can be extracted and updated
+ * We use <code>ChangeBoundsRequest</code> to be compatible with snap edit part tracker!
+ */
+ @SuppressWarnings({ "unchecked" })
+ public void snapPoint(ChangeBoundsRequest request) {
+ if(getSnapToHelper() != null && request.isSnapToEnabled()) {
+
+ //test to know if we are moving using keyboard
+ //TODO not useful here
+ // if(!getCurrentInput().isAnyButtonDown()) {
+ // calculateSnapPointFromArrowKey(request);
+ // return;
+ // }
+ int restrictedDirection = 0;
+ restrictedDirection = restrictedDirection | PositionConstants.EAST;
+ restrictedDirection = restrictedDirection | PositionConstants.WEST;
+ restrictedDirection = restrictedDirection | PositionConstants.SOUTH;
+ restrictedDirection = restrictedDirection | PositionConstants.NORTH;
+ request.getExtendedData().put(SnapToHelperUtil.RESTRICTED_DIRECTIONS, restrictedDirection);
+
+ final Map<Double, PrecisionPoint> distVSPoint = new HashMap<Double, PrecisionPoint>();
+ if(this.snapOnCorners) {
+ distVSPoint.putAll(getCornerDistances(request));
+ }
+
+ if(this.snapOnMiddles) {
+ distVSPoint.putAll(getMiddleDistances(request));
+ }
+
+ if(this.snapOnCenter) {
+ distVSPoint.putAll(getCenterDistances(request));
+ }
+
+ final List<Double> distances = new ArrayList<Double>(distVSPoint.keySet());
+ if(distances.size() > 0) {
+ double min = distances.get(0);
+ for(int i = 1; i < distances.size() - 1; i++) {
+ min = Math.min(min, distances.get(i));
+ }
+ request.setMoveDelta(distVSPoint.get(min));
+ }
+ }
+ }
+
+ /**
+ *
+ * @param request
+ * a move request
+ * @return
+ * the restricted direction for the request
+ */
+ protected final int getRestrictedDirection(final ChangeBoundsRequest request) {
+ int restrictedDirection = 0;
+ final Point delta = request.getMoveDelta();
+ if(delta.x > 0) {
+ restrictedDirection = restrictedDirection | PositionConstants.EAST;
+ restrictedDirection = restrictedDirection | PositionConstants.WEST;
+ }
+ if(delta.x < 0) {
+ restrictedDirection = restrictedDirection | PositionConstants.EAST;
+ restrictedDirection = restrictedDirection | PositionConstants.WEST;
+ }
+ if(delta.y > 0) {
+ restrictedDirection = restrictedDirection | PositionConstants.SOUTH;
+ restrictedDirection = restrictedDirection | PositionConstants.NORTH;
+ }
+ if(delta.y < 0) {
+ restrictedDirection = restrictedDirection | PositionConstants.SOUTH;
+ restrictedDirection = restrictedDirection | PositionConstants.NORTH;
+ }
+ return restrictedDirection;
+ }
+
+ /**
+ *
+ * @param request
+ * the move request
+ */
+ @SuppressWarnings("unchecked")
+ protected void calculateSnapPointFromArrowKey(final ChangeBoundsRequest request) {
+ if(request.getEditParts().size() == 0) {
+ return;
+ }
+ final Object ep = request.getEditParts().get(0);
+ if(!(ep instanceof IGraphicalEditPart)) {
+ return;
+ }
+ final RootEditPart root = ((IGraphicalEditPart)ep).getRoot();
+ if(!(root instanceof DiagramRootEditPart)) {
+ return;
+ }
+ final double gridSpacing = ((DiagramRootEditPart)root).getGridSpacing();
+ int max = (int)(1 + gridSpacing);
+ int restrictedDirection = getRestrictedDirection(request);
+ final Point delta = request.getMoveDelta();
+ final Point newDelta = new Point(0, 0);
+ int newMove = 0;
+ while(newMove < max) {
+ newMove++;
+ if(delta.x > 0) {
+ newDelta.x = (int)newMove + delta.x;
+ }
+ if(delta.x < 0) {
+ newDelta.x = (-newMove) + delta.x;
+ }
+ if(delta.y > 0) {
+ newDelta.y = newMove + delta.y;
+ }
+ if(delta.y < 0) {
+ newDelta.y = (-newMove) + delta.y;
+ }
+ request.setMoveDelta(newDelta);
+ request.getExtendedData().put(SnapToHelperUtil.RESTRICTED_DIRECTIONS, restrictedDirection);
+
+ final Map<Double, PrecisionPoint> distVSPoint = new HashMap<Double, PrecisionPoint>();
+ if(this.snapOnCorners) {
+ distVSPoint.putAll(getCornerDistances(request));
+ }
+
+ if(this.snapOnMiddles) {
+ distVSPoint.putAll(getMiddleDistances(request));
+ }
+
+ if(this.snapOnCenter) {
+ distVSPoint.putAll(getCenterDistances(request));
+ }
+
+ final List<Double> distances = new ArrayList<Double>(distVSPoint.keySet());
+ if(distances.size() > 0) {
+ double min = distances.get(0);
+ //We look for the minus distance
+ for(int i = 1; i < distances.size() - 1; i++) {
+ min = Math.min(min, distances.get(i));
+ }
+ final Point minPoint = distVSPoint.get(min);
+ //the distance can't be null
+ if(minPoint.x != 0 || minPoint.y != 0) {
+ //the calculate move must be in the same direction than the keyboard move
+ if(Integer.signum(minPoint.x) == Integer.signum(delta.x) && Integer.signum(minPoint.y) == Integer.signum(delta.y)) {
+ request.setMoveDelta(distVSPoint.get(min));
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * @param request
+ * @return
+ * a map with the couple distance and delta point to anchor by the corner of the figure
+ */
+ protected Map<Double, PrecisionPoint> getCornerDistances(final ChangeBoundsRequest request) {
+ final Map<Double, PrecisionPoint> distVSPoints = new HashMap<Double, PrecisionPoint>();
+ if(getSnapToHelper() != null && request.isSnapToEnabled()) {
+ final Point moveDelta = request.getMoveDelta();
+ PrecisionRectangle jointRect = getCompoundSourceRectangle();
+ jointRect.translate(moveDelta);
+
+ //calculate the delta to anchor on the top left corner
+ final PrecisionPoint topLeftCornerDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectTopLeft = getSourceRectangle();
+ baseRectTopLeft.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectTopLeft, jointRect }, topLeftCornerDelta);
+
+ //calculate the delta to anchor on the top right corner
+ final PrecisionPoint topRightCornerDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectTopRight = getSourceRectangle();
+ baseRectTopRight.setX(baseRectTopRight.x + baseRectTopRight.width);
+ baseRectTopRight.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectTopRight, jointRect }, topRightCornerDelta);
+
+ //calculate the delta to anchor on the bottom left corner
+ final PrecisionPoint bottomLeftCornerDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectBottomLeft = getSourceRectangle();
+ baseRectBottomLeft.setY(baseRectBottomLeft.y + baseRectBottomLeft.height);
+ baseRectBottomLeft.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomLeft, jointRect }, bottomLeftCornerDelta);
+
+ //calculate the delta to anchor on the bottom right corner
+ final PrecisionPoint bottomRightCornerDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectBottomRight = getSourceRectangle();
+ baseRectBottomRight.setX(baseRectBottomRight.x + baseRectBottomRight.width);
+ baseRectBottomRight.setY(baseRectBottomRight.y + baseRectBottomRight.height);
+ baseRectBottomRight.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomRight, jointRect }, bottomRightCornerDelta);
+
+ final Point ref = baseRectTopLeft.getTopLeft();
+ distVSPoints.put(distance(ref, topLeftCornerDelta), topLeftCornerDelta);
+ distVSPoints.put(distance(ref, topRightCornerDelta), topRightCornerDelta);
+ distVSPoints.put(distance(ref, bottomLeftCornerDelta), bottomLeftCornerDelta);
+ distVSPoints.put(distance(ref, bottomRightCornerDelta), bottomRightCornerDelta);
+ }
+ return distVSPoints;
+ }
+
+ /**
+ *
+ * @param request
+ * @return
+ * a map with the couple distance and delta point to anchor by the middle of each side of the figure
+ */
+ protected Map<Double, PrecisionPoint> getMiddleDistances(final ChangeBoundsRequest request) {
+ final Map<Double, PrecisionPoint> distVSPoints = new HashMap<Double, PrecisionPoint>();
+ if(getSnapToHelper() != null && request.isSnapToEnabled()) {
+ final Point moveDelta = request.getMoveDelta();
+
+ PrecisionRectangle jointRect = getCompoundSourceRectangle();
+ jointRect.translate(moveDelta);
+ //calculate the delta to anchor on the middle top point
+ final PrecisionPoint middleTopDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectMiddleTop = getSourceRectangle();
+ baseRectMiddleTop.setPreciseLocation(baseRectMiddleTop.preciseX() + (baseRectMiddleTop.preciseWidth() / 2), baseRectMiddleTop.preciseY());
+ baseRectMiddleTop.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectMiddleTop, jointRect }, middleTopDelta);
+
+ //calculate the delta to anchor on the middle left point
+ final PrecisionPoint middleLeftDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectMiddleLeft = getSourceRectangle();
+ baseRectMiddleLeft.setPreciseLocation(baseRectMiddleLeft.preciseX(), baseRectMiddleLeft.preciseY() + (baseRectMiddleLeft.preciseWidth() / 2));
+ baseRectMiddleLeft.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectMiddleLeft, jointRect }, middleLeftDelta);
+
+ //calculate the delta to anchor on the middle right point
+ final PrecisionPoint middleRightDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectMiddleRight = getSourceRectangle();
+ baseRectMiddleRight.setPreciseLocation(baseRectMiddleRight.preciseX() + baseRectMiddleRight.preciseWidth(), baseRectMiddleRight.preciseY() + (baseRectMiddleRight.preciseHeight() / 2));
+ baseRectMiddleRight.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectMiddleRight, jointRect }, middleRightDelta);
+
+ //calculate the delta to anchor on the middle bottom
+ final PrecisionPoint middleBottomDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectMiddleBottom = getSourceRectangle();
+ baseRectMiddleBottom.setPreciseLocation(baseRectMiddleBottom.preciseX() + (baseRectMiddleBottom.preciseWidth() / 2), baseRectMiddleBottom.preciseY() + baseRectMiddleBottom.preciseHeight());
+ baseRectMiddleBottom.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectMiddleBottom, jointRect }, middleBottomDelta);
+
+ final Point ref = baseRectMiddleTop.getTopLeft();
+ distVSPoints.put(distance(ref, middleTopDelta), middleTopDelta);
+ distVSPoints.put(distance(ref, middleLeftDelta), middleLeftDelta);
+ distVSPoints.put(distance(ref, middleRightDelta), middleRightDelta);
+ distVSPoints.put(distance(ref, middleBottomDelta), middleBottomDelta);
+ }
+
+ return distVSPoints;
+ }
+
+ /**
+ *
+ * @param request
+ * @return
+ * a map with the couple distance and delta point to anchor by the center of the figure
+ */
+ protected Map<Double, PrecisionPoint> getCenterDistances(final ChangeBoundsRequest request) {
+ final Map<Double, PrecisionPoint> distVSPoints = new HashMap<Double, PrecisionPoint>();
+ if(getSnapToHelper() != null && request.isSnapToEnabled()) {
+ final Point moveDelta = request.getMoveDelta();
+
+ PrecisionRectangle jointRect = getCompoundSourceRectangle();
+ jointRect.translate(moveDelta);
+ //calculate the delta to anchor on the middle top point
+ final PrecisionPoint centerDelta = new PrecisionPoint(moveDelta);
+ final PrecisionRectangle baseRectCenter = getSourceRectangle();
+ baseRectCenter.setPreciseLocation(baseRectCenter.preciseX() + (baseRectCenter.preciseWidth() / 2), baseRectCenter.preciseY() + (baseRectCenter.preciseHeight() / 2));
+ baseRectCenter.translate(moveDelta);
+ getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectCenter, jointRect }, centerDelta);
+
+ final Point ref = baseRectCenter.getTopLeft();
+ distVSPoints.put(distance(ref, centerDelta), centerDelta);
+ }
+
+ return distVSPoints;
+ }
+
+ /**
+ *
+ * @return
+ * the compoundSourceRectangle
+ */
+ private PrecisionRectangle getCompoundSourceRectangle() {
+ return new PrecisionRectangle(this.compoundSourceRectangle);
+ }
+
+ /**
+ *
+ * @return
+ * the source rectangle
+ */
+ private PrecisionRectangle getSourceRectangle() {
+ return new PrecisionRectangle(this.figureToSnapBounds);
+ }
+
+ /**
+ *
+ * @param pt1
+ * a first point
+ * @param pt2
+ * the second point
+ * @return
+ * the distance between the two points
+ */
+ protected final double distance(final Point pt1, final Point pt2) {
+ double deltaX = pt1.preciseX() - pt2.preciseX();
+ double deltaY = pt1.preciseY() - pt2.preciseY();
+ return Math.hypot(deltaX, deltaY);
+ }
+
+ /**
+ *
+ * @return
+ * the snap helper
+ */
+ protected final SnapToHelper getSnapToHelper() {
+ return this.helper;
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/PapyrusDragEditPartsTrackerEx.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/PapyrusDragEditPartsTrackerEx.java index e184e3ee46c..2371b34a767 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/PapyrusDragEditPartsTrackerEx.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/PapyrusDragEditPartsTrackerEx.java @@ -248,33 +248,35 @@ public class PapyrusDragEditPartsTrackerEx extends DragEditPartsTrackerEx { baseRectTopLeft.translate(moveDelta);
getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectTopLeft, jointRect }, topLeftCornerDelta);
- //calculate the delta to anchor on the top right corner
- final PrecisionPoint topRightCornerDelta = new PrecisionPoint(moveDelta);
- final PrecisionRectangle baseRectTopRight = getSourceRectangle();
- baseRectTopRight.setX(baseRectTopRight.x + baseRectTopRight.width);
- baseRectTopRight.translate(moveDelta);
- getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectTopRight, jointRect }, topRightCornerDelta);
-
- //calculate the delta to anchor on the bottom left corner
- final PrecisionPoint bottomLeftCornerDelta = new PrecisionPoint(moveDelta);
- final PrecisionRectangle baseRectBottomLeft = getSourceRectangle();
- baseRectBottomLeft.setY(baseRectBottomLeft.y + baseRectBottomLeft.height);
- baseRectBottomLeft.translate(moveDelta);
- getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomLeft, jointRect }, bottomLeftCornerDelta);
-
- //calculate the delta to anchor on the bottom right corner
- final PrecisionPoint bottomRightCornerDelta = new PrecisionPoint(moveDelta);
- final PrecisionRectangle baseRectBottomRight = getSourceRectangle();
- baseRectBottomRight.setX(baseRectBottomRight.x + baseRectBottomRight.width);
- baseRectBottomRight.setY(baseRectBottomRight.y + baseRectBottomRight.height);
- baseRectBottomRight.translate(moveDelta);
- getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomRight, jointRect }, bottomRightCornerDelta);
+ //FIXME : add preferences and re-activate this part of the code
+
+ // //calculate the delta to anchor on the top right corner
+ // final PrecisionPoint topRightCornerDelta = new PrecisionPoint(moveDelta);
+ // final PrecisionRectangle baseRectTopRight = getSourceRectangle();
+ // baseRectTopRight.setX(baseRectTopRight.x + baseRectTopRight.width);
+ // baseRectTopRight.translate(moveDelta);
+ // getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectTopRight, jointRect }, topRightCornerDelta);
+ //
+ // //calculate the delta to anchor on the bottom left corner
+ // final PrecisionPoint bottomLeftCornerDelta = new PrecisionPoint(moveDelta);
+ // final PrecisionRectangle baseRectBottomLeft = getSourceRectangle();
+ // baseRectBottomLeft.setY(baseRectBottomLeft.y + baseRectBottomLeft.height);
+ // baseRectBottomLeft.translate(moveDelta);
+ // getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomLeft, jointRect }, bottomLeftCornerDelta);
+ //
+ // //calculate the delta to anchor on the bottom right corner
+ // final PrecisionPoint bottomRightCornerDelta = new PrecisionPoint(moveDelta);
+ // final PrecisionRectangle baseRectBottomRight = getSourceRectangle();
+ // baseRectBottomRight.setX(baseRectBottomRight.x + baseRectBottomRight.width);
+ // baseRectBottomRight.setY(baseRectBottomRight.y + baseRectBottomRight.height);
+ // baseRectBottomRight.translate(moveDelta);
+ // getSnapToHelper().snapPoint(request, PositionConstants.HORIZONTAL | PositionConstants.VERTICAL, new PrecisionRectangle[]{ baseRectBottomRight, jointRect }, bottomRightCornerDelta);
final Point ref = baseRectTopLeft.getTopLeft();
distVSPoints.put(distance(ref, topLeftCornerDelta), topLeftCornerDelta);
- distVSPoints.put(distance(ref, topRightCornerDelta), topRightCornerDelta);
- distVSPoints.put(distance(ref, bottomLeftCornerDelta), bottomLeftCornerDelta);
- distVSPoints.put(distance(ref, bottomRightCornerDelta), bottomRightCornerDelta);
+ // distVSPoints.put(distance(ref, topRightCornerDelta), topRightCornerDelta);
+ // distVSPoints.put(distance(ref, bottomLeftCornerDelta), bottomLeftCornerDelta);
+ // distVSPoints.put(distance(ref, bottomRightCornerDelta), bottomRightCornerDelta);
}
return distVSPoints;
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/ResizeTrackerWithPreferences.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/ResizeTrackerWithPreferences.java new file mode 100644 index 00000000000..498c0885b38 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/ResizeTrackerWithPreferences.java @@ -0,0 +1,195 @@ +package org.eclipse.papyrus.infra.gmfdiag.common.snap;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PrecisionDimension;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.SnapToHelper;
+import org.eclipse.gef.handles.HandleBounds;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.tools.ResizeTracker;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.papyrus.infra.gmfdiag.common.Activator;
+import org.eclipse.papyrus.infra.gmfdiag.common.preferences.PreferencesConstantsHelper;
+
+/**
+ * Adapted code from ResizeTracker
+ * A resize tracker managing a preference for constrained resize
+ *
+ */
+public class ResizeTrackerWithPreferences extends ResizeTracker {
+
+ /**
+ * the snap helper to use
+ */
+ private SnapToHelper localSnapToHelper;
+
+ /**
+ * the source rect bounds
+ */
+ private PrecisionRectangle localSourceRect;
+
+ public ResizeTrackerWithPreferences(GraphicalEditPart owner, int direction) {
+ super(owner, direction);
+ }
+
+ @Override
+ public void activate() {
+ super.activate();
+ if(getOwner() != null) {
+ if(getTargetEditPart() != null)
+ localSnapToHelper = (SnapToHelper)getTargetEditPart().getAdapter(SnapToHelper.class);
+
+ IFigure figure = getOwner().getFigure();
+ if(figure instanceof HandleBounds)
+ localSourceRect = new PrecisionRectangle(((HandleBounds)figure).getHandleBounds());
+ else
+ localSourceRect = new PrecisionRectangle(figure.getBounds());
+ figure.translateToAbsolute(localSourceRect);
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.gef.tools.ResizeTracker#updateSourceRequest()
+ *
+ */
+ @Override
+ protected void updateSourceRequest() {
+ ChangeBoundsRequest request = (ChangeBoundsRequest)getSourceRequest();
+ Dimension d = getDragMoveDelta();
+
+ Point location = new Point(getLocation());
+ Point moveDelta = new Point(0, 0);
+ Dimension resizeDelta = new Dimension(0, 0);
+
+ request.setConstrainedResize(isConstrainedResizeAccordingToPreference());
+ request.setCenteredResize(getCurrentInput().isModKeyDown(SnapUtils.MODIFIER_CENTERED_RESIZE));
+ request.setSnapToEnabled(!getCurrentInput().isModKeyDown(SnapUtils.MODIFIER_NO_SNAPPING));
+
+ if(request.isConstrainedResize() && getOwner() != null) {
+ request.setConstrainedResize(true);
+
+ int origHeight = getOwner().getFigure().getBounds().height;
+ int origWidth = getOwner().getFigure().getBounds().width;
+ float ratio = 1;
+
+ if(origWidth != 0 && origHeight != 0)
+ ratio = ((float)origHeight / (float)origWidth);
+
+ if(getResizeDirection() == PositionConstants.SOUTH_EAST) {
+ if(d.height > (d.width * ratio))
+ d.width = (int)(d.height / ratio);
+ else
+ d.height = (int)(d.width * ratio);
+ } else if(getResizeDirection() == PositionConstants.NORTH_WEST) {
+ if(d.height < (d.width * ratio))
+ d.width = (int)(d.height / ratio);
+ else
+ d.height = (int)(d.width * ratio);
+ } else if(getResizeDirection() == PositionConstants.NORTH_EAST) {
+ if(-(d.height) > (d.width * ratio))
+ d.width = -(int)(d.height / ratio);
+ else
+ d.height = -(int)(d.width * ratio);
+ } else if(getResizeDirection() == PositionConstants.SOUTH_WEST) {
+ if(-(d.height) < (d.width * ratio))
+ d.width = -(int)(d.height / ratio);
+ else
+ d.height = -(int)(d.width * ratio);
+ }
+ }
+
+ if((getResizeDirection() & PositionConstants.NORTH) != 0) {
+ if(request.isCenteredResize()) {
+ resizeDelta.height -= d.height;
+ }
+ moveDelta.y += d.height;
+ resizeDelta.height -= d.height;
+ }
+ if((getResizeDirection() & PositionConstants.SOUTH) != 0) {
+ if(request.isCenteredResize()) {
+ moveDelta.y -= d.height;
+ resizeDelta.height += d.height;
+ }
+ resizeDelta.height += d.height;
+ }
+ if((getResizeDirection() & PositionConstants.WEST) != 0) {
+ if(request.isCenteredResize()) {
+ resizeDelta.width -= d.width;
+ }
+ moveDelta.x += d.width;
+ resizeDelta.width -= d.width;
+ }
+ if((getResizeDirection() & PositionConstants.EAST) != 0) {
+ if(request.isCenteredResize()) {
+ moveDelta.x -= d.width;
+ resizeDelta.width += d.width;
+ }
+ resizeDelta.width += d.width;
+ }
+
+ request.setMoveDelta(moveDelta);
+ request.setSizeDelta(resizeDelta);
+ request.setLocation(location);
+ request.setEditParts(getOperationSet());
+ request.getExtendedData().clear();
+ request.setResizeDirection(getResizeDirection());
+
+ if(request.isSnapToEnabled() && localSnapToHelper != null) {
+ PrecisionRectangle rect = localSourceRect.getPreciseCopy();
+ rect.translate(moveDelta);
+ rect.resize(resizeDelta);
+ PrecisionRectangle result = new PrecisionRectangle();
+
+ localSnapToHelper.snapRectangle(request, request.getResizeDirection(), rect, result);
+ if(request.isCenteredResize()) {
+ if(result.preciseX() != 0.0)
+ result.setPreciseWidth(result.preciseWidth() - result.preciseX());
+ else if(result.preciseWidth() != 0.0) {
+ result.setPreciseX(-result.preciseWidth());
+ result.setPreciseWidth(result.preciseWidth() * 2.0);
+ }
+
+ if(result.preciseY() != 0.0)
+ result.setPreciseHeight(result.preciseHeight() - result.preciseY());
+ else if(result.preciseHeight() != 0.0) {
+ result.setPreciseY(-result.preciseHeight());
+ result.setPreciseHeight(result.preciseHeight() * 2.0);
+ }
+ }
+
+ PrecisionPoint preciseMove = new PrecisionPoint(result.preciseX() + moveDelta.x, result.preciseY() + moveDelta.y);
+
+ PrecisionDimension preciseResize = new PrecisionDimension(result.preciseWidth() + resizeDelta.width, result.preciseHeight() + resizeDelta.height);
+
+ request.setMoveDelta(preciseMove);
+ request.setSizeDelta(preciseResize);
+ }
+
+ enforceConstraintsForResize(request);
+ }
+
+ /**
+ *
+ * @return
+ * <code>true</code> if the current resize must be constrained and <code>false</code> if not
+ */
+ private final boolean isConstrainedResizeAccordingToPreference() {
+ IPreferenceStore store = Activator.getInstance().getPreferenceStore();
+ boolean isInverted = false;
+ if(store.contains(PreferencesConstantsHelper.getPapyrusEditorConstant(PreferencesConstantsHelper.INVERT_BINDING_FOR_DEFAULT_RESIZE_AND_CONSTRAINED_RESIZE))) {
+ isInverted = store.getBoolean(PreferencesConstantsHelper.getPapyrusEditorConstant(PreferencesConstantsHelper.INVERT_BINDING_FOR_DEFAULT_RESIZE_AND_CONSTRAINED_RESIZE));
+ }
+ //to activate this preference use this code during the preference initialization of Papyrus
+ //org.eclipse.papyrus.infra.gmfdiag.common.Activator.getInstance().getPreferenceStore().setValue(PreferencesConstantsHelper.getPapyrusEditorConstant(PreferencesConstantsHelper.INVERT_BINDING_FOR_DEFAULT_RESIZE_AND_CONSTRAINED_RESIZE),true);
+ if(isInverted) {
+ return !getCurrentInput().isModKeyDown(SnapUtils.MODIFIER_CONSTRAINED_RESIZE);
+ }
+ return getCurrentInput().isModKeyDown(SnapUtils.MODIFIER_CONSTRAINED_RESIZE);
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/SnapUtils.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/SnapUtils.java new file mode 100644 index 00000000000..33b4cac3b65 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/SnapUtils.java @@ -0,0 +1,59 @@ +/*****************************************************************************
+ * Copyright (c) 2013 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.infra.gmfdiag.common.snap;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.swt.SWT;
+
+
+public class SnapUtils {
+
+ private SnapUtils() {
+ //to prevent instanciation
+ }
+
+ /**
+ * Key modifier for centered resizing. It's ALT on the Mac and MOD1 on all
+ * other platforms.
+ */
+ public static final int MODIFIER_CENTERED_RESIZE;
+
+ static {
+ if(Platform.OS_MACOSX.equals(Platform.getOS())) {
+ MODIFIER_CENTERED_RESIZE = SWT.ALT;
+ } else {
+ MODIFIER_CENTERED_RESIZE = SWT.MOD1;
+ }
+ }
+
+ /**
+ * Key modifier for constrained resizing. It's SHIFT on all platforms.
+ */
+ public static final int MODIFIER_CONSTRAINED_RESIZE = SWT.SHIFT;
+
+ /**
+ * Key modifier for ignoring snap while dragging. It's CTRL on Mac, and ALT
+ * on all other platforms.
+ */
+ public static final int MODIFIER_NO_SNAPPING;
+
+ static {
+ if (Platform.OS_MACOSX.equals(Platform.getOS())) {
+ MODIFIER_NO_SNAPPING = SWT.CTRL;
+ } else {
+ MODIFIER_NO_SNAPPING = SWT.ALT;
+ }
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/GMFUnsafe.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/GMFUnsafe.java new file mode 100644 index 00000000000..dd82a003f72 --- /dev/null +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/GMFUnsafe.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.gmfdiag.common.utils; + +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.command.AbstractCommand; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.util.WrappedException; +import org.eclipse.emf.transaction.RollbackException; +import org.eclipse.emf.transaction.Transaction; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.impl.InternalTransactionalEditingDomain; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.papyrus.commands.Activator; + + +/** + * Utilities for operations in the GMF context that we might consider as "unsafe" or exceptional cases. + */ +public class GMFUnsafe { + + /** + * Not instantiable by clients. + */ + private GMFUnsafe() { + super(); + } + + /** + * Performs an unsafe write to the model. The editing domain may or may not already have an active transaction, which may or may not be read-only; + * it does not matter. In any case, the changes performed will not be recorded for undo/redo or roll-back. Thus, this is appropriate only for use + * cases such as synchronization of canonical views, which are not considered logically as abstract model edits (though they be concrete changes). + * + * @param domain + * an editing domain that may or may not have a transaction in progress + * @param writeOperation + * an operation that will make unchecked/unsafe changes to the editing {@code domain} + * + * @throws RollbackException + * if the unprotected write transaction fails to commit. Note that this could occlude an uncaught exception thrown by the + * {@code writeOperation} runnable + * @throws InterruptedException + * if the current thread is interrupted while waiting for the unprotected write transaction to start + */ + public static void write(TransactionalEditingDomain domain, Runnable writeOperation) throws InterruptedException, RollbackException { + runUnprotected(domain, writeOperation); + } + + private static void runUnprotected(TransactionalEditingDomain domain, Runnable writeOperation) throws InterruptedException, RollbackException { + InternalTransactionalEditingDomain internalDomain = (InternalTransactionalEditingDomain)domain; + Transaction unprotected = internalDomain.startTransaction(false, Collections.singletonMap(Transaction.OPTION_UNPROTECTED, true)); + try { + writeOperation.run(); + } finally { + unprotected.commit(); + } + } + + /** + * Executes an unsafe command on the model. The editing domain may or may not already have an active transaction, which may or may not be + * read-only; it does not matter. In any case, the changes performed will not be recorded for undo/redo or roll-back. Thus, this is appropriate + * only for use cases such as synchronization of canonical views, which are not considered logically as abstract model edits (though they be + * concrete changes). + * + * @param domain + * an editing domain that may or may not have a transaction in progress + * @param command + * a command that will make unchecked/unsafe changes to the editing {@code domain} + * + * @throws RollbackException + * if the unprotected write transaction fails to commit. Note that this could occlude an uncaught exception thrown by the + * {@code writeOperation} runnable + * @throws InterruptedException + * if the current thread is interrupted while waiting for the unprotected write transaction to start + * + * @see #write(TransactionalEditingDomain, Runnable) + */ + public static void write(TransactionalEditingDomain domain, Command command) throws InterruptedException, RollbackException { + write(domain, new CommandRunnable(command)); + } + + /** + * Executes an unsafe command on the model. The editing domain may or may not already have an active transaction, which may or may not be + * read-only; it does not matter. In any case, the changes performed will not be recorded for undo/redo or roll-back. Thus, this is appropriate + * only for use cases such as synchronization of canonical views, which are not considered logically as abstract model edits (though they be + * concrete changes). + * + * @param domain + * an editing domain that may or may not have a transaction in progress + * @param command + * a command that will make unchecked/unsafe changes to the editing {@code domain} + * + * @throws RollbackException + * if the unprotected write transaction fails to commit. Note that this could occlude an uncaught exception thrown by the + * {@code writeOperation} runnable + * @throws InterruptedException + * if the current thread is interrupted while waiting for the unprotected write transaction to start + * @throws ExecutionException + * if the {@code command} fails to execute + * + * @see #write(TransactionalEditingDomain, Runnable) + */ + public static void write(TransactionalEditingDomain domain, ICommand command) throws InterruptedException, RollbackException, ExecutionException { + try { + write(domain, new GMFCommandRunnable(command)); + } catch (WrappedException e) { + if(e.exception() instanceof ExecutionException) { + throw (ExecutionException)e.exception(); + } else { + // It must have been an unchecked RuntimeException of some kind + throw (RuntimeException)e.exception(); + } + } + } + + /** + * Wraps a command for unprotected execution, undo, and redo on the command stack. + * + * @param domain + * a transactional editing domain on which the {@code command} operates + * @param command + * a command to wrap + * @return the wrapped command + */ + public static Command wrap(TransactionalEditingDomain domain, Command command) { + return new UnsafeCommandWrapper(domain, command); + } + + // + // Nested types + // + + /** + * A useful base class for commands that need to execute, undo, and redo in unprotected mode on the command stack. + */ + public static abstract class UnsafeCommand extends AbstractCommand { + + private final TransactionalEditingDomain domain; + + protected UnsafeCommand(TransactionalEditingDomain domain) { + this.domain = domain; + } + + protected UnsafeCommand(TransactionalEditingDomain domain, String label, String description) { + super(label, description); + + this.domain = domain; + } + + protected UnsafeCommand(TransactionalEditingDomain domain, String label) { + super(label); + + this.domain = domain; + } + + @Override + public final void execute() { + try { + runUnprotected(domain, new Runnable() { + + @Override + public void run() { + doExecute(); + } + }); + } catch (Exception e) { + handleException(e); + } + } + + protected abstract void doExecute(); + + @Override + public final void undo() { + try { + runUnprotected(domain, new Runnable() { + + @Override + public void run() { + doUndo(); + } + }); + } catch (Exception e) { + handleException(e); + } + } + + protected void doUndo() { + // Pass. Usually, unprotected changes are not undoable + } + + @Override + public final void redo() { + try { + runUnprotected(domain, new Runnable() { + + @Override + public void run() { + doRedo(); + } + }); + } catch (Exception e) { + handleException(e); + } + } + + protected void doRedo() { + // Pass. Usually, unprotected changes are not undoable + } + + void handleException(Exception e) { + Activator.log.error(e); + } + } + + private static class UnsafeCommandWrapper extends UnsafeCommand { + + private final Command command; + + UnsafeCommandWrapper(TransactionalEditingDomain domain, Command command) { + super(domain, command.getLabel(), command.getDescription()); + + this.command = command; + } + + @Override + public void dispose() { + command.dispose(); + } + + @Override + public boolean canExecute() { + return command.canExecute(); + } + + @Override + protected void doExecute() { + command.execute(); + } + + @Override + public boolean canUndo() { + return command.canUndo(); + } + + @Override + protected void doUndo() { + command.undo(); + } + + @Override + protected void doRedo() { + command.redo(); + } + + @Override + public Collection<?> getAffectedObjects() { + return command.getAffectedObjects(); + } + + @Override + public Collection<?> getResult() { + return command.getResult(); + } + + @Override + public String toString() { + return String.format("Unsafe(%s)", command.toString()); //$NON-NLS-1$ + } + } + + private static class CommandRunnable implements Runnable { + + private final Command command; + + CommandRunnable(Command command) { + this.command = command; + } + + @Override + public void run() { + command.execute(); + } + } + + private static class GMFCommandRunnable implements Runnable { + + private final ICommand command; + + GMFCommandRunnable(ICommand command) { + this.command = command; + } + + @Override + public void run() { + try { + command.execute(new NullProgressMonitor(), null); + } catch (ExecutionException e) { + throw new WrappedException(e); + } + } + } +} diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/databinding/ObservableGradientData.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/databinding/ObservableGradientData.java index 47caae7f46c..5520af4ff41 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/databinding/ObservableGradientData.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/databinding/ObservableGradientData.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
+ * Copyright (c) 2011, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,10 +8,14 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.databinding;
+import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.notation.datatype.GradientData;
/**
@@ -125,4 +129,16 @@ public class ObservableGradientData extends GradientData { notifySource();
}
+ public EObject getOwner() {
+ EObject result = null;
+
+ if(source instanceof IObserving) {
+ Object owner = ((IObserving)source).getObserved();
+ if(owner instanceof EObject) {
+ result = (EObject)owner;
+ }
+ }
+
+ return result;
+ }
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElement.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElement.java index 2956c311344..7afe625c3ff 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElement.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElement.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -94,7 +96,7 @@ public class CustomStyleModelElement extends EMFModelElement { }
@Override
- public boolean isEditable(String propertyPath) {
+ protected boolean isFeatureEditable(String propertyPath) {
return findProperty(propertyPath) != null;
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElement.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElement.java index 5e3ed3f7cb9..4792204ad56 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElement.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElement.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
+ * Copyright (c) 2011, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,6 +9,7 @@ * Contributors:
*
* CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -21,6 +22,7 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.databinding.custom.CustomBooleanStyleObservableValue;
import org.eclipse.papyrus.infra.gmfdiag.common.databinding.custom.CustomIntStyleObservableValue;
import org.eclipse.papyrus.infra.gmfdiag.common.providers.ShapeDecorator;
@@ -114,12 +116,8 @@ public class DecoratedModelElement extends AbstractModelElement { */
@Override
public boolean isEditable(String propertyPath) {
- if(ShapeDecorator.SHAPE_DECORATOR_DIRECTION.equals(propertyPath)) {
- return true;
- }
-
- if(ShapeDecorator.SHAPE_DECORATOR_VISIBILITY.equals(propertyPath)) {
- return true;
+ if(ShapeDecorator.SHAPE_DECORATOR_DIRECTION.equals(propertyPath) || ShapeDecorator.SHAPE_DECORATOR_VISIBILITY.equals(propertyPath)) {
+ return !EMFHelper.isReadOnly(source);
}
return super.isEditable(propertyPath);
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/GradientDataModelElement.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/GradientDataModelElement.java index c68abb5158f..07951aaf382 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/GradientDataModelElement.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/GradientDataModelElement.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
+ * Copyright (c) 2011, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,13 +8,17 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.notation.datatype.GradientData;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.gmfdiag.properties.Activator;
import org.eclipse.papyrus.infra.gmfdiag.properties.databinding.GradientDataObservableValue;
import org.eclipse.papyrus.infra.gmfdiag.properties.databinding.GradientDataObservableValue.GradientProperty;
@@ -31,20 +35,40 @@ import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElement; */
public class GradientDataModelElement extends AbstractModelElement {
+ private static final String PROPERTY_PATH = "gradientStyle"; //$NON-NLS-1$
+
/**
* The source GradientData
*/
protected GradientData sourceElement;
/**
+ * The notation style element that owns the {@link GradientData}.
+ */
+ protected EObject owner;
+
+ /**
+ * Constructor.
+ *
+ * @param sourceElement
+ * the source GradientData
+ * @param owner
+ * the owner of the gradient data (may be {@code null})
+ */
+ public GradientDataModelElement(GradientData sourceElement, EObject owner) {
+ this.sourceElement = sourceElement;
+ this.owner = owner;
+ }
+
+ /**
*
* Constructor.
*
* @param sourceElement
- * the soruce GradientData
+ * the source GradientData
*/
public GradientDataModelElement(GradientData sourceElement) {
- this.sourceElement = sourceElement;
+ this(sourceElement, null);
}
@Override
@@ -58,8 +82,14 @@ public class GradientDataModelElement extends AbstractModelElement { }
@Override
+ public boolean isEditable(String propertyPath) {
+ // Let owner be null for compatibility with plain GradientData objects that we don't know their owners
+ return (owner == null) || !EMFHelper.isReadOnly(owner);
+ }
+
+ @Override
public IStaticContentProvider getContentProvider(String propertyPath) {
- if(propertyPath.equals("gradientStyle")) { //$NON-NLS-1$
+ if(propertyPath.equals(PROPERTY_PATH)) {
return new AbstractStaticContentProvider() {
public Object[] getElements() {
@@ -74,7 +104,7 @@ public class GradientDataModelElement extends AbstractModelElement { @Override
public ILabelProvider getLabelProvider(String propertyPath) {
- if(propertyPath.equals("gradientStyle")) { //$NON-NLS-1$
+ if(propertyPath.equals(PROPERTY_PATH)) {
return new LabelProvider() {
@Override
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java index 5bcd44621e2..6a0889ccf7d 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
+ * Copyright (c) 2011, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -17,6 +19,7 @@ import org.eclipse.gmf.runtime.notation.View; import org.eclipse.gmf.runtime.notation.datatype.GradientData;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.infra.gmfdiag.properties.Activator;
+import org.eclipse.papyrus.infra.gmfdiag.properties.databinding.ObservableGradientData;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
@@ -30,7 +33,10 @@ public class NotationModelElementFactory implements ModelElementFactory { public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
- if(sourceElement instanceof GradientData) {
+ if (sourceElement instanceof ObservableGradientData) {
+ ObservableGradientData gradientData = (ObservableGradientData)sourceElement;
+ return new GradientDataModelElement(gradientData, gradientData.getOwner());
+ } else if(sourceElement instanceof GradientData) {
return new GradientDataModelElement((GradientData)sourceElement);
}
View view = NotationHelper.findView(sourceElement);
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java index 6a43b0a2d8b..3cff16ceb76 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java @@ -33,7 +33,10 @@ import com.google.inject.Injector; * This class is provided as a basis for contribution to the extension point directEditors of Papyrus,
* for the case of popup editors.
* Clients must simply override the method createPopupEditorHelper(Object editPart)
+ *
+ * This class is deprecated, use DefaultDirectEditorConfiguration instead
*/
+@Deprecated
public abstract class PopupEditorConfiguration implements IPopupEditorConfiguration {
private String language = "";
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableModelElement.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableModelElement.java index 40bf9058df3..65c431481cb 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableModelElement.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableModelElement.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.properties.modelelement;
@@ -418,15 +419,12 @@ public class NatTableModelElement extends EMFModelElement { }
/**
- *
- * @see org.eclipse.papyrus.views.properties.modelelement.EMFModelElement#isEditable(java.lang.String)
- *
* @param propertyPath
* @return
*/
@Override
- public boolean isEditable(String propertyPath) {
- boolean res = super.isEditable(propertyPath);
+ protected boolean isFeatureEditable(String propertyPath) {
+ boolean res = super.isFeatureEditable(propertyPath);
if(!res) {
//feature column label property
if(Constants.COLUMN_FEATURE_LABEL_CONFIGURATION_DISPLAY_ICON.equals(propertyPath)) {
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalCommandHandler.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalCommandHandler.java new file mode 100644 index 00000000000..539f4eb8662 --- /dev/null +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalCommandHandler.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.nattable.handler; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.nebula.widgets.nattable.command.ILayerCommand; +import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler; +import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommand; +import org.eclipse.nebula.widgets.nattable.layer.ILayer; +import org.eclipse.swt.widgets.Display; + + +/** + * A base layer command handler that executes commands on a {@link TransactionalEditingDomain}'s command-stack. + * This ensures atomic undo/redo of all model changes performed by the command. + */ +public abstract class TransactionalCommandHandler<T extends ILayerCommand> implements ILayerCommandHandler<T> { + + private final TransactionalEditingDomain domain; + + private String label; + + public TransactionalCommandHandler(TransactionalEditingDomain domain) { + this.domain = domain; + } + + public TransactionalCommandHandler(TransactionalEditingDomain domain, String label) { + this.domain = domain; + + this.label = label; + } + + public String getLabel() { + return (label != null) ? label : "Table Command"; + } + + public void setLabel(String label) { + this.label = label; + } + + @Override + public final boolean doCommand(final ILayer targetLayer, final T command) { + final boolean[] result = { false }; + + if(command.convertToTargetLayer(targetLayer)) { + domain.getCommandStack().execute(new RecordingCommand(domain, getLabel()) { + + @Override + protected void doExecute() { + ExecutionStatusKind status = doCommand(command); + + result[0] = status.isOK(); + + if(status.isRollback()) { + // Refresh the visual presentation of the layer because stereotype applications + // may have updated some cells + Display.getCurrent().asyncExec(new Runnable() { + + @Override + public void run() { + targetLayer.doCommand(new VisualRefreshCommand()); + } + }); + + // Roll back any changes that we made along the way + throw new OperationCanceledException(); + } + } + }); + } + + return result[0]; + } + + protected abstract ExecutionStatusKind doCommand(T command); + + // + // Nested types + // + + protected enum ExecutionStatusKind { + /** Command failed and should be rolled back so that it will not appear on the stack. */ + FAIL_ROLLBACK(false, true), + /** Command succeeded and should appear on the stack. */ + OK_COMPLETE(true, false), + /** Command succeeded but should be rolled back so that it will not appear on the stack. */ + OK_ROLLBACK(true, true); + + private final boolean ok; + + private final boolean rollback; + + private ExecutionStatusKind(boolean ok, boolean rollback) { + this.ok = ok; + this.rollback = rollback; + } + + public boolean isOK() { + return ok; + } + + public boolean isRollback() { + return rollback; + } + } +} diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalEditCellCommandHandler.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalEditCellCommandHandler.java new file mode 100644 index 00000000000..c32a105d93e --- /dev/null +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalEditCellCommandHandler.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * Dirk Fauth <dirk.fauth@gmail.com> - Initial API and implementation of EditController class + * + */ +package org.eclipse.papyrus.infra.nattable.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.jface.window.Window; +import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; +import org.eclipse.nebula.widgets.nattable.config.IEditableRule; +import org.eclipse.nebula.widgets.nattable.edit.ActiveCellEditorRegistry; +import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes; +import org.eclipse.nebula.widgets.nattable.edit.EditTypeEnum; +import org.eclipse.nebula.widgets.nattable.edit.InlineEditHandler; +import org.eclipse.nebula.widgets.nattable.edit.command.EditCellCommand; +import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand; +import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor; +import org.eclipse.nebula.widgets.nattable.edit.gui.CellEditDialogFactory; +import org.eclipse.nebula.widgets.nattable.edit.gui.ICellEditDialog; +import org.eclipse.nebula.widgets.nattable.layer.ILayer; +import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; +import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; +import org.eclipse.nebula.widgets.nattable.style.DisplayMode; +import org.eclipse.nebula.widgets.nattable.widget.EditModeEnum; +import org.eclipse.papyrus.infra.nattable.Activator; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + + +/** + * A variant of the {@link EditCellCommand} handler that executes changes on a {@link TransactionalEditingDomain}'s command-stack. + */ +public class TransactionalEditCellCommandHandler extends TransactionalCommandHandler<EditCellCommand> { + + public TransactionalEditCellCommandHandler(TransactionalEditingDomain domain) { + this(domain, "Edit Table Cell"); + } + + public TransactionalEditCellCommandHandler(TransactionalEditingDomain domain, String label) { + super(domain, label); + } + + @Override + public Class<EditCellCommand> getCommandClass() { + return EditCellCommand.class; + } + + protected ExecutionStatusKind doCommand(EditCellCommand command) { + ILayerCell cell = command.getCell(); + Composite parent = command.getParent(); + IConfigRegistry configRegistry = command.getConfigRegistry(); + + IEditableRule rule = (IEditableRule)configRegistry.getConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, DisplayMode.EDIT, cell.getConfigLabels().getLabels()); + + if(rule.isEditable(cell, configRegistry)) { + return editCell(cell, parent, cell.getDataValue(), configRegistry); + } + + return ExecutionStatusKind.FAIL_ROLLBACK; + } + + // From Nebula EditController (with minor tweaks) + protected ExecutionStatusKind editCell(ILayerCell cell, Composite parent, Object initialCanonicalValue, IConfigRegistry configRegistry) { + ExecutionStatusKind result = ExecutionStatusKind.FAIL_ROLLBACK; + + try { + Rectangle cellBounds = cell.getBounds(); + ILayer layer = cell.getLayer(); + + int columnPosition = cell.getColumnPosition(); + int rowPosition = cell.getRowPosition(); + + List<String> configLabels = cell.getConfigLabels().getLabels(); + + ICellEditor cellEditor = (ICellEditor)configRegistry.getConfigAttribute(EditConfigAttributes.CELL_EDITOR, DisplayMode.EDIT, configLabels); + + // Try to open an in-line editor before falling back to a dialog + if(cellEditor.openInline(configRegistry, configLabels)) { + MyInlineEditHandler editHandler = new MyInlineEditHandler(layer, columnPosition, rowPosition); + + Rectangle editorBounds = layer.getLayerPainter().adjustCellBounds(columnPosition, rowPosition, new Rectangle(cellBounds.x, cellBounds.y, cellBounds.width, cellBounds.height)); + + cellEditor.activateCell(parent, initialCanonicalValue, EditModeEnum.INLINE, editHandler, cell, configRegistry); + + Control editorControl = cellEditor.getEditorControl(); + if((editorControl != null) && (!(editorControl.isDisposed()))) { + editorControl.setBounds(editorBounds); + + cellEditor.addEditorControlListeners(); + ActiveCellEditorRegistry.registerActiveCellEditor(cellEditor); + } + + // Command succeeded but should not appear on the undo stack because we haven't completed an edit (only activated the cell editor), + // unless the cell editor is like the CheckBoxCellEditor that commits upon activation + result = editHandler.isCommitted() ? ExecutionStatusKind.OK_COMPLETE : ExecutionStatusKind.OK_ROLLBACK; + } else { + // The dialog case + List<ILayerCell> cells = new ArrayList<ILayerCell>(1); + cells.add(cell); + result = editCells(cells, parent, initialCanonicalValue, configRegistry); + } + } catch (OperationCanceledException e) { + // OK. The user cancelled a dialog or some such + result = ExecutionStatusKind.FAIL_ROLLBACK; + } catch (Exception e) { + Activator.log.error("Uncaught exception in table cell editor activation.", e); //$NON-NLS-1$ + } + + return result; + } + + // From Nebula EditController (with minor tweaks) + protected ExecutionStatusKind editCells(List<ILayerCell> cells, Composite parent, Object initialCanonicalValue, IConfigRegistry configRegistry) { + if((cells == null) || (cells.isEmpty())) { + return ExecutionStatusKind.FAIL_ROLLBACK; + } + + ICellEditor cellEditor = (ICellEditor)configRegistry.getConfigAttribute(EditConfigAttributes.CELL_EDITOR, DisplayMode.EDIT, ((ILayerCell)cells.get(0)).getConfigLabels().getLabels()); + + if((cells.size() != 1) && ((cells.size() <= 1) || !(supportMultiEdit(cells, cellEditor, configRegistry)))) { + return ExecutionStatusKind.FAIL_ROLLBACK; + } + + ExecutionStatusKind result = ExecutionStatusKind.FAIL_ROLLBACK; + + ICellEditDialog dialog = CellEditDialogFactory.createCellEditDialog((parent != null) ? parent.getShell() : null, initialCanonicalValue, (ILayerCell)cells.get(0), cellEditor, configRegistry); + + int returnValue = dialog.open(); + + if(returnValue == Window.OK) { + // The edit was completed and should appear on the undo stack + result = ExecutionStatusKind.OK_COMPLETE; + + for(ILayerCell selectedCell : cells) { + Object editorValue = dialog.getCommittedValue(); + if(dialog.getEditType() != EditTypeEnum.SET) { + editorValue = dialog.calculateValue(selectedCell.getDataValue(), editorValue); + } + ILayer layer = selectedCell.getLayer(); + + layer.doCommand(new UpdateDataCommand(layer, selectedCell.getColumnPosition(), selectedCell.getRowPosition(), editorValue)); + } + } + + return result; + } + + // From Nebula EditController (with minor tweaks) + private static boolean supportMultiEdit(List<ILayerCell> cells, ICellEditor cellEditor, IConfigRegistry configRegistry) { + for(ILayerCell cell : cells) { + if(!(cellEditor.supportMultiEdit(configRegistry, cell.getConfigLabels().getLabels()))) { + return false; + } + } + return true; + } + + // + // Nested types + // + + private static class MyInlineEditHandler extends InlineEditHandler { + + private boolean committed; + + MyInlineEditHandler(ILayer layer, int columnPosition, int rowPosition) { + super(layer, columnPosition, rowPosition); + } + + @Override + public boolean commit(Object canonicalValue, MoveDirectionEnum direction) { + boolean result = super.commit(canonicalValue, direction); + + committed = result || committed; + + return result; + } + + boolean isCommitted() { + return committed; + } + } +} diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/layer/PapyrusGridLayer.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/layer/PapyrusGridLayer.java index f0dc17d9864..0194de0f87e 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/layer/PapyrusGridLayer.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/layer/PapyrusGridLayer.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,13 +9,18 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.layer;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.edit.command.EditCellCommand;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.papyrus.infra.nattable.configuration.PapyrusGridLayerConfiguration;
+import org.eclipse.papyrus.infra.nattable.handler.TransactionalEditCellCommandHandler;
/**
* This grid layer ovverride the default edition behavior
@@ -25,6 +30,8 @@ import org.eclipse.papyrus.infra.nattable.configuration.PapyrusGridLayerConfigur */
public class PapyrusGridLayer extends GridLayer {
+ private final TransactionalEditingDomain domain;
+
/**
*
* Constructor.
@@ -34,8 +41,10 @@ public class PapyrusGridLayer extends GridLayer { * @param rowHeaderLayer
* @param cornerLayer
*/
- public PapyrusGridLayer(ILayer bodyLayer, ILayer columnHeaderLayer, ILayer rowHeaderLayer, ILayer cornerLayer) {
+ public PapyrusGridLayer(TransactionalEditingDomain domain, ILayer bodyLayer, ILayer columnHeaderLayer, ILayer rowHeaderLayer, ILayer cornerLayer) {
super(bodyLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);
+
+ this.domain = domain;
}
/**
@@ -48,8 +57,10 @@ public class PapyrusGridLayer extends GridLayer { * @param cornerLayer
* @param useDefaultConfiguration
*/
- public PapyrusGridLayer(ILayer bodyLayer, ILayer columnHeaderLayer, ILayer rowHeaderLayer, ILayer cornerLayer, boolean useDefaultConfiguration) {
+ public PapyrusGridLayer(TransactionalEditingDomain domain, ILayer bodyLayer, ILayer columnHeaderLayer, ILayer rowHeaderLayer, ILayer cornerLayer, boolean useDefaultConfiguration) {
super(bodyLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer, useDefaultConfiguration);
+
+ this.domain = domain;
}
/**
@@ -58,8 +69,10 @@ public class PapyrusGridLayer extends GridLayer { *
* @param useDefaultConfiguration
*/
- public PapyrusGridLayer(boolean useDefaultConfiguration) {
+ public PapyrusGridLayer(TransactionalEditingDomain domain, boolean useDefaultConfiguration) {
super(useDefaultConfiguration);
+
+ this.domain = domain;
}
@Override
@@ -71,7 +84,14 @@ public class PapyrusGridLayer extends GridLayer { }
}
+ @Override
+ public void registerCommandHandler(ILayerCommandHandler<?> commandHandler) {
+ // Override the default edit handler
+ if(commandHandler.getCommandClass() == EditCellCommand.class) {
+ commandHandler = new TransactionalEditCellCommandHandler(domain);
+ }
-
+ super.registerCommandHandler(commandHandler);
+ }
}
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/table/AbstractNattableWidgetManager.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/table/AbstractNattableWidgetManager.java index b4bf438bb2b..8cde6c07269 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/table/AbstractNattableWidgetManager.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/table/AbstractNattableWidgetManager.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.manager.table;
@@ -17,6 +18,7 @@ import java.util.List; import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
+import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
@@ -182,7 +184,7 @@ public abstract class AbstractNattableWidgetManager implements INattableModelMan final IDataProvider cornerDataProvider = new DefaultCornerDataProvider(this.columnHeaderDataProvider, this.rowHeaderDataProvider);
final CornerLayer cornerLayer = new CornerLayer(new DataLayer(cornerDataProvider), this.rowHeaderLayerStack, this.columnHeaderLayerStack);
cornerLayer.addConfiguration(new CornerConfiguration(this));
- this.gridLayer = new PapyrusGridLayer(this.bodyLayerStack, this.columnHeaderLayerStack, this.rowHeaderLayerStack, cornerLayer);
+ this.gridLayer = new PapyrusGridLayer(TransactionUtil.getEditingDomain(tableContext), this.bodyLayerStack, this.columnHeaderLayerStack, this.rowHeaderLayerStack, cornerLayer);
this.gridLayer.addConfiguration(new DefaultPrintBindings());
this.natTable = new NatTable(parent, this.gridLayer, false);
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/painter/CustomCheckBoxPainter.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/painter/CustomCheckBoxPainter.java index 449d7ffeb47..e3c566b7d81 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/painter/CustomCheckBoxPainter.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/painter/CustomCheckBoxPainter.java @@ -30,6 +30,11 @@ import org.eclipse.swt.graphics.Rectangle; public class CustomCheckBoxPainter extends CheckBoxPainter {
/**
+ * the text painter used to paint N/A
+ */
+ private TextPainter textPainter = new CustomizedCellPainter();
+
+ /**
*
* @see org.eclipse.nebula.widgets.nattable.painter.cell.ImagePainter#getCellPainterAt(int, int,
* org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell, org.eclipse.swt.graphics.GC, org.eclipse.swt.graphics.Rectangle,
@@ -48,8 +53,7 @@ public class CustomCheckBoxPainter extends CheckBoxPainter { try {
isChecked(cell, configRegistry);
} catch (Exception e) {
- TextPainter painter = new CustomizedCellPainter();
- return painter.getCellPainterAt(x, y, cell, gc, bounds, configRegistry);
+ return this;
}
return super.getCellPainterAt(x, y, cell, gc, bounds, configRegistry);
}
@@ -69,8 +73,7 @@ public class CustomCheckBoxPainter extends CheckBoxPainter { try {
isChecked(cell, configRegistry);
} catch (Exception e) {
- TextPainter painter = new CustomizedCellPainter();
- painter.paintCell(cell, gc, bounds, configRegistry);
+ this.textPainter.paintCell(cell, gc, bounds, configRegistry);
return;
}
super.paintCell(cell, gc, bounds, configRegistry);
@@ -91,8 +94,7 @@ public class CustomCheckBoxPainter extends CheckBoxPainter { try {
isChecked(cell, configRegistry);
} catch (Exception e) {
- TextPainter painter = new CustomizedCellPainter();
- return painter.getPreferredWidth(cell, gc, configRegistry);
+ return textPainter.getPreferredWidth(cell, gc, configRegistry);
}
return super.getPreferredWidth(cell, gc, configRegistry);
}
@@ -112,8 +114,7 @@ public class CustomCheckBoxPainter extends CheckBoxPainter { try {
isChecked(cell, configRegistry);
} catch (Exception e) {
- TextPainter painter = new CustomizedCellPainter();
- return painter.getPreferredHeight(cell, gc, configRegistry);
+ return textPainter.getPreferredHeight(cell, gc, configRegistry);
}
return super.getPreferredHeight(cell, gc, configRegistry);
}
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.decoration/src/org/eclipse/papyrus/infra/services/decoration/util/Decoration.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.decoration/src/org/eclipse/papyrus/infra/services/decoration/util/Decoration.java index 7ccf3b66884..c9b0c3d4d30 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.decoration/src/org/eclipse/papyrus/infra/services/decoration/util/Decoration.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.decoration/src/org/eclipse/papyrus/infra/services/decoration/util/Decoration.java @@ -286,7 +286,7 @@ public class Decoration implements IPapyrusDecoration { }
}
}
- if (message.length() > 0) {
+ if ((message != null) && message.length() > 0) {
return message;
}
else {
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/plugin.xml b/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/plugin.xml index 8b67866e84a..3c5b99602e9 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/plugin.xml +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/plugin.xml @@ -1,5 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
+<!--
+ Copyright (c) 2010, 2014 CEA and others.
+
+ 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 - Initial API and implementation
+ Christian W. Damus (CEA) - bug 323802
+
+-->
<plugin>
<extension point="org.eclipse.gmf.runtime.emf.type.core.elementTypeBindings">
@@ -40,7 +53,9 @@ <!-- ElementType that deals with View deletion when their related model element is deleted -->
<elementType ref="org.eclipse.gmf.runtime.diagram.core.advice.notationDepdendents"/>
<elementType ref="org.eclipse.gmf.runtime.diagram.core.advice.removeBookmarks"/>
-
+
+ <!-- Check for attempts to edit read-only objects that cannot reasonably be made writeable. -->
+ <advice ref="org.eclipse.papyrus.infra.emf.readOnlyAdvice" />
</binding>
</extension>
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/src/org/eclipse/papyrus/infra/services/edit/internal/ElementEditServiceProvider.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/src/org/eclipse/papyrus/infra/services/edit/internal/ElementEditServiceProvider.java index c6098144371..be57c143bd2 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/src/org/eclipse/papyrus/infra/services/edit/internal/ElementEditServiceProvider.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.edit/src/org/eclipse/papyrus/infra/services/edit/internal/ElementEditServiceProvider.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010, 2013 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -11,6 +11,7 @@ *
* Yann Tanguy (CEA LIST) yann.tanguy@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - support read-only objects (CDO)
+ * Christian W. Damus (CEA) - bug 323802
*
*****************************************************************************/
package org.eclipse.papyrus.infra.services.edit.internal;
@@ -21,6 +22,7 @@ import java.util.List; import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
import org.eclipse.gmf.runtime.emf.type.core.IClientContext;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
@@ -120,7 +122,8 @@ public class ElementEditServiceProvider implements IElementEditServiceProvider { }
private boolean isReadOnly(EObject object) {
- return EMFHelper.isReadOnly(object);
+ EditingDomain domain = EMFHelper.resolveEditingDomain(object);
+ return EMFHelper.isReadOnly(object, domain) && !EMFHelper.canMakeWritable(object, domain);
}
/**
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/MarkersMonitorService.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/MarkersMonitorService.java index cfdb91c8c0f..75baa651f37 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/MarkersMonitorService.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/MarkersMonitorService.java @@ -1,23 +1,24 @@ /*****************************************************************************
* Copyright (c) 2011, 2013 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:
- * Amine EL KOUHEN (CEA LIST/LIFL) - Amine.Elkouhen@cea.fr
+ * Amine EL KOUHEN (CEA LIST/LIFL) - Amine.Elkouhen@cea.fr
* Arnaud Cuccuru (CEA LIST) - arnaud.cuccuru@cea.fr
* Christian W. Damus (CEA) - refactor for non-workspace abstraction of problem markers (CDO)
- *
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.services.markerlistener;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
@@ -34,6 +35,7 @@ import org.eclipse.papyrus.infra.core.services.ServiceException; import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
import org.eclipse.papyrus.infra.services.markerlistener.providers.IMarkerMonitor;
+import org.eclipse.papyrus.infra.services.markerlistener.providers.IMarkerProvider;
import org.eclipse.papyrus.infra.services.markerlistener.providers.MarkerMonitorRegistry;
import org.eclipse.papyrus.infra.services.markerlistener.util.MarkerListenerUtils;
@@ -57,7 +59,7 @@ public class MarkersMonitorService implements IService { /**
* Gets the services registry.
- *
+ *
* @return the services registry
*/
public ServicesRegistry getServicesRegistry() {
@@ -67,7 +69,7 @@ public class MarkersMonitorService implements IService { /**
* Sets the services registry.
- *
+ *
* @param servicesRegistry
* the new services registry
*/
@@ -84,7 +86,7 @@ public class MarkersMonitorService implements IService { /**
* @see org.eclipse.papyrus.infra.core.services.IService#init(org.eclipse.papyrus.infra.core.services.ServicesRegistry)
- *
+ *
* @param servicesRegistry
* @throws ServiceException
*/
@@ -118,7 +120,7 @@ public class MarkersMonitorService implements IService { /**
* @see org.eclipse.papyrus.infra.core.services.IService#startService()
- *
+ *
* @throws ServiceException
*/
public void startService() throws ServiceException {
@@ -136,7 +138,7 @@ public class MarkersMonitorService implements IService { /**
* @see org.eclipse.papyrus.infra.core.services.IService#disposeService()
- *
+ *
* @throws ServiceException
*/
public void disposeService() throws ServiceException {
@@ -182,8 +184,11 @@ public class MarkersMonitorService implements IService { }
public Collection<? extends IPapyrusMarker> getMarkers(Resource resource, String type, boolean includeSubtypes) throws CoreException {
-
- return MarkerListenerUtils.getMarkerProvider(resource).getMarkers(resource, type, includeSubtypes);
+ List<IPapyrusMarker> result = new LinkedList<IPapyrusMarker>();
+ for(IMarkerProvider provider : MarkerListenerUtils.getMarkerProviders(resource)) {
+ result.addAll(provider.getMarkers(resource, type, includeSubtypes));
+ }
+ return result;
}
private IMarkerEventListener createRelayListener() {
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/providers/MarkerProviderRegistry.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/providers/MarkerProviderRegistry.java index e17ed9dcc20..314c1059b9f 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/providers/MarkerProviderRegistry.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/providers/MarkerProviderRegistry.java @@ -1,6 +1,6 @@ /***************************************************************************** * Copyright (c) 2013 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 @@ -15,6 +15,7 @@ import static org.eclipse.papyrus.infra.services.markerlistener.util.MarkerListe import java.util.Collection; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -59,17 +60,16 @@ public class MarkerProviderRegistry { * delegation. */ private void prune() { - if (needPrune) { + if(needPrune) { needPrune = false; - for (ListIterator<IMarkerProvider> iter = providers.listIterator(); iter - .hasNext();) { + for(ListIterator<IMarkerProvider> iter = providers.listIterator(); iter.hasNext();) { IMarkerProvider next = iter.next(); - if (next == IMarkerProvider.NULL) { + if(next == IMarkerProvider.NULL) { iter.remove(); - } else if (next instanceof MyRegistryReader.Descriptor) { - MyRegistryReader.Descriptor desc = (MyRegistryReader.Descriptor) next; - if (desc.instance != null) { + } else if(next instanceof MyRegistryReader.Descriptor) { + MyRegistryReader.Descriptor desc = (MyRegistryReader.Descriptor)next; + if(desc.instance != null) { iter.set(desc.instance); } } @@ -77,14 +77,22 @@ public class MarkerProviderRegistry { } } + /** + * @param resource + * @return + * + * @deprecated + * MarkerProviders should not be exclusive. Use #getMarkerProviders(Resource) instead + */ + @Deprecated public IMarkerProvider getMarkerProvider(Resource resource) { IMarkerProvider result = IMarkerProvider.NULL; - synchronized (providers) { + synchronized(providers) { prune(); - for (IMarkerProvider next : providers) { - if (next.canProvideMarkersFor(resource)) { + for(IMarkerProvider next : providers) { + if(next.canProvideMarkersFor(resource)) { result = next; break; } @@ -94,19 +102,34 @@ public class MarkerProviderRegistry { return result; } + public List<IMarkerProvider> getMarkerProviders(Resource resource) { + List<IMarkerProvider> result = new LinkedList<IMarkerProvider>(); + + synchronized(providers) { + prune(); + + for(IMarkerProvider next : providers) { + if(next.canProvideMarkersFor(resource)) { + result.add(next); + } + } + } + + return result; + } + private void removeProvider(String className) { - synchronized (providers) { - for (Iterator<IMarkerProvider> iter = providers.iterator(); iter - .hasNext();) { + synchronized(providers) { + for(Iterator<IMarkerProvider> iter = providers.iterator(); iter.hasNext();) { IMarkerProvider next = iter.next(); - if (next instanceof MyRegistryReader.Descriptor) { - MyRegistryReader.Descriptor desc = (MyRegistryReader.Descriptor) next; - if (className.equals(desc.getClassName())) { + if(next instanceof MyRegistryReader.Descriptor) { + MyRegistryReader.Descriptor desc = (MyRegistryReader.Descriptor)next; + if(className.equals(desc.getClassName())) { iter.remove(); break; } - } else if (className.equals(next.getClass().getName())) { + } else if(className.equals(next.getClass().getName())) { iter.remove(); break; } @@ -118,8 +141,7 @@ public class MarkerProviderRegistry { // Nested types // - private class MyRegistryReader - extends RegistryReader { + private class MyRegistryReader extends RegistryReader { private static final String E_ENABLEMENT = "enablement"; @@ -132,24 +154,21 @@ public class MarkerProviderRegistry { private boolean inEnablement; MyRegistryReader() { - super(Platform.getExtensionRegistry(), Activator.PLUGIN_ID, - EXT_POINT); + super(Platform.getExtensionRegistry(), Activator.PLUGIN_ID, EXT_POINT); } @Override protected boolean readElement(IConfigurationElement element, boolean add) { - return add - ? handleAdd(element) - : handleRemove(element); + return add ? handleAdd(element) : handleRemove(element); } private boolean handleAdd(IConfigurationElement element) { boolean result = false; - if (E_PROVIDER.equals(element.getName())) { + if(E_PROVIDER.equals(element.getName())) { inEnablement = false; - if (element.getAttribute(A_CLASS) == null) { + if(element.getAttribute(A_CLASS) == null) { logMissingAttribute(element, A_CLASS); } else { currentDescriptor = new Descriptor(element, A_CLASS); @@ -157,13 +176,11 @@ public class MarkerProviderRegistry { } result = true; - } else if (E_ENABLEMENT.equals(element.getName())) { - if (currentDescriptor != null) { + } else if(E_ENABLEMENT.equals(element.getName())) { + if(currentDescriptor != null) { inEnablement = true; try { - currentDescriptor - .setMatchResourceExpression(ExpressionConverter - .getDefault().perform(element)); + currentDescriptor.setMatchResourceExpression(ExpressionConverter.getDefault().perform(element)); result = true; } catch (CoreException e) { Activator.getDefault().getLog().log(e.getStatus()); @@ -179,9 +196,9 @@ public class MarkerProviderRegistry { private boolean handleRemove(IConfigurationElement element) { boolean result = true; - if (E_PROVIDER.equals(element.getName())) { + if(E_PROVIDER.equals(element.getName())) { String className = element.getAttribute(A_CLASS); - if (className == null) { + if(className == null) { logMissingAttribute(element, A_CLASS); result = false; } else { @@ -192,9 +209,7 @@ public class MarkerProviderRegistry { return result; } - private class Descriptor - extends PluginClassDescriptor - implements IMarkerProvider { + private class Descriptor extends PluginClassDescriptor implements IMarkerProvider { private Expression matchResource; @@ -213,13 +228,11 @@ public class MarkerProviderRegistry { } IMarkerProvider getInstance() { - if (instance == null) { + if(instance == null) { try { - instance = (IMarkerProvider) createInstance(); + instance = (IMarkerProvider)createInstance(); } catch (Exception e) { - Activator.log.error( - "Failed to instantiate marker provider extension.", - e); + Activator.log.error("Failed to instantiate marker provider extension.", e); instance = IMarkerProvider.NULL; } @@ -230,17 +243,14 @@ public class MarkerProviderRegistry { } public boolean canProvideMarkersFor(Resource resource) { - return (instance == null) - ? evaluateEnablement(resource) - : instance.canProvideMarkersFor(resource); + return (instance == null) ? evaluateEnablement(resource) : instance.canProvideMarkersFor(resource); } private boolean evaluateEnablement(Resource resource) { boolean result; - if (matchResource != null) { - IEvaluationContext ctx = new EvaluationContext(null, - resource); + if(matchResource != null) { + IEvaluationContext ctx = new EvaluationContext(null, resource); ctx.addVariable("isFile", getFile(resource) != null); @@ -259,46 +269,34 @@ public class MarkerProviderRegistry { return result; } - public Collection<? extends IPapyrusMarker> getMarkers( - Resource resource, String type, boolean includeSubtypes) - throws CoreException { + public Collection<? extends IPapyrusMarker> getMarkers(Resource resource, String type, boolean includeSubtypes) throws CoreException { - return getInstance() - .getMarkers(resource, type, includeSubtypes); + return getInstance().getMarkers(resource, type, includeSubtypes); } - public void createMarkers(Resource resource, Diagnostic diagnostic, - IProgressMonitor monitor) - throws CoreException { + public void createMarkers(Resource resource, Diagnostic diagnostic, IProgressMonitor monitor) throws CoreException { getInstance().createMarkers(resource, diagnostic, monitor); } @Deprecated - public void deleteMarkers(EObject object, IProgressMonitor monitor) - throws CoreException { + public void deleteMarkers(EObject object, IProgressMonitor monitor) throws CoreException { getInstance().deleteMarkers(object, monitor); } @Deprecated - public void deleteMarkers(Resource resource, - IProgressMonitor monitor) - throws CoreException { + public void deleteMarkers(Resource resource, IProgressMonitor monitor) throws CoreException { getInstance().deleteMarkers(resource, monitor); } - public void deleteMarkers(EObject object, IProgressMonitor monitor, - String markerType, boolean includeSubtypes) - throws CoreException { + public void deleteMarkers(EObject object, IProgressMonitor monitor, String markerType, boolean includeSubtypes) throws CoreException { getInstance().deleteMarkers(object, monitor, markerType, includeSubtypes); - + } - public void deleteMarkers(Resource resource, - IProgressMonitor monitor, String markerType, - boolean includeSubtypes) throws CoreException { + public void deleteMarkers(Resource resource, IProgressMonitor monitor, String markerType, boolean includeSubtypes) throws CoreException { getInstance().deleteMarkers(resource, monitor, markerType, includeSubtypes); } } diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/util/MarkerListenerUtils.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/util/MarkerListenerUtils.java index 01be0c76b9e..969b173f4d6 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/util/MarkerListenerUtils.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/util/MarkerListenerUtils.java @@ -1,22 +1,23 @@ /*****************************************************************************
* Copyright (c) 2011, 2013 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:
- * Amine EL KOUHEN (CEA LIST/LIFL) - Amine.Elkouhen@cea.fr
+ * Amine EL KOUHEN (CEA LIST/LIFL) - Amine.Elkouhen@cea.fr
* Christian W. Damus (CEA) - refactor for non-workspace abstraction of problem markers (CDO)
* Christian W. Damus (CEA) - support marker type hierarchy in CDO problem markers (CDO)
- *
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.services.markerlistener.util;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
@@ -121,10 +122,21 @@ public class MarkerListenerUtils { return null;
}
+ /**
+ * @param resource
+ * @return
+ * @deprecated
+ * MarkerProviders should not be exclusive. Use #getMarkerProviders(Resource) instead
+ */
+ @Deprecated
public static IMarkerProvider getMarkerProvider(Resource resource) {
return MarkerProviderRegistry.INSTANCE.getMarkerProvider(resource);
}
+ public static List<IMarkerProvider> getMarkerProviders(Resource resource) {
+ return MarkerProviderRegistry.INSTANCE.getMarkerProviders(resource);
+ }
+
public static IFile getFile(Resource resource) {
URI uri = resource.getURI();
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/strategies/AskUserStrategy.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/strategies/AskUserStrategy.java index 16ea2cb5d20..c99e64275fc 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/strategies/AskUserStrategy.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/strategies/AskUserStrategy.java @@ -1,6 +1,6 @@ /***************************************************************************** * Copyright (c) 2010, 2013 ATOS ORIGIN, CEA LIST, and others. - * + * * 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 @@ -10,7 +10,7 @@ * Tristan Faure (ATOS ORIGIN INTEGRATION) tristan.faure@atosorigin.com - Initial API and implementation * Christian W. Damus (CEA) - manage models by URI, not IFile (CDO) * Christian W. Damus (CEA LIST) - support control mode in CDO resources - * + * *****************************************************************************/ package org.eclipse.papyrus.infra.services.resourceloading.strategies; @@ -26,7 +26,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.papyrus.infra.core.editor.CoreMultiDiagramEditor; +import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor; import org.eclipse.papyrus.infra.core.resource.ModelSet; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager; import org.eclipse.papyrus.infra.core.services.ServiceException; @@ -53,9 +53,9 @@ import org.eclipse.ui.PlatformUI; /** * The strategy which ask user if the resource has to be loaded or not - * + * * @author tfaure - * + * */ public class AskUserStrategy implements ILoadingStrategy { @@ -97,7 +97,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * @see org.eclipse.papyrus.infra.services.resourceloading.ILoadingStrategy#loadResource(org.eclipse.papyrus.infra.core.resource.ModelSet, * org.eclipse.emf.common.util.URI) - * + * * @param modelSet * @param uri * @return @@ -106,7 +106,7 @@ public class AskUserStrategy implements ILoadingStrategy { // pathmap resource are always loaded boolean result = !modelSet.isUserModelResource(uri); URI initialURI = modelSet.getURIWithoutExtension(); - // if no listener is registered, a listener is added on the editor to remove the notifications + // if no listener is registered, a listener is added on the editor to remove the notifications // when the editor is closed the listener removes too the choices made by the user. addClosingEditorListener(initialURI); @@ -135,7 +135,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Create the ask notification to the user - * + * * @param modelSet * @param initialURI * @param trimFragment @@ -153,7 +153,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Add a listener closing the uri parameter - * + * * @param initialURI */ private void addClosingEditorListener(URI initialURI) { @@ -167,7 +167,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Remember that an uri has already be asked - * + * * @param initialURI * , the uri opened by the editor * @param guessed @@ -183,7 +183,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Check if the uri is already asked - * + * * @param initialURI * , the uri opened by the editor * @param toLoad @@ -201,7 +201,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * The extensions are saved to load all the specified resource if the user * wants to load a set of resources - * + * * @param uri * , the file to load * @param trimFragment @@ -222,20 +222,20 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Get the current editor - * + * * @return */ - protected CoreMultiDiagramEditor getCurrentEditor() { + protected IMultiDiagramEditor getCurrentEditor() { IEditorPart editor = getEditor(); - if(editor instanceof CoreMultiDiagramEditor) { - return (CoreMultiDiagramEditor)editor; + if(editor instanceof IMultiDiagramEditor) { + return (IMultiDiagramEditor)editor; } return null; } /** * Create the notification with Yes/No/Yes For All/No For All option - * + * * @param message * , the message to display * @param uri @@ -256,7 +256,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * NO for all registers the NoForAll URI and do nothing - * + * * @param uri * @param modelSet * @param initialURI @@ -295,7 +295,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Yes for All registers Yes For All URI and refresh the tabs to take in account the loaded elements - * + * * @param uri * @param modelSet * @param initialURI @@ -315,7 +315,7 @@ public class AskUserStrategy implements ILoadingStrategy { return new RefreshRunnable(modelSet, uri, initialURI, true, true) { @Override - public void run(CoreMultiDiagramEditor editor) { + public void run(IMultiDiagramEditor editor) { List<INotification> list = notifications.get(getInitialURI()); if(list != null) { for(INotification n : notifications.get(getInitialURI())) { @@ -355,7 +355,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * No runnable does not accept the URI asked - * + * * @param uri * @param modelSet * @param initialURI @@ -379,7 +379,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Yes registers the URI and refresh the tab to take in account the loaded elements - * + * * @param uri * @param modelSet * @param initialURI @@ -391,7 +391,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Register the notification created to the URI open by the editor - * + * * @param initialURI * @param notification */ @@ -434,9 +434,9 @@ public class AskUserStrategy implements ILoadingStrategy { /** * A basic runnable managing the load of a resource and a refresh of the tabs * If the editor is not opened or activated some listeners will be triggered to launch the refresh - * + * * @author tfaure - * + * */ private class LoadAndRefreshRunnable implements NotificationRunnable { @@ -516,7 +516,7 @@ public class AskUserStrategy implements ILoadingStrategy { protected void manageRefresh(IEditorReference ref, IEditorPart part) { addAuthorized(initialURI, uri); if(part != null) { - getRunnable().run((CoreMultiDiagramEditor)part); + getRunnable().run((IMultiDiagramEditor)part); } else { addPageListener(new EditorActivateListener(ref, modelSet, uri, initialURI, getRunnable())); } @@ -535,7 +535,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Add a page listener - * + * * @param listener * @return */ @@ -550,7 +550,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Register a listener of the perspective to know when the editor is finally closed - * + * * @param listener * @return */ @@ -564,7 +564,7 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Unregister a perspective listener - * + * * @param listener * @return */ @@ -592,20 +592,20 @@ public class AskUserStrategy implements ILoadingStrategy { protected static URI getURI(final IEditorInput input) { URI result; - + IFile file = (IFile)input.getAdapter(IFile.class); if((file != null) && (file.getFullPath() != null)) { result = URI.createPlatformResourceURI(file.getFullPath().removeFileExtension().toString(), true); } else { - result = (URI) input.getAdapter(URI.class); + result = (URI)input.getAdapter(URI.class); } return result; } - + /** * Notification containing the {@link URI} loaded - * + * */ public class EncapsulatedNotification implements INotification { @@ -633,9 +633,9 @@ public class AskUserStrategy implements ILoadingStrategy { /** * An empty {@link IPartListener} implementation - * + * * @author tfaure - * + * */ private class EditorAdapter implements IPartListener { @@ -658,9 +658,9 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Listener which is notifid when an editor is activated - * + * * @author tfaure - * + * */ private class EditorActivateListener extends EditorAdapter { @@ -675,8 +675,8 @@ public class AskUserStrategy implements ILoadingStrategy { @Override public void partActivated(IWorkbenchPart part) { - if(reference.getPart(false) == part && part instanceof CoreMultiDiagramEditor) { - refreshRunnable.run((CoreMultiDiagramEditor)part); + if(reference.getPart(false) == part && part instanceof IMultiDiagramEditor) { + refreshRunnable.run((IMultiDiagramEditor)part); removePageListener(this); } } @@ -685,20 +685,20 @@ public class AskUserStrategy implements ILoadingStrategy { /** * Listener which is notifid when an editor is closed - * + * * @author tfaure - * + * */ private class EditorCloseListener extends EditorAdapter { @Override public void partClosed(IWorkbenchPart part) { super.partClosed(part); - if(part instanceof CoreMultiDiagramEditor) { - CoreMultiDiagramEditor editor = (CoreMultiDiagramEditor)part; - + if(part instanceof IMultiDiagramEditor) { + IMultiDiagramEditor editor = (IMultiDiagramEditor)part; + URI uri = getURI(editor.getEditorInput()); - if (uri != null) { + if(uri != null) { uri = uri.trimFileExtension(); addPerspectiveListener(new EditorClosePerspectiveListener(uri)); removePageListener(this); @@ -711,9 +711,9 @@ public class AskUserStrategy implements ILoadingStrategy { /** * A perspective listener which choices of an user - * + * * @author tfaure - * + * */ protected class EditorClosePerspectiveListener implements IPerspectiveListener { @@ -744,9 +744,9 @@ public class AskUserStrategy implements ILoadingStrategy { /** * A runnable refreshing resource and/or pages - * + * * @author tfaure - * + * */ public class RefreshRunnable { @@ -770,7 +770,7 @@ public class AskUserStrategy implements ILoadingStrategy { this.refreshTab = refreshTab; } - public void run(CoreMultiDiagramEditor editor) { + public void run(IMultiDiagramEditor editor) { final Set<URI> alreadyLoaded = new HashSet<URI>(); try { pageMngr = editor.getServicesRegistry().getService(IPageManager.class); diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/util/LoadingUtils.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/util/LoadingUtils.java index 1a8fb06f784..b72d2528e05 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/util/LoadingUtils.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/util/LoadingUtils.java @@ -1,7 +1,7 @@ /*****************************************************************************
* Copyright (c) 2011 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
@@ -27,20 +27,16 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.util.EditPartUtilities;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
-import org.eclipse.papyrus.infra.core.editor.CoreMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
-import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
-import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelMngr;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
import org.eclipse.papyrus.infra.services.resourceloading.Activator;
@@ -77,8 +73,8 @@ public class LoadingUtils { IProgressMonitor monitor = dialog.getProgressMonitor();
IEditorPart editor = getEditor();
- if(editor instanceof CoreMultiDiagramEditor) {
- CoreMultiDiagramEditor core = (CoreMultiDiagramEditor)editor;
+ if(editor instanceof IMultiDiagramEditor) {
+ IMultiDiagramEditor core = (IMultiDiagramEditor)editor;
try {
IPageManager pageMngr = core.getServicesRegistry().getService(IPageManager.class);
List<Object> allPages = pageMngr.allPages();
@@ -150,7 +146,7 @@ public class LoadingUtils { * path of resources to unload without file extension
*/
public static void unloadResourcesFromModelSet(ModelSet modelSet, URI uriWithoutFileExtension) {
- unloadResourcesFromModelSet(modelSet, uriWithoutFileExtension, true);
+ unloadResourcesFromModelSet(modelSet, uriWithoutFileExtension, false);
}
/**
@@ -210,12 +206,23 @@ public class LoadingUtils { // (registered libraries in the model set have different URIs - e.g. due to a pathmap -
// although they point to the same location).
// TODO: Use a single detection mechanism in ResourceUpdateService and here
- String unloadPlatformString = uriWithoutFileExtension.toPlatformString(true);
- URIConverter uriConverter = modelSet.getURIConverter();
+ String unloadPlatformString;
+ if(uriWithoutFileExtension.isPlatform()) {
+ unloadPlatformString = uriWithoutFileExtension.toPlatformString(true);
+ } else {
+ unloadPlatformString = URI.decode(uriWithoutFileExtension.toString());
+ }
+ //URIConverter uriConverter = modelSet.getURIConverter();
// unload resource
for(Resource res : new ArrayList<Resource>(modelSet.getResources())) {
- URI normalizedURI = uriConverter.normalize(res.getURI());
- String platformString = normalizedURI.trimFileExtension().toPlatformString(true);
+ URI normalizedURI = res.getURI();
+ String platformString;
+ if(normalizedURI.isPlatform()) {
+ platformString = normalizedURI.trimFileExtension().toPlatformString(true);
+ } else {
+ platformString = URI.decode(normalizedURI.trimFileExtension().toString());
+ }
+
if((platformString != null) && platformString.equals(unloadPlatformString)) {
// unload this resource
modelSet.getResources().remove(res);
@@ -248,7 +255,13 @@ public class LoadingUtils { // refresh page's diagram if needed
Diagram diag = ((Diagram)eobject);
if(pageMngr.isOpen(diag)) {
- Object part = ((IDiagramGraphicalViewer)core.getAdapter(IDiagramGraphicalViewer.class)).getEditPartRegistry().get(diag);
+
+ IDiagramGraphicalViewer graphicalViewer = (IDiagramGraphicalViewer)core.getAdapter(IDiagramGraphicalViewer.class);
+ if(graphicalViewer == null) {
+ continue;
+ }
+
+ Object part = graphicalViewer.getEditPartRegistry().get(diag);
if(part instanceof GraphicalEditPart) {
// refresh nodes
for(Object child : EditPartUtilities.getAllChildren((GraphicalEditPart)part)) {
diff --git a/plugins/infra/services/org.eclipse.papyrus.infra.services.validation/src/org/eclipse/papyrus/infra/services/validation/commands/AbstractValidateCommand.java b/plugins/infra/services/org.eclipse.papyrus.infra.services.validation/src/org/eclipse/papyrus/infra/services/validation/commands/AbstractValidateCommand.java index 8918cea877b..dff5bbd8114 100644 --- a/plugins/infra/services/org.eclipse.papyrus.infra.services.validation/src/org/eclipse/papyrus/infra/services/validation/commands/AbstractValidateCommand.java +++ b/plugins/infra/services/org.eclipse.papyrus.infra.services.validation/src/org/eclipse/papyrus/infra/services/validation/commands/AbstractValidateCommand.java @@ -21,6 +21,7 @@ import java.util.Iterator; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.util.BasicDiagnostic; @@ -64,6 +65,8 @@ abstract public class AbstractValidateCommand extends AbstractTransactionalComma protected IPapyrusDiagnostician diagnostician; + protected boolean showUIfeedback; + /** * Creates a new ValidationCommand * @@ -94,9 +97,18 @@ abstract public class AbstractValidateCommand extends AbstractTransactionalComma this.domain = domain; this.selectedElement = selectedElement; this.diagnostician= diagnostician; + this.showUIfeedback = true; // default is true; } /** + * don't use a progress monitor to show validation progress. This is quite useful + * for diagnostics that are executed on a (shallow) subtree and do not take much time. + */ + public void disableUIFeedback() { + this.showUIfeedback = false; + } + + /** * @return The resource on which markers should be applied. */ protected Resource getValidationResource() { @@ -141,7 +153,12 @@ abstract public class AbstractValidateCommand extends AbstractTransactionalComma try { // runs the operation, and shows progress. diagnostic = null; - new ProgressMonitorDialog(shell).run(true, true, runValidationWithProgress); + if (showUIfeedback) { + new ProgressMonitorDialog(shell).run(true, true, runValidationWithProgress); + } + else { + runValidationWithProgress.run(new NullProgressMonitor()); + } if(diagnostic != null) { int markersToCreate = diagnostic.getChildren().size(); if((markersToCreate > 0) && PreferenceUtils.getAutoShowValidation()) { @@ -154,7 +171,12 @@ abstract public class AbstractValidateCommand extends AbstractTransactionalComma } // don't fork this dialog, i.e. run it in the UI thread. This avoids that the diagrams are constantly refreshing *while* // markers/decorations are changing. This greatly enhances update performance. See also bug 400593 - new ProgressMonitorDialog(shell).run(false, true, createMarkersWithProgress); + if (showUIfeedback) { + new ProgressMonitorDialog(shell).run(false, true, createMarkersWithProgress); + } + else { + createMarkersWithProgress.run(new NullProgressMonitor()); + } } } catch (Exception exception) { EMFEditUIPlugin.INSTANCE.log(exception); diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java index 8f326b0d196..28e586aa906 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.creation;
@@ -71,16 +72,9 @@ public class BooleanEditionFactory extends StringEditionFactory { super(title, label, new BooleanInputValidator());
}
- /**
- *
- * @see org.eclipse.papyrus.infra.widgets.creation.StringEditionFactory#createObject(org.eclipse.swt.widgets.Control)
- *
- * @param widget
- * @return
- */
@Override
- public Object createObject(Control widget) {
- String txt = super.createObject(widget).toString();
+ public Object createObject(Control widget, Object context) {
+ String txt = super.createObject(widget, context).toString();
if(txt != null) {
return Boolean.parseBoolean(txt);
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java new file mode 100644 index 00000000000..dc69d248b2b --- /dev/null +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.widgets.creation; + +import java.util.concurrent.Callable; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.papyrus.infra.widgets.Activator; + + +/** + * An interface that ensures execution of model changes as an atomic unit that is potentially undoable and redoable, such as on a "command stack" + * (whatever form it may take). + */ +public interface IAtomicOperationExecutor { + + IAtomicOperationExecutor DEFAULT = new Default(); + + /** + * Execute a runnable (an operation returning no result). + * + * @param operation + * the operation to execute + * @param label + * an optional label to associate with the operation for presentation in, for example, the Edit menu's Undo/Redo operations + */ + void execute(Runnable operation, String label); + + /** + * Execute a callable (an operation returning a result). + * + * @param operation + * the operation to execute + * @param label + * an optional label to associate with the operation for presentation in, for example, the Edit menu's Undo/Redo operations + * @return the {@code operation}'s result + */ + <V> V execute(Callable<V> operation, String label); + + // + // Nested types + // + + class Default implements IAtomicOperationExecutor { + + public void execute(final Runnable operation, String label) { + try { + operation.run(); + } catch (OperationCanceledException e) { + // We cannot really implement cancel because there is not command/transaction to roll back + } + } + + public <V> V execute(final Callable<V> operation, String label) { + class CallableWrapper implements Runnable { + + V result; + + @Override + public void run() { + try { + result = operation.call(); + } catch (OperationCanceledException e) { + // Don't trap this one + throw e; + } catch (Exception e) { + Activator.log.error("Callable operation failed.", e); //$NON-NLS-1$ + throw new OperationCanceledException(); // roll back + } + } + } + + CallableWrapper wrapper = new CallableWrapper(); + + execute(wrapper, label); + + return wrapper.result; + } + + } +} diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java index 3f2c4b05b43..a254d03cda8 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
- *
* 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
@@ -9,6 +8,7 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.creation;
@@ -69,16 +69,9 @@ public class IntegerEditionFactory extends StringEditionFactory { this(title, label, new IntegerInputValidator());
}
- /**
- *
- * @see org.eclipse.papyrus.infra.widgets.creation.StringEditionFactory#createObject(org.eclipse.swt.widgets.Control)
- *
- * @param widget
- * @return
- */
@Override
- public Object createObject(Control widget) {
- String txt = super.createObject(widget).toString();
+ public Object createObject(Control widget, Object context) {
+ String txt = super.createObject(widget, context).toString();
if(txt != null) {
return Integer.parseInt(txt);
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java index 25586368f79..f6fac32bac1 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.creation;
@@ -50,10 +52,13 @@ public interface ReferenceValueFactory { * @param widget
* The widget calling this factory. It can be used for example to retrieve
* the Display for opening a Dialog
+ * @param context
+ * The object being edited, in which context the new object is to be created and which will as a result have a reference to the new object.
+ * If there is no context object (creation of a free-floating object) or it cannot be determined, this may be {@code null}
* @return
* The newly created object, or null if no object has been created
*/
- public Object createObject(Control widget);
+ public Object createObject(Control widget, Object context);
/**
* The objects have been validated (For example, the user pressed "Ok")
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java index 837eaddffe9..cadc95e9bc0 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
+ * Copyright (c) 2011, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.creation;
@@ -90,7 +92,7 @@ public class StringEditionFactory implements ReferenceValueFactory { return true;
}
- public Object createObject(Control widget) {
+ public Object createObject(Control widget, Object context) {
InputDialog dialog = new InputDialog(widget.getShell(), title, label, "", validator); //$NON-NLS-1$
if(contentProvider != null) {
dialog.setContentProvider(contentProvider);
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java index 1b17b27193f..66e4780188c 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java @@ -1,7 +1,6 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
- *
* 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
@@ -9,6 +8,7 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
*
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.creation;
@@ -73,16 +73,9 @@ public class UnlimitedNaturalEditionFactory extends StringEditionFactory { super(title, label, validator);
}
- /**
- *
- * @see org.eclipse.papyrus.infra.widgets.creation.StringEditionFactory#createObject(org.eclipse.swt.widgets.Control)
- *
- * @param widget
- * @return
- */
@Override
- public Object createObject(Control widget) {
- String txt = super.createObject(widget).toString();
+ public Object createObject(Control widget, Object context) {
+ String txt = super.createObject(widget, context).toString();
if(UnlimitedNaturalValidator.INFINITE_STAR.equals(txt)) {
txt = UnlimitedNaturalValidator.INFINITE_MINUS_ONE;
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java index 4526632711c..28b7d8c9ee8 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -17,6 +19,9 @@ import java.util.Set; import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.conversion.IConverter;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
@@ -363,4 +368,34 @@ public abstract class AbstractEditor extends Composite implements DisposeListene dispose();
}
+ /**
+ * Obtains the most appropriate operation executor for the object being edited.
+ *
+ * @param context the object being edited
+ * @return the executor to use to run operations (never {@code null})
+ */
+ public IAtomicOperationExecutor getOperationExecutor(Object context) {
+ IAtomicOperationExecutor result;
+ if(context instanceof IAdaptable) {
+ result = (IAtomicOperationExecutor)((IAdaptable)context).getAdapter(IAtomicOperationExecutor.class);
+ } else if (context != null) {
+ result = (IAtomicOperationExecutor)Platform.getAdapterManager().getAdapter(context, IAtomicOperationExecutor.class);
+ } else {
+ // We can't adapt null, of course, so we will have to settle for the default executor
+ result = null;
+ }
+
+ if (result == null) {
+ result = IAtomicOperationExecutor.DEFAULT;
+ }
+
+ return result;
+ }
+
+ /**
+ * Queries the model element that I edit.
+ *
+ * @return the contextual model element
+ */
+ protected abstract Object getContextElement();
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java index f91c35bdb5e..857a0d72062 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,11 +8,14 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
import org.eclipse.core.databinding.UpdateListStrategy;
import org.eclipse.core.databinding.conversion.IConverter;
+import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.swt.widgets.Composite;
@@ -142,4 +145,10 @@ public abstract class AbstractListEditor extends AbstractEditor { binding = getBindingContext().bindList(widgetObservable, modelProperty, targetToModelStrategy, modelToTargetStrategy);
}
+
+ protected Object getContextElement() {
+ // Our observables for features of EMF objects are expected to implement IObserving because
+ // the observe the value of the object's feature
+ return (modelProperty instanceof IObserving) ? ((IObserving)modelProperty).getObserved() : null;
+ }
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java index 503b9a52bf0..150eb611907 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -15,6 +17,7 @@ import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.swt.widgets.Composite;
@@ -172,4 +175,11 @@ public abstract class AbstractValueEditor extends AbstractEditor { * The current value for this editor
*/
public abstract Object getValue();
+
+ @Override
+ protected Object getContextElement() {
+ // Our observables for features of EMF objects are expected to implement IObserving because
+ // the observe the value of the object's feature
+ return (modelProperty instanceof IObserving) ? ((IObserving)modelProperty).getObserved() : null;
+ }
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java index 44c5728e5cb..97e812c23f2 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -229,6 +231,7 @@ public class CompactMultipleValueEditor extends AbstractListEditor implements IC * {@inheritDoc} Handles the event when the edit button is pressed
*/
public void widgetSelected(SelectionEvent e) {
+ dialog.setContextElement(getContextElement());
dialog.setInitialSelections(modelProperty.toArray());
int returnCode = dialog.open();
if(returnCode == Window.CANCEL) {
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java index 5a5411df9e2..b0694e00bb4 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -18,6 +20,7 @@ import org.eclipse.core.databinding.observable.ChangeEvent; import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -25,6 +28,7 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.infra.widgets.Activator;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
import org.eclipse.papyrus.infra.widgets.messages.Messages;
@@ -399,45 +403,67 @@ public class MultipleValueEditor extends AbstractListEditor implements Selection * Handle add Action
*/
protected void addAction() {
+ final Object context = getContextElement();
+
if(directCreation) {
if(referenceFactory != null && referenceFactory.canCreateObject()) {
- Object newElement = referenceFactory.createObject(this);
- if(newElement != null) {
- modelProperty.add(newElement);
- commit();
- }
+ getOperationExecutor(context).execute(new Runnable() {
+
+ @Override
+ public void run() {
+ Object newElement = referenceFactory.createObject(MultipleValueEditor.this, context);
+ if(newElement == null) {
+ // Cancel the operation
+ throw new OperationCanceledException();
+ }
+
+ modelProperty.add(newElement);
+ commit();
+ }
+ }, NLS.bind(Messages.MultipleValueEditor_addOperation, labelText));
}
return;
}
- String dialogLabel = label == null ? null : label.getText();
- MultipleValueSelectorDialog dialog = createMultipleValueSelectorDialog(getParent(), selector, ordered, unique, dialogLabel);
- dialog.setLabelProvider((ILabelProvider)treeViewer.getLabelProvider());
- dialog.setFactory(referenceFactory);
- dialog.setUpperBound(upperBound);
-
- if(modelProperty != null) {
- dialog.setInitialSelections(modelProperty.toArray());
- } else {
- dialog.setInitialSelections(new Object[0]);
- }
+ getOperationExecutor(context).execute(new Runnable() {
+
+ @Override
+ public void run() {
+ String dialogLabel = label == null ? null : label.getText();
+ MultipleValueSelectorDialog dialog = createMultipleValueSelectorDialog(getParent(), selector, ordered, unique, dialogLabel);
+ dialog.setLabelProvider((ILabelProvider)treeViewer.getLabelProvider());
+ dialog.setFactory(referenceFactory);
+ dialog.setUpperBound(upperBound);
+ dialog.setContextElement(context);
+
+ if(modelProperty != null) {
+ dialog.setInitialSelections(modelProperty.toArray());
+ } else {
+ dialog.setInitialSelections(new Object[0]);
+ }
- int returnCode = dialog.open();
- if(returnCode == Window.CANCEL) {
- return;
- }
+ int returnCode = dialog.open();
+ if(returnCode == Window.CANCEL) {
+ // Clear out the element selector in case we open this dialog again
+ selector.clearTemporaryElements();
+
+ // Roll back whatever has been done, so far
+ throw new OperationCanceledException();
+ }
- modelProperty.clear();
+ modelProperty.clear();
- Object[] result = dialog.getResult();
- if(result == null) {
- return;
- }
+ Object[] result = dialog.getResult();
+ if(result == null) {
+ return;
+ }
- modelProperty.addAll(Arrays.asList(result));
+ modelProperty.addAll(Arrays.asList(result));
- commit();
+ commit();
+ }
+ }, NLS.bind(Messages.MultipleValueEditor_addOperation, labelText));
}
@Override
@@ -513,19 +539,26 @@ public class MultipleValueEditor extends AbstractListEditor implements Selection TreeItem selectedItem = treeViewer.getTree().getSelection()[0];
Tree parentTree = selectedItem.getParent();
- int index = parentTree.indexOf(selectedItem);
-
- Object currentValue = selection.getFirstElement();
- Object newValue = referenceFactory.edit(this.edit, selection.getFirstElement());
-
- if(newValue != currentValue && newValue != null) {
- modelProperty.remove(index);
- modelProperty.add(index, newValue);
-
- //commit(); // The commit only occurs in the case where we modify the list (We don't commit direct edition on objects)
- }
+ final int index = parentTree.indexOf(selectedItem);
+ final Object currentValue = selection.getFirstElement();
+
+ getOperationExecutor(currentValue).execute(new Runnable() {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run() {
+ Object newValue = referenceFactory.edit(MultipleValueEditor.this.edit, currentValue);
+
+ if(newValue != currentValue && newValue != null) {
+ modelProperty.remove(index);
+ modelProperty.add(index, newValue);
+
+ //commit(); // The commit only occurs in the case where we modify the list (We don't commit direct edition on objects)
+ }
- commit();
+ commit();
+ }
+ }, NLS.bind(Messages.MultipleValueEditor_editOperation, labelText));
}
/**
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java index dc5eeecdad0..cd2c84d8b5b 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -19,6 +21,7 @@ import java.util.LinkedList; import java.util.Set;
import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
@@ -47,10 +50,15 @@ import org.eclipse.ui.dialogs.SelectionDialog; /**
* Object Chooser. Defines a standard popup for selecting
- * multiple values.
+ * multiple values. If this dialog is used to select or create model
+ * elements to be added to or removed from some element that is being
+ * edited, then it is important to
+ * {@linkplain #setContextElement(Object) set that contextual element}
+ * in this dialog.
*
* @author Camille Letavernier
*
+ * @see #setContextElement(Object)
*/
public class MultipleValueSelectorDialog extends SelectionDialog implements ISelectionChangedListener, IDoubleClickListener, IElementSelectionListener, SelectionListener {
@@ -150,6 +158,11 @@ public class MultipleValueSelectorDialog extends SelectionDialog implements ISel * The factory for creating new elements
*/
protected ReferenceValueFactory factory;
+
+ /**
+ * The model element being edited (if any), to which elements are to be added or removed.
+ */
+ protected Object contextElement;
/**
* The list of newly created objects
@@ -534,7 +547,15 @@ public class MultipleValueSelectorDialog extends SelectionDialog implements ISel return;
}
- Object newObject = factory.createObject(this.create);
+ Object newObject;
+
+ try {
+ newObject = factory.createObject(this.create, contextElement);
+ } catch (OperationCanceledException e) {
+ // The user cancelled and we rolled back pending model changes
+ newObject = null;
+ }
+
if(newObject == null) {
return;
}
@@ -703,6 +724,25 @@ public class MultipleValueSelectorDialog extends SelectionDialog implements ISel this.upperBound = upperBound;
}
+ /**
+ * Sets the optional context of the element that is being edited, in which others will be added and removed.
+ *
+ * @param contextElement
+ * the model element that is being edited
+ */
+ public void setContextElement(Object contextElement) {
+ this.contextElement = contextElement;
+ }
+
+ /**
+ * Queries the optional context of the element that is being edited, in which others will be added and removed.
+ *
+ * @return the model element that is being edited
+ */
+ public Object getContextElement() {
+ return contextElement;
+ }
+
@Override
public boolean close() {
selector.removeElementSelectionListener(this);
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java index 86a70c761e9..84c2234678b 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -16,9 +18,11 @@ import java.util.Collections; import java.util.List;
import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.infra.widgets.Activator;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
import org.eclipse.papyrus.infra.widgets.databinding.CLabelObservableValue;
@@ -213,14 +217,22 @@ public class ReferenceDialog extends AbstractValueEditor implements SelectionLis */
protected void createAction() {
if(valueFactory != null && valueFactory.canCreateObject()) {
- Object value = valueFactory.createObject(createInstanceButton);
- if(value == null) {
- return;
- }
- Collection<Object> validatedObjects = valueFactory.validateObjects(Collections.singleton(value));
- if(!validatedObjects.isEmpty()) {
- setValue(validatedObjects.iterator().next());
- }
+ final Object context = getContextElement();
+ getOperationExecutor(context).execute(new Runnable() {
+
+ @Override
+ public void run() {
+ Object value = valueFactory.createObject(createInstanceButton, context);
+ if(value == null) {
+ // Cancel the operation
+ throw new OperationCanceledException();
+ }
+ Collection<Object> validatedObjects = valueFactory.validateObjects(Collections.singleton(value));
+ if(!validatedObjects.isEmpty()) {
+ setValue(validatedObjects.iterator().next());
+ }
+ }
+ }, NLS.bind(Messages.ReferenceDialog_setOperation, labelText));
}
}
@@ -229,13 +241,19 @@ public class ReferenceDialog extends AbstractValueEditor implements SelectionLis * that is currently selected
*/
protected void editAction() {
- Object currentValue = getValue();
+ final Object currentValue = getValue();
if(currentValue != null && valueFactory != null && valueFactory.canEdit()) {
- Object newValue = valueFactory.edit(editInstanceButton, getValue());
- if(newValue != currentValue) {
- setValue(newValue);
- }
- updateLabel();
+ getOperationExecutor(currentValue).execute(new Runnable() {
+
+ @Override
+ public void run() {
+ Object newValue = valueFactory.edit(editInstanceButton, currentValue);
+ if(newValue != currentValue) {
+ setValue(newValue);
+ }
+ updateLabel();
+ }
+ }, NLS.bind(Messages.ReferenceDialog_editOperation, labelText));
}
}
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java index 7944870de3e..82dcdde6ce7 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 402525
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.messages;
@@ -32,6 +34,10 @@ public class Messages extends NLS { /** The Multiple value editor_ add elements. */
public static String MultipleValueEditor_AddElements;
+ public static String MultipleValueEditor_addOperation;
+
+ public static String MultipleValueEditor_editOperation;
+
/** The Multiple value editor_ edit selected value */
public static String MultipleValueEditor_EditSelectedValue;
@@ -61,6 +67,8 @@ public class Messages extends NLS { public static String ReferenceDialog_CreateANewObject;
+ public static String ReferenceDialog_editOperation;
+
public static String ReferenceDialog_EditTheCurrentValue;
/** The Reference dialog_ edit value */
@@ -69,6 +77,8 @@ public class Messages extends NLS { /** The Reference dialog_ select value */
public static String ReferenceDialog_SelectValue;
+ public static String ReferenceDialog_setOperation;
+
/** The Reference dialog_ unset */
public static String ReferenceDialog_Unset;
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties index a5cdb982258..a9fbdf92c68 100644 --- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties +++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties @@ -1,8 +1,24 @@ -BooleanInputValidator_NotABoolean=The actual entry is not an Boolean.
+###############################################################################
+# Copyright (c) 2010, 2014 CEA LIST and others.
+#
+# 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:
+# Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+# Christian W. Damus (CEA) - bug 402525
+#
+###############################################################################
+
+BooleanInputValidator_NotABoolean=The actual entry is not a Boolean.
IntegerInputValidator_NotAnIntegerMessage=The actual entry is not an Integer.
RealInputValidator_NotaRealMessage=The actual entry is not a Real.
UnlimitedNaturalInputValidator_NotAnUnlimitedNaturalMessage=The actual entry is not an UnlimitedNatural. An UnlimitedNatural must be either -1, * or >= 0
MultipleValueEditor_AddElements=Add elements
+MultipleValueEditor_addOperation=Add {0}
+MultipleValueEditor_editOperation=Edit {0}
MultipleValueEditor_EditSelectedValue=Edit the selected value
MultipleValueEditor_MoveSelectedElementsDown=Move selected elements down
MultipleValueEditor_MoveSelectedElementsUp=Move selected elements up
@@ -13,9 +29,11 @@ MultipleValueSelectorDialog_RemoveAllElements=Remove all elements MultipleValueSelectorDialog_CreateNewElement=Create a new element
MultipleValueSelectorDialog_DeleteNewElement=Deletes a newly created element
ReferenceDialog_CreateANewObject=Create a new object
+ReferenceDialog_editOperation=Edit {0}
ReferenceDialog_EditTheCurrentValue=Edit the current value
ReferenceDialog_EditValue=Edit the reference value
ReferenceDialog_SelectValue=Select the value for this reference
+ReferenceDialog_setOperation=Set {0}
ReferenceDialog_Unset=<Undefined>
ReferenceDialog_UnsetValue=Unset the reference value
ReferenceDialogObservable_Unchanged=<Unchanged>
|