Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/infra')
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java97
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java45
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IRollbackStatus.java41
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java186
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/NestingTransactionalCommandStack.java263
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/RollbackStatus.java166
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/TransactionalEditingDomainManager.java7
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModel.java47
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/sasheditor/DiModelUtils.java16
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/EMFHelper.java12
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml7
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java21
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ControlledResourceTracker.java287
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java79
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java145
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainProvider.java7
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java53
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java76
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java71
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java192
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java13
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/Messages.java34
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/internal/messages/messages.properties14
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF1
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/plugin.xml36
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/EObjectAdapterFactory.java85
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/adapters/ResourceSetRootsAdapter.java107
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/advice/ReadOnlyObjectEditAdvice.java328
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/databinding/EMFObservableList.java11
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/dialog/NestedEditingDialogContext.java132
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/Messages.java28
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/messages/messages.properties19
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/providers/ResourceFilteredLabelProvider.java135
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java85
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/MultipleStylableElement.xwt2
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleDiagram.xwt2
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/model/properties/ui/SingleStylableElement.xwt2
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/widgets/ResetStyleWidget.java25
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.theme/theme/papyrus_theme.css3
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/configuration/DefaultDirectEditorConfiguration.java2
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.extensionpoints.editors/src/org/eclipse/papyrus/extensionpoints/editors/definition/DirectEditorExtensionPoint.java11
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.properties6
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/plugin.xml2
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/schema/historyListeners.exsd91
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/CheckedOperationHistory.java23
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStack.java231
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands/src/org/eclipse/papyrus/commands/NotifyingWorkspaceCommandStack.java6
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/META-INF/MANIFEST.MF5
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/icons/shortcut.gifbin0 -> 93 bytes
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml370
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/advice/GMFDiagramDuplicateEditHelperAdvice.java70
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/databinding/custom/AbstractCustomStyleObservableValue.java12
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceDecoration.java70
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/decoration/ExternalReferenceMarker.java135
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/ConnectionEditPart.java76
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/IControlParserForDirectEdit.java32
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ExternalReferenceEditPolicy.java121
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/PapyrusResizableShapeEditPolicy.java25
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/ShapeCompartmentEditPolicy.java119
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpolicies/XYLayoutWithConstrainedResizedEditPolicy.java38
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/helper/NotationHelper.java40
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/listener/RollbackNotificationHistoryListener.java143
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/Messages.java28
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/messages/messages.properties20
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java18
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/ExternalReferenceEditPolicyProvider.java55
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/BorderNodeSnapHelper.java36
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/NodeSnapHelper.java459
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/PapyrusDragEditPartsTrackerEx.java50
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/ResizeTrackerWithPreferences.java195
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/snap/SnapUtils.java59
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/GMFUnsafe.java317
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/databinding/ObservableGradientData.java18
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElement.java6
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElement.java12
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/GradientDataModelElement.java40
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java10
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.xtext.glue/src/org/eclipse/papyrus/infra/gmfdiag/xtext/glue/PopupEditorConfiguration.java3
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableModelElement.java10
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalCommandHandler.java118
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/handler/TransactionalEditCellCommandHandler.java197
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/layer/PapyrusGridLayer.java30
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/table/AbstractNattableWidgetManager.java6
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/painter/CustomCheckBoxPainter.java17
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.decoration/src/org/eclipse/papyrus/infra/services/decoration/util/Decoration.java2
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.edit/plugin.xml17
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.edit/src/org/eclipse/papyrus/infra/services/edit/internal/ElementEditServiceProvider.java7
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/MarkersMonitorService.java25
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/providers/MarkerProviderRegistry.java134
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.markerlistener/src/org/eclipse/papyrus/infra/services/markerlistener/util/MarkerListenerUtils.java18
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/strategies/AskUserStrategy.java100
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.resourceloading/src/org/eclipse/papyrus/infra/services/resourceloading/util/LoadingUtils.java39
-rw-r--r--plugins/infra/services/org.eclipse.papyrus.infra.services.validation/src/org/eclipse/papyrus/infra/services/validation/commands/AbstractValidateCommand.java26
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java14
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java91
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java15
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java9
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java6
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java15
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java37
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java11
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java12
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java5
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java113
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java46
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java48
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java12
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties20
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
new file mode 100644
index 00000000000..c8ebb3156a8
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/icons/shortcut.gif
Binary files differ
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>

Back to the top